diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 1641ee15..f2c42091 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -17,7 +17,7 @@ jobs: - name: system packages run: | sudo apt-get update - sudo apt-get install -y --no-install-recommends pkg-config libwayland-dev libxkbcommon-dev libfontconfig1-dev + sudo apt-get install -y --no-install-recommends pkg-config libwebkit2gtk-4.1-dev libxdo-dev libasound2-dev - uses: dtolnay/rust-toolchain@stable with: components: rustfmt, clippy @@ -25,12 +25,7 @@ jobs: - run: cargo fmt --all --check - run: cargo clippy --workspace --all-targets -- -D warnings - run: cargo test --workspace - - uses: actions/setup-node@v4 - with: - node-version: 22 - - name: the web app's offline engine matches the hub, and markdown stays safe + - name: the Dioxus app builds for the web too run: | - cargo build -p anend-hub - node hub/web/test/parity.mjs | tee parity.log - grep -q "all the same" parity.log - node hub/web/test/markdown.mjs + rustup target add wasm32-unknown-unknown + cargo build -p anend-app --target wasm32-unknown-unknown --no-default-features --features web diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 2454ceaa..d2ea3469 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -1,6 +1,6 @@ name: release -# Push a tag like v0.2.0 to build the app and the hub for Linux and Windows and +# Push a tag like v0.2.0 to build the desktop app (anend-app) and the hub for Linux and Windows and # attach them to a GitHub release of that name. "Run workflow" on the Actions tab # builds them too, as downloadable artifacts, without making a release. on: @@ -33,11 +33,18 @@ jobs: if: runner.os == 'Linux' run: | sudo apt-get update - sudo apt-get install -y --no-install-recommends pkg-config libwayland-dev libxkbcommon-dev libfontconfig1-dev + sudo apt-get install -y --no-install-recommends pkg-config libwebkit2gtk-4.1-dev libxdo-dev libasound2-dev - uses: dtolnay/rust-toolchain@stable + with: + targets: wasm32-unknown-unknown - uses: Swatinem/rust-cache@v2 - - name: build the app and the hub - run: cargo build --release --locked --workspace + - name: the web app (built into the hub) + shell: bash + run: | + cargo install --locked wasm-bindgen-cli --version 0.2.129 + sh app/web/build.sh + - name: build the desktop app and the hub + run: cargo build --release --locked -p anend-app -p anend-hub - name: package shell: bash @@ -45,7 +52,7 @@ jobs: dir=anend-${{ github.ref_name }}-${{ matrix.name }} dir=${dir//\//-} mkdir "$dir" - cp target/release/anend${{ matrix.exe }} target/release/anend-hub${{ matrix.exe }} README.md LICENSE "$dir"/ + cp target/release/anend-app${{ matrix.exe }} target/release/anend-hub${{ matrix.exe }} README.md LICENSE "$dir"/ if [ "$RUNNER_OS" = "Windows" ]; then 7z a "$dir.zip" "$dir" >/dev/null echo "ASSET=$dir.zip" >> "$GITHUB_ENV" diff --git a/Cargo.lock b/Cargo.lock index 137c72b1..f5f1d082 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -18,81 +18,6 @@ version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "366ffbaa4442f4684d91e2cd7c5ea7c4ed8add41959a31447066e279e432b618" -[[package]] -name = "accesskit" -version = "0.24.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3b7f7f85a7e5f68090000ed7622545829afd484d210358702ae4cb97dd0c320" -dependencies = [ - "uuid", -] - -[[package]] -name = "accesskit_consumer" -version = "0.38.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d10a236f96f87d70732e44520046785431ef01d5bcd6b041317bfadd2f88245" -dependencies = [ - "accesskit", - "hashbrown 0.16.1", -] - -[[package]] -name = "accesskit_ios" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "750c4e9f6ce888dfe8a10c0f1b5ceb646a7854fd46579d74919219d1bb314083" -dependencies = [ - "accesskit", - "accesskit_consumer", - "hashbrown 0.16.1", - "objc2 0.5.3", - "objc2-foundation 0.2.2", - "objc2-ui-kit", -] - -[[package]] -name = "accesskit_macos" -version = "0.26.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce02dc63b43f0c9296af9ac946312a2dc8814427d7a64d2d600971dac55b6076" -dependencies = [ - "accesskit", - "accesskit_consumer", - "hashbrown 0.16.1", - "objc2 0.5.3", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "accesskit_windows" -version = "0.34.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "106c2b961215864d1c2e703ee63269c25c4e80a577ffb2c1017b9c17dcdf83a1" -dependencies = [ - "accesskit", - "accesskit_consumer", - "hashbrown 0.16.1", - "static_assertions", - "windows", - "windows-core", -] - -[[package]] -name = "accesskit_winit" -version = "0.33.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5b41e63a69f36d9f1f41e70464c7e5f72eee485ef26aab19f0b4f86e6c0a84c" -dependencies = [ - "accesskit", - "accesskit_ios", - "accesskit_macos", - "accesskit_windows", - "raw-window-handle", - "winit", -] - [[package]] name = "adler2" version = "2.0.1" @@ -135,25 +60,30 @@ dependencies = [ ] [[package]] -name = "ahash" -version = "0.8.12" +name = "aho-corasick" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ - "cfg-if", - "getrandom 0.3.4", - "once_cell", - "version_check", - "zerocopy", + "memchr", ] [[package]] -name = "aho-corasick" -version = "1.1.5" +name = "aligned" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +checksum = "ee4508988c62edf04abd8d92897fca0c2995d907ce1dfeaf369dac3716a40685" dependencies = [ - "memchr", + "as-slice", +] + +[[package]] +name = "aligned-vec" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc890384c8602f339876ded803c97ad529f3842aba97f6392b3dba0dd171769b" +dependencies = [ + "equator", ] [[package]] @@ -178,35 +108,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" [[package]] -name = "android-activity" -version = "0.6.1" +name = "alsa" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f2a1bb052857d5dd49572219344a7332b31b76405648eabac5bc68978251bcd" +checksum = "ed7572b7ba83a31e20d1b48970ee402d2e3e0537dcfe0a3ff4d6eb7508617d43" dependencies = [ - "android-properties", + "alsa-sys", "bitflags 2.13.2", - "cc", - "jni", + "cfg-if", "libc", - "log", - "ndk", - "ndk-context", - "ndk-sys", - "num_enum", - "thiserror 2.0.21", ] [[package]] -name = "android-properties" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc7eb209b1518d6bb87b283c20095f5228ecda460da70b44f0802523dea6da04" - -[[package]] -name = "android_log-sys" -version = "0.3.2" +name = "alsa-sys" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84521a3cf562bc62942e294181d9eef17eb38ceb8c68677bc49f144e4c3d4f8d" +checksum = "db8fee663d06c4e303404ef5f40488a53e062f89ba8bfed81f42325aafad1527" +dependencies = [ + "libc", + "pkg-config", +] [[package]] name = "android_system_properties" @@ -218,21 +139,29 @@ dependencies = [ ] [[package]] -name = "anend" +name = "anend-app" version = "0.1.0" dependencies = [ "anend-core", - "bevy", - "bevy_slugtext", + "anend-render", "chrono", - "fontique", + "cpal", + "dioxus", + "futures-channel", + "futures-util", + "gtk", + "js-sys", + "png 0.17.16", "pulldown-cmark", "redb", "serde", "serde_json", - "ttf-parser", + "symphonia", + "tokio", "ureq", - "winit", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] @@ -240,10 +169,15 @@ name = "anend-core" version = "0.1.0" dependencies = [ "chrono", + "image", + "pollster", "pulldown-cmark", "redb", "serde", "serde_json", + "serde_path_to_error", + "ureq", + "wgpu", ] [[package]] @@ -269,100 +203,50 @@ dependencies = [ ] [[package]] -name = "annotate-snippets" -version = "0.12.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f211a51805bc641f3ad5b7664c77d2547af685cc33b4cd8d31964027a46f13f1" -dependencies = [ - "anstyle", - "memchr", - "unicode-width", -] - -[[package]] -name = "anstream" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824a212faf96e9acacdbd09febd34438f8f711fb84e09a8916013cd7815ca28d" -dependencies = [ - "anstyle", - "anstyle-parse", - "anstyle-query", - "anstyle-wincon", - "colorchoice", - "is_terminal_polyfill", - "utf8parse", -] - -[[package]] -name = "anstyle" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "940b3a0ca603d1eade50a4846a2afffd5ef57a9feac2c0e2ec2e14f9ead76000" - -[[package]] -name = "anstyle-parse" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52ce7f38b242319f7cabaa6813055467063ecdc9d355bbb4ce0c68908cd8130e" -dependencies = [ - "utf8parse", -] - -[[package]] -name = "anstyle-query" -version = "1.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" +name = "anend-render" +version = "0.1.0" dependencies = [ - "windows-sys 0.61.2", + "ab_glyph", + "base64 0.22.1", + "bytemuck", + "glam", + "image", + "pollster", + "serde_json", + "web-sys", + "wgpu", ] [[package]] -name = "anstyle-wincon" -version = "3.0.11" +name = "anyhow" +version = "1.0.104" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" -dependencies = [ - "anstyle", - "once_cell_polyfill", - "windows-sys 0.61.2", -] +checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] -name = "approx" -version = "0.5.1" +name = "arbitrary" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab112f0a86d568ea0e627cc1d6be74a1e9cd55214684db5561995f6dad897c6" -dependencies = [ - "num-traits", -] +checksum = "3bc62ac97cc33321f50863d514c3bc38a453947a8f9e781137e47c7401020aed" [[package]] -name = "arboard" -version = "3.6.1" +name = "arc-swap" +version = "1.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0348a1c054491f4bfe6ab86a7b6ab1e44e45d899005de92f58b3df180b36ddaf" +checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" dependencies = [ - "clipboard-win", - "log", - "objc2 0.6.5", - "objc2-app-kit 0.3.2", - "objc2-foundation 0.3.2", - "parking_lot", - "percent-encoding", - "windows-sys 0.60.2", - "wl-clipboard-rs", - "x11rb", + "rustversion", ] [[package]] -name = "arc-swap" -version = "1.9.2" +name = "arg_enum_proc_macro" +version = "0.3.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b" +checksum = "0ae92a5119aa49cdbcf6b9f893fe4e1d98b04ccbf82ee0584ad948a44a734dea" dependencies = [ - "rustversion", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] @@ -377,12 +261,6 @@ dependencies = [ "password-hash", ] -[[package]] -name = "arrayref" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76a2e8124351fda1ef8aaaa3bbd7ebbcb486bbcd4225aca0aa0d84bb2db8fecb" - [[package]] name = "arrayvec" version = "0.7.8" @@ -390,10 +268,13 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3fb67a6e08acf24fdeccbac2cb6ac4305825bd1f117462e0e6f2f193345ad56" [[package]] -name = "as-raw-xcb-connection" -version = "1.0.1" +name = "as-slice" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "175571dd1d178ced59193a6fc02dde1b972eb0bc56c892cde9beeceac5bf0f6b" +checksum = "516b6b4f0e40d50dcda9365d53964ec74560ad4284da2e7fc97122cd83174516" +dependencies = [ + "stable_deref_trait", +] [[package]] name = "ash" @@ -401,7 +282,7 @@ version = "0.38.0+1.3.281" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0bb44936d800fea8f016d7f2311c6a4f97aebd5dc86f09906139ec848cf3a46f" dependencies = [ - "libloading", + "libloading 0.8.9", ] [[package]] @@ -454,143 +335,136 @@ dependencies = [ "serde", "serde_derive", "unicode-ident", - "winnow", + "winnow 1.0.4", ] [[package]] -name = "assert_type_match" -version = "0.1.1" +name = "async-stream" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f548ad2c4031f2902e3edc1f29c29e835829437de49562d8eb5dc5584d3a1043" +checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", + "async-stream-impl", + "futures-core", + "pin-project-lite", ] [[package]] -name = "async-broadcast" -version = "0.7.2" +name = "async-stream-impl" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "435a87a52755b8f27fcf321ac4f04b2802e337c8c4872923137471ec39c37532" +checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" dependencies = [ - "event-listener", - "event-listener-strategy", - "futures-core", - "pin-project-lite", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] -name = "async-channel" -version = "2.5.0" +name = "async-trait" +version = "0.1.92" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "924ed96dd52d1b75e9c1a3e6275715fd320f5f9439fb5a4a11fa51f4221158d2" +checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" dependencies = [ - "concurrent-queue", - "event-listener-strategy", - "futures-core", - "pin-project-lite", + "proc-macro2", + "quote", + "syn 3.0.9", ] [[package]] -name = "async-executor" -version = "1.14.0" +name = "async-tungstenite" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c96bf972d85afc50bf5ab8fe2d54d1586b4e0b46c97c50a0c9e71e2f7bcd812a" +checksum = "ee88b4c88ac8c9ea446ad43498955750a4bbe64c4392f21ccfe5d952865e318f" dependencies = [ - "async-task", - "concurrent-queue", - "fastrand", - "futures-lite", + "atomic-waker", + "futures-core", + "futures-io", + "futures-task", + "futures-util", + "log", "pin-project-lite", - "slab", + "tungstenite 0.27.0", ] [[package]] -name = "async-fs" -version = "2.2.0" +name = "atk" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8034a681df4aed8b8edbd7fbe472401ecf009251c8b40556b304567052e294c5" +checksum = "241b621213072e993be4f6f3a9e4b45f65b7e6faad43001be957184b7bb1824b" dependencies = [ - "async-lock", - "blocking", - "futures-lite", + "atk-sys", + "glib", + "libc", ] [[package]] -name = "async-io" -version = "2.6.0" +name = "atk-sys" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "456b8a8feb6f42d237746d4b3e9a178494627745c3c56c6ea55d92ba50d026fc" +checksum = "c5e48b684b0ca77d2bbadeef17424c2ea3c897d44d566a1617e7e8f30614d086" dependencies = [ - "autocfg", - "cfg-if", - "concurrent-queue", - "futures-io", - "futures-lite", - "parking", - "polling", - "rustix 1.1.5", - "slab", - "windows-sys 0.61.2", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", ] [[package]] -name = "async-lock" -version = "3.4.2" +name = "atomic-waker" +version = "1.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "290f7f2596bd5b78a9fec8088ccd89180d7f9f55b94b0576823bbbdc72ee8311" -dependencies = [ - "event-listener", - "event-listener-strategy", - "pin-project-lite", -] +checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" [[package]] -name = "async-task" -version = "4.7.1" +name = "autocfg" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b75356056920673b02621b35afd0f7dda9306d03c79a30f5c56c44cf256e3de" -dependencies = [ - "portable-atomic", -] +checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" [[package]] -name = "async-trait" -version = "0.1.92" +name = "av-scenechange" +version = "0.14.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82f6aeea286b8eb4dd3431a1be1b59d290ace00f5bfd8e2a159bc2a05e2c1667" +checksum = "0f321d77c20e19b92c39e7471cf986812cbb46659d2af674adc4331ef3f18394" dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", + "aligned", + "anyhow", + "arg_enum_proc_macro", + "arrayvec", + "log", + "num-rational", + "num-traits", + "pastey", + "rayon", + "thiserror 2.0.21", + "v_frame", + "y4m", ] [[package]] -name = "atomic-waker" -version = "1.1.2" +name = "av1-grain" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" +checksum = "8cfddb07216410377231960af4fcab838eaa12e013417781b78bd95ee22077f8" dependencies = [ - "portable-atomic", + "anyhow", + "arrayvec", + "log", + "nom 8.0.0", + "num-rational", + "v_frame", ] [[package]] -name = "atomicow" -version = "1.2.0" +name = "avif-serialize" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301801c08259e328a1c7da556608c0c22687708831b22024dbd3a57ea741e6de" +checksum = "e7178fe5f7d460b13895ebb9dcb28a3a6216d2df2574a0806cb51b555d297f38" dependencies = [ - "portable-atomic", - "portable-atomic-util", + "arrayvec", ] -[[package]] -name = "autocfg" -version = "1.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" - [[package]] name = "aws-lc-rs" version = "1.18.2" @@ -615,2070 +489,1513 @@ dependencies = [ ] [[package]] -name = "base64" -version = "0.22.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" - -[[package]] -name = "base64" -version = "0.23.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" - -[[package]] -name = "base64ct" -version = "1.8.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" - -[[package]] -name = "basic-toml" -version = "0.1.10" +name = "axum" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" +checksum = "31b698c5f9a010f6573133b09e0de5408834d0c82f8d7475a89fc1867a71cd90" dependencies = [ - "serde", + "axum-core", + "bytes", + "form_urlencoded", + "futures-util", + "http", + "http-body", + "http-body-util", + "itoa", + "matchit", + "memchr", + "mime", + "multer", + "percent-encoding", + "pin-project-lite", + "serde_core", + "serde_json", + "serde_path_to_error", + "serde_urlencoded", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", ] [[package]] -name = "bevy" -version = "0.20.0" +name = "axum-core" +version = "0.5.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8bd0e4ea5ec677698955f9f285221eab78606d8c27b57b889def199c16ce36e6" +checksum = "08c78f31d7b1291f7ee735c1c6780ccde7785daae9a9206026862dab7d8792d1" dependencies = [ - "bevy_internal", + "bytes", + "futures-core", + "http", + "http-body", + "http-body-util", + "mime", + "pin-project-lite", + "sync_wrapper", + "tower-layer", + "tower-service", ] [[package]] -name = "bevy_a11y" -version = "0.20.0" +name = "base64" +version = "0.22.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" + +[[package]] +name = "base64" +version = "0.23.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1070b9b7f087a5073be2da713367f29a831c85cd3391afcfc95bc0498125704" -dependencies = [ - "accesskit", - "bevy_app", - "bevy_derive", - "bevy_ecs", - "bevy_reflect", -] +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" [[package]] -name = "bevy_android" -version = "0.20.0" +name = "base64ct" +version = "1.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "17fd56a4708085b36f8aa1a011e347f8bd9334f0343bb3d5d9c3742897968a55" -dependencies = [ - "android-activity", -] +checksum = "2af50177e190e07a26ab74f8b1efbfe2ef87da2116221318cb1c2e82baf7de06" [[package]] -name = "bevy_animation" -version = "0.20.0" +name = "basic-toml" +version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9409aa300e8b023281b78759b3aed4124ec745dc7e1c9f96cbb445110e4b32ad" +checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" dependencies = [ - "bevy_animation_macros", - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_curve", - "bevy_derive", - "bevy_ecs", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "bevy_time", - "bevy_transform", - "bevy_utils", - "bitvec", - "blake3", - "derive_more", - "downcast-rs 2.0.2", - "either", - "petgraph", - "ron", "serde", - "smallvec", - "thiserror 2.0.21", - "thread_local", - "tracing", - "uuid", ] [[package]] -name = "bevy_animation_macros" -version = "0.20.0" +name = "bindgen" +version = "0.72.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "011144ef75ba95b665b1e6b03f3b7bbe9aa85d55472abb1d21e64813dac1c0a4" +checksum = "993776b509cfb49c750f11b8f07a46fa23e0a1386ffc01fb1e7d343efc387895" dependencies = [ - "bevy_macro_utils", + "bitflags 2.13.2", + "cexpr", + "clang-sys", + "itertools 0.13.0", + "proc-macro2", "quote", + "regex", + "rustc-hash 2.1.3", + "shlex 1.3.0", "syn 2.0.119", ] [[package]] -name = "bevy_app" -version = "0.20.0" +name = "bit-set" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2489da2972d57cccd19060d7faa44c4c4cfb296a657c84ee6ab8bde2b1c0115" +checksum = "09ec2f926cc3060f09db9ebc5b52823d85268d24bb917e472c0c4bea35780a7d" dependencies = [ - "bevy_derive", - "bevy_ecs", - "bevy_platform", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "console_error_panic_hook", - "ctrlc", - "downcast-rs 2.0.2", - "log", - "thiserror 2.0.21", - "variadics_please", - "wasm-bindgen", - "web-sys", + "bit-vec", ] [[package]] -name = "bevy_asset" -version = "0.20.0" +name = "bit-vec" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b88b3767a2c3f5a017b2febca08a670819ea2acb46846e4d8cd02980aeb0ed3e" -dependencies = [ - "async-broadcast", - "async-channel", - "async-fs", - "async-io", - "async-lock", - "atomicow", - "bevy_android", - "bevy_app", - "bevy_asset_macros", - "bevy_diagnostic", - "bevy_ecs", - "bevy_platform", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "bitflags 2.13.2", - "blake3", - "crossbeam-channel", - "derive_more", - "disqualified", - "downcast-rs 2.0.2", - "either", - "futures-io", - "futures-lite", - "futures-util", - "js-sys", - "ron", - "serde", - "stackfuture", - "thiserror 2.0.21", - "tracing", - "uuid", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] +checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" [[package]] -name = "bevy_asset_macros" -version = "0.20.0" +name = "bit_field" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "875b4fd236612744dbd61fb0a77ffde0aee37b8b780cf8a89caa308511c70646" -dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn 2.0.119", -] +checksum = "1e4b40c7323adcfc0a41c4b88143ed58346ff65a288fc144329c5c45e05d70c6" + +[[package]] +name = "bitflags" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] -name = "bevy_camera" -version = "0.20.0" +name = "bitflags" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f32c0d8436fb9373dc3b64fa30c3dec51d6a7cfda61de3c70fd1f62f8a903887" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_derive", - "bevy_ecs", - "bevy_image", - "bevy_math", - "bevy_mesh", - "bevy_reflect", - "bevy_shape", - "bevy_transform", - "bevy_utils", - "bevy_window", - "derive_more", - "downcast-rs 2.0.2", - "serde", - "smallvec", - "thiserror 2.0.21", - "wgpu-types", + "serde_core", ] [[package]] -name = "bevy_clipboard" -version = "0.20.0" +name = "bitstream-io" +version = "4.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0267b0beafd7e587a1b25b5ce14b271577f5fc1d8fd7828b2b66f0cf5dd649b" +checksum = "7eff00be299a18769011411c9def0d827e8f2d7bf0c3dbf53633147a8867fd1f" dependencies = [ - "arboard", - "bevy_app", - "bevy_ecs", - "bevy_log", - "bevy_platform", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", + "no_std_io2", ] [[package]] -name = "bevy_color" -version = "0.20.0" +name = "blake2" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0e57bfc1a0da1c018235fb98bb0e15ab61f1d0253122020ab6e1450e6cfbcf9" +checksum = "5b5d4d889834ee8ecfc0f8426ad30faf7cdcb10f741a8e6d7224d95325479f6f" dependencies = [ - "bevy_curve", - "bevy_math", - "bevy_reflect", - "bytemuck", - "derive_more", - "encase", - "serde", - "thiserror 2.0.21", - "wgpu-types", + "digest 0.11.3", ] [[package]] -name = "bevy_core_pipeline" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4a077b301be4b373a4cb224c54988e1f8385ecf3ab9e60bd3727a65b3d6901a" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_color", - "bevy_derive", - "bevy_diagnostic", - "bevy_ecs", - "bevy_extract", - "bevy_image", - "bevy_light", - "bevy_log", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_shader", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bitflags 2.13.2", - "indexmap", - "nonmax", -] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" [[package]] -name = "bevy_curve" -version = "0.20.0" +name = "block-buffer" +version = "0.10.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21ae28ed95c1c8a1bfc8930471840ee5a4b99b6b31138b17598e7ee6f4291b64" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" dependencies = [ - "approx", - "bevy_math", - "bevy_reflect", - "itertools 0.14.0", - "serde", - "thiserror 2.0.21", - "variadics_please", + "generic-array", ] [[package]] -name = "bevy_derive" -version = "0.20.0" +name = "block-buffer" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd59e9e600d792e60df17b4d52719b28c288bf047884ac89ad29d9c7a6592d2c" +checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" dependencies = [ - "bevy_macro_utils", - "quote", - "syn 2.0.119", + "hybrid-array", ] [[package]] -name = "bevy_diagnostic" -version = "0.20.0" +name = "block2" +version = "0.6.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f8851dc1b253b350bf941695457007e6e44ad4b8f075bf52a1ef202e6866b6a" +checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" dependencies = [ - "atomic-waker", - "bevy_app", - "bevy_ecs", - "bevy_platform", - "bevy_tasks", - "bevy_time", - "const-fnv1a-hash", - "log", - "serde", + "objc2", ] [[package]] -name = "bevy_ecs" -version = "0.20.0" +name = "brotli" +version = "9.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d5541a1658c5029b39e3ec59c6ecb47ad0a6d85fa083312a5ee2a95d6982a926" +checksum = "f8b851b75c23ca7873623d612fe49bd1989aeb03d08fb9432187eb253d3d4c6b" dependencies = [ - "arrayvec", - "bevy_ecs_macros", - "bevy_platform", - "bevy_ptr", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "bitflags 2.13.2", - "bumpalo", - "concurrent-queue", - "derive_more", - "fixedbitset", - "indexmap", - "log", - "nonmax", - "serde", - "slotmap", - "smallvec", - "thiserror 2.0.21", - "variadics_please", + "alloc-no-stdlib", + "alloc-stdlib", + "brotli-decompressor", ] [[package]] -name = "bevy_ecs_macro_logic" -version = "0.20.0" +name = "brotli-decompressor" +version = "6.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5197fea7643d2733e8b6d81c3dfa99adad3a754cdfd159c00255cea157b795d7" +checksum = "941cd9bd4ddab83cb46fa5a2d428f1c857b24ac78cb876cf7beb710840934bd7" dependencies = [ - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn 2.0.119", + "alloc-no-stdlib", + "alloc-stdlib", ] [[package]] -name = "bevy_ecs_macros" -version = "0.20.0" +name = "built" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3dde5305169503c9101404bf8cf17e8351f56fccf5152b8e5d7d7c32dcf1c486" -dependencies = [ - "bevy_ecs_macro_logic", - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn 2.0.119", -] +checksum = "5c0e531d93d39c34eef561e929e8a7f86d77a5af08aac4f6d6e39976c51858e9" [[package]] -name = "bevy_encase_derive" -version = "0.20.0" +name = "bumpalo" +version = "3.20.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4e4c4183c39ae8d00e53afeeab66aa71c41b08d82638149f9d485a2a62df569" -dependencies = [ - "bevy_macro_utils", - "encase_derive_impl", -] +checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] -name = "bevy_extract" -version = "0.20.0" +name = "bytemuck" +version = "1.25.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "08e27fc07ef8e3ab7c217fed1b171d42c90f3b6e4f7f526ffa28f9006ac49aa4" +checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" dependencies = [ - "bevy_app", - "bevy_camera", - "bevy_derive", - "bevy_ecs", - "bevy_extract_macros", - "bevy_log", - "bevy_platform", - "bevy_reflect", - "bevy_time", - "bevy_utils", + "bytemuck_derive", ] [[package]] -name = "bevy_extract_macros" -version = "0.20.0" +name = "bytemuck_derive" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a5c67e8c55ef35c65295e8cb614eda169780e21e2748f6df470d3bff21849a3" +checksum = "6a1f896587b6f2c069c73d2f0913e2d590c3990285cd2f0b6aa02b786b4c679c" dependencies = [ - "bevy_macro_utils", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.9", ] [[package]] -name = "bevy_feathers" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c4566f226580b5d852e3fa4fdb821e45367f598c0c6090896d686e446fa91f4" -dependencies = [ - "accesskit", - "bevy_a11y", - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_color", - "bevy_derive", - "bevy_ecs", - "bevy_input", - "bevy_input_focus", - "bevy_log", - "bevy_math", - "bevy_picking", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_scene", - "bevy_shader", - "bevy_text", - "bevy_ui", - "bevy_ui_render", - "bevy_ui_widgets", - "bevy_window", - "smol_str", -] - -[[package]] -name = "bevy_gizmos" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfc92f635ec5eaef5733afee45e6a0452e8c65de42d818dc7269dc5265087689" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_color", - "bevy_curve", - "bevy_ecs", - "bevy_gizmos_macros", - "bevy_input", - "bevy_log", - "bevy_math", - "bevy_mesh", - "bevy_reflect", - "bevy_shape", - "bevy_time", - "bevy_transform", - "bevy_utils", - "bevy_window", -] - -[[package]] -name = "bevy_gizmos_macros" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501e72c4ac31caef17ef9e627dee212d2107b95402a891ec6f0fc4107dd0cdf4" -dependencies = [ - "bevy_macro_utils", - "quote", - "syn 2.0.119", -] +name = "byteorder" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] -name = "bevy_gizmos_render" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42f5be0c9f114dc9b2c929076517d088e059b971edec5dfff4d5a225df6796df" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_color", - "bevy_core_pipeline", - "bevy_ecs", - "bevy_extract", - "bevy_gizmos", - "bevy_image", - "bevy_log", - "bevy_material", - "bevy_math", - "bevy_mesh", - "bevy_pbr", - "bevy_reflect", - "bevy_render", - "bevy_shader", - "bevy_shape", - "bevy_sprite_render", - "bevy_transform", - "bevy_utils", - "bytemuck", - "tracing", -] +name = "byteorder-lite" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] -name = "bevy_image" -version = "0.20.0" +name = "bytes" +version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb818dd8d705809d54adea08e346edce81a51ddbf06406ddf12a72ee467a3855" +checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_color", - "bevy_ecs", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "bevy_utils", - "bitflags 2.13.2", - "bytemuck", - "futures-lite", - "guillotiere", - "half", - "image", - "rectangle-pack", "serde", - "thiserror 2.0.21", - "tracing", - "wgpu-types", ] [[package]] -name = "bevy_input" -version = "0.20.0" +name = "cairo-rs" +version = "0.18.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "261ca5cc8a0bf228bfe4e841570db18a3ab1d034ce089772b8ec49c163ae74ea" +checksum = "8ca26ef0159422fb77631dc9d17b102f253b876fe1586b03b803e63a309b4ee2" dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "derive_more", - "log", - "smol_str", - "thiserror 2.0.21", + "bitflags 2.13.2", + "cairo-sys-rs", + "glib", + "libc", + "once_cell", + "thiserror 1.0.69", ] [[package]] -name = "bevy_input_focus" -version = "0.20.0" +name = "cairo-sys-rs" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83c81d369d0ab3ec17ba14bab1e07da7cacf3751a3104a93b1a3cd99d887887b" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" dependencies = [ - "bevy_app", - "bevy_camera", - "bevy_ecs", - "bevy_input", - "bevy_math", - "bevy_picking", - "bevy_reflect", - "bevy_window", - "log", - "thiserror 2.0.21", -] - -[[package]] -name = "bevy_internal" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4ed1cb58d1761426a077a8aff55e6a2e0cdfd19e411211d4b0217409330bb84" -dependencies = [ - "bevy_a11y", - "bevy_android", - "bevy_animation", - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_clipboard", - "bevy_color", - "bevy_core_pipeline", - "bevy_curve", - "bevy_derive", - "bevy_diagnostic", - "bevy_ecs", - "bevy_extract", - "bevy_feathers", - "bevy_gizmos", - "bevy_gizmos_render", - "bevy_image", - "bevy_input", - "bevy_input_focus", - "bevy_light", - "bevy_log", - "bevy_material", - "bevy_math", - "bevy_mesh", - "bevy_pbr", - "bevy_picking", - "bevy_platform", - "bevy_ptr", - "bevy_reflect", - "bevy_render", - "bevy_scene", - "bevy_shader", - "bevy_shape", - "bevy_sprite", - "bevy_sprite_render", - "bevy_state", - "bevy_tasks", - "bevy_text", - "bevy_time", - "bevy_transform", - "bevy_ui", - "bevy_ui_render", - "bevy_ui_widgets", - "bevy_utils", - "bevy_window", - "bevy_winit", - "bevy_world_serialization", -] - -[[package]] -name = "bevy_light" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "529d5ec7db637bbce7d016b2bfd0798362ad67118de8e9d37aaac24ecb3337cd" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_color", - "bevy_curve", - "bevy_ecs", - "bevy_gizmos", - "bevy_image", - "bevy_log", - "bevy_math", - "bevy_mesh", - "bevy_platform", - "bevy_reflect", - "bevy_shape", - "bevy_transform", - "bevy_utils", - "half", - "smallvec", - "tracing", - "wgpu-types", + "glib-sys", + "libc", + "system-deps", ] [[package]] -name = "bevy_log" -version = "0.20.0" +name = "cc" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a87d5152292b0e581a589cffb6b7e83e0afe345279d4126545ce7b786bd8a47a" +checksum = "6651c9ed80effdc7db0ff72512157f901af5e3549e341e24b1dd4887d836d838" dependencies = [ - "android_log-sys", - "bevy_app", - "bevy_ecs", - "bevy_platform", - "bevy_utils", - "tracing", - "tracing-log", - "tracing-oslog", - "tracing-subscriber", - "tracing-wasm", + "find-msvc-tools", + "jobserver", + "libc", + "shlex 2.0.1", ] [[package]] -name = "bevy_macro_utils" -version = "0.20.0" +name = "cesu8" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0d03a948df65138e30917d91237797d7e38763135ebacd0f28c891e1a3b2b52" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", - "toml_edit", -] +checksum = "6d43a04d8753f35258c91f8ec639f792891f748a1edbd759cf1dcea3382ad83c" [[package]] -name = "bevy_material" -version = "0.20.0" +name = "cexpr" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5be7ee4b2f4764e8d58a59afb47a3ba8bae36f955f409f08c658cace2808ef40" +checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766" dependencies = [ - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_material_macros", - "bevy_mesh", - "bevy_platform", - "bevy_reflect", - "bevy_shader", - "bevy_utils", - "encase", - "smallvec", - "thiserror 2.0.21", - "tracing", - "variadics_please", - "wgpu-types", + "nom 7.1.3", ] [[package]] -name = "bevy_material_macros" -version = "0.20.0" +name = "cfb" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70551fa201e1416ab44968631b7ce6320c194acfdb652a1971ec6882af122333" +checksum = "d38f2da7a0a2c4ccf0065be06397cc26a81f4e528be095826eee9d4adbb8c60f" dependencies = [ - "bevy_macro_utils", - "quote", - "syn 2.0.119", + "byteorder", + "fnv", + "uuid", ] [[package]] -name = "bevy_math" -version = "0.20.0" +name = "cfg-expr" +version = "0.15.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "598cbdcec4d0f0d966905996240ac76f77a644c583f95fb612d4f59f5f649038" +checksum = "d067ad48b8650848b989a59a86c6c36a995d02d2bf778d45c3c5d57bc2718f02" dependencies = [ - "approx", - "bevy_reflect", - "derive_more", - "glam", - "libm", - "rand 0.10.3", - "serde", - "thiserror 2.0.21", - "variadics_please", + "smallvec", + "target-lexicon", ] [[package]] -name = "bevy_mesh" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09358ac9a3ede5855568c10eaba6bcf126bf86639e786fb21b413457ebec5f26" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_encase_derive", - "bevy_math", - "bevy_mikktspace", - "bevy_platform", - "bevy_reflect", - "bevy_shape", - "bevy_transform", - "bitflags 2.13.2", - "bytemuck", - "derive_more", - "encase", - "glam", - "half", - "hexasphere", - "thiserror 2.0.21", - "tracing", - "wgpu-types", -] - -[[package]] -name = "bevy_mikktspace" -version = "1.0.0" +name = "cfg-if" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff34eb29ff4b8a8688bc7299f14fb6b597461ca80fec03ed7d22939ab33e48f" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] -name = "bevy_pbr" -version = "0.20.0" +name = "cfg_aliases" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb760932d1e683e7c00011f5c99e4e1cc893646a3a7b7224da6daf9bfa94853d" -dependencies = [ - "arrayvec", - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_color", - "bevy_core_pipeline", - "bevy_derive", - "bevy_diagnostic", - "bevy_ecs", - "bevy_extract", - "bevy_image", - "bevy_light", - "bevy_log", - "bevy_material", - "bevy_math", - "bevy_mesh", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_shader", - "bevy_shape", - "bevy_tasks", - "bevy_transform", - "bevy_utils", - "bitflags 2.13.2", - "bytemuck", - "derive_more", - "fixedbitset", - "indexmap", - "nonmax", - "offset-allocator", - "smallvec", - "static_assertions", - "thiserror 2.0.21", - "tracing", - "wgpu-types", -] +checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" [[package]] -name = "bevy_picking" -version = "0.20.0" +name = "chacha20" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47a04fb644c62a57a4f338f5cd8b61519c569139742eafe87dccb523e4b7cf2e" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_derive", - "bevy_ecs", - "bevy_input", - "bevy_math", - "bevy_mesh", - "bevy_platform", - "bevy_reflect", - "bevy_shape", - "bevy_time", - "bevy_transform", - "bevy_window", - "crossbeam-channel", - "tracing", - "uuid", + "cfg-if", + "cpufeatures 0.3.1", + "rand_core 0.10.1", ] [[package]] -name = "bevy_platform" -version = "0.20.0" +name = "chardetng" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "000bc467d1b344b6609fcf217a9b08d349d49c8e85dc4179fb7656f2b6e3db47" +checksum = "13de944a44b5064ee5d3a5ceccc49a41bfec50f2580e66f82e87703acdb88b53" dependencies = [ - "bytemuck", - "critical-section", - "foldhash 0.2.0", - "futures-channel", - "futures-lite", - "hashbrown 0.16.1", - "js-sys", - "portable-atomic", - "portable-atomic-util", - "serde", - "spin", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-time", - "windows-sys 0.61.2", + "cfg-if", + "encoding_rs", + "memchr", ] [[package]] -name = "bevy_ptr" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41935a00c02004753bd7ed5094754397800b3f673bf15553bb007b06216872d5" - -[[package]] -name = "bevy_reflect" -version = "0.20.0" +name = "charset" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46eecc733575b873deedcc37639e36290092388657091b3321fa6e073e7818e6" +checksum = "f1f927b07c74ba84c7e5fe4db2baeb3e996ab2688992e39ac68ce3220a677c7e" dependencies = [ - "assert_type_match", - "bevy_platform", - "bevy_ptr", - "bevy_reflect_derive", - "bevy_utils", - "derive_more", - "disqualified", - "downcast-rs 2.0.2", - "erased-serde", - "foldhash 0.2.0", - "glam", - "indexmap", - "inventory", - "petgraph", - "serde", - "smallvec", - "smol_str", - "thiserror 2.0.21", - "uuid", - "variadics_please", - "wgpu-types", + "base64 0.22.1", + "encoding_rs", ] [[package]] -name = "bevy_reflect_derive" -version = "0.20.0" +name = "chrono" +version = "0.4.45" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfaa1e315676c625ed8d30ba8a671ebf917cad6355320295b9802a8cbc06853b" +checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" dependencies = [ - "bevy_macro_utils", - "indexmap", - "proc-macro2", - "quote", - "syn 2.0.119", - "uuid", -] - -[[package]] -name = "bevy_render" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f438a921fd3ef82cc09ccf5e0cd8f1214dcae6286890f9d4acba0409d9a61a8" -dependencies = [ - "async-channel", - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_color", - "bevy_derive", - "bevy_diagnostic", - "bevy_ecs", - "bevy_encase_derive", - "bevy_extract", - "bevy_extract_macros", - "bevy_image", - "bevy_log", - "bevy_material", - "bevy_material_macros", - "bevy_math", - "bevy_mesh", - "bevy_platform", - "bevy_reflect", - "bevy_render_macros", - "bevy_shader", - "bevy_shape", - "bevy_tasks", - "bevy_time", - "bevy_transform", - "bevy_utils", - "bevy_window", - "bitflags 2.13.2", - "bytemuck", - "derive_more", - "downcast-rs 2.0.2", - "encase", - "glam", - "image", - "indexmap", - "itertools 0.14.0", + "iana-time-zone", "js-sys", - "nonmax", - "offset-allocator", - "send_wrapper", - "smallvec", - "static_assertions", - "thiserror 2.0.21", - "tracing", - "variadics_please", + "num-traits", + "serde", "wasm-bindgen", - "weak-table", - "web-sys", - "wgpu", - "wgpu-types", + "windows-link 0.2.1", ] [[package]] -name = "bevy_render_macros" -version = "0.20.0" +name = "ciborium" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119ca6d445eba5c9976c658f29bac854094b27c27624aa92c4d9668c319618d0" +checksum = "42e69ffd6f0917f5c029256a24d0161db17cea3997d185db0d35926308770f0e" dependencies = [ - "bevy_extract_macros", - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn 2.0.119", + "ciborium-io", + "ciborium-ll", + "serde", ] [[package]] -name = "bevy_scene" -version = "0.20.0" +name = "ciborium-io" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98c4b1677c948e4c1453883f4441136003c53fd9caa44e0f7d78b37618bdb9ad" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_log", - "bevy_platform", - "bevy_reflect", - "bevy_scene_macros", - "bevy_utils", - "smallvec", - "thiserror 2.0.21", - "tracing", - "variadics_please", -] +checksum = "05afea1e0a06c9be33d539b876f1ce3692f4afea2cb41f740e7743225ed1c757" [[package]] -name = "bevy_scene_macros" -version = "0.20.0" +name = "ciborium-ll" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4da846d8418ca6e38943707c88075a4a0b8f6eea0fd286d33a024d0257439d0" +checksum = "57663b653d948a338bfb3eeba9bb2fd5fcfaecb9e199e87e1eda4d9e8b240fd9" dependencies = [ - "bevy_ecs_macro_logic", - "bevy_macro_utils", - "proc-macro2", - "quote", - "syn 2.0.119", + "ciborium-io", + "half", ] [[package]] -name = "bevy_shader" -version = "0.20.0" +name = "cipher" +version = "0.4.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c2becafd54079da13835d6a42fc743e305d6270c27a91de613afe6e3f4b5de19" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" dependencies = [ - "bevy_asset", - "bevy_platform", - "bevy_reflect", - "bevy_utils", - "serde", - "thiserror 2.0.21", - "tracing", - "wesl", - "wgpu-types", + "crypto-common 0.1.7", + "inout", ] [[package]] -name = "bevy_shape" -version = "0.20.0" +name = "clang-sys" +version = "1.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa8b6096ad1ec7dfe1af8e51d7cfa7de1a9e0a3bd02be58a061092c5e1ff1eb1" +checksum = "157a8ba7b480713b56f4c09fd13fc3e0a22a5dfab8097ba61cbc5feef950788a" dependencies = [ - "arrayvec", - "bevy_math", - "bevy_reflect", - "derive_more", - "rand 0.10.3", - "rand_distr", - "serde", - "thiserror 2.0.21", + "glob", + "libc", + "libloading 0.8.9", ] [[package]] -name = "bevy_slugtext" -version = "0.1.0" -source = "git+https://github.com/SaulDoesCode/bevy_slugtext?rev=1cfb7d5#1cfb7d58036fa36b8cd8e44071bee859c11791c8" +name = "cmake" +version = "0.1.58" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" dependencies = [ - "bevy", - "ttf-parser", -] - -[[package]] -name = "bevy_sprite" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24dc4f69160513952a1969a3df5b4a2c729acfe0caf773854acea4a8c71f0918" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_color", - "bevy_derive", - "bevy_ecs", - "bevy_image", - "bevy_log", - "bevy_math", - "bevy_mesh", - "bevy_picking", - "bevy_reflect", - "bevy_text", - "bevy_transform", - "bevy_window", - "radsort", - "tracing", - "wgpu-types", + "cc", ] [[package]] -name = "bevy_sprite_render" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8918649806697740b61d3fd0559cb8c7de2ade5046aacf8abbef20e49ea1de0c" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_color", - "bevy_core_pipeline", - "bevy_derive", - "bevy_ecs", - "bevy_extract", - "bevy_image", - "bevy_material", - "bevy_math", - "bevy_mesh", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_shader", - "bevy_shape", - "bevy_sprite", - "bevy_text", - "bevy_transform", - "bevy_utils", - "bitflags 2.13.2", - "bytemuck", - "derive_more", - "fixedbitset", - "nonmax", - "smallvec", - "static_assertions", - "tracing", -] +name = "cmov" +version = "0.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" [[package]] -name = "bevy_state" -version = "0.20.0" +name = "cocoa" +version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09292e08e1eb34d2dd915630fb3c04ba75220c7819943c9f213d3a5f9a8be1e8" +checksum = "ad36507aeb7e16159dfe68db81ccc27571c3ccd4b76fb2fb72fc59e7a4b1b64c" dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_platform", - "bevy_reflect", - "bevy_state_macros", - "bevy_utils", - "log", - "variadics_please", + "bitflags 2.13.2", + "block", + "cocoa-foundation", + "core-foundation", + "core-graphics 0.24.0", + "foreign-types 0.5.0", + "libc", + "objc", ] [[package]] -name = "bevy_state_macros" -version = "0.20.0" +name = "cocoa-foundation" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fec1a8f6a253e39ddf7e447b1b9286caacb205ed8e619e6fb9a2e010d58dd04b" +checksum = "81411967c50ee9a1fc11365f8c585f863a22a9697c89239c452292c40ba79b0d" dependencies = [ - "bevy_macro_utils", - "quote", - "syn 2.0.119", + "bitflags 2.13.2", + "block", + "core-foundation", + "core-graphics-types", + "objc", ] [[package]] -name = "bevy_tasks" -version = "0.20.0" +name = "codespan-reporting" +version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbd8116f12dc50bde3758a72fba85e1f4c00e6c66d0ad58bdc46c0c0690829a8" +checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" dependencies = [ - "async-channel", - "async-executor", - "async-task", - "atomic-waker", - "bevy_platform", - "concurrent-queue", - "crossbeam-queue", - "derive_more", - "futures-lite", - "heapless", - "web-task", -] - -[[package]] -name = "bevy_text" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "119d2b37ce3f5ea5a5b9092a7c9eec8d3734de62592d2869bd1d925976f34d05" -dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_clipboard", - "bevy_color", - "bevy_derive", - "bevy_ecs", - "bevy_image", - "bevy_log", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "bevy_utils", - "parley", "serde", - "smallvec", - "smol_str", - "swash", - "sys-locale", - "thiserror 2.0.21", - "tracing", - "wgpu-types", + "termcolor", + "unicode-width", ] [[package]] -name = "bevy_time" -version = "0.20.0" +name = "color_quant" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13901174b792bb7848d8e088075f0009ea409b99179934c0d5bdd2b95622694e" -dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_platform", - "bevy_reflect", - "crossbeam-channel", - "log", - "serde", -] +checksum = "3d7b894f5411737b7867f4827955924d7c254fc9f4d91a6aad6b097804b1018b" [[package]] -name = "bevy_transform" -version = "0.20.0" +name = "combine" +version = "4.6.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83379023d77a0739569a5bcb859eed652781a1b3271e94a86dfbb56fc5d067e0" +checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" dependencies = [ - "bevy_app", - "bevy_ecs", - "bevy_math", - "bevy_reflect", - "bevy_tasks", - "bevy_utils", - "derive_more", - "serde", - "thiserror 2.0.21", -] - -[[package]] -name = "bevy_ui" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7926fba78f133376db0cba73a054db6931952379b5bfdc63f2fe9ba0c3b96c39" -dependencies = [ - "accesskit", - "bevy_a11y", - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_color", - "bevy_derive", - "bevy_ecs", - "bevy_image", - "bevy_input", - "bevy_input_focus", - "bevy_log", - "bevy_math", - "bevy_picking", - "bevy_platform", - "bevy_reflect", - "bevy_sprite", - "bevy_text", - "bevy_time", - "bevy_transform", - "bevy_utils", - "bevy_window", - "derive_more", - "parley", - "smallvec", - "swash", - "taffy", - "thiserror 2.0.21", - "tracing", - "uuid", -] - -[[package]] -name = "bevy_ui_render" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "620b51b51eb8e7d8b2362ba96263142829560d9aa254e2f28032570667c6b0fb" -dependencies = [ - "bevy_a11y", - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_color", - "bevy_core_pipeline", - "bevy_derive", - "bevy_ecs", - "bevy_extract", - "bevy_image", - "bevy_input_focus", - "bevy_math", - "bevy_mesh", - "bevy_platform", - "bevy_reflect", - "bevy_render", - "bevy_shader", - "bevy_sprite", - "bevy_sprite_render", - "bevy_text", - "bevy_transform", - "bevy_ui", - "bevy_utils", - "bytemuck", - "derive_more", - "indexmap", - "smallvec", - "tracing", + "bytes", + "memchr", ] [[package]] -name = "bevy_ui_widgets" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6442cd402df6a54f0e51ed8c1bd004c8f9c6715d0f8045e33c68ea9aebb1ce16" -dependencies = [ - "accesskit", - "bevy_a11y", - "bevy_app", - "bevy_camera", - "bevy_ecs", - "bevy_input", - "bevy_input_focus", - "bevy_log", - "bevy_math", - "bevy_picking", - "bevy_platform", - "bevy_reflect", - "bevy_text", - "bevy_time", - "bevy_ui", - "bevy_window", - "parley", - "smol_str", - "web-sys", -] +name = "const-oid" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" [[package]] -name = "bevy_utils" -version = "0.20.0" +name = "const-serialize" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cbd58495039d4e63e6fcfef1242fecab33ffe62b4a5e010467e69e790879812" +checksum = "ad7154afa56de2f290e3c82c2c6dc4f5b282b6870903f56ef3509aba95866edc" dependencies = [ - "async-channel", - "bevy_platform", - "disqualified", - "indexmap", - "thread_local", + "const-serialize-macro 0.7.2", ] [[package]] -name = "bevy_window" -version = "0.20.0" +name = "const-serialize" +version = "0.8.0-alpha.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc9a83f3cbaa04155b5dc9b247819c0e215aee754451a4324b82ddeb80dc53f1" +checksum = "9e42cd5aabba86f128b3763da1fec1491c0f728ce99245062cd49b6f9e6d235b" dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_ecs", - "bevy_image", - "bevy_input", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "log", - "raw-window-handle", + "const-serialize 0.7.2", + "const-serialize-macro 0.8.0-alpha.1", "serde", ] [[package]] -name = "bevy_winit" -version = "0.20.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ef0a5a55524e793ab13536ef244229fa66a4839fae6564df2aa4b3c13956a82" -dependencies = [ - "accesskit", - "accesskit_winit", - "approx", - "bevy_a11y", - "bevy_android", - "bevy_app", - "bevy_asset", - "bevy_derive", - "bevy_ecs", - "bevy_image", - "bevy_input", - "bevy_input_focus", - "bevy_log", - "bevy_math", - "bevy_platform", - "bevy_reflect", - "bevy_tasks", - "bevy_window", - "bytemuck", - "js-sys", - "tracing", - "wasm-bindgen", - "web-sys", - "wgpu-types", - "winit", -] - -[[package]] -name = "bevy_world_serialization" -version = "0.20.0" +name = "const-serialize-macro" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eef3a23ed3899c88467ce27a0420a1dadeb543981c2e1b9617f6ecf6e5fce1bf" +checksum = "4f160aad86b4343e8d4e261fee9965c3005b2fd6bc117d172ab65948779e4acf" dependencies = [ - "bevy_app", - "bevy_asset", - "bevy_camera", - "bevy_derive", - "bevy_ecs", - "bevy_platform", - "bevy_reflect", - "bevy_transform", - "bevy_utils", - "derive_more", - "ron", - "serde", - "thiserror 2.0.21", - "uuid", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] -name = "bit-set" -version = "0.10.0" +name = "const-serialize-macro" +version = "0.8.0-alpha.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2f926cc3060f09db9ebc5b52823d85268d24bb917e472c0c4bea35780a7d" +checksum = "8e4c3b1c2ce89797adff100c510b92c7cf32983fdbc632e703253f2ef516ef56" dependencies = [ - "bit-vec", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] -name = "bit-vec" -version = "0.9.1" +name = "const-str" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b71798fca2c1fe1086445a7258a4bc81e6e49dcd24c8d0dd9a1e57395b603f51" +checksum = "b0664d2867b4a32697dfe655557f5c3b187e9b605b38612a748e5ec99811d160" [[package]] -name = "bitflags" -version = "1.3.2" +name = "const_format" +version = "0.2.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "4481a617ad9a412be3b97c5d403fef8ed023103368908b9c50af598ff467cc1e" +dependencies = [ + "const_format_proc_macros", + "konst", +] [[package]] -name = "bitflags" -version = "2.13.2" +name = "const_format_proc_macros" +version = "0.2.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" +checksum = "1d57c2eccfb16dbac1f4e61e206105db5820c9d26c3c472bc17c774259ef7744" dependencies = [ - "bytemuck", - "serde_core", + "proc-macro2", + "quote", + "unicode-xid", ] [[package]] -name = "bitvec" -version = "1.1.1" +name = "content_disposition" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddcec3d12c579d40898fe0a9a358a803c23e9c52ca3c425707f81c9436211837" +checksum = "ebc14a88e1463ddd193906285abe5c360c7e8564e05ccc5d501755f7fbc9ca9c" dependencies = [ - "funty", - "radium", - "tap", - "wyz", + "charset", ] [[package]] -name = "blake2" -version = "0.11.0" +name = "content_inspector" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b5d4d889834ee8ecfc0f8426ad30faf7cdcb10f741a8e6d7224d95325479f6f" +checksum = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38" dependencies = [ - "digest 0.11.3", + "memchr", ] [[package]] -name = "blake3" -version = "1.8.7" +name = "convert_case" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d9e454fc11f76977dc803893aff6304ed33d6a26efae8696573bea74baa27ae" +checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" + +[[package]] +name = "convert_case" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" dependencies = [ - "arrayvec", - "cc", - "cfg-if", - "constant_time_eq", - "cpufeatures 0.3.1", + "unicode-segmentation", ] [[package]] -name = "block-buffer" -version = "0.10.4" +name = "convert_case" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ - "generic-array", + "unicode-segmentation", ] [[package]] -name = "block-buffer" -version = "0.12.1" +name = "cookie" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa" +checksum = "1a373e3602691c3cdea496d2f0ee5935151e6168fe87739483c463db1b2f2f87" dependencies = [ - "hybrid-array", + "aes-gcm", + "base64 0.22.1", + "hmac", + "percent-encoding", + "rand 0.8.8", + "sha2 0.10.9", + "subtle", + "time", + "version_check", ] [[package]] -name = "block2" -version = "0.5.1" +name = "cookie_store" +version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" +checksum = "15b2c103cf610ec6cae3da84a766285b42fd16aad564758459e6ecf128c75206" dependencies = [ - "objc2 0.5.3", + "cookie", + "document-features", + "idna", + "log", + "publicsuffix", + "serde", + "serde_derive", + "serde_json", + "time", + "url", ] [[package]] -name = "block2" -version = "0.6.2" +name = "core-foundation" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdeb9d870516001442e364c5220d3574d2da8dc765554b4a617230d33fa58ef5" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" dependencies = [ - "objc2 0.6.5", + "core-foundation-sys", + "libc", ] [[package]] -name = "blocking" -version = "1.7.0" +name = "core-foundation-sys" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a70e4329df6cb94385eed412ec92375c3cdd8a6e502493d1229b6414e4036dfa" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + +[[package]] +name = "core-graphics" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa95a34622365fa5bbf40b20b75dba8dfa8c94c734aea8ac9a5ca38af14316f1" dependencies = [ - "async-channel", - "async-task", - "futures-io", - "futures-lite", - "piper", + "bitflags 2.13.2", + "core-foundation", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", ] [[package]] -name = "brotli" -version = "9.0.0" +name = "core-graphics" +version = "0.25.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8b851b75c23ca7873623d612fe49bd1989aeb03d08fb9432187eb253d3d4c6b" +checksum = "064badf302c3194842cf2c5d61f56cc88e54a759313879cdf03abdd27d0c3b97" dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", - "brotli-decompressor", + "bitflags 2.13.2", + "core-foundation", + "core-graphics-types", + "foreign-types 0.5.0", + "libc", ] [[package]] -name = "brotli-decompressor" -version = "6.0.1" +name = "core-graphics-types" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "941cd9bd4ddab83cb46fa5a2d428f1c857b24ac78cb876cf7beb710840934bd7" +checksum = "3d44a101f213f6c4cdc1853d4b78aef6db6bdfa3468798cc1d9912f4735013eb" dependencies = [ - "alloc-no-stdlib", - "alloc-stdlib", + "bitflags 2.13.2", + "core-foundation", + "libc", ] [[package]] -name = "bumpalo" -version = "3.20.3" +name = "core_detect" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" +checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" [[package]] -name = "bytemuck" -version = "1.25.2" +name = "coreaudio-rs" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95832e849adfb21180ccb6826a99da14e5d266ae5c2e668e1602cf234f153797" +checksum = "321077172d79c662f64f5071a03120748d5bb652f5231570141be24cfcd2bace" dependencies = [ - "bytemuck_derive", + "bitflags 1.3.2", + "core-foundation-sys", + "coreaudio-sys", ] [[package]] -name = "bytemuck_derive" -version = "1.12.1" +name = "coreaudio-sys" +version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a1f896587b6f2c069c73d2f0913e2d590c3990285cd2f0b6aa02b786b4c679c" +checksum = "b9b4739a805a62757a83e5654fa3faabec0442666b263bb2287d5a8185bfd953" dependencies = [ - "proc-macro2", - "quote", - "syn 3.0.9", + "bindgen", ] [[package]] -name = "byteorder" -version = "1.5.0" +name = "cpal" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" +checksum = "873dab07c8f743075e57f524c583985fbaf745602acbe916a01539364369a779" +dependencies = [ + "alsa", + "core-foundation-sys", + "coreaudio-rs", + "dasp_sample", + "jni 0.21.1", + "js-sys", + "libc", + "mach2", + "ndk 0.8.0", + "ndk-context", + "oboe", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", + "windows 0.54.0", +] [[package]] -name = "byteorder-lite" -version = "0.1.0" +name = "cpufeatures" +version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" +checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +dependencies = [ + "libc", +] [[package]] -name = "bytes" -version = "1.12.1" +name = "cpufeatures" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +dependencies = [ + "libc", +] [[package]] -name = "calloop" -version = "0.13.0" +name = "crc32fast" +version = "1.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b99da2f8558ca23c71f4fd15dc57c906239752dd27ff3c00a1d56b685b7cbfec" +checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" dependencies = [ - "bitflags 2.13.2", - "log", - "polling", - "rustix 0.38.44", - "slab", - "thiserror 1.0.69", + "cfg-if", ] [[package]] -name = "calloop-wayland-source" -version = "0.3.0" +name = "crossbeam-channel" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95a66a987056935f7efce4ab5668920b5d0dac4a7c99991a67395f13702ddd20" +checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" dependencies = [ - "calloop", - "rustix 0.38.44", - "wayland-backend", - "wayland-client", + "crossbeam-utils", ] [[package]] -name = "cc" -version = "1.8.0" +name = "crossbeam-deque" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6651c9ed80effdc7db0ff72512157f901af5e3549e341e24b1dd4887d836d838" +checksum = "622f3fc73690be383c7214310406f28a90e6edeadc3cea882f9d71e495b9711a" dependencies = [ - "find-msvc-tools", - "jobserver", - "libc", - "shlex", + "crossbeam-epoch", + "crossbeam-utils", ] [[package]] -name = "cfg-if" -version = "1.0.5" +name = "crossbeam-epoch" +version = "0.9.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" +checksum = "dc74980687109a3b14c72fd458107bf0baa1da1a1a805e178d15501ba9b86d9d" +dependencies = [ + "crossbeam-utils", +] [[package]] -name = "cfg_aliases" -version = "0.2.2" +name = "crossbeam-utils" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" [[package]] -name = "chacha20" -version = "0.10.2" +name = "crunchy" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" -dependencies = [ - "cfg-if", - "cpufeatures 0.3.1", - "rand_core 0.10.1", -] +checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" [[package]] -name = "chardetng" -version = "1.0.0" +name = "crypto-common" +version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13de944a44b5064ee5d3a5ceccc49a41bfec50f2580e66f82e87703acdb88b53" +checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" dependencies = [ - "cfg-if", - "encoding_rs", - "memchr", + "generic-array", + "rand_core 0.6.4", + "typenum", ] [[package]] -name = "chrono" -version = "0.4.45" +name = "crypto-common" +version = "0.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aa79e62e7697b8e29b513a68abacf485adcd1fe8284a4316c5ae868e6633327" +checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" dependencies = [ - "iana-time-zone", - "js-sys", - "num-traits", - "serde", - "wasm-bindgen", - "windows-link", + "hybrid-array", ] [[package]] -name = "cipher" -version = "0.4.4" +name = "cssparser" +version = "0.29.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +checksum = "f93d03419cb5950ccfd3daf3ff1c7a36ace64609a1a8746d493df1ca0afde0fa" dependencies = [ - "crypto-common 0.1.7", - "inout", + "cssparser-macros", + "dtoa-short", + "itoa", + "matches", + "phf 0.10.1", + "proc-macro2", + "quote", + "smallvec", + "syn 1.0.109", ] [[package]] -name = "clipboard-win" -version = "5.4.1" +name = "cssparser-macros" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bde03770d3df201d4fb868f2c9c59e66a3e4e2bd06692a0fe701e7103c7e84d4" +checksum = "13b588ba4ac1a99f7f2964d24b3d896ddc6bf847ee3855dbd4366f058cfcd331" dependencies = [ - "error-code", + "quote", + "syn 2.0.119", ] [[package]] -name = "cmake" -version = "0.1.58" +name = "ctr" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" dependencies = [ - "cc", + "cipher", ] [[package]] -name = "cmov" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c9ea0ac24bc397ab3c98583a3c9ba74fa56b09a4449bbe172b9b1ddb016027a" - -[[package]] -name = "codespan-reporting" -version = "0.13.1" +name = "ctutils" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "af491d569909a7e4dee0ad7db7f5341fef5c614d5b8ec8cf765732aba3cff681" +checksum = "03bb0e1cc970d482d121d9a1744999169b69a07470b3d644a7894e53fcaf4574" dependencies = [ - "unicode-width", + "cmov", ] [[package]] -name = "colorchoice" -version = "1.0.5" +name = "darling" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +checksum = "9cdf337090841a411e2a7f3deb9187445851f91b309c0c0a29e05f74a00a48c0" +dependencies = [ + "darling_core", + "darling_macro", +] [[package]] -name = "combine" -version = "4.6.8" +name = "darling_core" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" +checksum = "1247195ecd7e3c85f83c8d2a366e4210d588e802133e1e355180a9870b517ea4" dependencies = [ - "bytes", - "memchr", + "fnv", + "ident_case", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] -name = "concurrent-queue" -version = "2.5.0" +name = "darling_macro" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca0197aee26d1ae37445ee532fefce43251d24cc7c166799f4d46817f1d3973" +checksum = "d38308df82d1080de0afee5d069fa14b0326a88c14f15c5ccda35b4a6c414c81" dependencies = [ - "crossbeam-utils", - "portable-atomic", + "darling_core", + "quote", + "syn 2.0.119", ] [[package]] -name = "console_error_panic_hook" -version = "0.1.7" +name = "dasp_sample" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a06aeb73f470f66dcdbf7223caeebb85984942f22f1adb2a088cf9668146bbbc" -dependencies = [ - "cfg-if", - "wasm-bindgen", -] +checksum = "0c87e182de0887fd5361989c677c4e8f5000cd9491d6d563161a8f3a5519fc7f" [[package]] -name = "const-fnv1a-hash" -version = "1.1.0" +name = "data-encoding" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32b13ea120a812beba79e34316b3942a857c86ec1593cb34f27bb28272ce2cca" +checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" [[package]] -name = "const-oid" -version = "0.10.2" +name = "deranged" +version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c" +checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" [[package]] -name = "const_panic" -version = "0.2.17" +name = "derive_more" +version = "0.99.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9603f79528ece8163c496f8932121cb36cfe46259e9c907bb3d8205139d7caa3" +checksum = "6edb4b64a43d977b8e99788fe3a04d483834fba1215a7e02caa415b626497f7f" dependencies = [ - "typewit", + "convert_case 0.4.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.119", ] [[package]] -name = "const_soft_float" -version = "0.1.4" +name = "derive_more" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "87ca1caa64ef4ed453e68bb3db612e51cf1b2f5b871337f0fcab1c8f87cc3dff" +checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +dependencies = [ + "derive_more-impl", +] [[package]] -name = "constant_time_eq" -version = "0.4.2" +name = "derive_more-impl" +version = "2.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d52eff69cd5e647efe296129160853a42795992097e8af39800e1060caeea9b" +checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +dependencies = [ + "convert_case 0.10.0", + "proc-macro2", + "quote", + "rustc_version", + "syn 2.0.119", + "unicode-xid", +] [[package]] -name = "constgebra" -version = "0.1.4" +name = "digest" +version = "0.10.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1aaf9b65849a68662ac6c0810c8893a765c960b907dd7cfab9c4a50bf764fbc" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ - "const_soft_float", + "block-buffer 0.10.4", + "crypto-common 0.1.7", + "subtle", ] [[package]] -name = "content_inspector" -version = "0.2.4" +name = "digest" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7bda66e858c683005a53a9a60c69a4aca7eeaa45d124526e389f7aec8e62f38" +checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" dependencies = [ - "memchr", + "block-buffer 0.12.1", + "const-oid", + "crypto-common 0.2.2", + "ctutils", ] [[package]] -name = "convert_case" -version = "0.10.0" +name = "dioxus" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" +checksum = "9320593eda4f01858f046698b42441603d2af5fcb62a6c1f9046a0c2eebd6d9b" dependencies = [ - "unicode-segmentation", + "dioxus-asset-resolver", + "dioxus-cli-config", + "dioxus-config-macro", + "dioxus-config-macros", + "dioxus-core", + "dioxus-core-macro", + "dioxus-desktop", + "dioxus-document", + "dioxus-fullstack", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-signals", + "dioxus-stores", + "dioxus-web", + "manganis", + "subsecond", + "warnings", ] [[package]] -name = "cookie" -version = "0.18.2" +name = "dioxus-asset-resolver" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a373e3602691c3cdea496d2f0ee5935151e6168fe87739483c463db1b2f2f87" +checksum = "84235ff0e272f15d4537603cdd50df6d45d50e51bb96326dbc0bdfd01d825226" dependencies = [ - "aes-gcm", - "base64 0.22.1", - "hmac", + "dioxus-cli-config", + "http", + "infer", + "jni 0.21.1", + "js-sys", + "ndk 0.9.0", + "ndk-context", + "ndk-sys 0.6.0+11769913", "percent-encoding", - "rand 0.8.8", - "sha2 0.10.9", - "subtle", - "time", - "version_check", + "thiserror 2.0.21", + "tokio", + "wasm-bindgen-futures", + "web-sys", ] [[package]] -name = "core-foundation" -version = "0.9.4" +name = "dioxus-cli-config" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91e195e091a93c46f7102ec7818a2aa394e1e1771c3ab4825963fa03e45afb8f" +checksum = "322d10f47effebd85ee0662a2cb083ff920d40dd6295a4afd8cfa4f9bc2e05c6" dependencies = [ - "core-foundation-sys", - "libc", + "wasm-bindgen", ] [[package]] -name = "core-foundation" -version = "0.10.1" +name = "dioxus-config-macro" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +checksum = "9f3a906c8219e94fa48189a793c760a4e3193cbb7791f799e9d37633fe41161d" dependencies = [ - "core-foundation-sys", - "libc", + "proc-macro2", + "quote", ] [[package]] -name = "core-foundation-sys" -version = "0.8.7" +name = "dioxus-config-macros" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +checksum = "20de015bc89c20f4ffc7b4f849943420308365fa66f991250b5c075261990a21" [[package]] -name = "core-graphics" -version = "0.23.2" +name = "dioxus-core" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" +checksum = "1b232228ada232c0adc151e41ebd9ef70cc04683db097fa0dc6015979fa01722" dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "core-graphics-types", - "foreign-types", - "libc", + "anyhow", + "const_format", + "dioxus-core-types", + "futures-channel", + "futures-util", + "generational-box", + "longest-increasing-subsequence", + "rustc-hash 2.1.3", + "rustversion", + "serde", + "slab", + "slotmap", + "subsecond", + "tracing", ] [[package]] -name = "core-graphics-types" -version = "0.1.3" +name = "dioxus-core-macro" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" +checksum = "6256a68462222f0600f5fd7d9542cbd9f299bc19355d900f7827dd3fc9e09fdb" dependencies = [ - "bitflags 1.3.2", - "core-foundation 0.9.4", - "libc", + "convert_case 0.8.0", + "dioxus-rsx", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] -name = "core_detect" -version = "1.0.0" +name = "dioxus-core-types" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7f8f80099a98041a3d1622845c271458a2d73e688351bf3cb999266764b81d48" +checksum = "96007ed6cbad951dfed82d83c581aabd95bc591f351f5666d454ddbe7845b324" [[package]] -name = "cpufeatures" -version = "0.2.17" +name = "dioxus-desktop" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59ed5838eebb26a2bb2e58f6d5b5316989ae9d08bab10e0e6d103e656d1b0280" +checksum = "236deb81f1a04de704fb80cf7838c65607441c76914de2e036709540c540a39d" dependencies = [ + "anyhow", + "async-trait", + "base64 0.22.1", + "bytes", + "cocoa", + "core-foundation", + "dioxus-asset-resolver", + "dioxus-cli-config", + "dioxus-core", + "dioxus-devtools", + "dioxus-document", + "dioxus-history", + "dioxus-hooks", + "dioxus-html", + "dioxus-interpreter-js", + "dioxus-signals", + "dunce", + "futures-channel", + "futures-util", + "generational-box", + "global-hotkey", + "image", + "infer", + "jni 0.21.1", + "lazy-js-bundle", "libc", + "muda", + "ndk 0.9.0", + "ndk-context", + "ndk-sys 0.6.0+11769913", + "objc", + "objc_id", + "percent-encoding", + "rand 0.9.5", + "rfd", + "rustc-hash 2.1.3", + "serde", + "serde_json", + "signal-hook", + "slab", + "subtle", + "tao", + "thiserror 2.0.21", + "tokio", + "tracing", + "tray-icon", + "tungstenite 0.28.0", + "webbrowser", + "wry", +] + +[[package]] +name = "dioxus-devtools" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434cebb282b3f820a341582ebfd37dab907d5a25c3eeafd87802468afcd2a959" +dependencies = [ + "dioxus-cli-config", + "dioxus-core", + "dioxus-devtools-types", + "dioxus-signals", + "serde", + "serde_json", + "subsecond", + "thiserror 2.0.21", + "tracing", + "tungstenite 0.28.0", +] + +[[package]] +name = "dioxus-devtools-types" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfd6f3475e38c93be245a664a9ce11679a8f2b99832620705cf7837f42aa39ce" +dependencies = [ + "dioxus-core", + "serde", + "subsecond-types", +] + +[[package]] +name = "dioxus-document" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f6fadd5c6d886b48b762820abae1a08142a2159f8a1136c0466b4b4ed9f547e" +dependencies = [ + "dioxus-core", + "dioxus-core-macro", + "dioxus-core-types", + "dioxus-html", + "futures-channel", + "futures-util", + "generational-box", + "lazy-js-bundle", + "serde", + "serde_json", + "tracing", +] + +[[package]] +name = "dioxus-fullstack" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a91d5acabd1470145bcf164cab9fd2edcf2e4fba0fa6fb0fd6dca23079fcc169" +dependencies = [ + "anyhow", + "async-stream", + "async-tungstenite", + "axum", + "axum-core", + "base64 0.22.1", + "bytes", + "ciborium", + "const-str", + "const_format", + "content_disposition", + "derive_more 2.1.1", + "dioxus-asset-resolver", + "dioxus-cli-config", + "dioxus-core", + "dioxus-fullstack-core", + "dioxus-fullstack-macro", + "dioxus-hooks", + "dioxus-html", + "dioxus-signals", + "form_urlencoded", + "futures", + "futures-channel", + "futures-util", + "gloo-net", + "headers", + "http", + "http-body", + "http-body-util", + "js-sys", + "mime", + "pin-project", + "reqwest 0.12.28", + "rustversion", + "send_wrapper", + "serde", + "serde_json", + "serde_qs", + "serde_urlencoded", + "thiserror 2.0.21", + "tokio-util", + "tracing", + "tungstenite 0.27.0", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.4.2", + "web-sys", + "xxhash-rust", ] [[package]] -name = "cpufeatures" -version = "0.3.1" +name = "dioxus-fullstack-core" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" +checksum = "0011e9bca8da2ae6bf02ba9ef93ba6c5fa539e402de3aeb316ad86ca77c59079" dependencies = [ - "libc", + "anyhow", + "axum-core", + "base64 0.22.1", + "ciborium", + "dioxus-core", + "dioxus-document", + "dioxus-history", + "dioxus-hooks", + "dioxus-signals", + "futures-channel", + "futures-util", + "generational-box", + "http", + "inventory", + "parking_lot", + "serde", + "serde_json", + "thiserror 2.0.21", + "tokio", + "tracing", ] [[package]] -name = "crc32fast" -version = "1.5.2" +name = "dioxus-fullstack-macro" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "01a7799fd6b852db0e61728dde9a204c423b44d689dbd432522543614b490e78" +checksum = "681f39665de36af7bb724b1cc0ca9c2b7c36a2b93febf1b2911716479eac3db0" dependencies = [ - "cfg-if", + "const_format", + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.119", + "xxhash-rust", ] [[package]] -name = "critical-section" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b" - -[[package]] -name = "crossbeam-channel" -version = "0.5.17" +name = "dioxus-history" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" +checksum = "2404b77d4441e694a5e93afb5c9a729efb26a3f6920f769cfe6cfedf5c7ac210" dependencies = [ - "crossbeam-utils", + "dioxus-core", + "tracing", ] [[package]] -name = "crossbeam-queue" -version = "0.3.14" +name = "dioxus-hooks" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03e8bd762f7479489c70ed6c768ddca99d7296857de437a68dcb2a94365b3fae" +checksum = "9d3807a1bc039299cd37ad85f1c56ae7088210e8a38e3e877f01034d68c15fbb" dependencies = [ - "crossbeam-utils", + "dioxus-core", + "dioxus-signals", + "futures-channel", + "futures-util", + "generational-box", + "rustversion", + "slab", + "tracing", ] [[package]] -name = "crossbeam-utils" -version = "0.8.23" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" - -[[package]] -name = "crunchy" -version = "0.2.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5" - -[[package]] -name = "crypto-common" -version = "0.1.7" +name = "dioxus-html" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78c8292055d1c1df0cce5d180393dc8cce0abec0a7102adb6c7b1eef6016d60a" +checksum = "40b9a85679c4dfd8699407a9ad5041a6a4fe6be0ee386353951cd03b57a12030" dependencies = [ - "generic-array", - "rand_core 0.6.4", - "typenum", + "async-trait", + "bytes", + "dioxus-core", + "dioxus-core-macro", + "dioxus-core-types", + "dioxus-hooks", + "dioxus-html-internal-macro", + "enumset", + "euclid", + "futures-channel", + "futures-util", + "generational-box", + "keyboard-types", + "lazy-js-bundle", + "rustversion", + "serde", + "serde_json", + "serde_repr", + "tracing", ] [[package]] -name = "crypto-common" -version = "0.2.2" +name = "dioxus-html-internal-macro" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453" +checksum = "500282dad5b62e91f93e127cbf41c587bf1c457d52514a75f3ff2a55fd0ea9f6" dependencies = [ - "hybrid-array", + "convert_case 0.8.0", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] -name = "ctr" -version = "0.9.2" +name = "dioxus-interpreter-js" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0369ee1ad671834580515889b80f2ea915f23b8be8d0daa4bbaf2ac5c7590835" +checksum = "faa22cc3431e7efdbae28069542a1763c977d5edbe4d4fbfb0b7667b9c9966e9" dependencies = [ - "cipher", + "dioxus-core", + "dioxus-core-types", + "dioxus-html", + "js-sys", + "lazy-js-bundle", + "rustc-hash 2.1.3", + "serde", + "sledgehammer_bindgen", + "sledgehammer_utils", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] -name = "ctrlc" -version = "3.5.2" +name = "dioxus-rsx" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0b1fab2ae45819af2d0731d60f2afe17227ebb1a1538a236da84c93e9a60162" +checksum = "aea662c9e13a91279d8acbc0d02a80430c7081704c20e8c791e4c4a151268596" dependencies = [ - "dispatch2", - "nix", - "windows-sys 0.61.2", + "proc-macro2", + "proc-macro2-diagnostics", + "quote", + "rustversion", + "syn 2.0.119", ] [[package]] -name = "ctutils" -version = "0.4.3" +name = "dioxus-signals" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03bb0e1cc970d482d121d9a1744999169b69a07470b3d644a7894e53fcaf4574" +checksum = "95d85e36fcaf7abdc986836801bf248776da7d5961f5fac65fdbf5ed491afb4f" dependencies = [ - "cmov", + "dioxus-core", + "futures-channel", + "futures-util", + "generational-box", + "parking_lot", + "rustc-hash 2.1.3", + "tracing", + "warnings", ] [[package]] -name = "cursor-icon" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27ae1dd37df86211c42e150270f82743308803d90a6f6e6651cd730d5e1732f" - -[[package]] -name = "deranged" -version = "0.5.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7cd812cc2bc1d69d4764bd80df88b4317eaef9e773c75226407d9bc0876b211c" - -[[package]] -name = "derive_more" -version = "2.1.1" +name = "dioxus-stores" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134" +checksum = "15eaa9f2ccc5ce962d056515e61345c846a54b13a2b880cf7e8ac93faa53a178" dependencies = [ - "derive_more-impl", + "dioxus-core", + "dioxus-signals", + "dioxus-stores-macro", + "generational-box", ] [[package]] -name = "derive_more-impl" -version = "2.1.1" +name = "dioxus-stores-macro" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb" +checksum = "a13bd8a693d7042544fa3ac79698a08783bbc698d1ed257e88c5d4059e9ac476" dependencies = [ - "convert_case", + "convert_case 0.8.0", "proc-macro2", "quote", - "rustc_version", "syn 2.0.119", - "unicode-xid", ] [[package]] -name = "digest" -version = "0.10.7" +name = "dioxus-web" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +checksum = "481093233d789c5ffbdde66e7970e803b01a199a7ab0c0f8ef84c65d30b7384f" dependencies = [ - "block-buffer 0.10.4", - "crypto-common 0.1.7", - "subtle", + "dioxus-cli-config", + "dioxus-core", + "dioxus-core-types", + "dioxus-devtools", + "dioxus-document", + "dioxus-history", + "dioxus-html", + "dioxus-interpreter-js", + "dioxus-signals", + "futures-channel", + "futures-util", + "generational-box", + "js-sys", + "lazy-js-bundle", + "rustc-hash 2.1.3", + "send_wrapper", + "serde", + "serde-wasm-bindgen", + "serde_json", + "tracing", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.4.2", + "web-sys", ] [[package]] -name = "digest" -version = "0.11.3" +name = "dirs" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ - "block-buffer 0.12.1", - "const-oid", - "crypto-common 0.2.2", - "ctutils", + "dirs-sys", ] [[package]] -name = "dispatch" -version = "0.2.0" +name = "dirs-sys" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users", + "windows-sys 0.61.2", +] [[package]] name = "dispatch2" @@ -2687,9 +2004,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e0e367e4e7da84520dedcac1901e4da967309406d1e51017ae1abfb97adbd38" dependencies = [ "bitflags 2.13.2", - "block2 0.6.2", + "block2", "libc", - "objc2 0.6.5", + "objc2", ] [[package]] @@ -2703,41 +2020,46 @@ dependencies = [ "syn 3.0.9", ] -[[package]] -name = "disqualified" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e90a5dd66beeca277ae954f8055b02a712792b6b6b43f2bc2f92b0b7d8291614" - [[package]] name = "dlib" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ab8ecd87370524b461f8557c119c405552c396ed91fc0a8eec68679eab26f94a" dependencies = [ - "libloading", + "libloading 0.8.9", ] [[package]] -name = "document-features" -version = "0.2.12" +name = "dlopen2" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +checksum = "5e2c5bd4158e66d1e215c49b837e11d62f3267b30c92f1d171c4d3105e3dc4d4" dependencies = [ - "litrs", + "dlopen2_derive", + "libc", + "once_cell", + "winapi", ] [[package]] -name = "downcast-rs" -version = "1.2.1" +name = "dlopen2_derive" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75b325c5dbd37f80359721ad39aca5a29fb04c89279657cffdda8736d0c0b9d2" +checksum = "0fbbb781877580993a8707ec48672673ec7b81eeba04cfd2310bd28c08e47c8f" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] [[package]] -name = "downcast-rs" -version = "2.0.2" +name = "document-features" +version = "0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "117240f60069e65410b3ae1bb213295bd828f707b5bec6596a1afc8793ce0cbc" +checksum = "d4b8a88685455ed29a21542a33abd9cb6510b6b129abadabdcef0f4c55bc8f61" +dependencies = [ + "litrs", +] [[package]] name = "dpi" @@ -2746,47 +2068,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d8b14ccef22fc6f5a8f4d7d768562a182c04ce9a3b3157b91390b52ddfdf1a76" [[package]] -name = "dunce" -version = "1.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" - -[[package]] -name = "either" -version = "1.19.0" +name = "dtoa" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" +checksum = "4c3cf4824e2d5f025c7b531afcb2325364084a16806f6d47fbc1f5fbd9960590" [[package]] -name = "encase" -version = "0.12.1" +name = "dtoa-short" +version = "0.3.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b1acbc46b960480c4959213714511e22f9a2e0d361520693bcf5057b5924f53e" +checksum = "cd1511a7b6a56299bd043a9c167a6d2bfb37bf84a6dfceaba651168adfb43c87" dependencies = [ - "const_panic", - "encase_derive", - "thiserror 2.0.21", + "dtoa", ] [[package]] -name = "encase_derive" -version = "0.12.1" +name = "dunce" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e30d38c47336a0afbdfde297b442944041cf6dccbb1a79eceea16abfb27a92a" -dependencies = [ - "encase_derive_impl", -] +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" [[package]] -name = "encase_derive_impl" -version = "0.12.1" +name = "either" +version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "495d24abe406f090f2ba8fc362ecaa8a001e192522aa75eae7b144163c3235ff" -dependencies = [ - "proc-macro2", - "quote", - "syn 2.0.119", -] +checksum = "0e9c71c2167ca323c882b99918929403426e2373ea17242ff5653e0d5e1058be" [[package]] name = "encoding_rs" @@ -2823,22 +2129,52 @@ dependencies = [ ] [[package]] -name = "equivalent" -version = "1.0.2" +name = "enumset" +version = "1.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +checksum = "ccc5801fd11762e24d1e420d01d2ac518f2a2ca4329d4fbb6639f2412b6204e0" +dependencies = [ + "enumset_derive", +] + +[[package]] +name = "enumset_derive" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bd536557b58c682b217b8fb199afdff47cd3eff260623f19e77074eb073d63a" +dependencies = [ + "darling", + "proc-macro2", + "quote", + "syn 2.0.119", +] [[package]] -name = "erased-serde" -version = "0.4.10" +name = "equator" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2add8a07dd6a8d93ff627029c51de145e12686fbc36ecb298ac22e74cf02dec" +checksum = "4711b213838dfee0117e3be6ac926007d7f433d7bbe33595975d4190cb07e6fc" dependencies = [ - "serde", - "serde_core", - "typeid", + "equator-macro", +] + +[[package]] +name = "equator-macro" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44f23cf4b44bfce11a86ace86f8a73ffdec849c9fd00a386a53d278bd9e81fb3" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" version = "0.3.14" @@ -2849,12 +2185,6 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "error-code" -version = "3.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b5343afd4a8365a643ac588dab4cf234a190c7f6c88c9f6dd6ffe00837661b7" - [[package]] name = "etag" version = "4.0.0" @@ -2872,27 +2202,31 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1a05365e3b1c6d1650318537c7460c6923f1abdd272ad6842baa2b509957a06" dependencies = [ "num-traits", + "serde", ] [[package]] -name = "event-listener" -version = "5.4.2" +name = "exr" +version = "1.74.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a23add41df1562121a9393cb065eab5146a1242410f23a644851e90cfd669d2" +checksum = "711fe42c9964295e01ee3fba3f9fe0e1d24b98886950d68efe81b1c76e21adf3" dependencies = [ - "parking", - "pin-project-lite", + "bit_field", + "half", + "lebe", + "miniz_oxide 0.8.9", + "num-complex", + "pulp", + "rayon-core", + "smallvec", + "zune-inflate", ] [[package]] -name = "event-listener-strategy" -version = "0.5.4" +name = "extended" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8be9f3dfaaffdae2972880079a491a1a8bb7cbed0b8dd7a347f668b4150a3b93" -dependencies = [ - "event-listener", - "pin-project-lite", -] +checksum = "af9673d8203fcb076b19dfd17e38b3d4ae9f44959416ea532ce72415a6020365" [[package]] name = "fastrand" @@ -2900,6 +2234,12 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" +[[package]] +name = "fax" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caf1079563223d5d59d83c85886a56e586cfd5c1a26292e971a0fa266531ac5a" + [[package]] name = "fdeflate" version = "0.3.7" @@ -2909,18 +2249,22 @@ dependencies = [ "simd-adler32", ] +[[package]] +name = "field-offset" +version = "0.3.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38e2275cc4e4fc009b0669731a1e5ab7ebf11f469eaede2bab9309a5b4d6057f" +dependencies = [ + "memoffset", + "rustc_version", +] + [[package]] name = "find-msvc-tools" version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" -[[package]] -name = "fixedbitset" -version = "0.5.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" - [[package]] name = "flate2" version = "1.1.10" @@ -2938,12 +2282,6 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" -[[package]] -name = "foldhash" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" - [[package]] name = "foldhash" version = "0.2.0" @@ -2951,34 +2289,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" [[package]] -name = "font-types" -version = "0.12.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c92d9081c7ab3bd83ef1eecdfad090f3d966e3ce74106779664114cfe1a6274" -dependencies = [ - "bytemuck", -] - -[[package]] -name = "fontique" -version = "0.11.1" +name = "foreign-types" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6688bc1294fe7117d788937b6c53480169b29c566954af490830d4c09da9516a" +checksum = "f6f339eb8adc052cd2ca78910fda869aefa38d22d5cb648e6485e4d3fc06f3b1" dependencies = [ - "hashbrown 0.17.1", - "linebender_resource_handle", - "memmap2", - "objc2 0.6.5", - "objc2-core-foundation", - "objc2-core-text", - "objc2-foundation 0.3.2", - "parlance", - "read-fonts", - "roxmltree", - "smallvec", - "windows", - "windows-core", - "yeslogic-fontconfig-sys", + "foreign-types-shared 0.1.1", ] [[package]] @@ -2988,7 +2304,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" dependencies = [ "foreign-types-macros", - "foreign-types-shared", + "foreign-types-shared 0.3.1", ] [[package]] @@ -3002,6 +2318,12 @@ dependencies = [ "syn 3.0.9", ] +[[package]] +name = "foreign-types-shared" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "00b0228411908ca8685dba7fc2cdd70ec9990a6e753e89b6ac91a84c40fbaf4b" + [[package]] name = "foreign-types-shared" version = "0.3.1" @@ -3024,10 +2346,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" [[package]] -name = "funty" -version = "2.0.0" +name = "futf" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df420e2e84819663797d1ec6544b13c5be84629e7bb00dc960d6917db2987843" +dependencies = [ + "mac", + "new_debug_unreachable", +] + +[[package]] +name = "futures" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" +checksum = "9a31d2a3fbaaeb2af2368bbdd904aa8e812d3c04a1ee10d3171f52d556e5d0a3" +dependencies = [ + "futures-channel", + "futures-core", + "futures-executor", + "futures-io", + "futures-sink", + "futures-task", + "futures-util", +] [[package]] name = "futures-channel" @@ -3036,6 +2377,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", + "futures-sink", ] [[package]] @@ -3045,24 +2387,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] -name = "futures-io" +name = "futures-executor" version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" - -[[package]] -name = "futures-lite" -version = "2.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f78e10609fe0e0b3f4157ffab1876319b5b0db102a2c60dc4626306dc46b44ad" +checksum = "031b47cf1a3c6cc8bc2fc76cd437f521619387907d469316e7c0bc278f1f5432" dependencies = [ - "fastrand", "futures-core", - "futures-io", - "parking", - "pin-project-lite", + "futures-task", + "futures-util", ] +[[package]] +name = "futures-io" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" + [[package]] name = "futures-macro" version = "0.3.34" @@ -3092,6 +2432,7 @@ version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ + "futures-channel", "futures-core", "futures-io", "futures-macro", @@ -3102,6 +2443,110 @@ dependencies = [ "slab", ] +[[package]] +name = "fxhash" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c31b6d751ae2c7f11320402d34e41349dd1016f8d5d45e48c4312bc8625af50c" +dependencies = [ + "byteorder", +] + +[[package]] +name = "gdk" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9f245958c627ac99d8e529166f9823fb3b838d1d41fd2b297af3075093c2691" +dependencies = [ + "cairo-rs", + "gdk-pixbuf", + "gdk-sys", + "gio", + "glib", + "libc", + "pango", +] + +[[package]] +name = "gdk-pixbuf" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50e1f5f1b0bfb830d6ccc8066d18db35c487b1b2b1e8589b5dfe9f07e8defaec" +dependencies = [ + "gdk-pixbuf-sys", + "gio", + "glib", + "libc", + "once_cell", +] + +[[package]] +name = "gdk-pixbuf-sys" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9839ea644ed9c97a34d129ad56d38a25e6756f99f3a88e15cd39c20629caf7" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "gdk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c2d13f38594ac1e66619e188c6d5a1adb98d11b2fcf7894fc416ad76aa2f3f7" +dependencies = [ + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkwayland-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "140071d506d223f7572b9f09b5e155afbd77428cd5cc7af8f2694c41d98dfe69" +dependencies = [ + "gdk-sys", + "glib-sys", + "gobject-sys", + "libc", + "pkg-config", + "system-deps", +] + +[[package]] +name = "gdkx11-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e7445fe01ac26f11601db260dd8608fe172514eb63b3b5e261ea6b0f4428d" +dependencies = [ + "gdk-sys", + "glib-sys", + "libc", + "system-deps", + "x11", +] + +[[package]] +name = "generational-box" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8b2dc9b873cd1a8adb80aa5dcef9a8205f781a8a313d5ffb867248cb3bcb764" +dependencies = [ + "parking_lot", + "tracing", +] + [[package]] name = "generic-array" version = "0.14.7" @@ -3118,79 +2563,265 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1bd49230192a3797a9a4d6abe9b3eed6f7fa4c8a8a4947977c6f80025f92cbd8" dependencies = [ - "rustix 1.1.5", - "windows-link", + "rustix", + "windows-link 0.2.1", +] + +[[package]] +name = "getrandom" +version = "0.1.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.9.0+wasi-snapshot-preview1", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "wasi 0.11.1+wasi-snapshot-preview1", + "wasm-bindgen", +] + +[[package]] +name = "getrandom" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +dependencies = [ + "cfg-if", + "libc", + "r-efi 5.3.0", + "wasip2", +] + +[[package]] +name = "getrandom" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +dependencies = [ + "cfg-if", + "js-sys", + "libc", + "r-efi 6.0.0", + "rand_core 0.10.1", + "wasm-bindgen", +] + +[[package]] +name = "ghash" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +dependencies = [ + "opaque-debug", + "polyval", +] + +[[package]] +name = "gif" +version = "0.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ee8cfcc411d9adbbaba82fb72661cc1bcca13e8bba98b364e62b2dba8f960159" +dependencies = [ + "color_quant", + "weezl", +] + +[[package]] +name = "gio" +version = "0.18.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d4fc8f532f87b79cbc51a79748f16a6828fb784be93145a322fa14d06d354c73" +dependencies = [ + "futures-channel", + "futures-core", + "futures-io", + "futures-util", + "gio-sys", + "glib", + "libc", + "once_cell", + "pin-project-lite", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "gio-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37566df850baf5e4cb0dfb78af2e4b9898d817ed9263d1090a2df958c64737d2" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", + "winapi", +] + +[[package]] +name = "gl_generator" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a95dfc23a2b4a9a2f5ab41d194f8bfda3cabec42af4e39f08c339eb2a0c124d" +dependencies = [ + "khronos_api", + "log", + "xml-rs", +] + +[[package]] +name = "glam" +version = "0.33.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37bfe73dc8ec21f54d181e5a60554327ec3f1c600c455a75ccbfc65d2106a6c4" + +[[package]] +name = "glib" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "233daaf6e83ae6a12a52055f568f9d7cf4671dabb78ff9560ab6da230ce00ee5" +dependencies = [ + "bitflags 2.13.2", + "futures-channel", + "futures-core", + "futures-executor", + "futures-task", + "futures-util", + "gio-sys", + "glib-macros", + "glib-sys", + "gobject-sys", + "libc", + "memchr", + "once_cell", + "smallvec", + "thiserror 1.0.69", +] + +[[package]] +name = "glib-macros" +version = "0.18.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0bb0228f477c0900c880fd78c8759b95c7636dbd7842707f49e132378aa2acdc" +dependencies = [ + "heck 0.4.1", + "proc-macro-crate 2.0.2", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "glib-sys" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "063ce2eb6a8d0ea93d2bf8ba1957e78dbab6be1c2220dd3daca57d5a9d869898" +dependencies = [ + "libc", + "system-deps", +] + +[[package]] +name = "glob" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" + +[[package]] +name = "global-hotkey" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b9247516746aa8e53411a0db9b62b0e24efbcf6a76e0ba73e5a91b512ddabed7" +dependencies = [ + "crossbeam-channel", + "keyboard-types", + "objc2", + "objc2-app-kit", + "once_cell", + "thiserror 2.0.21", + "windows-sys 0.59.0", + "x11rb", + "xkeysym", ] [[package]] -name = "getrandom" -version = "0.2.17" +name = "gloo-net" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +checksum = "c06f627b1a58ca3d42b45d6104bf1e1a03799df472df00988b6ba21accc10580" dependencies = [ - "cfg-if", + "futures-channel", + "futures-core", + "futures-sink", + "gloo-utils", + "http", "js-sys", - "libc", - "wasi", + "pin-project", + "serde", + "serde_json", + "thiserror 1.0.69", "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] -name = "getrandom" -version = "0.3.4" +name = "gloo-utils" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" +checksum = "0b5555354113b18c547c1d3a98fbf7fb32a9ff4f6fa112ce823a21641a0ba3aa" dependencies = [ - "cfg-if", - "libc", - "r-efi 5.3.0", - "wasip2", + "js-sys", + "serde", + "serde_json", + "wasm-bindgen", + "web-sys", ] [[package]] -name = "getrandom" -version = "0.4.3" +name = "glow" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300e883d756b2e4ec94e02791f39b04b522276138852cfc41d9fb7e904106099" +checksum = "29038e1c483364cc6bb3cf78feee1816002e127c331a1eec55a4d202b9e1adb5" dependencies = [ - "cfg-if", "js-sys", - "libc", - "r-efi 6.0.0", - "rand_core 0.10.1", + "slotmap", "wasm-bindgen", + "web-sys", ] [[package]] -name = "ghash" -version = "0.5.1" +name = "glutin_wgl_sys" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0d8a4362ccb29cb0b265253fb0a2728f592895ee6854fd9bc13f2ffda266ff1" +checksum = "2c4ee00b289aba7a9e5306d57c2d05499b2e5dc427f84ac708bd2c090212cf3e" dependencies = [ - "opaque-debug", - "polyval", + "gl_generator", ] [[package]] -name = "glam" -version = "0.33.12" +name = "gobject-sys" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37bfe73dc8ec21f54d181e5a60554327ec3f1c600c455a75ccbfc65d2106a6c4" +checksum = "0850127b514d1c4a4654ead6dedadb18198999985908e6ffe4436f53c785ce44" dependencies = [ - "approx", - "bytemuck", - "encase", - "libm", - "rand 0.10.3", - "serde_core", + "glib-sys", + "libc", + "system-deps", ] -[[package]] -name = "glob" -version = "0.3.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4eba85ea1d0a966a983acd07deee566e67395d2d96b6fb39e62b5a833f1eb0b" - [[package]] name = "gpu-allocator" version = "0.28.0" @@ -3202,16 +2833,59 @@ dependencies = [ "log", "presser", "thiserror 2.0.21", - "windows", + "windows 0.62.2", ] [[package]] -name = "guillotiere" -version = "0.7.0" +name = "gtk" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b17e70c989c36bad147b27a58d148c0741c51448aa5653436547323e524d0ab" +checksum = "fd56fb197bfc42bd5d2751f4f017d44ff59fbb58140c6b49f9b3b2bdab08506a" dependencies = [ - "euclid", + "atk", + "cairo-rs", + "field-offset", + "futures-channel", + "gdk", + "gdk-pixbuf", + "gio", + "glib", + "gtk-sys", + "gtk3-macros", + "libc", + "pango", + "pkg-config", +] + +[[package]] +name = "gtk-sys" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f29a1c21c59553eb7dd40e918be54dccd60c52b049b75119d5d96ce6b624414" +dependencies = [ + "atk-sys", + "cairo-sys-rs", + "gdk-pixbuf-sys", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "pango-sys", + "system-deps", +] + +[[package]] +name = "gtk3-macros" +version = "0.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52ff3c5b21f14f0736fed6dcfc0bfb4225ebf5725f3c0209edeec181e4d73e9d" +dependencies = [ + "proc-macro-crate 1.3.1", + "proc-macro-error", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] @@ -3239,43 +2913,12 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea2d84b969582b4b1864a92dc5d27cd2b77b622a8d79306834f1be5ba20d84b" dependencies = [ - "bytemuck", "cfg-if", "crunchy", "num-traits", "zerocopy", ] -[[package]] -name = "harfrust" -version = "0.12.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c03d949a14aa089bbb282f7dd76a498a7f684428e4257202efc119ec010376f9" -dependencies = [ - "bitflags 2.13.2", - "bytemuck", - "read-fonts", - "smallvec", -] - -[[package]] -name = "hash32" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47d60b12902ba28e2730cd37e95b8c9223af2808df9e902d4df49588d1470606" -dependencies = [ - "byteorder", -] - -[[package]] -name = "hashbrown" -version = "0.15.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" -dependencies = [ - "foldhash 0.1.5", -] - [[package]] name = "hashbrown" version = "0.16.1" @@ -3284,9 +2927,7 @@ checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" dependencies = [ "allocator-api2", "equivalent", - "foldhash 0.2.0", - "serde", - "serde_core", + "foldhash", ] [[package]] @@ -3295,7 +2936,7 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" dependencies = [ - "foldhash 0.2.0", + "foldhash", ] [[package]] @@ -3323,40 +2964,36 @@ dependencies = [ ] [[package]] -name = "heapless" -version = "0.9.3" +name = "heck" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25ba4bd83f9415b58b4ed8dc5714c76e626a105be4646c02630ad730ad3b5aa4" -dependencies = [ - "hash32", - "portable-atomic", - "stable_deref_trait", -] +checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] -name = "hermit-abi" -version = "0.5.3" +name = "heck" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] -name = "hexasphere" -version = "19.0.0" +name = "hmac" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "163385eff5a0cf606ebe2c10b3a44ab02f4306e83fbd068a64f5e1d72a3049ac" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" dependencies = [ - "constgebra", - "glam", - "tinyvec", + "digest 0.10.7", ] [[package]] -name = "hmac" -version = "0.12.1" +name = "html5ever" +version = "0.29.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +checksum = "3b7410cae13cbc75623c98ac4cbfd1f0bedddf3227afc24f370cf0f50a44a11c" dependencies = [ - "digest 0.10.7", + "log", + "mac", + "markup5ever", + "match_token", ] [[package]] @@ -3489,7 +3126,7 @@ dependencies = [ "js-sys", "log", "wasm-bindgen", - "windows-core", + "windows-core 0.62.2", ] [[package]] @@ -3523,32 +3160,11 @@ checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" dependencies = [ "displaydoc", "litemap", - "serde", "tinystr", "writeable", "zerovec", ] -[[package]] -name = "icu_locale_fallback" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "251af8e57c9400e3eb58242fe5b8b1152b2a64fdf4cf632f923c38ccee6f2fa9" -dependencies = [ - "icu_locale_core", - "icu_locale_fallback_data", - "icu_provider", - "potential_utf", - "tinystr", - "zerovec", -] - -[[package]] -name = "icu_locale_fallback_data" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "decf2a22ec8fa68f1a0c1129a3f8583f8f8bc24e8b9ccbe98ead99f62a4dc3a8" - [[package]] name = "icu_normalizer" version = "2.3.0" @@ -3598,8 +3214,6 @@ checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" dependencies = [ "displaydoc", "icu_locale_core", - "serde", - "stable_deref_trait", "writeable", "yoke", "zerofrom", @@ -3608,26 +3222,10 @@ dependencies = [ ] [[package]] -name = "icu_segmenter" -version = "2.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82d07aafccd67af15d02512a6adf5896fbc5ed00f2e99b471d2efa14016db3db" -dependencies = [ - "icu_collections", - "icu_locale_fallback", - "icu_provider", - "icu_segmenter_data", - "potential_utf", - "smallvec", - "utf8_iter", - "zerovec", -] - -[[package]] -name = "icu_segmenter_data" -version = "2.3.0" +name = "ident_case" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae293c039020f9ec10710af98d29ce6aa2051486638b49c9a6409f3b4a9e98ad" +checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" [[package]] name = "idna" @@ -3658,11 +3256,38 @@ checksum = "85ab80394333c02fe689eaf900ab500fbd0c2213da414687ebf995a65d5a6104" dependencies = [ "bytemuck", "byteorder-lite", + "color_quant", + "exr", + "gif", + "image-webp", "moxcms", "num-traits", - "png", + "png 0.18.1", + "qoi", + "ravif", + "rayon", + "rgb", + "tiff", + "zune-core", + "zune-jpeg", ] +[[package]] +name = "image-webp" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525e9ff3e1a4be2fbea1fdf0e98686a6d98b4d8f937e1bf7402245af1909e8c3" +dependencies = [ + "byteorder-lite", + "quick-error", +] + +[[package]] +name = "imgref" +version = "1.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e44b0a4eaa4c82f441d50a963f2d5f05a787240aeee097597033e72accfd22f" + [[package]] name = "indexmap" version = "2.14.2" @@ -3671,8 +3296,15 @@ checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", "hashbrown 0.17.1", - "serde", - "serde_core", +] + +[[package]] +name = "infer" +version = "0.19.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a588916bfdfd92e71cacef98a63d9b1f0d74d6599980d11894290e7ddefffcf7" +dependencies = [ + "cfb", ] [[package]] @@ -3684,6 +3316,17 @@ dependencies = [ "generic-array", ] +[[package]] +name = "interpolate_name" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c34819042dc3d3971c46c2190835914dfbe0c3c13f61449b2997f4e9722dfa60" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "inventory" version = "0.3.25" @@ -3699,26 +3342,20 @@ version = "2.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0" -[[package]] -name = "is_terminal_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6cb138bb79a146c1bd460005623e142ef0181e3d0219cb493e02f7d08a35695" - [[package]] name = "itertools" -version = "0.14.0" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" +checksum = "413ee7dfc52ee1a4949ceeb7dbc8a33f2d6c088194d9f922fb8318faf1f01186" dependencies = [ "either", ] [[package]] name = "itertools" -version = "0.15.0" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" +checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" dependencies = [ "either", ] @@ -3729,6 +3366,45 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "javascriptcore-rs" +version = "1.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca5671e9ffce8ffba57afc24070e906da7fc4b1ba66f2cabebf61bf2ea257fcc" +dependencies = [ + "bitflags 1.3.2", + "glib", + "javascriptcore-rs-sys", +] + +[[package]] +name = "javascriptcore-rs-sys" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af1be78d14ffa4b75b66df31840478fef72b51f8c2465d4ca7c194da9f7a5124" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "jni" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a87aa2bb7d2af34197c04845522473242e1aa17c12f4935d5856491a7fb8c97" +dependencies = [ + "cesu8", + "cfg-if", + "combine", + "jni-sys 0.3.1", + "log", + "thiserror 1.0.69", + "walkdir", + "windows-sys 0.45.0", +] + [[package]] name = "jni" version = "0.22.4" @@ -3743,7 +3419,7 @@ dependencies = [ "simd_cesu8", "thiserror 2.0.21", "walkdir", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -3809,13 +3485,65 @@ dependencies = [ ] [[package]] -name = "lalrpop-util" -version = "0.23.1" +name = "keyboard-types" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b750dcadc39a09dbadd74e118f6dd6598df77fa01df0cfcdc52c28dece74528a" +dependencies = [ + "bitflags 2.13.2", + "serde", + "unicode-segmentation", +] + +[[package]] +name = "khronos-egl" +version = "6.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6aae1df220ece3c0ada96b8153459b67eebe9ae9212258bb0134ae60416fdf76" +dependencies = [ + "libc", + "libloading 0.8.9", + "pkg-config", +] + +[[package]] +name = "khronos_api" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2db585e1d738fc771bf08a151420d3ed193d9d895a36df7f6f8a9456b911ddc" + +[[package]] +name = "konst" +version = "0.2.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "128133ed7824fcd73d6e7b17957c5eb7bacb885649bd8c69708b2331a10bcefb" +dependencies = [ + "konst_macro_rules", +] + +[[package]] +name = "konst_macro_rules" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4933f3f57a8e9d9da04db23fb153356ecaf00cbd14aee46279c33dc80925c37" + +[[package]] +name = "kuchikiki" +version = "0.8.8-speedreader" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "02cb977175687f33fa4afa0c95c112b987ea1443e5a51c8f8ff27dc618270cc2" +dependencies = [ + "cssparser", + "html5ever", + "indexmap", + "selectors", +] + +[[package]] +name = "lazy-js-bundle" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "884f3e747ed2dcee867cda1b0c31a048f9e20de2d916a248949319921a2e666e" -dependencies = [ - "regex-automata", -] +checksum = "51cdaa5abc885e2d606e6985281ace220778bde190be20aab1ec2346ed8bd1fa" [[package]] name = "lazy_static" @@ -3824,77 +3552,61 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" [[package]] -name = "lexical" -version = "7.0.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bc8a009b2ff1f419ccc62706f04fe0ca6e67b37460513964a3dfdb919bb37d6" -dependencies = [ - "lexical-core", -] - -[[package]] -name = "lexical-core" -version = "1.0.6" +name = "lebe" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d8d125a277f807e55a77304455eb7b1cb52f2b18c143b60e766c120bd64a594" -dependencies = [ - "lexical-parse-float", - "lexical-parse-integer", - "lexical-util", - "lexical-write-float", - "lexical-write-integer", -] +checksum = "7a79a3332a6609480d7d0c9eab957bca6b455b91bb84e66d19f5ff66294b85b8" [[package]] -name = "lexical-parse-float" -version = "1.0.6" +name = "libappindicator" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52a9f232fbd6f550bc0137dcb5f99ab674071ac2d690ac69704593cb4abbea56" +checksum = "03589b9607c868cc7ae54c0b2a22c8dc03dd41692d48f2d7df73615c6a95dc0a" dependencies = [ - "lexical-parse-integer", - "lexical-util", + "glib", + "gtk", + "gtk-sys", + "libappindicator-sys", + "log", ] [[package]] -name = "lexical-parse-integer" -version = "1.0.6" +name = "libappindicator-sys" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a7a039f8fb9c19c996cd7b2fcce303c1b2874fe1aca544edc85c4a5f8489b34" +checksum = "6e9ec52138abedcc58dc17a7c6c0c00a2bdb4f3427c7f63fa97fd0d859155caf" dependencies = [ - "lexical-util", + "gtk-sys", + "libloading 0.7.4", + "once_cell", ] [[package]] -name = "lexical-util" -version = "1.0.7" +name = "libc" +version = "0.2.190" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2604dd126bb14f13fb5d1bd6a66155079cb9fa655b37f875b3a742c705dbed17" +checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" [[package]] -name = "lexical-write-float" -version = "1.0.6" +name = "libfuzzer-sys" +version = "0.4.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50c438c87c013188d415fbabbb1dceb44249ab81664efbd31b14ae55dabb6361" +checksum = "a9fd2f41a1cba099f79a0b6b6c35656cf7c03351a7bae8ff0f28f25270f929d2" dependencies = [ - "lexical-util", - "lexical-write-integer", + "arbitrary", + "cc", ] [[package]] -name = "lexical-write-integer" -version = "1.0.6" +name = "libloading" +version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "409851a618475d2d5796377cad353802345cba92c867d9fbcde9cf4eac4e14df" +checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f" dependencies = [ - "lexical-util", + "cfg-if", + "winapi", ] -[[package]] -name = "libc" -version = "0.2.190" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce5d3ddc6d3fa000eb1536d85e147bfe31aacaba692ed6a876f95cb7c855be78" - [[package]] name = "libloading" version = "0.8.9" @@ -3902,7 +3614,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7c4b02199fee7c5d21a5ae7d8cfa79a6ef5bb2fc834d6e9058e89c825efdc55" dependencies = [ "cfg-if", - "windows-link", + "windows-link 0.2.1", ] [[package]] @@ -3917,23 +3629,27 @@ version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" dependencies = [ - "bitflags 2.13.2", "libc", - "plain", - "redox_syscall 0.9.4", ] [[package]] -name = "linebender_resource_handle" -version = "0.1.1" +name = "libxdo" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d4a5ff6bcca6c4867b1c4fd4ef63e4db7436ef363e0ad7531d1558856bae64f4" +checksum = "00333b8756a3d28e78def82067a377de7fa61b24909000aeaa2b446a948d14db" +dependencies = [ + "libxdo-sys", +] [[package]] -name = "linux-raw-sys" -version = "0.4.15" +name = "libxdo-sys" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" +checksum = "db23b9e7e2b7831bbd8aac0bbeeeb7b68cbebc162b227e7052e8e55829a09212" +dependencies = [ + "libc", + "x11", +] [[package]] name = "linux-raw-sys" @@ -3969,50 +3685,150 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] -name = "logos" -version = "0.16.1" +name = "longest-increasing-subsequence" +version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb2c55a318a87600ea870ff8c2012148b44bf18b74fad48d0f835c38c7d07c5f" +checksum = "b3bd0dd2cd90571056fdb71f6275fada10131182f84899f4b2a916e565d81d86" + +[[package]] +name = "loop9" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fae87c125b03c1d2c0150c90365d7d6bcc53fb73a9acaef207d2d065860f062" dependencies = [ - "logos-derive", + "imgref", ] [[package]] -name = "logos-codegen" -version = "0.16.1" +name = "lru-slab" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4050469837a6ff301cd14c1f8f24f88549e6d548f24f64e2148eb0f72cebc51f" + +[[package]] +name = "mac" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4" + +[[package]] +name = "mach2" +version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58b3ffaa284e1350d017a57d04ada118c4583cf260c8fb01e0fe28a2e9cf8970" +checksum = "d640282b302c0bb0a2a8e0233ead9035e3bed871f0b7e81fe4a1ec829765db44" +dependencies = [ + "libc", +] + +[[package]] +name = "macro-string" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b27834086c65ec3f9387b096d66e99f221cf081c2b738042aa252bcd41204e3" dependencies = [ - "fnv", "proc-macro2", "quote", - "regex-automata", - "regex-syntax", "syn 2.0.119", ] [[package]] -name = "logos-derive" -version = "0.16.1" +name = "malloc_buf" +version = "0.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d3a9855747c17eaf4383823f135220716ab49bea5fbea7dd42cc9a92f8aa31" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" dependencies = [ - "logos-codegen", + "libc", ] [[package]] -name = "lru-slab" -version = "0.1.3" +name = "manganis" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4050469837a6ff301cd14c1f8f24f88549e6d548f24f64e2148eb0f72cebc51f" +checksum = "1ed2af894a724a0b6e521f9efe84f98cfdc74a4de6828efef77ffd3b1679fd52" +dependencies = [ + "const-serialize 0.7.2", + "const-serialize 0.8.0-alpha.0", + "jni 0.21.1", + "manganis-core", + "manganis-macro", + "ndk-context", + "objc2", + "thiserror 2.0.21", +] [[package]] -name = "matchers" -version = "0.2.0" +name = "manganis-core" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" +checksum = "e258c71b137bf48deaffb48b8a8a2f994af9e5c3ca201daa20d41e26b379da11" dependencies = [ - "regex-automata", + "const-serialize 0.7.2", + "const-serialize 0.8.0-alpha.0", + "dioxus-cli-config", + "dioxus-core-types", + "serde", + "winnow 0.7.15", +] + +[[package]] +name = "manganis-macro" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abae8346bbf637e6d21ac3831863bd5a98657517f5cd2d69d651046b95e7ce9" +dependencies = [ + "dunce", + "macro-string", + "manganis-core", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "markup5ever" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7a7213d12e1864c0f002f52c2923d4556935a43dec5e71355c2760e0f6e7a18" +dependencies = [ + "log", + "phf 0.11.3", + "phf_codegen 0.11.3", + "string_cache", + "string_cache_codegen", + "tendril", +] + +[[package]] +name = "match_token" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88a9689d8d44bf9964484516275f5cd4c9b59457a6940c1d5d0ecbb94510a36b" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "matches" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2532096657941c2fea9c289d370a250971c689d4f143798ff67113ec042024a5" + +[[package]] +name = "matchit" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47e1ffaa40ddd1f3ed91f717a33c8c0ee23fff369e3aa8772b9605cc1d22f4c3" + +[[package]] +name = "maybe-rayon" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8ea1f30cedd69f0a2954655f7188c6a834246d2bcf1e315e2ac40c4b24dc9519" +dependencies = [ + "cfg-if", + "rayon", ] [[package]] @@ -4021,6 +3837,15 @@ version = "2.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" +[[package]] +name = "memfd" +version = "0.6.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57804b2c9b69967f1536a56f86297e367a33b19e98852ed624b84551cdbc0d90" +dependencies = [ + "rustix", +] + [[package]] name = "memmap2" version = "0.9.11" @@ -4030,6 +3855,15 @@ dependencies = [ "libc", ] +[[package]] +name = "memoffset" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" +dependencies = [ + "autocfg", +] + [[package]] name = "mime" version = "0.3.17" @@ -4056,6 +3890,12 @@ dependencies = [ "unicase", ] +[[package]] +name = "minimal-lexical" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" + [[package]] name = "miniz_oxide" version = "0.8.9" @@ -4083,7 +3923,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1788edb87fdc09c7e26304471e2f5be8cdefb1b6930d6e3985fc02ff53bf86ee" dependencies = [ "libc", - "wasi", + "wasi 0.11.1+wasi-snapshot-preview1", "windows-sys 0.61.2", ] @@ -4097,6 +3937,44 @@ dependencies = [ "pxfm", ] +[[package]] +name = "muda" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c9fec5a4e89860383d778d10563a605838f8f0b2f9303868937e5ff32e86177" +dependencies = [ + "crossbeam-channel", + "dpi", + "gtk", + "keyboard-types", + "libxdo", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "once_cell", + "png 0.17.16", + "thiserror 2.0.21", + "windows-sys 0.60.2", +] + +[[package]] +name = "multer" +version = "3.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "83e87776546dc87511aa5ee218730c92b666d7264ab6ed41f9d215af9cd5224b" +dependencies = [ + "bytes", + "encoding_rs", + "futures-util", + "http", + "httparse", + "memchr", + "mime", + "spin", + "version_check", +] + [[package]] name = "multimap" version = "0.10.1" @@ -4127,12 +4005,6 @@ dependencies = [ "mime", ] -[[package]] -name = "mutants" -version = "0.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc0287524726960e07b119cebd01678f852f147742ae0d925e6a520dca956126" - [[package]] name = "naga" version = "30.0.1" @@ -4168,10 +4040,40 @@ dependencies = [ "hashbrown 0.17.1", "indexmap", "rustc-hash 1.1.0", - "serde", "thiserror 2.0.21", ] +[[package]] +name = "native-tls" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "465500e14ea162429d264d44189adc38b199b62b1c21eea9f69e4b73cb03bbf2" +dependencies = [ + "libc", + "log", + "openssl", + "openssl-probe", + "openssl-sys", + "schannel", + "security-framework", + "security-framework-sys", + "tempfile", +] + +[[package]] +name = "ndk" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2076a31b7010b17a38c01907c45b945e8f11495ee4dd588309718901b1f7a5b7" +dependencies = [ + "bitflags 2.13.2", + "jni-sys 0.3.1", + "log", + "ndk-sys 0.5.0+25.2.9519653", + "num_enum", + "thiserror 1.0.69", +] + [[package]] name = "ndk" version = "0.9.0" @@ -4181,9 +4083,9 @@ dependencies = [ "bitflags 2.13.2", "jni-sys 0.3.1", "log", - "ndk-sys", + "ndk-sys 0.6.0+11769913", "num_enum", - "raw-window-handle", + "raw-window-handle 0.6.2", "thiserror 1.0.69", ] @@ -4193,6 +4095,15 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "27b02d87554356db9e9a873add8782d4ea6e3e58ea071a9adb9a2e8ddb884a8b" +[[package]] +name = "ndk-sys" +version = "0.5.0+25.2.9519653" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c196769dd60fd4f363e11d948139556a344e79d451aeb2fa2fd040738ef7691" +dependencies = [ + "jni-sys 0.3.1", +] + [[package]] name = "ndk-sys" version = "0.6.0+11769913" @@ -4203,15 +4114,34 @@ dependencies = [ ] [[package]] -name = "nix" -version = "0.31.3" +name = "new_debug_unreachable" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "650eef8c711430f1a879fdd01d4745a7deea475becfb90269c06775983bbf086" + +[[package]] +name = "no_std_io2" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf20d2fde8ff38632c426f1165ed7436270b44f199fc55284c38276f9db47c3d" +checksum = "418abd1b6d34fbf6cae440dc874771b0525a604428704c76e48b29a5e67b8003" dependencies = [ - "bitflags 2.13.2", - "cfg-if", - "cfg_aliases", - "libc", + "memchr", +] + +[[package]] +name = "nodrop" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "72ef4a56884ca558e5ddb05a1d1e7e1bfd9a68d9ed024c21704cc98872dae1bb" + +[[package]] +name = "nom" +version = "7.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a" +dependencies = [ + "memchr", + "minimal-lexical", ] [[package]] @@ -4224,10 +4154,10 @@ dependencies = [ ] [[package]] -name = "nonmax" -version = "0.5.5" +name = "noop_proc_macro" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "610a5acd306ec67f907abe5567859a3c693fb9886eb1f012ab8f2a47bef3db51" +checksum = "0676bb32a98c1a483ce53e500a81ad9c3d5b3f7c920c28c24e9cb0980d0b5bc8" [[package]] name = "nu-ansi-term" @@ -4239,10 +4169,61 @@ dependencies = [ ] [[package]] -name = "num-conv" -version = "0.2.2" +name = "num-bigint" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c89e69e7e0f03bea5ef08013795c25018e101932225a656383bd384495ecc367" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-complex" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73f88a1307638156682bada9d7604135552957b7818057dcef22705b4d509495" +dependencies = [ + "bytemuck", + "num-traits", +] + +[[package]] +name = "num-conv" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" + +[[package]] +name = "num-derive" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed3955f1a9c7c0c15e092f9c887db08b1fc683305fdf6eb6684f22555355e202" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "num-integer" +version = "0.1.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-rational" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "521739c6d2bac4aa25192232afe6841231376b2b26d4d9fae5ecf8ca5772e441" +checksum = "f83d14da390562dca69fc84082e73e548e1ad308d24accdedd2720017cb37824" +dependencies = [ + "num-bigint", + "num-integer", + "num-traits", +] [[package]] name = "num-traits" @@ -4270,26 +4251,19 @@ version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", "syn 2.0.119", ] [[package]] -name = "objc-sys" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" - -[[package]] -name = "objc2" -version = "0.5.3" +name = "objc" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19d5490aaf8f1d7cf7688dfa9b0ce07900e168852c45cd2c03f534dfd27cfd0b" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" dependencies = [ - "objc-sys", - "objc2-encode", + "malloc_buf", ] [[package]] @@ -4299,22 +4273,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08849bbd4767dfae9457696856ae1c84fe4e0281bbe4a7abff2d0e06fb7981f8" dependencies = [ "objc2-encode", -] - -[[package]] -name = "objc2-app-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" -dependencies = [ - "bitflags 2.13.2", - "block2 0.5.1", - "libc", - "objc2 0.5.3", - "objc2-core-data", - "objc2-core-image", - "objc2-foundation 0.2.2", - "objc2-quartz-core 0.2.2", + "objc2-exception-helper", ] [[package]] @@ -4324,45 +4283,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d49e936b501e5c5bf01fda3a9452ff86dc3ea98ad5f283e1455153142d97518c" dependencies = [ "bitflags 2.13.2", - "objc2 0.6.5", - "objc2-core-graphics", - "objc2-foundation 0.3.2", -] - -[[package]] -name = "objc2-cloud-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "74dd3b56391c7a0596a295029734d3c1c5e7e510a4cb30245f8221ccea96b009" -dependencies = [ - "bitflags 2.13.2", - "block2 0.5.1", - "objc2 0.5.3", - "objc2-core-location", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-contacts" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a5ff520e9c33812fd374d8deecef01d4a840e7b41862d849513de77e44aa4889" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.3", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-core-data" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" -dependencies = [ - "bitflags 2.13.2", - "block2 0.5.1", - "objc2 0.5.3", - "objc2-foundation 0.2.2", + "block2", + "objc2", + "objc2-core-foundation", + "objc2-foundation", ] [[package]] @@ -4373,7 +4297,7 @@ checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" dependencies = [ "bitflags 2.13.2", "dispatch2", - "objc2 0.6.5", + "objc2", ] [[package]] @@ -4384,45 +4308,11 @@ checksum = "e022c9d066895efa1345f8e33e584b9f958da2fd4cd116792e15e07e4720a807" dependencies = [ "bitflags 2.13.2", "dispatch2", - "objc2 0.6.5", + "objc2", "objc2-core-foundation", "objc2-io-surface", ] -[[package]] -name = "objc2-core-image" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.3", - "objc2-foundation 0.2.2", - "objc2-metal 0.2.2", -] - -[[package]] -name = "objc2-core-location" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "000cfee34e683244f284252ee206a27953279d370e309649dc3ee317b37e5781" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.3", - "objc2-contacts", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-core-text" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0cde0dfb48d25d2b4862161a4d5fcc0e3c24367869ad306b0c9ec0073bfed92d" -dependencies = [ - "bitflags 2.13.2", - "objc2-core-foundation", -] - [[package]] name = "objc2-encode" version = "4.1.0" @@ -4430,16 +4320,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] -name = "objc2-foundation" -version = "0.2.2" +name = "objc2-exception-helper" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +checksum = "c7a1c5fbb72d7735b076bb47b578523aedc40f3c439bea6dfd595c089d79d98a" dependencies = [ - "bitflags 2.13.2", - "block2 0.5.1", - "dispatch", - "libc", - "objc2 0.5.3", + "cc", ] [[package]] @@ -4449,7 +4335,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3e0adef53c21f888deb4fa59fc59f7eb17404926ee8a6f59f5df0fd7f9f3272" dependencies = [ "bitflags 2.13.2", - "objc2 0.6.5", + "block2", + "objc2", "objc2-core-foundation", ] @@ -4460,34 +4347,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "180788110936d59bab6bd83b6060ffdfffb3b922ba1396b312ae795e1de9d81d" dependencies = [ "bitflags 2.13.2", - "objc2 0.6.5", + "objc2", "objc2-core-foundation", ] -[[package]] -name = "objc2-link-presentation" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1a1ae721c5e35be65f01a03b6d2ac13a54cb4fa70d8a5da293d7b0020261398" -dependencies = [ - "block2 0.5.1", - "objc2 0.5.3", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", -] - -[[package]] -name = "objc2-metal" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" -dependencies = [ - "bitflags 2.13.2", - "block2 0.5.1", - "objc2 0.5.3", - "objc2-foundation 0.2.2", -] - [[package]] name = "objc2-metal" version = "0.3.2" @@ -4495,101 +4358,81 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a0125f776a10d00af4152d74616409f0d4a2053a6f57fa5b7d6aa2854ac04794" dependencies = [ "bitflags 2.13.2", - "block2 0.6.2", - "objc2 0.6.5", - "objc2-foundation 0.3.2", + "block2", + "objc2", + "objc2-foundation", ] [[package]] name = "objc2-quartz-core" -version = "0.2.2" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" dependencies = [ "bitflags 2.13.2", - "block2 0.5.1", - "objc2 0.5.3", - "objc2-foundation 0.2.2", - "objc2-metal 0.2.2", + "objc2", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "objc2-metal", ] [[package]] -name = "objc2-quartz-core" +name = "objc2-ui-kit" version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96c1358452b371bf9f104e21ec536d37a650eb10f7ee379fff67d2e08d537f1f" +checksum = "d87d638e33c06f577498cbcc50491496a3ed4246998a7fbba7ccb98b1e7eab22" dependencies = [ "bitflags 2.13.2", - "objc2 0.6.5", + "objc2", "objc2-core-foundation", - "objc2-core-graphics", - "objc2-foundation 0.3.2", - "objc2-metal 0.3.2", + "objc2-foundation", ] [[package]] -name = "objc2-symbols" -version = "0.2.2" +name = "objc2-web-kit" +version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0a684efe3dec1b305badae1a28f6555f6ddd3bb2c2267896782858d5a78404dc" +checksum = "b2e5aaab980c433cf470df9d7af96a7b46a9d892d521a2cbbb2f8a4c16751e7f" dependencies = [ - "objc2 0.5.3", - "objc2-foundation 0.2.2", + "bitflags 2.13.2", + "block2", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", ] [[package]] -name = "objc2-ui-kit" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8bb46798b20cd6b91cbd113524c490f1686f4c4e8f49502431415f3512e2b6f" -dependencies = [ - "bitflags 2.13.2", - "block2 0.5.1", - "objc2 0.5.3", - "objc2-cloud-kit", - "objc2-core-data", - "objc2-core-image", - "objc2-core-location", - "objc2-foundation 0.2.2", - "objc2-link-presentation", - "objc2-quartz-core 0.2.2", - "objc2-symbols", - "objc2-uniform-type-identifiers", - "objc2-user-notifications", -] - -[[package]] -name = "objc2-uniform-type-identifiers" -version = "0.2.2" +name = "objc_id" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44fa5f9748dbfe1ca6c0b79ad20725a11eca7c2218bceb4b005cb1be26273bfe" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" dependencies = [ - "block2 0.5.1", - "objc2 0.5.3", - "objc2-foundation 0.2.2", + "objc", ] [[package]] -name = "objc2-user-notifications" -version = "0.2.2" +name = "oboe" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76cfcbf642358e8689af64cee815d139339f3ed8ad05103ed5eaf73db8d84cb3" +checksum = "e8b61bebd49e5d43f5f8cc7ee2891c16e0f41ec7954d36bcb6c14c5e0de867fb" dependencies = [ - "bitflags 2.13.2", - "block2 0.5.1", - "objc2 0.5.3", - "objc2-core-location", - "objc2-foundation 0.2.2", + "jni 0.21.1", + "ndk 0.8.0", + "ndk-context", + "num-derive", + "num-traits", + "oboe-sys", ] [[package]] -name = "offset-allocator" -version = "0.2.0" +name = "oboe-sys" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e234d535da3521eb95106f40f0b73483d80bfb3aacf27c40d7e2b72f1a3e00a2" +checksum = "6c8bb09a4a2b1d668170cfe0a7d5bc103f8999fb316c98099b6a9939c9f2e79d" dependencies = [ - "log", - "nonmax", + "cc", ] [[package]] @@ -4598,18 +4441,37 @@ version = "1.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" -[[package]] -name = "once_cell_polyfill" -version = "1.70.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" - [[package]] name = "opaque-debug" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08d65885ee38876c4f86fa503fb49d7b507c2b62552df7c70b2fce627e06381" +[[package]] +name = "openssl" +version = "0.10.81" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77823a27f0babb03091cb9ed9ef80af3b39dbc82f97e8fa530374b7dafd87a45" +dependencies = [ + "bitflags 2.13.2", + "cfg-if", + "foreign-types 0.3.2", + "libc", + "openssl-macros", + "openssl-sys", +] + +[[package]] +name = "openssl-macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + [[package]] name = "openssl-probe" version = "0.2.1" @@ -4617,15 +4479,23 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" [[package]] -name = "orbclient" -version = "0.3.55" +name = "openssl-sys" +version = "0.9.117" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5df339f526ea9a60e371768d50efc2f2508c7203290731565d1f7a6f71d21747" +checksum = "b47e7e6bb2c38cd930d25a23b40fa52e068c10e85f3e03a7f5ba5aaca5713695" dependencies = [ + "cc", "libc", - "libredox", + "pkg-config", + "vcpkg", ] +[[package]] +name = "option-ext" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" + [[package]] name = "ordered-float" version = "5.5.0" @@ -4636,29 +4506,38 @@ dependencies = [ ] [[package]] -name = "os_pipe" -version = "1.2.3" +name = "owned_ttf_parser" +version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d8fae84b431384b68627d0f9b3b1245fcf9f46f6c0e3dc902e9dce64edd1967" +checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" dependencies = [ - "libc", - "windows-sys 0.61.2", + "ttf-parser", ] [[package]] -name = "owned_ttf_parser" -version = "0.25.1" +name = "pango" +version = "0.18.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36820e9051aca1014ddc75770aab4d68bc1e9e632f0f5627c4086bc216fb583b" +checksum = "7ca27ec1eb0457ab26f3036ea52229edbdb74dee1edd29063f5b9b010e7ebee4" dependencies = [ - "ttf-parser", + "gio", + "glib", + "libc", + "once_cell", + "pango-sys", ] [[package]] -name = "parking" -version = "2.2.1" +name = "pango-sys" +version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f38d5652c16fde515bb1ecef450ab0f6a219d619a7274976324d5e377f7dceba" +checksum = "436737e391a843e5933d6d9aa102cb126d501e815b83601365a948a518555dc5" +dependencies = [ + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] [[package]] name = "parking_lot" @@ -4678,82 +4557,168 @@ checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" dependencies = [ "cfg-if", "libc", - "redox_syscall 0.5.18", + "redox_syscall", "smallvec", - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "password-hash" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "aab41826031698d6ffcd9cff78ef56ef998e39dc7e5067cdfebe373842d4723b" +dependencies = [ + "getrandom 0.4.3", + "phc", ] [[package]] -name = "parlance" +name = "paste" +version = "1.0.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57c0d7b74b563b49d38dae00a0c37d4d6de9b432382b2892f0574ddcae73fd0a" + +[[package]] +name = "pastey" version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "73072a9470554c8e794778acece2312661218aaabb635600957d952cf01c716e" +checksum = "35fb2e5f958ec131621fdd531e9fc186ed768cbe395337403ae56c17a74c68ec" [[package]] -name = "parley" -version = "0.11.1" +name = "percent-encoding" +version = "2.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" + +[[package]] +name = "phc" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22d2ff88bd3f7d68d1d9b09c7e6209f9a8e8c05088295140a2bcf2e9b17038c5" +checksum = "44dc769b75f93afdddd8c7fa12d685292ddeff1e66f7f0f3a234cf1818afe892" dependencies = [ - "fontique", - "harfrust", - "hashbrown 0.17.1", - "icu_normalizer", - "icu_properties", - "icu_segmenter", - "linebender_resource_handle", - "parlance", - "parley_data", - "skrifa", + "base64ct", + "ctutils", + "getrandom 0.4.3", ] [[package]] -name = "parley_data" -version = "0.11.1" +name = "phf" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1567535334d6ba2d3cde19221ba9a7bd0fabb3cbd99046ddfb10ae061cfcc889" +checksum = "3dfb61232e34fcb633f43d12c58f83c1df82962dcdfa565a4e866ffc17dafe12" dependencies = [ - "icu_properties", + "phf_shared 0.8.0", ] [[package]] -name = "password-hash" -version = "0.6.1" +name = "phf" +version = "0.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aab41826031698d6ffcd9cff78ef56ef998e39dc7e5067cdfebe373842d4723b" +checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" dependencies = [ - "getrandom 0.4.3", - "phc", + "phf_macros", + "phf_shared 0.10.0", + "proc-macro-hack", ] [[package]] -name = "percent-encoding" -version = "2.3.2" +name = "phf" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" +checksum = "1fd6780a80ae0c52cc120a26a1a42c1ae51b247a253e4e06113d23d2c2edd078" +dependencies = [ + "phf_shared 0.11.3", +] [[package]] -name = "petgraph" -version = "0.8.3" +name = "phf_codegen" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8701b58ea97060d5e5b155d383a69952a60943f0e6dfe30b04c287beb0b27455" +checksum = "cbffee61585b0411840d3ece935cce9cb6321f01c45477d30066498cd5e1a815" dependencies = [ - "fixedbitset", - "hashbrown 0.15.5", - "indexmap", - "serde", - "serde_derive", + "phf_generator 0.8.0", + "phf_shared 0.8.0", ] [[package]] -name = "phc" -version = "0.6.1" +name = "phf_codegen" +version = "0.11.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44dc769b75f93afdddd8c7fa12d685292ddeff1e66f7f0f3a234cf1818afe892" +checksum = "aef8048c789fa5e851558d709946d6d79a8ff88c0440c587967f8e94bfb1216a" dependencies = [ - "base64ct", - "ctutils", - "getrandom 0.4.3", + "phf_generator 0.11.3", + "phf_shared 0.11.3", +] + +[[package]] +name = "phf_generator" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "17367f0cc86f2d25802b2c26ee58a7b23faeccf78a396094c13dced0d0182526" +dependencies = [ + "phf_shared 0.8.0", + "rand 0.7.3", +] + +[[package]] +name = "phf_generator" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +dependencies = [ + "phf_shared 0.10.0", + "rand 0.8.8", +] + +[[package]] +name = "phf_generator" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c80231409c20246a13fddb31776fb942c38553c51e871f8cbd687a4cfb5843d" +dependencies = [ + "phf_shared 0.11.3", + "rand 0.8.8", +] + +[[package]] +name = "phf_macros" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +dependencies = [ + "phf_generator 0.10.0", + "phf_shared 0.10.0", + "proc-macro-hack", + "proc-macro2", + "quote", + "syn 1.0.109", +] + +[[package]] +name = "phf_shared" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c00cf8b9eafe68dde5e9eaa2cef8ee84a9336a47d566ec55ca16589633b65af7" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" +dependencies = [ + "siphasher 0.3.11", +] + +[[package]] +name = "phf_shared" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67eabc2ef2a60eb7faa00097bd1ffdb5bd28e62bf39990626a582201b7a754e5" +dependencies = [ + "siphasher 1.0.4", ] [[package]] @@ -4782,17 +4747,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" -[[package]] -name = "piper" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c835479a4443ded371d6c535cbfd8d31ad92c5d23ae9770a61bc155e4992a3c1" -dependencies = [ - "atomic-waker", - "fastrand", - "futures-io", -] - [[package]] name = "pkg-config" version = "0.3.34" @@ -4800,10 +4754,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" [[package]] -name = "plain" -version = "0.2.3" +name = "png" +version = "0.17.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4596b6d070b27117e987119b4dac604f3c58cfb0b191112e24771b2faeac1a6" +checksum = "82151a2fc869e011c153adc57cf2789ccb8d9906ce52c0b39a6b5697749d7526" +dependencies = [ + "bitflags 1.3.2", + "crc32fast", + "fdeflate", + "flate2", + "miniz_oxide 0.8.9", +] [[package]] name = "png" @@ -4819,18 +4780,10 @@ dependencies = [ ] [[package]] -name = "polling" -version = "3.11.0" +name = "pollster" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d0e4f59085d47d8241c88ead0f274e8a0cb551f3625263c05eb8dd897c34218" -dependencies = [ - "cfg-if", - "concurrent-queue", - "hermit-abi", - "pin-project-lite", - "rustix 1.1.5", - "windows-sys 0.61.2", -] +checksum = "2f3a9f18d041e6d0e102a0a46750538147e5e8992d3b4873aaafee2520b00ce3" [[package]] name = "polyval" @@ -4865,8 +4818,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" dependencies = [ - "serde_core", - "writeable", "zerovec", ] @@ -4885,21 +4836,77 @@ dependencies = [ "zerocopy", ] +[[package]] +name = "precomputed-hash" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" + [[package]] name = "presser" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8cf8e6a8aa66ce33f63993ffc4ea4271eb5b0530a9002db8455ea6050c77bfa" +[[package]] +name = "proc-macro-crate" +version = "1.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" +dependencies = [ + "once_cell", + "toml_edit 0.19.15", +] + +[[package]] +name = "proc-macro-crate" +version = "2.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b00f26d3400549137f92511a46ac1cd8ce37cb5598a96d382381458b992a5d24" +dependencies = [ + "toml_datetime 0.6.3", + "toml_edit 0.20.2", +] + [[package]] name = "proc-macro-crate" version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f" dependencies = [ - "toml_edit", + "toml_edit 0.25.17+spec-1.1.0", +] + +[[package]] +name = "proc-macro-error" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" +dependencies = [ + "proc-macro-error-attr", + "proc-macro2", + "quote", + "syn 1.0.109", + "version_check", +] + +[[package]] +name = "proc-macro-error-attr" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" +dependencies = [ + "proc-macro2", + "quote", + "version_check", ] +[[package]] +name = "proc-macro-hack" +version = "0.5.20+deprecated" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" + [[package]] name = "proc-macro2" version = "1.0.107" @@ -4909,11 +4916,52 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "proc-macro2-diagnostics" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af066a9c399a26e020ada66a034357a868728e72cd426f3adcd35f80d88d88c8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", + "version_check", +] + [[package]] name = "profiling" version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d595e54a326bc53c1c197b32d295e14b169e3cfeaa8dc82b529f947fba6bcf5" +dependencies = [ + "profiling-procmacros", +] + +[[package]] +name = "profiling-procmacros" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4488a4a36b9a4ba6b9334a32a39971f77c1436ec82c38707bce707699cc3bbcb" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "psl-types" +version = "2.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33cb294fe86a74cbcf50d4445b37da762029549ebeea341421c7c70370f86cac" + +[[package]] +name = "publicsuffix" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6f42ea446cab60335f76979ec15e12619a2165b5ae2c12166bef27d283a9fadf" +dependencies = [ + "idna", + "psl-types", +] [[package]] name = "pulldown-cmark" @@ -4923,9 +4971,39 @@ checksum = "e9f068eba8e7071c5f9511831b44f32c740d5adf574e990f946ddb53db2f314e" dependencies = [ "bitflags 2.13.2", "memchr", + "pulldown-cmark-escape", "unicase", ] +[[package]] +name = "pulldown-cmark-escape" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "007d8adb5ddab6f8e3f491ac63566a7d5002cc7ed73901f72057943fa71ae1ae" + +[[package]] +name = "pulp" +version = "0.22.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "046aa45b989642ec2e4717c8e72d677b13edd831a4d3b6cf37d9a3e54912496a" +dependencies = [ + "bytemuck", + "cfg-if", + "libm", + "num-complex", + "paste", + "pulp-wasm-simd-flag", + "raw-cpuid", + "reborrow", + "version_check", +] + +[[package]] +name = "pulp-wasm-simd-flag" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d8f70e07b9c3962945a74e59ca1c511bba65b6419468acc217c457d93f3c740" + [[package]] name = "pxfm" version = "0.1.30" @@ -4933,14 +5011,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d55d956fa96f5ec02be2e13af0e20391a5aa83d6a074e3ad368959d0fab299ea" [[package]] -name = "quick-xml" -version = "0.41.0" +name = "qoi" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e660451e55124f798a69a5af3f49ccfbefbd41910eefd25caf2393e1f3473ec1" +checksum = "7f6d64c71eb498fe9eae14ce4ec935c555749aef511cca85b5568910d6e48001" dependencies = [ - "memchr", + "bytemuck", ] +[[package]] +name = "quick-error" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3" + [[package]] name = "quinn" version = "0.11.12" @@ -4972,7 +5056,7 @@ dependencies = [ "getrandom 0.4.3", "lru-slab", "rand 0.10.3", - "rand_pcg", + "rand_pcg 0.10.2", "ring", "rustc-hash 2.1.3", "rustls", @@ -5020,16 +5104,18 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] -name = "radium" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09" - -[[package]] -name = "radsort" -version = "0.1.1" +name = "rand" +version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "019b4b213425016d7d84a153c4c73afb0946fbb4840e4eece7ba8848b9d6da22" +checksum = "6a6b1679d49b24bbfe0c803429aa1874472f50d9b363131f0e89fc356b544d03" +dependencies = [ + "getrandom 0.1.16", + "libc", + "rand_chacha 0.2.2", + "rand_core 0.5.1", + "rand_hc", + "rand_pcg 0.2.1", +] [[package]] name = "rand" @@ -5063,6 +5149,16 @@ dependencies = [ "rand_core 0.10.1", ] +[[package]] +name = "rand_chacha" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4c8ed856279c9737206bf725bf36935d8666ead7aa69b52be55af369d193402" +dependencies = [ + "ppv-lite86", + "rand_core 0.5.1", +] + [[package]] name = "rand_chacha" version = "0.3.1" @@ -5083,6 +5179,15 @@ dependencies = [ "rand_core 0.9.5", ] +[[package]] +name = "rand_core" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90bde5296fc891b0cef12a6d03ddccc162ce7b2aff54160af9338f8d40df6d19" +dependencies = [ + "getrandom 0.1.16", +] + [[package]] name = "rand_core" version = "0.6.4" @@ -5108,13 +5213,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "63b8176103e19a2643978565ca18b50549f6101881c443590420e4dc998a3c69" [[package]] -name = "rand_distr" -version = "0.6.0" +name = "rand_hc" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d431c2703ccf129de4d45253c03f49ebb22b97d6ad79ee3ecfc7e3f4862c1d8" +checksum = "ca3129af7b92a17112d59ad498c6f81eaf463253766b90396d39ea7a39d6613c" dependencies = [ - "num-traits", - "rand 0.10.3", + "rand_core 0.5.1", +] + +[[package]] +name = "rand_pcg" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16abd0c1b639e9eb4d7c50c0b8100b0d0f849be2349829c740fe8e6eb4816429" +dependencies = [ + "rand_core 0.5.1", ] [[package]] @@ -5132,6 +5245,71 @@ version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ca45419789ae5a7899559e9512e58ca889e41f04f1f2445e9f4b290ceccd1d08" +[[package]] +name = "rav1e" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43b6dd56e85d9483277cde964fd1bdb0428de4fec5ebba7540995639a21cb32b" +dependencies = [ + "aligned-vec", + "arbitrary", + "arg_enum_proc_macro", + "arrayvec", + "av-scenechange", + "av1-grain", + "bitstream-io", + "built", + "cfg-if", + "interpolate_name", + "itertools 0.14.0", + "libc", + "libfuzzer-sys", + "log", + "maybe-rayon", + "new_debug_unreachable", + "noop_proc_macro", + "num-derive", + "num-traits", + "paste", + "profiling", + "rand 0.9.5", + "rand_chacha 0.9.0", + "simd_helpers", + "thiserror 2.0.21", + "v_frame", + "wasm-bindgen", +] + +[[package]] +name = "ravif" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e52310197d971b0f5be7fe6b57530dcd27beb35c1b013f29d66c1ad73fbbcc45" +dependencies = [ + "avif-serialize", + "imgref", + "loop9", + "quick-error", + "rav1e", + "rayon", + "rgb", +] + +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags 2.13.2", +] + +[[package]] +name = "raw-window-handle" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" + [[package]] name = "raw-window-handle" version = "0.6.2" @@ -5144,28 +5322,37 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40d213455a5f1dc59214213c7330e074ddf8114c9a42411eb890c767357ce135" dependencies = [ - "objc2 0.6.5", + "objc2", "objc2-core-foundation", - "objc2-foundation 0.3.2", - "objc2-quartz-core 0.3.2", + "objc2-foundation", + "objc2-quartz-core", ] [[package]] -name = "read-fonts" -version = "0.41.0" +name = "rayon" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "046a7d674daf459825b32f5062056d6882db0d2f5a479fbd76ccfc870ac18709" +checksum = "fb39b166781f92d482534ef4b4b1b2568f42613b53e5b6c160e24cfbfa30926d" dependencies = [ - "bytemuck", - "font-types", - "once_cell", + "either", + "rayon-core", ] [[package]] -name = "rectangle-pack" -version = "0.4.2" +name = "rayon-core" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91" +dependencies = [ + "crossbeam-deque", + "crossbeam-utils", +] + +[[package]] +name = "reborrow" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a0d463f2884048e7153449a55166f91028d5b0ea53c79377099ce4e8cf0cf9bb" +checksum = "03251193000f4bd3b042892be858ee50e8b3719f2b08e5833ac4353724632430" [[package]] name = "redb" @@ -5176,15 +5363,6 @@ dependencies = [ "libc", ] -[[package]] -name = "redox_syscall" -version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4722d768eff46b75989dd134e5c353f0d6296e5aaa3132e776cbdb56be7731aa" -dependencies = [ - "bitflags 1.3.2", -] - [[package]] name = "redox_syscall" version = "0.5.18" @@ -5195,12 +5373,13 @@ dependencies = [ ] [[package]] -name = "redox_syscall" -version = "0.9.4" +name = "redox_users" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "737970939a87c6fa31e7acad13307bccbb017a073b695b6089a2c484f929e20e" +checksum = "60dc65c0ff1a7ae1294b0c67b9f14baf70b644404010370171787bfac1038fc0" dependencies = [ - "bitflags 2.13.2", + "libredox", + "thiserror 2.0.21", ] [[package]] @@ -5238,6 +5417,50 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "19b30a45b0cd0bcca8037f3d0dc3421eaf95327a17cad11964fb8179b4fc4832" +[[package]] +name = "reqwest" +version = "0.12.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +dependencies = [ + "base64 0.22.1", + "bytes", + "cookie", + "cookie_store", + "futures-core", + "futures-util", + "http", + "http-body", + "http-body-util", + "hyper", + "hyper-rustls", + "hyper-util", + "js-sys", + "log", + "mime_guess", + "percent-encoding", + "pin-project-lite", + "quinn", + "rustls", + "rustls-pki-types", + "serde", + "serde_json", + "serde_urlencoded", + "sync_wrapper", + "tokio", + "tokio-rustls", + "tokio-util", + "tower", + "tower-http", + "tower-service", + "url", + "wasm-bindgen", + "wasm-bindgen-futures", + "wasm-streams 0.4.2", + "web-sys", + "webpki-roots", +] + [[package]] name = "reqwest" version = "0.13.5" @@ -5275,10 +5498,40 @@ dependencies = [ "url", "wasm-bindgen", "wasm-bindgen-futures", - "wasm-streams", + "wasm-streams 0.5.0", + "web-sys", +] + +[[package]] +name = "rfd" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20dafead71c16a34e1ff357ddefc8afc11e7d51d6d2b9fbd07eaa48e3e540220" +dependencies = [ + "block2", + "dispatch2", + "js-sys", + "libc", + "log", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "percent-encoding", + "pollster", + "raw-window-handle 0.6.2", + "wasm-bindgen", + "wasm-bindgen-futures", "web-sys", + "windows-sys 0.61.2", ] +[[package]] +name = "rgb" +version = "0.8.53" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47b34b781b31e5d73e9fbc8689c70551fd1ade9a19e3e28cfec8580a79290cc4" + [[package]] name = "ring" version = "0.17.14" @@ -5293,29 +5546,6 @@ dependencies = [ "windows-sys 0.52.0", ] -[[package]] -name = "ron" -version = "0.12.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81116b9531d61eabc41aeb228e4b6b2435bcca3233b98cf3b3077d4e6e9debb3" -dependencies = [ - "bitflags 2.13.2", - "once_cell", - "serde", - "serde_derive", - "typeid", - "unicode-ident", -] - -[[package]] -name = "roxmltree" -version = "0.21.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1964b10c76125c36f8afe190065a4bf9a87bf324842c05701330bba9f1cacbb" -dependencies = [ - "memchr", -] - [[package]] name = "rust-embed" version = "8.13.0" @@ -5372,19 +5602,6 @@ dependencies = [ "semver", ] -[[package]] -name = "rustix" -version = "0.38.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154" -dependencies = [ - "bitflags 2.13.2", - "errno", - "libc", - "linux-raw-sys 0.4.15", - "windows-sys 0.59.0", -] - [[package]] name = "rustix" version = "1.1.5" @@ -5394,7 +5611,7 @@ dependencies = [ "bitflags 2.13.2", "errno", "libc", - "linux-raw-sys 0.12.1", + "linux-raw-sys", "windows-sys 0.61.2", ] @@ -5442,9 +5659,9 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1167586491e2b18b8bfbb293e8180ec17c201c4f076d7cb3070ca964e7598f98" dependencies = [ - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", - "jni", + "jni 0.22.4", "log", "once_cell", "rustls", @@ -5510,7 +5727,7 @@ dependencies = [ "hyper-rustls", "hyper-util", "percent-encoding", - "reqwest", + "reqwest 0.13.5", "rustls", "salvo_core", "tokio", @@ -5608,7 +5825,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b7644c99267dd8a97d97a00ad1358c6d597db764354fe6c7679105af62d1f7c" dependencies = [ - "proc-macro-crate", + "proc-macro-crate 3.5.0", "proc-macro2", "quote", "salvo-serde-util", @@ -5633,31 +5850,12 @@ dependencies = [ "windows-sys 0.61.2", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" -[[package]] -name = "sctk-adwaita" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6277f0217056f77f1d8f49f2950ac6c278c0d607c45f5ee99328d792ede24ec" -dependencies = [ - "ab_glyph", - "log", - "memmap2", - "smithay-client-toolkit", - "tiny-skia", -] - [[package]] name = "security-framework" version = "3.7.0" @@ -5665,7 +5863,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" dependencies = [ "bitflags 2.13.2", - "core-foundation 0.10.1", + "core-foundation", "core-foundation-sys", "libc", "security-framework-sys", @@ -5681,6 +5879,24 @@ dependencies = [ "libc", ] +[[package]] +name = "selectors" +version = "0.24.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c37578180969d00692904465fb7f6b3d50b9a2b952b87c23d0e2e5cb5013416" +dependencies = [ + "bitflags 1.3.2", + "cssparser", + "derive_more 0.99.20", + "fxhash", + "log", + "phf 0.8.0", + "phf_codegen 0.8.0", + "precomputed-hash", + "servo_arc", + "smallvec", +] + [[package]] name = "semver" version = "1.0.28" @@ -5692,6 +5908,9 @@ name = "send_wrapper" version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cd0b0ec5f1c1ca621c432a25813d8d60c88abe6d3e08a3eb9cf37d97a0fe3d73" +dependencies = [ + "futures-core", +] [[package]] name = "serde" @@ -5703,6 +5922,17 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde-wasm-bindgen" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8302e169f0eddcc139c70f139d19d6467353af16f9fce27e8c30158036a1e16b" +dependencies = [ + "js-sys", + "serde", + "wasm-bindgen", +] + [[package]] name = "serde-xml-rs" version = "0.8.2" @@ -5749,14 +5979,47 @@ dependencies = [ ] [[package]] -name = "serde_spanned" -version = "1.1.2" +name = "serde_path_to_error" +version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e7523beb55eece201a2356bee0bbca0d1ab466c14c07703b2e0ee6d42cb0c2c" +checksum = "10a9ff822e371bb5403e391ecd83e182e0e77ba7f6fe0160b795797109d1b457" dependencies = [ + "itoa", + "serde", "serde_core", ] +[[package]] +name = "serde_qs" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3faaf9e727533a19351a43cc5a8de957372163c7d35cc48c90b75cdda13c352" +dependencies = [ + "percent-encoding", + "serde", + "thiserror 2.0.21", +] + +[[package]] +name = "serde_repr" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.9", +] + +[[package]] +name = "serde_spanned" +version = "0.6.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf41e0cfaf7226dca15e8197172c295a782857fcb97fad1808a166870dee75a3" +dependencies = [ + "serde", +] + [[package]] name = "serde_urlencoded" version = "0.7.1" @@ -5769,6 +6032,16 @@ dependencies = [ "serde", ] +[[package]] +name = "servo_arc" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52aa42f8fdf0fed91e5ce7f23d8138441002fa31dca008acf47e6fd4721f741" +dependencies = [ + "nodrop", + "stable_deref_trait", +] + [[package]] name = "sha1" version = "0.10.7" @@ -5803,193 +6076,424 @@ dependencies = [ ] [[package]] -name = "sharded-slab" -version = "0.1.7" +name = "sharded-slab" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "signal-hook" +version = "0.3.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d881a16cf4426aa584979d30bd82cb33429027e42122b169753d6ef1085ed6e2" +dependencies = [ + "libc", + "signal-hook-registry", +] + +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + +[[package]] +name = "simd-adler32" +version = "0.3.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" + +[[package]] +name = "simd_cesu8" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +dependencies = [ + "rustc_version", + "simdutf8", +] + +[[package]] +name = "simd_helpers" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95890f873bec569a0362c235787f3aca6e1e887302ba4840839bcc6459c42da6" +dependencies = [ + "quote", +] + +[[package]] +name = "simdutf8" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" + +[[package]] +name = "siphasher" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38b58827f4464d87d377d175e90bf58eb00fd8716ff0a62f80356b5e61555d0d" + +[[package]] +name = "siphasher" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33f4fe9184a62d842c9ef383018f3306d8ba224fd9d836f56d7288308847c256" + +[[package]] +name = "slab" +version = "0.4.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" + +[[package]] +name = "sledgehammer_bindgen" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "49e83e178d176459c92bc129cfd0958afac3ced925471b889b3a75546cfc4133" +dependencies = [ + "sledgehammer_bindgen_macro", + "wasm-bindgen", +] + +[[package]] +name = "sledgehammer_bindgen_macro" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb251b407f50028476a600541542b605bb864d35d9ee1de4f6cab45d88475e6d" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "sledgehammer_utils" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "debdd4b83524961983cea3c55383b3910fd2f24fd13a188f5b091d2d504a61ae" +dependencies = [ + "rustc-hash 1.1.0", +] + +[[package]] +name = "slotmap" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" +dependencies = [ + "serde", + "version_check", +] + +[[package]] +name = "smallvec" +version = "1.16.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b" + +[[package]] +name = "socket2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +dependencies = [ + "libc", + "windows-sys 0.61.2", +] + +[[package]] +name = "soup3" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "471f924a40f31251afc77450e781cb26d55c0b650842efafc9c6cbd2f7cc4f9f" +dependencies = [ + "futures-channel", + "gio", + "glib", + "libc", + "soup3-sys", +] + +[[package]] +name = "soup3-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ebe8950a680a12f24f15ebe1bf70db7af98ad242d9db43596ad3108aab86c27" +dependencies = [ + "gio-sys", + "glib-sys", + "gobject-sys", + "libc", + "system-deps", +] + +[[package]] +name = "spin" +version = "0.9.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3763264f6b73151db08c50ff20d7d8a0b8796e021cdea7ceedad07b80155fa0e" + +[[package]] +name = "spirv" +version = "0.4.0+sdk-1.4.341.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" +checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" dependencies = [ - "lazy_static", + "bitflags 2.13.2", ] [[package]] -name = "shlex" -version = "2.0.1" +name = "stable_deref_trait" +version = "1.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" +checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" [[package]] -name = "signal-hook-registry" -version = "1.4.8" +name = "static_assertions" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" -dependencies = [ - "errno", - "libc", -] +checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" [[package]] -name = "simd-adler32" -version = "0.3.10" +name = "str-buf" +version = "3.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a219298ac11a56ea9a6d2120044824d6f01aeb034955e7af7bc16858527deea" +checksum = "0ceb97b7225c713c2fd4db0153cb6b3cab244eb37900c3f634ed4d43310d8c34" [[package]] -name = "simd_cesu8" -version = "1.2.0" +name = "string_cache" +version = "0.8.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" +checksum = "bf776ba3fa74f83bf4b63c3dcbbf82173db2632ed8452cb2d891d33f459de70f" dependencies = [ - "rustc_version", - "simdutf8", + "new_debug_unreachable", + "parking_lot", + "phf_shared 0.11.3", + "precomputed-hash", + "serde", ] [[package]] -name = "simdutf8" -version = "0.1.5" +name = "string_cache_codegen" +version = "0.5.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" +checksum = "c711928715f1fe0fe509c53b43e993a9a557babc2d0a3567d0a3006f1ac931a0" +dependencies = [ + "phf_generator 0.11.3", + "phf_shared 0.11.3", + "proc-macro2", + "quote", +] [[package]] -name = "skrifa" -version = "0.44.0" +name = "subsecond" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "819ab7d62b1d3e72d9d9dea5650bac30424f9111364bb94928dbf5ecad1baa68" +checksum = "d350d5788fa94d560d92269266a50efc77b036bfca6675e420b64df7b3211f37" dependencies = [ - "bytemuck", - "read-fonts", + "js-sys", + "libc", + "libloading 0.8.9", + "memfd", + "memmap2", + "serde", + "subsecond-types", + "thiserror 2.0.21", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] -name = "slab" -version = "0.4.12" +name = "subsecond-types" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" +checksum = "dcf32d66269b5fbb8558334e8d22b657b2f7af0dd2ef56c231541099a862e464" +dependencies = [ + "serde", +] [[package]] -name = "slotmap" -version = "1.1.1" +name = "subtle" +version = "2.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdd58c3c93c3d278ca835519292445cb4b0d4dc59ccfdf7ceadaab3f8aeb4038" -dependencies = [ - "version_check", -] +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] -name = "smallvec" -version = "1.16.3" +name = "symphonia" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5b3dc8af474f516a851ff4bd12db780f948b9250ad37211e4eec0bccea54e01b" +checksum = "5773a4c030a19d9bfaa090f49746ff35c75dfddfa700df7a5939d5e076a57039" +dependencies = [ + "lazy_static", + "symphonia-bundle-flac", + "symphonia-bundle-mp3", + "symphonia-codec-aac", + "symphonia-codec-pcm", + "symphonia-codec-vorbis", + "symphonia-core", + "symphonia-format-isomp4", + "symphonia-format-ogg", + "symphonia-format-riff", + "symphonia-metadata", +] [[package]] -name = "smithay-client-toolkit" -version = "0.19.2" +name = "symphonia-bundle-flac" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3457dea1f0eb631b4034d61d4d8c32074caa6cd1ab2d59f2327bd8461e2c0016" +checksum = "c91565e180aea25d9b80a910c546802526ffd0072d0b8974e3ebe59b686c9976" dependencies = [ - "bitflags 2.13.2", - "calloop", - "calloop-wayland-source", - "cursor-icon", - "libc", "log", - "memmap2", - "rustix 0.38.44", - "thiserror 1.0.69", - "wayland-backend", - "wayland-client", - "wayland-csd-frame", - "wayland-cursor", - "wayland-protocols", - "wayland-protocols-wlr", - "wayland-scanner", - "xkeysym", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", ] [[package]] -name = "smol_str" -version = "0.2.2" +name = "symphonia-bundle-mp3" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd538fb6910ac1099850255cf94a94df6551fbdd602454387d0adb2d1ca6dead" +checksum = "4872dd6bb56bf5eac799e3e957aa1981086c3e613b27e0ac23b176054f7c57ed" dependencies = [ - "serde", + "lazy_static", + "log", + "symphonia-core", + "symphonia-metadata", ] [[package]] -name = "socket2" -version = "0.6.5" +name = "symphonia-codec-aac" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +checksum = "4c263845aa86881416849c1729a54c7f55164f8b96111dba59de46849e73a790" dependencies = [ - "libc", - "windows-sys 0.61.2", + "lazy_static", + "log", + "symphonia-core", ] [[package]] -name = "spin" -version = "0.12.3" +name = "symphonia-codec-pcm" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0134f9043ed38b087ac4f7d4af44c79e2c9e5094421fe3164f435ce585953b10" +checksum = "4e89d716c01541ad3ebe7c91ce4c8d38a7cf266a3f7b2f090b108fb0cb031d95" dependencies = [ - "portable-atomic", + "log", + "symphonia-core", ] [[package]] -name = "spirv" -version = "0.4.0+sdk-1.4.341.0" +name = "symphonia-codec-vorbis" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9571ea910ebd84c86af4b3ed27f9dbdc6ad06f17c5f96146b2b671e2976744f" +checksum = "f025837c309cd69ffef572750b4a2257b59552c5399a5e49707cc5b1b85d1c73" dependencies = [ - "bitflags 2.13.2", + "log", + "symphonia-core", + "symphonia-utils-xiph", ] [[package]] -name = "stable_deref_trait" -version = "1.2.1" +name = "symphonia-core" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ce2be8dc25455e1f91df71bfa12ad37d7af1092ae736f3a6cd0e37bc7810596" +checksum = "ea00cc4f79b7f6bb7ff87eddc065a1066f3a43fe1875979056672c9ef948c2af" +dependencies = [ + "arrayvec", + "bitflags 1.3.2", + "bytemuck", + "lazy_static", + "log", +] [[package]] -name = "stackfuture" -version = "0.3.1" +name = "symphonia-format-isomp4" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "115beb9c69db2393ff10b75a1b8587a51716e5551d015001e55320ed279d32f9" +checksum = "243739585d11f81daf8dac8d9f3d18cc7898f6c09a259675fc364b382c30e0a5" dependencies = [ - "const_panic", + "encoding_rs", + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", ] [[package]] -name = "static_assertions" -version = "1.1.0" +name = "symphonia-format-ogg" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" +checksum = "2b4955c67c1ed3aa8ae8428d04ca8397fbef6a19b2b051e73b5da8b1435639cb" +dependencies = [ + "log", + "symphonia-core", + "symphonia-metadata", + "symphonia-utils-xiph", +] [[package]] -name = "str-buf" -version = "3.0.3" +name = "symphonia-format-riff" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceb97b7225c713c2fd4db0153cb6b3cab244eb37900c3f634ed4d43310d8c34" +checksum = "c2d7c3df0e7d94efb68401d81906eae73c02b40d5ec1a141962c592d0f11a96f" +dependencies = [ + "extended", + "log", + "symphonia-core", + "symphonia-metadata", +] [[package]] -name = "strict-num" -version = "0.1.1" +name = "symphonia-metadata" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6637bab7722d379c8b41ba849228d680cc12d0a45ba1fa2b48f2a30577a06731" +checksum = "36306ff42b9ffe6e5afc99d49e121e0bd62fe79b9db7b9681d48e29fa19e6b16" +dependencies = [ + "encoding_rs", + "lazy_static", + "log", + "symphonia-core", +] [[package]] -name = "subtle" -version = "2.6.1" +name = "symphonia-utils-xiph" +version = "0.5.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" +checksum = "ee27c85ab799a338446b68eec77abf42e1a6f1bb490656e121c6e27bfbab9f16" +dependencies = [ + "symphonia-core", + "symphonia-metadata", +] [[package]] -name = "swash" -version = "0.2.10" +name = "syn" +version = "1.0.109" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c2499c2d826531388872b2268718aed907a39bd785ab0dcfe57fab26283f92e" +checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237" dependencies = [ - "skrifa", - "yazi", - "zeno", + "proc-macro2", + "quote", + "unicode-ident", ] [[package]] @@ -6035,31 +6539,73 @@ dependencies = [ ] [[package]] -name = "sys-locale" -version = "0.3.2" +name = "system-deps" +version = "6.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3e535eb8dded36d55ec13eddacd30dec501792ff23a0b1682c38601b8cf2349" +dependencies = [ + "cfg-expr", + "heck 0.5.0", + "pkg-config", + "toml", + "version-compare", +] + +[[package]] +name = "tao" +version = "0.34.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +checksum = "9103edf55f2da3c82aea4c7fab7c4241032bfeea0e71fa557d98e00e7ce7cc20" dependencies = [ + "bitflags 2.13.2", + "block2", + "core-foundation", + "core-graphics 0.25.0", + "crossbeam-channel", + "dispatch2", + "dlopen2", + "dpi", + "gdkwayland-sys", + "gdkx11-sys", + "gtk", + "jni 0.21.1", "libc", + "log", + "ndk 0.9.0", + "ndk-context", + "ndk-sys 0.6.0+11769913", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "once_cell", + "parking_lot", + "raw-window-handle 0.5.2", + "raw-window-handle 0.6.2", + "tao-macros", + "unicode-segmentation", + "url", + "windows 0.61.3", + "windows-core 0.61.2", + "windows-version", + "x11-dl", ] [[package]] -name = "taffy" -version = "0.14.0" +name = "tao-macros" +version = "0.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "639627c87f43b9181c811f40a6296409e093a17bc761214cba3c15df74f86b99" +checksum = "5f7eeb6d99155545da6150a1795945f16ac9c178deb2a5f2e74d776107bd5849" dependencies = [ - "arrayvec", - "serde", - "slotmap", - "smallvec", + "proc-macro2", + "quote", + "syn 2.0.119", ] [[package]] -name = "tap" -version = "1.0.1" +name = "target-lexicon" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369" +checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" [[package]] name = "tempfile" @@ -6070,10 +6616,30 @@ dependencies = [ "fastrand", "getrandom 0.4.3", "once_cell", - "rustix 1.1.5", + "rustix", "windows-sys 0.61.2", ] +[[package]] +name = "tendril" +version = "0.4.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d24a120c5fc464a3458240ee02c299ebcb9d67b5249c8848b09d639dca8d7bb0" +dependencies = [ + "futf", + "mac", + "utf-8", +] + +[[package]] +name = "termcolor" +version = "1.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06794f8f6c5c898b3275aebefa6b8a1cb24cd2c6c79397ab15774837a0bc5755" +dependencies = [ + "winapi-util", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -6123,6 +6689,20 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "tiff" +version = "0.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b63feaf3343d35b6ca4d50483f94843803b0f51634937cc2ec519fc32232bc52" +dependencies = [ + "fax", + "flate2", + "half", + "quick-error", + "weezl", + "zune-jpeg", +] + [[package]] name = "time" version = "0.3.55" @@ -6153,31 +6733,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "tiny-skia" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "83d13394d44dae3207b52a326c0c85a8bf87f1541f23b0d143811088497b09ab" -dependencies = [ - "arrayref", - "arrayvec", - "bytemuck", - "cfg-if", - "log", - "tiny-skia-path", -] - -[[package]] -name = "tiny-skia-path" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9c9e7fc0c2e86a30b117d0462aa261b72b7a99b7ebd7deb3a14ceda95c5bdc93" -dependencies = [ - "arrayref", - "bytemuck", - "strict-num", -] - [[package]] name = "tinystr" version = "0.8.4" @@ -6185,7 +6740,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" dependencies = [ "displaydoc", - "serde_core", "zerovec", ] @@ -6241,7 +6795,7 @@ dependencies = [ "futures-util", "log", "tokio", - "tungstenite", + "tungstenite 0.30.0", ] [[package]] @@ -6252,7 +6806,9 @@ checksum = "e464cf451ba96ebfc6f9b6542f17ee8b8956e33f1e40d9690624e59d7a7f8a4b" dependencies = [ "bytes", "futures-core", + "futures-io", "futures-sink", + "futures-util", "libc", "pin-project-lite", "tokio", @@ -6260,17 +6816,23 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.8+spec-1.1.0" +version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "20489e00e4d8741d6be680764cc12e270655e375a20d1011e844a9c3379e678d" +checksum = "185d8ab0dfbb35cf1399a6344d8484209c088f75f8f68230da55d48d95d43e3d" dependencies = [ - "indexmap", - "serde_core", + "serde", "serde_spanned", - "toml_datetime", - "toml_parser", - "toml_writer", - "winnow", + "toml_datetime 0.6.3", + "toml_edit 0.20.2", +] + +[[package]] +name = "toml_datetime" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cda73e2f1397b1262d6dfdcef8aafae14d1de7748d66822d3bfeeb6d03e5e4b" +dependencies = [ + "serde", ] [[package]] @@ -6282,6 +6844,30 @@ dependencies = [ "serde_core", ] +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + +[[package]] +name = "toml_edit" +version = "0.20.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "396e4d48bbb2b7554c944bde63101b5ae446cff6ec4a24227428f15eb72ef338" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime 0.6.3", + "winnow 0.5.40", +] + [[package]] name = "toml_edit" version = "0.25.17+spec-1.1.0" @@ -6289,9 +6875,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e3641d5bbb5349a79e1020a242d251efbc546ad8048d133958323ce9c40a9c9c" dependencies = [ "indexmap", - "toml_datetime", + "toml_datetime 1.1.2+spec-1.1.0", "toml_parser", - "winnow", + "winnow 1.0.4", ] [[package]] @@ -6300,15 +6886,9 @@ version = "1.1.5+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baa693a8032d7e1cada7d0041e96126df243179ff061456783ac7f12bda4744c" dependencies = [ - "winnow", + "winnow 1.0.4", ] -[[package]] -name = "toml_writer" -version = "1.1.3+spec-1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06bdbd8cfc056b8d2e2e85f29b56a3bdbecb527cef81eb39e3e7b98af4652770" - [[package]] name = "tower" version = "0.5.3" @@ -6400,15 +6980,13 @@ dependencies = [ ] [[package]] -name = "tracing-oslog" -version = "0.3.0" +name = "tracing-serde" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d76902d2a8d5f9f55a81155c08971734071968c90f2d9bfe645fe700579b2950" +checksum = "704b1aeb7be0d0a84fc9828cae51dab5970fee5088f83d1dd7ee6f6246fc6ff1" dependencies = [ - "cc", - "cfg-if", + "serde", "tracing-core", - "tracing-subscriber", ] [[package]] @@ -6417,38 +6995,36 @@ version = "0.3.23" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7f578e5945fb242538965c2d0b04418d38ec25c79d160cd279bf0731c8d319" dependencies = [ - "matchers", "nu-ansi-term", - "once_cell", - "regex-automata", + "serde", + "serde_json", "sharded-slab", "smallvec", "thread_local", - "tracing", "tracing-core", "tracing-log", + "tracing-serde", ] [[package]] -name = "tracing-wasm" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4575c663a174420fa2d78f4108ff68f65bf2fbb7dd89f33749b6e826b3626e07" -dependencies = [ - "tracing", - "tracing-subscriber", - "wasm-bindgen", -] - -[[package]] -name = "tree_magic_mini" -version = "3.2.2" +name = "tray-icon" +version = "0.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8765b90061cba6c22b5831f675da109ae5561588290f9fa2317adab2714d5a6" +checksum = "a5e85aa143ceb072062fc4d6356c1b520a51d636e7bc8e77ec94be3608e5e80c" dependencies = [ - "memchr", - "nom", - "petgraph", + "crossbeam-channel", + "dirs", + "libappindicator", + "muda", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-core-graphics", + "objc2-foundation", + "once_cell", + "png 0.17.16", + "thiserror 2.0.21", + "windows-sys 0.60.2", ] [[package]] @@ -6465,33 +7041,57 @@ checksum = "d2df906b07856748fa3f6e0ad0cbaa047052d4a7dd609e231c4f72cee8c36f31" [[package]] name = "tungstenite" -version = "0.30.0" +version = "0.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e48ac77174b19c110a50ab2128b24215ac9cb40e0e12e093fb602d175c569d22" +checksum = "eadc29d668c91fcc564941132e17b28a7ceb2f3ebf0b9dae3e03fd7a6748eb0d" dependencies = [ "bytes", + "data-encoding", + "http", + "httparse", "log", - "rand 0.10.3", + "rand 0.9.5", + "sha1", "thiserror 2.0.21", + "utf-8", ] [[package]] -name = "typeid" -version = "1.0.3" +name = "tungstenite" +version = "0.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc7d623258602320d5c55d1bc22793b57daff0ec7efc270ea7d55ce1d5f5471c" +checksum = "8628dcc84e5a09eb3d8423d6cb682965dea9133204e8fb3efee74c2a0c259442" +dependencies = [ + "bytes", + "data-encoding", + "http", + "httparse", + "log", + "native-tls", + "rand 0.9.5", + "rustls", + "sha1", + "thiserror 2.0.21", + "utf-8", +] [[package]] -name = "typenum" -version = "1.20.1" +name = "tungstenite" +version = "0.30.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" +checksum = "e48ac77174b19c110a50ab2128b24215ac9cb40e0e12e093fb602d175c569d22" +dependencies = [ + "bytes", + "log", + "rand 0.10.3", + "thiserror 2.0.21", +] [[package]] -name = "typewit" -version = "1.15.2" +name = "typenum" +version = "1.20.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "214ca0b2191785cbc06209b9ca1861e048e39b5ba33574b3cedd58363d5bb5f6" +checksum = "b6f5e870be6c3b371b77fe0ee0bafb859fa4964b4404c27de1d380043c4dda20" [[package]] name = "ulid" @@ -6543,17 +7143,6 @@ dependencies = [ "subtle", ] -[[package]] -name = "unsynn" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501a7adf1a4bd9951501e5c66621e972ef8874d787628b7f90e64f936ef7ec0a" -dependencies = [ - "mutants", - "proc-macro2", - "rustc-hash 2.1.3", -] - [[package]] name = "untrusted" version = "0.9.0" @@ -6578,9 +7167,9 @@ dependencies = [ [[package]] name = "ureq-proto" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f86fd172ccca569e458f61b6bdd6220965a9ef36e672a6852953b51a0e1583be" +checksum = "841583fc36089d7d59419568ae157f43a5a03a2e5a81ba87c77d1596ef46e922" dependencies = [ "base64 0.23.1", "http", @@ -6600,6 +7189,12 @@ dependencies = [ "serde", ] +[[package]] +name = "utf-8" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9" + [[package]] name = "utf8-zero" version = "0.8.1" @@ -6612,21 +7207,24 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" -[[package]] -name = "utf8parse" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" - [[package]] name = "uuid" version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7cc1186384beb7dd8eedea376413fd654937285ea6c9cfbb928dc3043ea4b606" dependencies = [ - "getrandom 0.4.3", "js-sys", - "serde_core", + "wasm-bindgen", +] + +[[package]] +name = "v_frame" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "666b7727c8875d6ab5db9533418d7c764233ac9c0cff1d469aec8fa127597be2" +dependencies = [ + "aligned-vec", + "num-traits", "wasm-bindgen", ] @@ -6637,14 +7235,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" [[package]] -name = "variadics_please" -version = "2.0.0" +name = "vcpkg" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b53d0f7f2d0182759a549f1f313ce16b07d8f9ba93098157b5fa10ee3e61117f" -dependencies = [ - "quote", - "unsynn", -] +checksum = "accd4ea62f7bb7a82fe23066fb0957d48ef677f6eeb8215f372f52e48bb32426" + +[[package]] +name = "version-compare" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03c2856837ef78f57382f06b2b8563a2f512f7185d732608fd9176cb3b8edf0e" [[package]] name = "version_check" @@ -6671,6 +7271,34 @@ dependencies = [ "try-lock", ] +[[package]] +name = "warnings" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64f68998838dab65727c9b30465595c6f7c953313559371ca8bf31759b3680ad" +dependencies = [ + "pin-project", + "tracing", + "warnings-macro", +] + +[[package]] +name = "warnings-macro" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59195a1db0e95b920366d949ba5e0d3fc0e70b67c09be15ce5abb790106b0571" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "wasi" +version = "0.9.0+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519" + [[package]] name = "wasi" version = "0.11.1+wasi-snapshot-preview1" @@ -6744,9 +7372,9 @@ dependencies = [ [[package]] name = "wasm-streams" -version = "0.5.0" +version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" +checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65" dependencies = [ "futures-util", "js-sys", @@ -6756,100 +7384,16 @@ dependencies = [ ] [[package]] -name = "wayland-backend" -version = "0.3.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38a91b4eaddff87b1cd1074985e3713da4af2c49742d1b356b2c01670a67a078" -dependencies = [ - "cc", - "downcast-rs 1.2.1", - "rustix 1.1.5", - "scoped-tls", - "smallvec", - "wayland-sys", -] - -[[package]] -name = "wayland-client" -version = "0.31.15" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3c36a0f861ad76d0901f2800b46321410d9f73f2ea88aac0650d86c32688073" -dependencies = [ - "bitflags 2.13.2", - "rustix 1.1.5", - "wayland-backend", - "wayland-scanner", -] - -[[package]] -name = "wayland-csd-frame" -version = "0.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625c5029dbd43d25e6aa9615e88b829a5cad13b2819c4ae129fdbb7c31ab4c7e" -dependencies = [ - "bitflags 2.13.2", - "cursor-icon", - "wayland-backend", -] - -[[package]] -name = "wayland-cursor" -version = "0.31.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4a52d18780be9b1314328a3de5f930b73d2200112e3849ca6cb11822793fb34d" -dependencies = [ - "rustix 1.1.5", - "wayland-client", - "xcursor", -] - -[[package]] -name = "wayland-protocols" -version = "0.32.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23d0c813de3daa2ed6520af85a3bd49b0e722a3078506899aa9686fea58dc4b6" -dependencies = [ - "bitflags 2.13.2", - "wayland-backend", - "wayland-client", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-plasma" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2b6d8cf1eb2c1c31ed1f5643c88a6e53538129d4af80030c8cabd1f9fa884d91" -dependencies = [ - "bitflags 2.13.2", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-protocols-wlr" -version = "0.3.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eb04e52f7836d7c7976c78ca0250d61e33873c34156a2a1fc9474828ec268234" -dependencies = [ - "bitflags 2.13.2", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-scanner", -] - -[[package]] -name = "wayland-scanner" -version = "0.31.11" +name = "wasm-streams" +version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "338e30461b3a2b67d70eb30a6d89f8e0c93a833e07d2ae89085cd070c4a00ac0" +checksum = "9d1ec4f6517c9e11ae630e200b2b65d193279042e28edd4a2cda233e46670bbb" dependencies = [ - "proc-macro2", - "quick-xml", - "quote", + "futures-util", + "js-sys", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", ] [[package]] @@ -6860,19 +7404,10 @@ checksum = "d8eab23fefc9e41f8e841df4a9c707e8a8c4ed26e944ef69297184de2785e3be" dependencies = [ "dlib", "log", + "once_cell", "pkg-config", ] -[[package]] -name = "weak-table" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eba2ec791141b0bf4db542f6b038a8f9310cee33e076cb181245780b09a24ff" -dependencies = [ - "cfg-if", - "hashbrown 0.16.1", -] - [[package]] name = "web-sys" version = "0.3.106" @@ -6884,25 +7419,73 @@ dependencies = [ ] [[package]] -name = "web-task" -version = "1.1.3" +name = "web-time" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1cdc136a53ccd64a1211f107ccc34404769fbcc0f165f1afa065f5d88ab93538" +checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" dependencies = [ - "async-task", - "cfg-if", "js-sys", "wasm-bindgen", ] [[package]] -name = "web-time" -version = "1.1.0" +name = "webbrowser" +version = "1.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" +checksum = "62c35be770821a214dbc362fc26908c853e776c0004294d0b10b8a6bad582f94" dependencies = [ - "js-sys", - "wasm-bindgen", + "jni 0.22.4", + "log", + "ndk-context", + "objc2", + "objc2-app-kit", + "objc2-foundation", + "url", + "web-sys", +] + +[[package]] +name = "webkit2gtk" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "76b1bc1e54c581da1e9f179d0b38512ba358fb1af2d634a1affe42e37172361a" +dependencies = [ + "bitflags 1.3.2", + "cairo-rs", + "gdk", + "gdk-sys", + "gio", + "gio-sys", + "glib", + "glib-sys", + "gobject-sys", + "gtk", + "gtk-sys", + "javascriptcore-rs", + "libc", + "once_cell", + "soup3", + "webkit2gtk-sys", +] + +[[package]] +name = "webkit2gtk-sys" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62daa38afc514d1f8f12b8693d30d5993ff77ced33ce30cd04deebc267a6d57c" +dependencies = [ + "bitflags 1.3.2", + "cairo-sys-rs", + "gdk-sys", + "gio-sys", + "glib-sys", + "gobject-sys", + "gtk-sys", + "javascriptcore-rs-sys", + "libc", + "pkg-config", + "soup3-sys", + "system-deps", ] [[package]] @@ -6924,45 +7507,47 @@ dependencies = [ ] [[package]] -name = "wesl" -version = "0.6.0" +name = "webview2-com" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdd8f9619baa4c7bde4df0899d6f626b70ee92d6e9c18c5f74473419b5bb6fa6" +checksum = "7130243a7a5b33c54a444e54842e6a9e133de08b5ad7b5861cd8ed9a6a5bc96a" dependencies = [ - "annotate-snippets", - "anstream", - "derive_more", - "glob", - "half", - "itertools 0.15.0", - "num-traits", - "serde", - "thiserror 2.0.21", - "toml", - "wesl-core", - "wesl-macros", - "wgsl-parse", - "wgsl-types", + "webview2-com-macros", + "webview2-com-sys", + "windows 0.61.3", + "windows-core 0.61.2", + "windows-implement", + "windows-interface", ] [[package]] -name = "wesl-core" -version = "0.1.0" +name = "webview2-com-macros" +version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "84dd3e600497eda0b47afcd21bd84c8953a9dfce7e93ed27a38ba97ac0747e03" +checksum = "67a921c1b6914c367b2b823cd4cde6f96beec77d30a939c8199bb377cf9b9b54" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.119", +] [[package]] -name = "wesl-macros" -version = "0.6.0" +name = "webview2-com-sys" +version = "0.38.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac8767ec26e75262a8e581d5f188b1f63a288baaf885bb33c9f4f73a693e06fc" +checksum = "381336cfffd772377d291702245447a5251a2ffa5bad679c99e61bc48bacbf9c" dependencies = [ - "itertools 0.15.0", - "proc-macro2", - "quote", - "syn 3.0.9", + "thiserror 2.0.21", + "windows 0.61.3", + "windows-core 0.61.2", ] +[[package]] +name = "weezl" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88" + [[package]] name = "wgpu" version = "30.0.1" @@ -6976,12 +7561,18 @@ dependencies = [ "cfg_aliases", "document-features", "hashbrown 0.17.1", + "js-sys", "log", + "naga", + "parking_lot", "portable-atomic", "profiling", - "raw-window-handle", + "raw-window-handle 0.6.2", "smallvec", "static_assertions", + "wasm-bindgen", + "wasm-bindgen-futures", + "web-sys", "wgpu-core", "wgpu-hal", "wgpu-types", @@ -7009,11 +7600,12 @@ dependencies = [ "parking_lot", "portable-atomic", "profiling", - "raw-window-handle", + "raw-window-handle 0.6.2", "rustc-hash 1.1.0", "smallvec", "thiserror 2.0.21", "wgpu-core-deps-apple", + "wgpu-core-deps-emscripten", "wgpu-core-deps-windows-linux-android", "wgpu-hal", "wgpu-naga-bridge", @@ -7029,6 +7621,15 @@ dependencies = [ "wgpu-hal", ] +[[package]] +name = "wgpu-core-deps-emscripten" +version = "30.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d98b86cf4abf524a902dd35f18ca6a3f08fc2ae9847c8f10b48e30491b1f0b86" +dependencies = [ + "wgpu-hal", +] + [[package]] name = "wgpu-core-deps-windows-linux-android" version = "30.0.1" @@ -7049,23 +7650,28 @@ dependencies = [ "ash", "bit-set", "bitflags 2.13.2", - "block2 0.6.2", + "block2", "bytemuck", "cfg-if", "cfg_aliases", + "glow", + "glutin_wgl_sys", "gpu-allocator", "hashbrown 0.17.1", + "js-sys", + "khronos-egl", "libc", - "libloading", + "libloading 0.8.9", "log", "naga", "naga-types", - "objc2 0.6.5", + "ndk-sys 0.6.0+11769913", + "objc2", "objc2-core-foundation", "objc2-core-graphics", - "objc2-foundation 0.3.2", - "objc2-metal 0.3.2", - "objc2-quartz-core 0.3.2", + "objc2-foundation", + "objc2-metal", + "objc2-quartz-core", "once_cell", "ordered-float", "parking_lot", @@ -7073,16 +7679,20 @@ dependencies = [ "portable-atomic-util", "profiling", "range-alloc", - "raw-window-handle", + "raw-window-handle 0.6.2", "raw-window-metal", "renderdoc-sys", "smallvec", "static_assertions", "thiserror 2.0.21", + "wasm-bindgen", + "wayland-sys", + "web-sys", "wgpu-naga-bridge", "wgpu-types", - "windows", - "windows-core", + "windows 0.62.2", + "windows-core 0.62.2", + "windows-result 0.4.1", ] [[package]] @@ -7106,38 +7716,26 @@ dependencies = [ "js-sys", "log", "naga-types", - "raw-window-handle", - "serde", + "raw-window-handle 0.6.2", "static_assertions", "web-sys", ] [[package]] -name = "wgsl-parse" -version = "0.6.0" +name = "winapi" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37cee524ba5cfabfd65d10a316b646f8a4c50f3663e7e787471f21b783261f47" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" dependencies = [ - "annotate-snippets", - "derive_more", - "itertools 0.15.0", - "lalrpop-util", - "lexical", - "logos", - "thiserror 2.0.21", - "wgsl-types", + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", ] [[package]] -name = "wgsl-types" -version = "0.6.0" +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e119dd12e57d937397535201959ddddb5dbf26505402db5ef305ebb1ca9a7e5f" -dependencies = [ - "half", - "itertools 0.15.0", - "num-traits", -] +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" @@ -7148,16 +7746,54 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9252e5725dbed82865af151df558e754e4a3c2c30818359eb17465f1346a1b49" +dependencies = [ + "windows-core 0.54.0", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows" +version = "0.61.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9babd3a767a4c1aef6900409f85f5d53ce2544ccdfaa86dad48c91782c6d6893" +dependencies = [ + "windows-collections 0.2.0", + "windows-core 0.61.2", + "windows-future 0.2.1", + "windows-link 0.1.3", + "windows-numerics 0.2.0", +] + [[package]] name = "windows" version = "0.62.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" dependencies = [ - "windows-collections", - "windows-core", - "windows-future", - "windows-numerics", + "windows-collections 0.3.2", + "windows-core 0.62.2", + "windows-future 0.3.2", + "windows-numerics 0.3.1", +] + +[[package]] +name = "windows-collections" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3beeceb5e5cfd9eb1d76b381630e82c4241ccd0d27f1a39ed41b2760b255c5e8" +dependencies = [ + "windows-core 0.61.2", ] [[package]] @@ -7166,7 +7802,30 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" dependencies = [ - "windows-core", + "windows-core 0.62.2", +] + +[[package]] +name = "windows-core" +version = "0.54.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12661b9c89351d684a50a8a643ce5f608e20243b9fb84687800163429f161d65" +dependencies = [ + "windows-result 0.1.2", + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-core" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0fdd3ddb90610c7638aa2b3a3ab2904fb9e5cdbecc643ddb3647212781c4ae3" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link 0.1.3", + "windows-result 0.3.4", + "windows-strings 0.4.2", ] [[package]] @@ -7177,9 +7836,20 @@ checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" dependencies = [ "windows-implement", "windows-interface", - "windows-link", - "windows-result", - "windows-strings", + "windows-link 0.2.1", + "windows-result 0.4.1", + "windows-strings 0.5.1", +] + +[[package]] +name = "windows-future" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc6a41e98427b19fe4b73c550f060b59fa592d7d686537eebf9385621bfbad8e" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", + "windows-threading 0.1.0", ] [[package]] @@ -7188,9 +7858,9 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" dependencies = [ - "windows-core", - "windows-link", - "windows-threading", + "windows-core 0.62.2", + "windows-link 0.2.1", + "windows-threading 0.2.1", ] [[package]] @@ -7215,20 +7885,54 @@ dependencies = [ "syn 2.0.119", ] +[[package]] +name = "windows-link" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e6ad25900d524eaabdbbb96d20b4311e1e7ae1699af4fb28c17ae66c80d798a" + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9150af68066c4c5c07ddc0ce30421554771e528bde427614c61038bc2c92c2b1" +dependencies = [ + "windows-core 0.61.2", + "windows-link 0.1.3", +] + [[package]] name = "windows-numerics" version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" dependencies = [ - "windows-core", - "windows-link", + "windows-core 0.62.2", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-result" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5e383302e8ec8515204254685643de10811af0ed97ea37210dc26fb0032647f8" +dependencies = [ + "windows-targets 0.52.6", +] + +[[package]] +name = "windows-result" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56f42bd332cc6c8eac5af113fc0c1fd6a8fd2aa08a0119358686e5160d0586c6" +dependencies = [ + "windows-link 0.1.3", ] [[package]] @@ -7237,7 +7941,16 @@ version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" dependencies = [ - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-strings" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56e6c93f3a0c3b36176cb1327a4958a0353d5d166c2a35cb268ace15e91d3b57" +dependencies = [ + "windows-link 0.1.3", ] [[package]] @@ -7246,7 +7959,16 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" dependencies = [ - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets 0.42.2", ] [[package]] @@ -7282,7 +8004,22 @@ version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm 0.42.2", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm 0.42.2", + "windows_x86_64_msvc 0.42.2", ] [[package]] @@ -7307,7 +8044,7 @@ version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" dependencies = [ - "windows-link", + "windows-link 0.2.1", "windows_aarch64_gnullvm 0.53.1", "windows_aarch64_msvc 0.53.1", "windows_i686_gnu 0.53.1", @@ -7318,15 +8055,39 @@ dependencies = [ "windows_x86_64_msvc 0.53.1", ] +[[package]] +name = "windows-threading" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b66463ad2e0ea3bbf808b7f1d371311c80e115c0b71d60efc142cafbcfb057a6" +dependencies = [ + "windows-link 0.1.3", +] + [[package]] name = "windows-threading" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" dependencies = [ - "windows-link", + "windows-link 0.2.1", +] + +[[package]] +name = "windows-version" +version = "0.1.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4060a1da109b9d0326b7262c8e12c84df67cc0dbc9e33cf49e01ccc2eb63631" +dependencies = [ + "windows-link 0.2.1", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_gnullvm" version = "0.52.6" @@ -7339,6 +8100,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_aarch64_msvc" version = "0.52.6" @@ -7351,6 +8118,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_gnu" version = "0.52.6" @@ -7375,6 +8148,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_i686_msvc" version = "0.52.6" @@ -7387,6 +8166,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + [[package]] name = "windows_x86_64_gnu" version = "0.52.6" @@ -7399,6 +8184,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_gnullvm" version = "0.52.6" @@ -7411,6 +8202,12 @@ version = "0.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "windows_x86_64_msvc" version = "0.52.6" @@ -7424,55 +8221,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" [[package]] -name = "winit" -version = "0.30.13" +name = "winnow" +version = "0.5.40" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a6755fa58a9f8350bd1e472d4c3fcc25f824ec358933bba33306d0b63df5978d" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" dependencies = [ - "ahash", - "android-activity", - "atomic-waker", - "bitflags 2.13.2", - "block2 0.5.1", - "bytemuck", - "calloop", - "cfg_aliases", - "concurrent-queue", - "core-foundation 0.9.4", - "core-graphics", - "cursor-icon", - "dpi", - "js-sys", - "libc", - "memmap2", - "ndk", - "objc2 0.5.3", - "objc2-app-kit 0.2.2", - "objc2-foundation 0.2.2", - "objc2-ui-kit", - "orbclient", - "percent-encoding", - "pin-project", - "raw-window-handle", - "redox_syscall 0.4.1", - "rustix 0.38.44", - "sctk-adwaita", - "smithay-client-toolkit", - "smol_str", - "tracing", - "unicode-segmentation", - "wasm-bindgen", - "wasm-bindgen-futures", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-protocols-plasma", - "web-sys", - "web-time", - "windows-sys 0.52.0", - "x11-dl", - "x11rb", - "xkbcommon-dl", + "memchr", +] + +[[package]] +name = "winnow" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df79d97927682d2fd8adb29682d1140b343be4ac0f08fd68b7765d9c059d3945" +dependencies = [ + "memchr", ] [[package]] @@ -7491,36 +8254,62 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] -name = "wl-clipboard-rs" -version = "0.9.4" +name = "writeable" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" + +[[package]] +name = "wry" +version = "0.53.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4d7888ccd4896447b2d14d3a9350a85df2aeb6f181e2e7a31349d104ac46cac1" +checksum = "728b7d4c8ec8d81cab295e0b5b8a4c263c0d41a785fb8f8c4df284e5411140a2" dependencies = [ + "base64 0.22.1", + "block2", + "cookie", + "crossbeam-channel", + "dirs", + "dpi", + "dunce", + "gtk", + "html5ever", + "http", + "javascriptcore-rs", + "jni 0.21.1", + "kuchikiki", "libc", - "log", - "os_pipe", - "rustix 1.1.5", + "ndk 0.9.0", + "objc2", + "objc2-app-kit", + "objc2-core-foundation", + "objc2-foundation", + "objc2-ui-kit", + "objc2-web-kit", + "once_cell", + "percent-encoding", + "raw-window-handle 0.6.2", + "sha2 0.10.9", + "soup3", + "tao-macros", "thiserror 2.0.21", - "tree_magic_mini", - "wayland-backend", - "wayland-client", - "wayland-protocols", - "wayland-protocols-wlr", + "url", + "webkit2gtk", + "webkit2gtk-sys", + "webview2-com", + "windows 0.61.3", + "windows-core 0.61.2", + "windows-version", ] [[package]] -name = "writeable" -version = "0.6.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" - -[[package]] -name = "wyz" -version = "0.5.1" +name = "x11" +version = "2.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed" +checksum = "502da5464ccd04011667b11c435cb992822c2c0dbde1770c988480d312a0db2e" dependencies = [ - "tap", + "libc", + "pkg-config", ] [[package]] @@ -7540,12 +8329,8 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9993aa5be5a26815fe2c3eacfc1fde061fc1a1f094bf1ad2a18bf9c495dd7414" dependencies = [ - "as-raw-xcb-connection", "gethostname", - "libc", - "libloading", - "once_cell", - "rustix 1.1.5", + "rustix", "x11rb-protocol", ] @@ -7555,25 +8340,6 @@ version = "0.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ea6fc2961e4ef194dcbfe56bb845534d0dc8098940c7e5c012a258bfec6701bd" -[[package]] -name = "xcursor" -version = "0.3.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "163b33ed8786455e2fa5d72f554057ce3f3182425434f756cd39c99839d88e23" - -[[package]] -name = "xkbcommon-dl" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d039de8032a9a8856a6be89cea3e5d12fdd82306ab7c94d74e6deab2460651c5" -dependencies = [ - "bitflags 2.13.2", - "dlib", - "log", - "once_cell", - "xkeysym", -] - [[package]] name = "xkeysym" version = "0.2.1" @@ -7587,27 +8353,22 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2f45bb2c13fec6a6cb4c0f76a7e94839e110a14ec803ec2940777a94c347bc52" [[package]] -name = "xxhash-rust" -version = "0.8.19" +name = "xml-rs" +version = "0.8.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "550a2b930b62486a393c52d5c3b84bff264b28aa437ed64694d31e93b1757af7" +checksum = "e450f9b2ed1dff33c94c12589a87338689467b9c4f5d8a5710bd09a847d2c8a7" [[package]] -name = "yazi" -version = "0.2.1" +name = "xxhash-rust" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e01738255b5a16e78bbb83e7fbba0a1e7dd506905cfc53f4622d89015a03fbb5" +checksum = "550a2b930b62486a393c52d5c3b84bff264b28aa437ed64694d31e93b1757af7" [[package]] -name = "yeslogic-fontconfig-sys" -version = "6.0.1" +name = "y4m" +version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d8b8abf912b9a29ff112e1671c97c33636903d13a69712037190e6805af4f76" -dependencies = [ - "dlib", - "once_cell", - "pkg-config", -] +checksum = "7a5a4b21e1a62b67a2970e6831bc091d7b87e119e7f9791aef9702e3bef04448" [[package]] name = "yoke" @@ -7632,12 +8393,6 @@ dependencies = [ "synstructure", ] -[[package]] -name = "zeno" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6df3dc4292935e51816d896edcd52aa30bc297907c26167fec31e2b0c6a32524" - [[package]] name = "zerocopy" version = "0.8.62" @@ -7694,7 +8449,6 @@ dependencies = [ "displaydoc", "yoke", "zerofrom", - "zerovec", ] [[package]] @@ -7703,7 +8457,6 @@ version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" dependencies = [ - "serde", "yoke", "zerofrom", "zerovec-derive", @@ -7759,3 +8512,27 @@ dependencies = [ "cc", "pkg-config", ] + +[[package]] +name = "zune-core" +version = "0.5.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56377fd46368984a170bc5aac5567e52ca5da874caa60bea39fcbca78fb658b" + +[[package]] +name = "zune-inflate" +version = "0.2.54" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73ab332fe2f6680068f3582b16a24f90ad7096d5d39b974d1c0aff0125116f02" +dependencies = [ + "simd-adler32", +] + +[[package]] +name = "zune-jpeg" +version = "0.5.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27bc9d5b815bc103f142aa054f561d9187d191692ec7c2d1e2b4737f8dbd7296" +dependencies = [ + "zune-core", +] diff --git a/Cargo.toml b/Cargo.toml index d733df50..e08e7cd5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,47 +1,5 @@ -[package] -name = "anend" -version = "0.1.0" -edition = "2024" -description = "anend notes: a desktop markdown note app, grown out of the anend blog server" -license-file = "LICENSE" -publish = false - +# anend: the core (the entry graph, models), the hub (the server: the sharing site and the +# web app's API) and the app (Dioxus: the desktop app, and the web app from the same code) [workspace] -members = ["core", "hub"] - -[dependencies] -anend-core = { path = "core" } -bevy = { version = "0.20", default-features = false, features = [ - "std", - "multi_threaded", - "default_app", - "ui_api", - "ui_bevy_render", - "scene", - "picking", - "bevy_ui_widgets", - "bevy_feathers", - "bevy_winit", - "bevy_clipboard", - "default_font", - "custom_cursor", - "x11", - "wayland", - "system_font_discovery", - "bevy_pbr", - "bevy_light", -] } -bevy_slugtext = { git = "https://github.com/SaulDoesCode/bevy_slugtext", rev = "1cfb7d5" } -ttf-parser = "0.25" -fontique = "0.11" -chrono = "0.4" -redb = "4.3" -serde = { version = "1", features = ["derive"] } -serde_json = "1" -# the window icon; the same winit bevy_winit uses -winit = { version = "0.30", default-features = false } -pulldown-cmark = { version = "0.13", default-features = false } - -ureq = { version = "3", default-features = false, features = ["rustls"] } - - +members = ["core", "hub", "app", "render"] +resolver = "3" diff --git a/README.md b/README.md index 524d44fb..b79d601d 100644 --- a/README.md +++ b/README.md @@ -1,348 +1,258 @@ # anend -anend started out as a Go blog server: posts ("writs") in ArangoDB, magic-link email -logins, and a sand-coloured admin panel for writing markdown. Both halves are Rust now. +anend is a memory palace for short texts. You type a word or phrase and it is stored as +an entry with its gematria sums. You find it again by its numbers, its words, its tags or +the lists it's in, and you can fly through your memories laid out in space. It +continues [weum](docs/weum-reference/README.md), whose numbers it reproduces exactly. -**anend notes** is its Rust successor: a desktop markdown note app with no server. It -keeps the admin panel's look and workflow, and is built with -[Bevy 0.20](https://bevy.org)'s feathers widgets. Notes are stored locally in an -embedded [redb](https://www.redb.org) (4.3) database, and you can keep several of them -as saves and swap between them like a game's. +It comes as: -**anend hub** is what became of the server: a self-hosted place to share saves, the way a -game has a workshop or a mod hub. People join, share their saves, star and download each -other's, and earn points, levels and badges when others use what they made; the app -browses and shares straight from its settings. See [the hub](#the-hub). - -**New here?** [The guide](docs/guide.md) explains what anend is and how to use every part -of it, in the desktop app and the web app (a hub serves it at `/guide` too). - -![the editor](docs/editor.png) -![the reader](docs/reader.png) -![the memory view](docs/memory.png) -![the space](docs/space.png) -![the settings](docs/settings.png) -![the night colours](docs/night.png) - -## Using it +- **the app** (`app/`, [Dioxus](https://dioxuslabs.com)): a desktop app, and the same + app built to WebAssembly for the browser; +- **the hub** (`hub/`, [Salvo](https://salvo.rs)): a self-hosted server that runs the app + for its members and serves it at `/app/`, and a place to share saves, like a game's + workshop; +- **the core** (`core/`): what both share. That includes the entry graph store, gematria, + the app's API, and a deterministic transformer engine for classifiers and generators. | | | |---|---| -| **editor** | the note list (with **+ new**) next to the editor card. The first `# line` is the note's title, the rest is markdown. **‹** (or **Ctrl+B**) slides the list away to the left; it peeks back out while the pointer is at the left edge. | -| **tags** | type a tag in the box at the top of the card and press Enter (or `,`); click a tag to remove it | -| **view / edit** | switch between the markdown source and the rendered note | -| **reader** | your notes, newest first, the way the old front page listed writs; click a `#tag` to filter | -| **stats** | counts of notes, words, saves and tags | -| **memory** | weum's memory view: short texts ("memories") and your notes, searched by gematria or by words | -| **command bar** | the line at the bottom, one for every view (see below) | -| **space** | weum's spatial memory (remem): fly through a room where memory texts float, laid out by their sums. **Ctrl+right click** a text and the search line in the top bar ends with its triangle: sides s (ordinal), r (reversed) and ⌊√(s·r)⌋, drawn small, with its angles (or "don't close" when the three can't make one) | -| **lists** | every list in the save, side by side: its members (× takes one out), its figures (members, the sums of the whole list, its means, its gsum and pfR chain), its 26 letter frequencies drawn as a vector, and a grid of how alike every two lists are (the cosine of those vectors, as if each list were an entry in a learning system). Type in the bar and press Enter to put the text into the chosen list, or start a new one | -| **settings** | saves, fonts, colours, sizes, zen mode and the bars: the top bar and the command bar can swap places, and the note list can sit on the right (also **Ctrl+,**); the key remap menu is in there too (also **K**, or **Ctrl+K** in the space) | - -Shortcuts: **Ctrl+S** save, **Ctrl+N** new note, **Ctrl+E** toggle view/edit, **Ctrl+B** the note list, -**Ctrl+1..6** editor / reader / memory / stats / space / lists, **Ctrl+,** settings, **/** the -command bar. All of them can be changed in **keys**. - -Unsaved changes (marked `•` in the list) are saved when you switch notes or close the -window. A note needs a `# title` before it can be saved. - -## The command bar - -There's one place to type, the bar at the bottom, and it does what the view you're in -needs. Its name at the left says which; each view keeps its own text, so switching views -doesn't lose what you typed. - -| view | the bar | at its right | -|---|---|---| -| editor, reader, stats | finds notes: the list (and the reader) narrow to notes with words starting with what you type; Enter opens the first | how many notes match | -| memory | weum's term bar (below) | the sidecar of the term's sums, the buckets, the toggles | -| space | the space's terminal (below) | the terminal's sums and the chips | - -**/** goes to the bar, **Escape** leaves it. - -## Saves and settings - -Every database is a save. **settings** lists the saves in your saves folder, the open one -first and then the most recently used, each with its notes, memories, date and size: -**load** one (the open note is saved first), start a **new save** by name, **copy**, -**rename** (the open one too) or **delete** one (not the open one, and only after a -second click). The folder box changes the saves folder; a path ending in `.redb` there -opens (or starts) that file instead. The app comes back to the save you had open. - -Also in settings: +| ![memory](app/docs/shots/desktop-memory-menu.png) | ![space](app/docs/shots/desktop-space.png) | +| the memory view, with its menu | the space | +| ![buckets](app/docs/shots/desktop-memory-buckets.png) | ![notes](app/docs/shots/desktop-notes.png) | +| sums as buckets | notes | +| ![reader at night](app/docs/shots/desktop-reader-night.png) | ![a list in the browser](app/docs/shots/web-list.png) | +| the reader, night colours | a list's page (web) | +| ![stats](app/docs/shots/web-stats.png) | ![filters](app/docs/shots/web-filters.png) | +| stats (web) | filters (web) | +| ![a chain](app/docs/shots/web-space-chain.png) | ![a bent block](app/docs/shots/web-block-bend.png) | +| a chain of texts under its title (web) | a block bent by a ripple and a fold (web) | +| ![textures](app/docs/shots/web-textures-room.png) | ![lights](app/docs/shots/web-lights.png) | +| a texture recipe on a block, a colour on one face, a sky (web) | blocks and spheres under baked lights (web) | +| ![the spec builder](app/docs/shots/spec-builder.png) | ![a staging zone](app/docs/shots/web-zone.png) | +| a spec model in the builder | texts spreading inside a staging zone (web) | +| ![switches, a gate and a lamp](app/docs/shots/web-gates-lit.png) | ![the prefabs window](app/docs/shots/desktop-prefabs.png) | +| two switches through an AND gate light a lamp, while the room plays (web) | a copy of a prefab selected, with its menu (desktop) | +| ![superflight](app/docs/shots/web-superflight.png) | ![placing by hand](app/docs/shots/web-ghost-red.png) | +| superflight: the texts flown through, ready to become an entry (web) | placing a prefab by hand: red where it would overlap (web) | +| ![an s program asking a classifier](app/docs/shots/web-s-learn.png) | ![the step debugger](app/docs/shots/web-s-editor.png) | +| an s program asking a classifier, its output beside each line (web) | an s program in the editor (web) | + +## The views + +**Ctrl+1 … Ctrl+9** switch views, **Ctrl+,** opens settings, and **Esc** closes things. +Every view has the command bar at the bottom, and each view keeps its own text there. | | | |---|---| -| **fonts** | the interface font (every text in the app, the space's floating texts too) and the memory view's font, from the fonts on your system; filter the list by typing | -| **zen** | while the mouse rests the bars and panels fade away (after 1, 2.5, 5 or 10 seconds); typing in the editor doesn't bring them back, moving the mouse does | -| **colours** | every colour the app uses has a name (window, bars, bar text, cards, writing pad, buttons, accent, text, links, code, the space's room...): pick one and set it with the hue, saturation and lightness sliders or a hex. **sand** (the old admin panel's), **night**, **paper** and **sea** are starting points; **reset** puts one colour back. The memory view keeps weum's own colours | -| **sizes** | the whole interface's scale, and the top bar's and command bar's heights in pixels, the way a desktop panel is set; their text and buttons are sized to fit | -| **hide the top bar** | it slides up out of the way and back down when the pointer comes to the top edge | -| **slide the note list away** | the same as **Ctrl+B**: it stays away until the pointer comes to the left edge | -| **the space's search line** | in the space, what was searched, its counts and its sum's prime factor chain sit in the top bar (fading with it under zen); this turns that off | - -**hub**, in settings, under the saves: give it a hub's address and an app token (made on -your page on the hub) and connect. Browse the hub's saves (search, and sort by new, stars, -downloads or featured) and **download** one: it's checked, then lands in your saves -folder, ready to load. **Share this save** sends the open one with a name, description and -tags. The app only ever talks to the hub you give it, on a background thread. - -These settings and your key bindings live in `config.json` in the platform config folder -(`~/.config/anend` on Linux, `~/Library/Application Support/anend` on macOS, -`%APPDATA%\anend` on Windows), not in a save, so they stay the same whichever save is -open. `ANEND_CONFIG` points it somewhere else. - -## Memory and gsearch - -The memory view is weum's `memory.html`, without the browser. Type in the command bar; -the sidecar at its right shows the term's four gsearch keys: - -| bucket | measure | -|---|---| -| ordinal | a=1 .. z=26 | -| reversed | a=26 .. z=1 | -| atbash | every letter swapped for its mirror in its alphabet, `n + 1 − v`: a=26 .. z=1 for Latin (the reversed value), α=24 .. ω=1 for Greek, א=22 .. ת=1 for Hebrew | -| frequency | the letter frequency table, so anagrams share a bucket (shown as the sorted letters, `eilnst`) | +| **memory** (Ctrl+1) | weum's memory view. **Enter** on text gsearches its sum and saves it when it's new. **Enter** on a number gsearches that bucket. **Ctrl+Enter** saves, **Shift+Enter** shows a key, **Delete** forgets. `Enlist` `List` `Delist` `Unlist` work on lists. **r / o / f** pick the bucket (reversed, ordinal, frequency), and **← →** gsearch the term's sums. Hover shows the gsum line, and texts that share a sum are underlined in its colour. The circles at the left edge are the buckets. **Shift+click** (or Alt+click, or a box dragged on the field) selects several texts to put in a list or tag; **Ctrl+Shift+click** picks the list. Right-click opens the menu: edit, tag, select, list, candidate, key, forget. | +| **space** (Ctrl+2) | memory texts floating in a room, laid out by their sums. On the desktop the room is Rust, drawn with [wgpu](https://wgpu.rs) with no JavaScript (`render/`; under the page on Linux, shown in it on macOS and Windows); on the web it is [three.js](https://threejs.org) for now. Clicking a text puts its triangle in the top bar: sides s (ordinal), r (reversed) and ⌊√(s·r)⌋. The arrow keys glide to the nearest text in that direction, and its card opens on the right. It's also where you build: copies that inherit, have their own text or are detached; each placement's size; chains of texts that hang under their title; saved scenes, combined with overlaps settled; and blocks showing texts, pictures, colours or texture recipes (cropped, tiled, tinted, with variants; on a whole block or one face), which move, resize, turn and bend or become spheres; a sky; lights baked onto the blocks; and staging zones whose texts spread among themselves. Blocks act on each other: each can listen for clicks, other blocks' rays, texts entering its zone, timers or signals, run an s program, cast a ray, play keyframe animations and sounds; blocks group into prefabs placed as copies, and starter prefabs (a switch, logic gates, a lamp, a door) show it working. Shift+click or a box selects many things at once to move, turn or delete together. Besides flying you can walk (V: gravity, collisions, run, sneak, crouch, lean, mantle), swing on a grapple (G), place prefabs by hand where you look, and superflight (B) through texts to collect them, in order, into an entry, a chain or a list. | +| **lists** (Ctrl+3) | every list as a tile. A list's page has an editable name and members, and figures for the whole list: its sums, means, gsum and pfR chain. | +| **reader** (Ctrl+4) | everything that matches, in pages. Short texts appear as a tiny grid, and notes appear as markdown. Besides its own three views (everything, notes, texts), it shows views written as s programs: a pipe or a search, an order, headings, a layout and pipes' effects. | +| **notes** (Ctrl+5) | markdown notes, in a list by date, with tags and a read mode. A note can be attached to any entry. Typing stays quick in a note of any length. A note tagged `s` is a program in s (below), and the notes view is its code editor. | +| **tags** (Ctrl+6) | tags on any entry: pick tags (all or any) and see the entries that have them. | +| **stats** (Ctrl+7) | figures for the whole save | +| **models** (Ctrl+8) | classifiers (learned from lists, trained and run here) and spec models: models described as data (what they read, their heads, what they learn from, critics for a writer), made in a builder with a control for every part or as JSON, then trained, run and, for a writer, asked to write. Tag sets are word types of your own (a language's, a conlang checker's right and wrong), learned from words you mark. Taxonomies put classifiers in a tree: each answer picks the next classifier, and every step can be marked right or wrong, which each node counts and its classifier learns from. | +| **filters** (Ctrl+9) | words, a sum range, written between two dates, a tag, a kind. Each filter is kept by name in the save. It's also the pipe editor: a filter with effects (a colour, a classifier's colours, an underline, a label, a size, a glow, gathering in the space) shown in the memory view and the space while it's on, stacked with other pipes, and actions (a list, a tag, a program on each) done when asked. | + +The top bar holds the view icons, the search line with its triangle, undo (**Ctrl+Z**) and +settings. **Ctrl+= / Ctrl+−** zoom and **0** resets it. + +**Settings** are a dialog with folding sections: +- colours (palettes, or your own) and the text size; +- the memory view's sizes and spacing, and the space's room colour; +- zen: the bars fade while you rest, and the top bar can hide until the pointer reaches + the top edge; +- keys, and the hub (a hub's address, to browse and share); +- saves: open, new, copy, delete, **backup**, and **import from weum**. + +## Programs + +A save can be scripted in s, the project's own language ([docs/s.md](docs/s.md)). A program +is a note tagged `s`: its title names it, its body is the code. The notes view is its +editor: the text stands right-aligned (each line's acting word at the right), coloured by +kind of word, with an outline, Ctrl+click to a definition, completion, ▶ to run it with each +line's output beside it, and a step debugger showing the stack and the values. + +A program reaches the rest of the save through two library modules of anend's own. With +`std/anend.s.`, `op` calls any of the app's ops ([docs/app-api.md](docs/app-api.md)) and +`json`, `#json` and `obj` read and build their JSON. With `std/learn.s.`, classifiers and +models are words whose answers are s values: -**Term bar** +``` +std/learn.s. +{c is the top class, c/p its probability} // +{things} {a ripe mango} class +{~c~ (~c/p~)} > +{found lists what the search finds} // +{mango} search +found all {, } l/ +{found: ~all~} > +``` + +With the "things" starter classifier made under the name `things`, that prints +`fruit, stones and animals: fruit (0.888…)` and the texts with "mango" in them. + +Programs run from the notes view, from the bar anywhere (`Run [arguments]`, the +output as a toast), from blocks in the space (a block's wiring runs a program when it's +clicked, hit by a ray or signalled), and from a shell with `anend-app run` (below). On a +shared hub a run takes at most 2 million steps, and the hub's limits apply to what it asks. + +## The taxonomy engine + +The classifiers are meant to work together rather than one at a time +([docs/architecture.md](docs/architecture.md)): + +- **Taxonomies** put classifiers in a tree: each answer decides which classifier reads the + text next ("English or not?" before "which kind of thing?"). Every step of a routing can + be marked right or wrong; each node counts its marks beside its classifier's held-out + accuracy, and every mark teaches that classifier. +- **Pipes** take the texts a filter lets through (words, sums, lists, tags, what + classifiers say) and give them effects: a colour, a classifier's class colours, an + underline, a label, a size, a glow, gathering in the space. Turned on, a pipe's effects + show in the memory view and the space, stacked with other pipes'; nothing is written + onto the texts. Its actions (a list, a tag, a program on each) run when asked. +- **Views are programs:** an s program that loads `std/view.s.` says where a view's texts + come from (a pipe, or a search), their order, headings and layout, and the reader shows + it beside its own views, which are presets of the same thing. +- **Tag sets** are word types of your own, learned from words you mark: a language's (a + set can claim the texts a language classifier picks out), or a checker for a language of + your own that flags wrong words with the nearest right ones. | | | |---|---| -| Enter on a number | gsearch it in the current bucket, under its prime factor reduction line (weum's `pfR`, numbers clickable) | -| Enter on text | gsearch the text's key in the current bucket and show the text itself, saving it as a memory when it's new. With gsearch-typed-text off (**G**): an ordinary word search over every variation weum's search tries (case, plurals, suffixes) | -| Ctrl+Enter | gsearch the text and save it | -| Shift+Enter | show the item under a key (`3,4`, or `note:1000001`) | -| Delete | forget the memory under the key typed | -| `Enlist` `List` `Delist` `Unlist` | list commands, using the list and candidate picked below | -| Escape | leave the term bar so the single keys work (**/** goes back) | - -**Results**: click puts a text in the term bar, double-click its key, Ctrl+click picks it -as list candidate, Shift+click as the list, Ctrl+right-click forgets it and saves it again -under a new key, middle-click opens a note. Hovering shows weum's gsum line (sums, -difference, vowels, consonants, words, atbash). - -**Underlines**: a text that shares its reversed sum with any other text is underlined in -a colour taken from its reversed sum (all its matches share the hue) and ordinal sum (the -shade). Texts alone with their reversed sum get none. - -**Single keys** (outside text boxes): **O** / **R** / **A** / **F** pick the bucket (**R** -again goes back to ordinal), **←** **→** **↑** **↓** gsearch the term's ordinal / -reversed / atbash / letters, **G** gsearch typed text, **S** save searches as memories, -**W** white mode. The buckets and toggles also sit at the bar's right, to click. - -To bring weum's memories over, back them up there (`memory.backup` writes -`all-of-it.json`) and run +| ![a taxonomy](app/docs/shots/desktop-taxonomy.png) | ![a pipe's effects in the space](app/docs/shots/desktop-pipes-space.png) | +| a taxonomy: English or not, then which kind of thing; marks per node (desktop) | a pipe's colour, label, size and gathering in the space (desktop) | +| ![a view program](app/docs/shots/web-view-program.png) | ![a tag set](app/docs/shots/web-tagset.png) | +| a view of one's own in the reader: a pipe's texts as a list (web) | an Afrikaans tag set, learned from marked words (web) | -```sh -anend --import-weum all-of-it.json -``` +## Saves -They keep their keys, and new memories continue weum's key allocation (one byte keys, -then two, three and four, reusing forgotten ones). Images and embedding search (esearch) -from weum aren't part of the app. - -## The space - -The space is remem (kuis), weum's spatial memory, as a view of the app. Memory texts -float in a warm room as camera-facing billboards, drawn as GPU vector text with -[bevy_slugtext](https://github.com/SaulDoesCode/bevy_slugtext). A gsearch pulls its -bucket's memories in and spread lays them out in front of you: each bucket (texts with -the same reversed sum, or ordinal with **reversed** on) clusters on an Archimedean spiral -by its sum, deeper the higher the sum, with texts repelling each other (more so when one -isn't the other's atbash). Texts sharing a bucket are underlined in its colour. - -**Flying**: hold the right mouse button to look, **W A S D** move, **Space** / **C** up and -down, **Q** / **E** roll, **Shift** fast, **[** **]** or the wheel over empty space change -the speed, **R** levels the horizon, **Home** goes back to the start. - -**Texts**: drag one to move it (a spread text you move stays pinned, **U** toggles that), -the wheel on a text pushes it away or pulls it near, click puts its text in the terminal, -double click edits it (a memory text: its key into the terminal), double click on empty -space or **N** makes a new text, **Enter** edits the selected one, **Delete** removes it, -**Ctrl+C** copies it, **Ctrl+Z** undoes (a forget too). Ctrl+click picks a list candidate, -Shift+click the list, Ctrl+right click gsearches ⌊√(s·r)⌋. Hovering shows its metrics -card: s, r, their sums, product, roots and differences, vowels, consonants, words, its -key and bucket, every number gsearching itself. - -**Terminal**, the command bar in the space (**/**, or **Enter** with nothing selected; it -says "editing" while you edit a text in it): a number gsearches that bucket, -text gsearches its sum (with **gsearch** off, searches its words), **Ctrl+Enter** -saturates the text and gsearches its sum, **Shift+Enter** recalls a key, **Delete** -forgets the key typed, **↑** **↓** walk the history, **Esc** goes back to flying. `#123`, -`#r123` and `#name` go to an ordinal bucket, a reversed one or a saved map. The words -`Enlist` `List` `Delist` `Unlist` `Count` `Backup` `Clear` `ClearAll` `Settle` `Maps` and -`Save name` are commands. The chips at its right: **gsearch**, **reversed** (**F**), -**saturate** (searches save new texts) and **keep** (new results join the spread instead -of replacing it). - -**More keys**: **O** the spread's sliders, **P** pauses the physics, **K** settles it now, -**←** **→** gsearch the terminal's sums, **X** exports every text to a JSON file in your -Downloads, **Shift+X** saves the map in the database (**Maps** lists them), **H** help, -**I** the position card. Every key can be remapped in **keys**. weum's esearch, speech -and image memories aren't part of it. - -## Downloads - -Builds for Linux and Windows are on the repository's -[releases page](https://github.com/SaulDoesCode/anend/releases), each with the app -(`anend`) and the hub (`anend-hub`). On Linux the app needs the Wayland or X11 -libraries a desktop already has. - -They're made by GitHub Actions (`.github/workflows/release.yml`). To make a release, tag a -commit and push the tag: +A save is one file, an entry graph in [redb](https://www.redb.org). Every text, note, +tag, list and setting is an entry with timestamps. Lists and tags are edges between +entries. Identical texts are stored once, and an entry can borrow another's text. +[docs/format.md](docs/format.md) describes the format. The desktop keeps saves in +`<data dir>/anend/saves/` (`~/.local/share/anend/saves` on Linux), and starts with `main`. -```sh -git tag v0.2.0 -git push origin v0.2.0 -``` +**Backup** writes `texts.json` (every text) and `other.json` (everything else) into the +save's `backups/` folder. **Import from weum** reads weum's `all-of-it.json` (made by +`memory.backup` in weum), and the texts keep their keys. Saves from older anend versions +aren't read. -The workflow builds both on Linux and Windows and attaches a `.tar.gz` and a -`.zip` to a new release named after the tag, with notes listing the merged pull requests. -**Run workflow** on the repository's Actions tab (release) builds the same packages as -downloadable artifacts without making a release. `.github/workflows/ci.yml` checks -formatting, clippy and the tests of both on every push to master and every pull request. +There's no limit on how long a text can be: one over 64 KiB is stored in pieces, and the +views show long texts piece by piece. The limits a save does set (how much a call reads, +the spelling check's size, and so on) are its own settings, under "limits of this save". -## Building +Gematria modes are **ordinal** (a=1 … z=26), **reversed** (a=26 … z=1) and **frequency** +(the letters sorted, so anagrams share a bucket). Byte sums (bytes valued 1–256) are a +separate measure, in `core/src/measure.rs`. -```sh -cargo run --release -``` +## Building and running -Bevy 0.20 needs Rust 1.97.1 or newer. On Linux you also need the usual Bevy system -packages, e.g. on Debian/Ubuntu: `libwayland-dev libxkbcommon-dev libfontconfig1-dev` (plus -`libxkbcommon-x11-0` at runtime on X11). The memory view uses a system serif font -(Times New Roman, or whatever serif fontconfig offers). +```sh +# the desktop app (Linux needs libwebkit2gtk-4.1-dev, libxdo-dev and libasound2-dev) +cargo run --release -p anend-app -The tokenizer, the gematria sums and the frequency table have AVX2 kernels picked at -runtime on x86_64, with scalar fallbacks elsewhere. +# the app for the browser: needs the wasm32-unknown-unknown target and wasm-bindgen-cli 0.2.129 +app/web/build.sh # writes app/web/dist -## Data +# a hub on your own machine: no logins, the app at http://127.0.0.1:8080/app/ +cargo run --release -p anend-hub -- --local -A save holds the notes, the memories, the search tables and the space's maps and -settings. Saves go in the saves folder, by default the platform data directory -(`~/.local/share/anend` on Linux, `~/Library/Application Support/anend` on macOS, -`%APPDATA%\anend` on Windows), starting with `notes.redb`; settings can move it. -`--db <file>` opens a particular save for one run. +# an s program on a save, headless: a file, or the save's program (a note tagged s) by +# title; stdin, when it isn't a terminal, is read to its end as the program's stdin +# (give it </dev/null when there's none); its output comes out, and its exit code +cargo run --release -p anend-app -- run tally --save ~/.local/share/anend/saves/main.redb +``` -To bring writs over from the old server, export the `writs` collection (for example -`arangoexport --collection writs --type json`) and import it: +On Linux the app turns off WebKitGTK's DMA-BUF renderer, which leaves a white window +("Failed to create GBM buffer") on some drivers. If the window is still blank, try +`WEBKIT_DISABLE_COMPOSITING_MODE=1 anend-app`. To keep DMA-BUF on, set +`WEBKIT_DISABLE_DMABUF_RENDERER=0`. -```sh -anend --import writs.json -``` +Build the web app before the hub, so the hub can serve it at `/app/`. Without it, +`/app/` shows a page saying to run `app/web/build.sh`. -This keeps their keys, titles, markdown, tags, dates and edit history. +Before a change goes in, run the checks: `cargo fmt --all --check`, +`cargo clippy --workspace --all-targets -- -D warnings`, `cargo test --workspace`, and the +wasm build (`cargo build -p anend-app --target wasm32-unknown-unknown +--no-default-features --features web`). `.github/workflows/ci.yml` runs the same +checks, and `release.yml` builds the desktop app and the hub (with the web app inside) +for Linux and Windows when a `v*` tag is pushed. ## The hub ![the hub](docs/hub.png) -`anend-hub` (in `hub/`, built with [Salvo](https://salvo.rs)) is a website and an API for -sharing saves. Start one and make yourself its admin: - ```sh cargo run --release -p anend-hub -- --admin yourname ``` -It prints a login link (good once, within an hour); open it and set a password on your -page. The hub listens on `127.0.0.1:8080` and keeps everything in `./hub-data`: its own -redb database (people, sessions, saves' details, stars) and the save files in -`hub-data/saves/`. Back it up by copying the folder while the hub is stopped. - -**What's in it** - -| | | -|---|---| -| **the grid** | every shared save as a card, headed by its name's ordinal and reversed sums in a colour taken from them; search by words, author or `#tag`, sort by new, stars, downloads or featured | -| **a save's page** | its description and tags, some of its memories with their sums, its notes' titles, stars, downloads, and the download | -| **joining** | name and password (email optional). By default it's an application an admin answers; `--open` lets people straight in | -| **sharing** | upload a `.redb` save with a name, description and tags. The hub opens its own copy to check it's a save the app made (a copy of an open save is fine) and reads its counts and memories. It waits for an admin unless you're trusted; a new version keeps its stars and downloads | -| **the game** | points when others use what you share: 50 when a save is let in, 5 a star, 1 for each person who downloads it, 100 when it's featured, and 1 for each save you star. Levels go seeker, reader, scribe, counter, cipherer, numerologist, gematrian, archivist, palace keeper, sage; badges for milestones (first save, prolific, beloved, well read, library, memory palace, curator, founder...). Stars and downloads count once per person, and your own don't count | -| **people** | a page each, with level, badges, saves and a bio; the leaderboard ranks them, and the most starred saves | -| **admin** | saves waiting (let in, or turn down with a reason), people applying, everyone (member, trusted (no review), admin, ban, make a login link), and every save (approve, turn down, feature, remove) | -| **app tokens** | made on your page and pasted into the app (settings → hub), which uses them to share (see [the API](docs/hub-api.md)) | - -**Options**: `--addr` where it listens, `--url` the address people reach it at (for login -links, and https cookies when it starts with `https://`), `--data` its folder, `--name` and -`--about` what it calls itself, `--open`, `--max-upload` in MB (64), `--quota` in MB (1024: how much disk each member's saves in the web app may fill; 0 for no limit), `--behind-proxy` to -trust `X-Forwarded-For`, `--no-ratelimit`, `--local` (below), and `--tls-cert` / -`--tls-key` (PEM files) to speak https itself. Those two can also be set on -**admin → server settings**, a page that only opens from the machine the hub runs on; they -take effect at the next start. Without them it speaks plain http, and a reverse proxy -(Caddy, nginx) can do the https. - -### The app in a browser - -The hub is also the app's daemon: **/app/** is the app as a web page (plain HTML, CSS and -JavaScript in `hub/web/`, built into the binary, with [three.js](https://threejs.org) for the -space), talking to the hub over a WebSocket (`/app/ws`, falling back to `POST -/app/api/{op}`). It has the desktop app's views: the editor, reader, stats, the memory -view, the space (the texts as crisp CSS3D labels in a WebGL room, the search line with its -triangle), lists, and settings with saves (download and upload too), the forge, the hub -and colours. Each person who logs in gets their own workspace of saves in -`hub-data/users/<name>/saves`. - -```sh -cargo run --release -p anend-hub -- --local # just you: no logins, one workspace -``` - -**Offline**: the same files work from any static web server (`python3 -m http.server -d -hub/web`, a static host) with no hub at all. When no hub answers at load, the page runs the -app's calls itself in JavaScript (`hub/web/local/`, the same results as the hub's down to -the last bit; `node hub/web/test/parity.mjs` checks it against a live `--local` hub) and -keeps its saves in the browser's IndexedDB. Only then: a page a hub serves always works on -the hub. A save moves between the two as a bundle, a JSON file with every key kept -(settings → export bundle, then import bundle on the other side). - -`--local` is for running it on your own machine; on a shared hub people log in and the -app is theirs. The calls are listed in [the app API](docs/app-api.md), so anything that -speaks WebSocket or JSON can drive a save. To keep it running as a service, -`hub/anend-hub.service` is a systemd unit (its comments say where to put things). - -Passwords are hashed with argon2; sessions and tokens are random and stored only as -hashes; forms posted from other sites are refused; logins, joins and uploads are limited -per address. +This prints a one-time login link. The hub keeps everything in `./hub-data`, and listens +on `127.0.0.1:8080`. +- **`--mode`** picks what it serves: + - `hub`: the sharing site; + - `app`: the web app for members, each with their own saves; + - `both`: both, the default. +- **`--join`** sets how people get in: `invite`, `apply` or `open`. +- **Visibility:** each save is private, unlisted or public. + +Members share saves, star and download each other's, and earn points, levels and badges +when others use what they made. The admin panel reviews saves and people. +[docs/deploy.md](docs/deploy.md) covers running one for real: modes, joining, TLS, +backups, Docker, and running it as a paid service. [docs/security.md](docs/security.md) +covers the security model. + +The web app and the desktop make the same calls ([the app API](docs/app-api.md)), over +a WebSocket at `/app/ws` or `POST /app/api/{op}`. Anything that speaks JSON can drive +a save. [docs/hub-api.md](docs/hub-api.md) covers the sharing API. + +## Models + +`core/src/classify` is a transformer engine written from scratch: RMSNorm, SwiGLU, RoPE, +grouped key/value heads. The same inputs give the same output bits on any machine and +thread count. Models are described by a declarative spec ([docs/models.md](docs/models.md)): +- **inputs:** bytes, numbers, pictures, and optionally gematria channels (off unless you + choose them); +- **heads:** classify, regress, and generate; +- **data queries**, and **critics:** classifiers that steer generation, by reranking, + guidance or reinforcement. + +**Pretrained models:** Llama-family checkpoints (Llama, Mistral, Qwen2/3, SmolLM) load +from safetensors and a `tokenizer.json`. Use `"from": {"pretrained": "<dir>"}` in a spec, +or see `core/examples/pretrained.rs`. + +**The GPU:** a backend (wgpu, the cargo feature `gpu`, on in the desktop app and the hub) +trains and reads texts on the GPU. Classifiers read on it (trying, search, indexing, +buckets, colouring, filters) with every text's windows packed into a few submissions; +the settings' GPU section picks auto, the CPU, the GPU or the GPU fast. In exact +precision it gives the CPU's bits on a device whose kernels the probe finds exact (this +was checked on a software GPU, llvmpipe, only). **write a GPU report** in the settings +(`gpu.report`) writes a JSON file about your GPU: the adapter, driver, limits, the probe +of every kernel, and training and reading timings next to the CPU. +`core/examples/gpu_bench.rs` measures larger models. + +**Starter classifiers** (`core/src/starters.rs`) have texts whose classes are known for +certain (made by rules, or public-domain books), so each is scored on held-out texts: +`cargo run --release -p anend-core --example starters` prints the table. + +[core/src/classify/STATUS.md](core/src/classify/STATUS.md) has the details and what's +measured. ## Layout -| file | what | +| | | |---|---| -| `core/` | `anend-core`, what the app and the hub share: the note model, redb storage, markdown, the SIMD sums, the memory tables, weum, the spread layout and the triangle, list figures, the forge | -| `src/main.rs` | startup, command line, window | -| `src/lists_ui.rs` | the lists view | -| `src/ui.rs` | the interface: layout scenes, actions, rebuild systems, markdown rendering | -| `src/theme.rs` | the sand palette from `admin.css` as a feathers theme | -| `core/src/note.rs` | the note model, title/body splitting, dates | -| `core/src/store.rs` | redb storage | -| `core/src/markdown.rs` | markdown to styled text blocks | -| `core/src/simd.rs` | AVX2 tokenizer, gematria dual sum (ordinal, reversed, atbash) and letter frequencies | -| `core/src/memory.rs` | the memory and search tables: weum's allocator, token index, the four gsearch buckets, lists | -| `core/src/weum.rs` | ports of memory.js helpers: pfR, the gsum line, the search variations | -| `src/memory_ui.rs` | the memory view | -| `src/keys.rs` | actions, bindings and the remap logic | -| `core/src/fmath.rs` | sin, cos and hypot the same on every machine and in the browser | -| `core/src/bundle.rs` | a save as JSON, keys and all | -| `core/src/spread.rs` | spread.js: the layout of memory texts by their sums, checked step by step against the original | -| `src/space.rs` | the space: flying, the texts as slug billboards, picking, the terminal's memory commands, maps | -| `src/space_ui.rs` | the space's panels: position line, help, metrics, sliders, search line | -| `src/bar.rs` | the command bar every view shares | -| `src/settings.rs` | the settings menu and the saves: load, new, copy, rename, delete | -| `src/config.rs` | the settings file | -| `src/typeface.rs` | swapping the interface font and the memory view's font | -| `src/zen.rs` | zen's fade, the hiding top bar and the sliding note list | -| `src/palette.rs` | the colours the settings change, and repainting the interface with them | -| `src/sizing.rs` | the interface scale and the bars' heights | -| `src/hub.rs` | talking to a hub: its API, downloads, uploads | -| `src/hub_ui.rs` | the hub section of the settings | -| `hub/src/main.rs` | the hub: command line and routes | -| `hub/src/hub.rs` | taking uploads in, finding saves, stars, downloads, reviews | -| `hub/src/store.rs` | the hub's redb tables | -| `hub/src/inspect.rs` | reading an uploaded save | -| `hub/src/game.rs` | points, levels and badges | -| `hub/src/auth.rs` | passwords, sessions, tokens, login links, rate limits | -| `hub/src/web.rs`, `hub/templates/` | the pages | -| `hub/src/api.rs` | the JSON API | -| `hub/src/app.rs` | the app's calls on a workspace of saves (the daemon) | -| `hub/src/appweb.rs` | the web app's files, its WebSocket and posts, moving saves in and out | -| `hub/src/server.rs`, `hub/templates/server.html` | the https settings page | -| `hub/web/` | the web app: `app.js` (routes, bars, keys), `api.js` (the socket), `space.js` (three.js), `views/` | +| `core/src/graph/` | the entry graph store: records, the 5-bit codec with references and calls, posting lists, edges, queries | +| `core/src/ops/` | the app API over a save and a folder of saves, merge and forge, shared by the desktop and the hub | +| `core/src/classify/` | the transformer engine, the spec, generation, pretrained import, the GPU backend | +| `core/src/measure.rs` | byte sums | +| `app/src/` | the Dioxus app: `shell.rs` (bars, keys, menu), `views/`, `backend/` (`local.rs` the graph in-process, `hub.rs` the WebSocket), `gem.rs` (weum's numbers), `native.rs` (the room's picture under the page on Linux), `picture.rs` (in the page on macOS and Windows), `space.js` (the three.js room on the web) | +| `render/` | the room in Rust (`anend-render`): the wgpu renderer, the room itself (`room.rs`, `room/`: the spread, building, wires, sounds, walking), blocks and their tiles | +| `app/web/` | the web build: `build.sh`, the page, its loader | +| `hub/src/` | the hub: modes, accounts, saves, sharing, the game, the app's API (`app.rs`, `appweb.rs`) | +| `docs/` | the formats, the APIs, deployment, security, models, and `next.md` (the plan and status) | +| `docs/weum-reference/` | weum's own code, the reference for its numbers | + +[docs/guide.md](docs/guide.md) is the guide for people using the app: every view, the +command bar, lists, classifiers and spec models, settings and the hub. diff --git a/app/Cargo.toml b/app/Cargo.toml new file mode 100644 index 00000000..cb2f7e32 --- /dev/null +++ b/app/Cargo.toml @@ -0,0 +1,50 @@ +[package] +name = "anend-app" +version = "0.1.0" +edition = "2024" +description = "anend's app in Rust with Dioxus: the desktop app and, from the same code, the web app" +license-file = "../LICENSE" +publish = false + +[[bin]] +name = "anend-app" +path = "src/main.rs" + +[features] +default = ["desktop", "hub"] +# the desktop app: the system webview (wry), the saves on disk through anend-core's Store +desktop = ["dioxus/desktop", "dep:tokio", "dep:png", "dep:ureq", "anend-core/gpu", "anend-core/fetch", "dep:anend-render", "dep:gtk", "dep:cpal", "dep:symphonia"] +# the web app: WebAssembly in the browser, talking to the hub's app API over a WebSocket +web = ["dioxus/web", "dep:wasm-bindgen", "dep:web-sys", "dep:js-sys", "dep:wasm-bindgen-futures", "dep:anend-render"] +# the hub's settings (its address, the app token); leave out for a hub-free build +hub = [] + +[dependencies] +anend-core = { path = "../core" } +dioxus = { version = "=0.7.10", default-features = false, features = ["launch", "lib"] } +serde = { version = "1", features = ["derive"] } +serde_json = "1" +futures-channel = "0.3" +futures-util = { version = "0.3", default-features = false, features = ["std"] } +chrono = "0.4" +pulldown-cmark = { version = "0.13", default-features = false, features = ["html"] } +redb = "4.3" +# the space drawn natively (wgpu), on the desktop +anend-render = { path = "../render", optional = true } +# the native space's sounds: decoded with symphonia, mixed on cpal's output +cpal = { version = "0.15", optional = true } +symphonia = { version = "0.5", optional = true, default-features = false, features = ["wav", "pcm", "ogg", "vorbis", "flac", "mp3", "isomp4", "aac"] } + +tokio = { version = "1", features = ["rt", "time"], optional = true } +png = { version = "0.17", optional = true } +ureq = { version = "3", default-features = false, features = ["rustls"], optional = true } + +wasm-bindgen = { version = "=0.2.129", optional = true } +wasm-bindgen-futures = { version = "0.4", optional = true } +js-sys = { version = "0.3", optional = true } +web-sys = { version = "0.3", optional = true, features = ["WebSocket", "MessageEvent", "Window", "Storage", "Location", "CloseEvent", "BinaryType", "Document", "Element", "HtmlCanvasElement", "Navigator", "console"] } + +# the native space's drawing area under the webview (Linux: GTK, as tao and wry use) +[target.'cfg(target_os = "linux")'.dependencies] +gtk = { version = "0.18", optional = true } + diff --git a/app/docs/shots/anims.png b/app/docs/shots/anims.png new file mode 100644 index 00000000..3daccbd0 Binary files /dev/null and b/app/docs/shots/anims.png differ diff --git a/app/docs/shots/desktop-bar-stable.png b/app/docs/shots/desktop-bar-stable.png new file mode 100644 index 00000000..603d7e6f Binary files /dev/null and b/app/docs/shots/desktop-bar-stable.png differ diff --git a/app/docs/shots/desktop-bar-widths.png b/app/docs/shots/desktop-bar-widths.png new file mode 100644 index 00000000..544f3af3 Binary files /dev/null and b/app/docs/shots/desktop-bar-widths.png differ diff --git a/app/docs/shots/desktop-block-bend.png b/app/docs/shots/desktop-block-bend.png new file mode 100644 index 00000000..25744d42 Binary files /dev/null and b/app/docs/shots/desktop-block-bend.png differ diff --git a/app/docs/shots/desktop-block-menu.png b/app/docs/shots/desktop-block-menu.png new file mode 100644 index 00000000..dea56a46 Binary files /dev/null and b/app/docs/shots/desktop-block-menu.png differ diff --git a/app/docs/shots/desktop-copy-menu.png b/app/docs/shots/desktop-copy-menu.png new file mode 100644 index 00000000..9f1eb8d5 Binary files /dev/null and b/app/docs/shots/desktop-copy-menu.png differ diff --git a/app/docs/shots/desktop-editor-alternatives.png b/app/docs/shots/desktop-editor-alternatives.png new file mode 100644 index 00000000..6189c334 Binary files /dev/null and b/app/docs/shots/desktop-editor-alternatives.png differ diff --git a/app/docs/shots/desktop-filter.png b/app/docs/shots/desktop-filter.png new file mode 100644 index 00000000..c4df3328 Binary files /dev/null and b/app/docs/shots/desktop-filter.png differ diff --git a/app/docs/shots/desktop-gates.png b/app/docs/shots/desktop-gates.png new file mode 100644 index 00000000..5342435b Binary files /dev/null and b/app/docs/shots/desktop-gates.png differ diff --git a/app/docs/shots/desktop-ghost.png b/app/docs/shots/desktop-ghost.png new file mode 100644 index 00000000..9d8cc10b Binary files /dev/null and b/app/docs/shots/desktop-ghost.png differ diff --git a/app/docs/shots/desktop-gpu-report.png b/app/docs/shots/desktop-gpu-report.png new file mode 100644 index 00000000..c548ea8c Binary files /dev/null and b/app/docs/shots/desktop-gpu-report.png differ diff --git a/app/docs/shots/desktop-group.png b/app/docs/shots/desktop-group.png new file mode 100644 index 00000000..3ab07487 Binary files /dev/null and b/app/docs/shots/desktop-group.png differ diff --git a/app/docs/shots/desktop-help-walking.png b/app/docs/shots/desktop-help-walking.png new file mode 100644 index 00000000..a9eb5232 Binary files /dev/null and b/app/docs/shots/desktop-help-walking.png differ diff --git a/app/docs/shots/desktop-memory-buckets.png b/app/docs/shots/desktop-memory-buckets.png new file mode 100644 index 00000000..f087fbda Binary files /dev/null and b/app/docs/shots/desktop-memory-buckets.png differ diff --git a/app/docs/shots/desktop-memory-frame.png b/app/docs/shots/desktop-memory-frame.png new file mode 100644 index 00000000..0ecb42bd Binary files /dev/null and b/app/docs/shots/desktop-memory-frame.png differ diff --git a/app/docs/shots/desktop-memory-hover-types.png b/app/docs/shots/desktop-memory-hover-types.png new file mode 100644 index 00000000..5a04a0df Binary files /dev/null and b/app/docs/shots/desktop-memory-hover-types.png differ diff --git a/app/docs/shots/desktop-memory-long-open.png b/app/docs/shots/desktop-memory-long-open.png new file mode 100644 index 00000000..7b134afb Binary files /dev/null and b/app/docs/shots/desktop-memory-long-open.png differ diff --git a/app/docs/shots/desktop-memory-long-piece.png b/app/docs/shots/desktop-memory-long-piece.png new file mode 100644 index 00000000..13074d39 Binary files /dev/null and b/app/docs/shots/desktop-memory-long-piece.png differ diff --git a/app/docs/shots/desktop-memory-menu.png b/app/docs/shots/desktop-memory-menu.png new file mode 100644 index 00000000..8fd72b0e Binary files /dev/null and b/app/docs/shots/desktop-memory-menu.png differ diff --git a/app/docs/shots/desktop-memory-types-and-underlines.png b/app/docs/shots/desktop-memory-types-and-underlines.png new file mode 100644 index 00000000..e0481af9 Binary files /dev/null and b/app/docs/shots/desktop-memory-types-and-underlines.png differ diff --git a/app/docs/shots/desktop-memory-word-types.png b/app/docs/shots/desktop-memory-word-types.png new file mode 100644 index 00000000..584b26cf Binary files /dev/null and b/app/docs/shots/desktop-memory-word-types.png differ diff --git a/app/docs/shots/desktop-models-trained.png b/app/docs/shots/desktop-models-trained.png new file mode 100644 index 00000000..335b756b Binary files /dev/null and b/app/docs/shots/desktop-models-trained.png differ diff --git a/app/docs/shots/desktop-models-try.png b/app/docs/shots/desktop-models-try.png new file mode 100644 index 00000000..064b7025 Binary files /dev/null and b/app/docs/shots/desktop-models-try.png differ diff --git a/app/docs/shots/desktop-native-space.png b/app/docs/shots/desktop-native-space.png new file mode 100644 index 00000000..c01d2596 Binary files /dev/null and b/app/docs/shots/desktop-native-space.png differ diff --git a/app/docs/shots/desktop-native-texts.png b/app/docs/shots/desktop-native-texts.png new file mode 100644 index 00000000..7e9823cc Binary files /dev/null and b/app/docs/shots/desktop-native-texts.png differ diff --git a/app/docs/shots/desktop-notes-highlight.png b/app/docs/shots/desktop-notes-highlight.png new file mode 100644 index 00000000..7778f56c Binary files /dev/null and b/app/docs/shots/desktop-notes-highlight.png differ diff --git a/app/docs/shots/desktop-notes-segments.png b/app/docs/shots/desktop-notes-segments.png new file mode 100644 index 00000000..ba7702ff Binary files /dev/null and b/app/docs/shots/desktop-notes-segments.png differ diff --git a/app/docs/shots/desktop-notes-spelling.png b/app/docs/shots/desktop-notes-spelling.png new file mode 100644 index 00000000..6d03eeeb Binary files /dev/null and b/app/docs/shots/desktop-notes-spelling.png differ diff --git a/app/docs/shots/desktop-notes.png b/app/docs/shots/desktop-notes.png new file mode 100644 index 00000000..07430024 Binary files /dev/null and b/app/docs/shots/desktop-notes.png differ diff --git a/app/docs/shots/desktop-pictures.png b/app/docs/shots/desktop-pictures.png new file mode 100644 index 00000000..19ffa836 Binary files /dev/null and b/app/docs/shots/desktop-pictures.png differ diff --git a/app/docs/shots/desktop-pipes-memory.png b/app/docs/shots/desktop-pipes-memory.png new file mode 100644 index 00000000..6739f2a7 Binary files /dev/null and b/app/docs/shots/desktop-pipes-memory.png differ diff --git a/app/docs/shots/desktop-pipes-space.png b/app/docs/shots/desktop-pipes-space.png new file mode 100644 index 00000000..ee424433 Binary files /dev/null and b/app/docs/shots/desktop-pipes-space.png differ diff --git a/app/docs/shots/desktop-prefabs-before.png b/app/docs/shots/desktop-prefabs-before.png new file mode 100644 index 00000000..0944b8a3 Binary files /dev/null and b/app/docs/shots/desktop-prefabs-before.png differ diff --git a/app/docs/shots/desktop-prefabs.png b/app/docs/shots/desktop-prefabs.png new file mode 100644 index 00000000..d2712484 Binary files /dev/null and b/app/docs/shots/desktop-prefabs.png differ diff --git a/app/docs/shots/desktop-reader-night.png b/app/docs/shots/desktop-reader-night.png new file mode 100644 index 00000000..c764efa3 Binary files /dev/null and b/app/docs/shots/desktop-reader-night.png differ diff --git a/app/docs/shots/desktop-run-bar.png b/app/docs/shots/desktop-run-bar.png new file mode 100644 index 00000000..d034ca3b Binary files /dev/null and b/app/docs/shots/desktop-run-bar.png differ diff --git a/app/docs/shots/desktop-s-editor.png b/app/docs/shots/desktop-s-editor.png new file mode 100644 index 00000000..5de67323 Binary files /dev/null and b/app/docs/shots/desktop-s-editor.png differ diff --git a/app/docs/shots/desktop-s-learn.png b/app/docs/shots/desktop-s-learn.png new file mode 100644 index 00000000..2238e8c3 Binary files /dev/null and b/app/docs/shots/desktop-s-learn.png differ diff --git a/app/docs/shots/desktop-s-run.png b/app/docs/shots/desktop-s-run.png new file mode 100644 index 00000000..6fe4c1cc Binary files /dev/null and b/app/docs/shots/desktop-s-run.png differ diff --git a/app/docs/shots/desktop-scenes-combine.png b/app/docs/shots/desktop-scenes-combine.png new file mode 100644 index 00000000..1f41907f Binary files /dev/null and b/app/docs/shots/desktop-scenes-combine.png differ diff --git a/app/docs/shots/desktop-scenes-combined.png b/app/docs/shots/desktop-scenes-combined.png new file mode 100644 index 00000000..d655ebee Binary files /dev/null and b/app/docs/shots/desktop-scenes-combined.png differ diff --git a/app/docs/shots/desktop-scenes-migrated.png b/app/docs/shots/desktop-scenes-migrated.png new file mode 100644 index 00000000..096b84e0 Binary files /dev/null and b/app/docs/shots/desktop-scenes-migrated.png differ diff --git a/app/docs/shots/desktop-search-gpu.png b/app/docs/shots/desktop-search-gpu.png new file mode 100644 index 00000000..e4c5f721 Binary files /dev/null and b/app/docs/shots/desktop-search-gpu.png differ diff --git a/app/docs/shots/desktop-select-many.png b/app/docs/shots/desktop-select-many.png new file mode 100644 index 00000000..d2c25006 Binary files /dev/null and b/app/docs/shots/desktop-select-many.png differ diff --git a/app/docs/shots/desktop-settings-gpu-speed.png b/app/docs/shots/desktop-settings-gpu-speed.png new file mode 100644 index 00000000..0fa4d858 Binary files /dev/null and b/app/docs/shots/desktop-settings-gpu-speed.png differ diff --git a/app/docs/shots/desktop-settings-gpu.png b/app/docs/shots/desktop-settings-gpu.png new file mode 100644 index 00000000..5a0c808a Binary files /dev/null and b/app/docs/shots/desktop-settings-gpu.png differ diff --git a/app/docs/shots/desktop-settings-hsl.png b/app/docs/shots/desktop-settings-hsl.png new file mode 100644 index 00000000..0c9a47b5 Binary files /dev/null and b/app/docs/shots/desktop-settings-hsl.png differ diff --git a/app/docs/shots/desktop-settings-limits.png b/app/docs/shots/desktop-settings-limits.png new file mode 100644 index 00000000..360a1b2e Binary files /dev/null and b/app/docs/shots/desktop-settings-limits.png differ diff --git a/app/docs/shots/desktop-sounds.png b/app/docs/shots/desktop-sounds.png new file mode 100644 index 00000000..ee6725ab Binary files /dev/null and b/app/docs/shots/desktop-sounds.png differ diff --git a/app/docs/shots/desktop-space-blocks.png b/app/docs/shots/desktop-space-blocks.png new file mode 100644 index 00000000..7f04f7c4 Binary files /dev/null and b/app/docs/shots/desktop-space-blocks.png differ diff --git a/app/docs/shots/desktop-space-chain.png b/app/docs/shots/desktop-space-chain.png new file mode 100644 index 00000000..f0024c2f Binary files /dev/null and b/app/docs/shots/desktop-space-chain.png differ diff --git a/app/docs/shots/desktop-space-copy-menu.png b/app/docs/shots/desktop-space-copy-menu.png new file mode 100644 index 00000000..6112f9d9 Binary files /dev/null and b/app/docs/shots/desktop-space-copy-menu.png differ diff --git a/app/docs/shots/desktop-space-inherit.png b/app/docs/shots/desktop-space-inherit.png new file mode 100644 index 00000000..da1ed098 Binary files /dev/null and b/app/docs/shots/desktop-space-inherit.png differ diff --git a/app/docs/shots/desktop-space-onebar.png b/app/docs/shots/desktop-space-onebar.png new file mode 100644 index 00000000..5bf4f9b1 Binary files /dev/null and b/app/docs/shots/desktop-space-onebar.png differ diff --git a/app/docs/shots/desktop-space-physics.png b/app/docs/shots/desktop-space-physics.png new file mode 100644 index 00000000..296f7b89 Binary files /dev/null and b/app/docs/shots/desktop-space-physics.png differ diff --git a/app/docs/shots/desktop-space-size-saved.png b/app/docs/shots/desktop-space-size-saved.png new file mode 100644 index 00000000..5f5cf4dd Binary files /dev/null and b/app/docs/shots/desktop-space-size-saved.png differ diff --git a/app/docs/shots/desktop-space-size.png b/app/docs/shots/desktop-space-size.png new file mode 100644 index 00000000..06cb8c84 Binary files /dev/null and b/app/docs/shots/desktop-space-size.png differ diff --git a/app/docs/shots/desktop-space.png b/app/docs/shots/desktop-space.png new file mode 100644 index 00000000..72f46a74 Binary files /dev/null and b/app/docs/shots/desktop-space.png differ diff --git a/app/docs/shots/desktop-specs-device.png b/app/docs/shots/desktop-specs-device.png new file mode 100644 index 00000000..eeb3a41c Binary files /dev/null and b/app/docs/shots/desktop-specs-device.png differ diff --git a/app/docs/shots/desktop-specs-error.png b/app/docs/shots/desktop-specs-error.png new file mode 100644 index 00000000..f33e0618 Binary files /dev/null and b/app/docs/shots/desktop-specs-error.png differ diff --git a/app/docs/shots/desktop-specs-trained.png b/app/docs/shots/desktop-specs-trained.png new file mode 100644 index 00000000..12ea6619 Binary files /dev/null and b/app/docs/shots/desktop-specs-trained.png differ diff --git a/app/docs/shots/desktop-specs-write.png b/app/docs/shots/desktop-specs-write.png new file mode 100644 index 00000000..326a9fc2 Binary files /dev/null and b/app/docs/shots/desktop-specs-write.png differ diff --git a/app/docs/shots/desktop-starter-held-out.png b/app/docs/shots/desktop-starter-held-out.png new file mode 100644 index 00000000..6e2c2c1c Binary files /dev/null and b/app/docs/shots/desktop-starter-held-out.png differ diff --git a/app/docs/shots/desktop-starters.png b/app/docs/shots/desktop-starters.png new file mode 100644 index 00000000..c044c84e Binary files /dev/null and b/app/docs/shots/desktop-starters.png differ diff --git a/app/docs/shots/desktop-tagset-checker.png b/app/docs/shots/desktop-tagset-checker.png new file mode 100644 index 00000000..408827e0 Binary files /dev/null and b/app/docs/shots/desktop-tagset-checker.png differ diff --git a/app/docs/shots/desktop-taxonomy.png b/app/docs/shots/desktop-taxonomy.png new file mode 100644 index 00000000..8002b5a7 Binary files /dev/null and b/app/docs/shots/desktop-taxonomy.png differ diff --git a/app/docs/shots/desktop-view-program.png b/app/docs/shots/desktop-view-program.png new file mode 100644 index 00000000..6e3bdaf2 Binary files /dev/null and b/app/docs/shots/desktop-view-program.png differ diff --git a/app/docs/shots/desktop-walking.png b/app/docs/shots/desktop-walking.png new file mode 100644 index 00000000..f85fc81a Binary files /dev/null and b/app/docs/shots/desktop-walking.png differ diff --git a/app/docs/shots/desktop-wire-drag.png b/app/docs/shots/desktop-wire-drag.png new file mode 100644 index 00000000..f4f8d6cb Binary files /dev/null and b/app/docs/shots/desktop-wire-drag.png differ diff --git a/app/docs/shots/desktop-wiring.png b/app/docs/shots/desktop-wiring.png new file mode 100644 index 00000000..2a2fbcc2 Binary files /dev/null and b/app/docs/shots/desktop-wiring.png differ diff --git a/app/docs/shots/lights.png b/app/docs/shots/lights.png new file mode 100644 index 00000000..300ebb6f Binary files /dev/null and b/app/docs/shots/lights.png differ diff --git a/app/docs/shots/native-default.png b/app/docs/shots/native-default.png new file mode 100644 index 00000000..6aa5cacd Binary files /dev/null and b/app/docs/shots/native-default.png differ diff --git a/app/docs/shots/native-gizmo.png b/app/docs/shots/native-gizmo.png new file mode 100644 index 00000000..9d8b2410 Binary files /dev/null and b/app/docs/shots/native-gizmo.png differ diff --git a/app/docs/shots/native-lights.png b/app/docs/shots/native-lights.png new file mode 100644 index 00000000..cb4e6f3d Binary files /dev/null and b/app/docs/shots/native-lights.png differ diff --git a/app/docs/shots/native-picture-path.png b/app/docs/shots/native-picture-path.png new file mode 100644 index 00000000..324e686a Binary files /dev/null and b/app/docs/shots/native-picture-path.png differ diff --git a/app/docs/shots/native-prefab-thumbs.png b/app/docs/shots/native-prefab-thumbs.png new file mode 100644 index 00000000..d71096cc Binary files /dev/null and b/app/docs/shots/native-prefab-thumbs.png differ diff --git a/app/docs/shots/native-sky.png b/app/docs/shots/native-sky.png new file mode 100644 index 00000000..effbe170 Binary files /dev/null and b/app/docs/shots/native-sky.png differ diff --git a/app/docs/shots/native-texture-previews.png b/app/docs/shots/native-texture-previews.png new file mode 100644 index 00000000..ae4f848f Binary files /dev/null and b/app/docs/shots/native-texture-previews.png differ diff --git a/app/docs/shots/native-wires.png b/app/docs/shots/native-wires.png new file mode 100644 index 00000000..98c4b657 Binary files /dev/null and b/app/docs/shots/native-wires.png differ diff --git a/app/docs/shots/native-zone.png b/app/docs/shots/native-zone.png new file mode 100644 index 00000000..08d1818e Binary files /dev/null and b/app/docs/shots/native-zone.png differ diff --git a/app/docs/shots/polish-lists.png b/app/docs/shots/polish-lists.png new file mode 100644 index 00000000..488672ce Binary files /dev/null and b/app/docs/shots/polish-lists.png differ diff --git a/app/docs/shots/polish-memory.png b/app/docs/shots/polish-memory.png new file mode 100644 index 00000000..1b5a26e1 Binary files /dev/null and b/app/docs/shots/polish-memory.png differ diff --git a/app/docs/shots/polish-models.png b/app/docs/shots/polish-models.png new file mode 100644 index 00000000..075b3522 Binary files /dev/null and b/app/docs/shots/polish-models.png differ diff --git a/app/docs/shots/polish-notes.png b/app/docs/shots/polish-notes.png new file mode 100644 index 00000000..20715895 Binary files /dev/null and b/app/docs/shots/polish-notes.png differ diff --git a/app/docs/shots/polish-reader.png b/app/docs/shots/polish-reader.png new file mode 100644 index 00000000..b9987fec Binary files /dev/null and b/app/docs/shots/polish-reader.png differ diff --git a/app/docs/shots/polish-space-empty-after.png b/app/docs/shots/polish-space-empty-after.png new file mode 100644 index 00000000..c6943986 Binary files /dev/null and b/app/docs/shots/polish-space-empty-after.png differ diff --git a/app/docs/shots/polish-space-empty-before.png b/app/docs/shots/polish-space-empty-before.png new file mode 100644 index 00000000..2f8af526 Binary files /dev/null and b/app/docs/shots/polish-space-empty-before.png differ diff --git a/app/docs/shots/polish-space-many.png b/app/docs/shots/polish-space-many.png new file mode 100644 index 00000000..93ce4daf Binary files /dev/null and b/app/docs/shots/polish-space-many.png differ diff --git a/app/docs/shots/polish-space.png b/app/docs/shots/polish-space.png new file mode 100644 index 00000000..d0386016 Binary files /dev/null and b/app/docs/shots/polish-space.png differ diff --git a/app/docs/shots/polish-stats.png b/app/docs/shots/polish-stats.png new file mode 100644 index 00000000..e07cf091 Binary files /dev/null and b/app/docs/shots/polish-stats.png differ diff --git a/app/docs/shots/polish-tags-after.png b/app/docs/shots/polish-tags-after.png new file mode 100644 index 00000000..cb4f91fc Binary files /dev/null and b/app/docs/shots/polish-tags-after.png differ diff --git a/app/docs/shots/polish-tags-before.png b/app/docs/shots/polish-tags-before.png new file mode 100644 index 00000000..4b4f4f43 Binary files /dev/null and b/app/docs/shots/polish-tags-before.png differ diff --git a/app/docs/shots/saves-folder.png b/app/docs/shots/saves-folder.png new file mode 100644 index 00000000..b785fd17 Binary files /dev/null and b/app/docs/shots/saves-folder.png differ diff --git a/app/docs/shots/space-searchline.png b/app/docs/shots/space-searchline.png new file mode 100644 index 00000000..852a2f90 Binary files /dev/null and b/app/docs/shots/space-searchline.png differ diff --git a/app/docs/shots/spec-builder-json.png b/app/docs/shots/spec-builder-json.png new file mode 100644 index 00000000..48554605 Binary files /dev/null and b/app/docs/shots/spec-builder-json.png differ diff --git a/app/docs/shots/spec-builder.png b/app/docs/shots/spec-builder.png new file mode 100644 index 00000000..6abc8cf4 Binary files /dev/null and b/app/docs/shots/spec-builder.png differ diff --git a/app/docs/shots/sphere-menu.png b/app/docs/shots/sphere-menu.png new file mode 100644 index 00000000..370de539 Binary files /dev/null and b/app/docs/shots/sphere-menu.png differ diff --git a/app/docs/shots/system-font-applied.png b/app/docs/shots/system-font-applied.png new file mode 100644 index 00000000..91efef1b Binary files /dev/null and b/app/docs/shots/system-font-applied.png differ diff --git a/app/docs/shots/system-fonts.png b/app/docs/shots/system-fonts.png new file mode 100644 index 00000000..b2cc079e Binary files /dev/null and b/app/docs/shots/system-fonts.png differ diff --git a/app/docs/shots/textures-sky.png b/app/docs/shots/textures-sky.png new file mode 100644 index 00000000..749b1e13 Binary files /dev/null and b/app/docs/shots/textures-sky.png differ diff --git a/app/docs/shots/textures-window.png b/app/docs/shots/textures-window.png new file mode 100644 index 00000000..1cc081a5 Binary files /dev/null and b/app/docs/shots/textures-window.png differ diff --git a/app/docs/shots/web-anim-scrub.png b/app/docs/shots/web-anim-scrub.png new file mode 100644 index 00000000..dd4d71a4 Binary files /dev/null and b/app/docs/shots/web-anim-scrub.png differ diff --git a/app/docs/shots/web-anim-window.png b/app/docs/shots/web-anim-window.png new file mode 100644 index 00000000..5019ab56 Binary files /dev/null and b/app/docs/shots/web-anim-window.png differ diff --git a/app/docs/shots/web-bar-memory.png b/app/docs/shots/web-bar-memory.png new file mode 100644 index 00000000..f8817ad3 Binary files /dev/null and b/app/docs/shots/web-bar-memory.png differ diff --git a/app/docs/shots/web-block-bend-editor.png b/app/docs/shots/web-block-bend-editor.png new file mode 100644 index 00000000..d4e628bd Binary files /dev/null and b/app/docs/shots/web-block-bend-editor.png differ diff --git a/app/docs/shots/web-block-bend.png b/app/docs/shots/web-block-bend.png new file mode 100644 index 00000000..96159162 Binary files /dev/null and b/app/docs/shots/web-block-bend.png differ diff --git a/app/docs/shots/web-block-menu.png b/app/docs/shots/web-block-menu.png new file mode 100644 index 00000000..6a3943a8 Binary files /dev/null and b/app/docs/shots/web-block-menu.png differ diff --git a/app/docs/shots/web-classifier-buckets.png b/app/docs/shots/web-classifier-buckets.png new file mode 100644 index 00000000..beb75fa5 Binary files /dev/null and b/app/docs/shots/web-classifier-buckets.png differ diff --git a/app/docs/shots/web-copy-group.png b/app/docs/shots/web-copy-group.png new file mode 100644 index 00000000..f26b3680 Binary files /dev/null and b/app/docs/shots/web-copy-group.png differ diff --git a/app/docs/shots/web-copy-open.png b/app/docs/shots/web-copy-open.png new file mode 100644 index 00000000..462ea637 Binary files /dev/null and b/app/docs/shots/web-copy-open.png differ diff --git a/app/docs/shots/web-filters-builder.png b/app/docs/shots/web-filters-builder.png new file mode 100644 index 00000000..b0de22e4 Binary files /dev/null and b/app/docs/shots/web-filters-builder.png differ diff --git a/app/docs/shots/web-filters.png b/app/docs/shots/web-filters.png new file mode 100644 index 00000000..c3b65af1 Binary files /dev/null and b/app/docs/shots/web-filters.png differ diff --git a/app/docs/shots/web-forge.png b/app/docs/shots/web-forge.png new file mode 100644 index 00000000..e8ffe9da Binary files /dev/null and b/app/docs/shots/web-forge.png differ diff --git a/app/docs/shots/web-gates-lit.png b/app/docs/shots/web-gates-lit.png new file mode 100644 index 00000000..6bce916d Binary files /dev/null and b/app/docs/shots/web-gates-lit.png differ diff --git a/app/docs/shots/web-gates-menu.png b/app/docs/shots/web-gates-menu.png new file mode 100644 index 00000000..d66c20e6 Binary files /dev/null and b/app/docs/shots/web-gates-menu.png differ diff --git a/app/docs/shots/web-ghost-red.png b/app/docs/shots/web-ghost-red.png new file mode 100644 index 00000000..f244e309 Binary files /dev/null and b/app/docs/shots/web-ghost-red.png differ diff --git a/app/docs/shots/web-grapple.png b/app/docs/shots/web-grapple.png new file mode 100644 index 00000000..4d083292 Binary files /dev/null and b/app/docs/shots/web-grapple.png differ diff --git a/app/docs/shots/web-groups.png b/app/docs/shots/web-groups.png new file mode 100644 index 00000000..4aff15e3 Binary files /dev/null and b/app/docs/shots/web-groups.png differ diff --git a/app/docs/shots/web-lights.png b/app/docs/shots/web-lights.png new file mode 100644 index 00000000..98cc262b Binary files /dev/null and b/app/docs/shots/web-lights.png differ diff --git a/app/docs/shots/web-list.png b/app/docs/shots/web-list.png new file mode 100644 index 00000000..9d96c277 Binary files /dev/null and b/app/docs/shots/web-list.png differ diff --git a/app/docs/shots/web-lists.png b/app/docs/shots/web-lists.png new file mode 100644 index 00000000..75c01889 Binary files /dev/null and b/app/docs/shots/web-lists.png differ diff --git a/app/docs/shots/web-memory-box.png b/app/docs/shots/web-memory-box.png new file mode 100644 index 00000000..f92a9c76 Binary files /dev/null and b/app/docs/shots/web-memory-box.png differ diff --git a/app/docs/shots/web-memory-long-piece.png b/app/docs/shots/web-memory-long-piece.png new file mode 100644 index 00000000..df975550 Binary files /dev/null and b/app/docs/shots/web-memory-long-piece.png differ diff --git a/app/docs/shots/web-memory-types-and-underlines.png b/app/docs/shots/web-memory-types-and-underlines.png new file mode 100644 index 00000000..d2f434a8 Binary files /dev/null and b/app/docs/shots/web-memory-types-and-underlines.png differ diff --git a/app/docs/shots/web-memory.png b/app/docs/shots/web-memory.png new file mode 100644 index 00000000..e51dc804 Binary files /dev/null and b/app/docs/shots/web-memory.png differ diff --git a/app/docs/shots/web-models-training.png b/app/docs/shots/web-models-training.png new file mode 100644 index 00000000..42126f15 Binary files /dev/null and b/app/docs/shots/web-models-training.png differ diff --git a/app/docs/shots/web-notes-long.png b/app/docs/shots/web-notes-long.png new file mode 100644 index 00000000..0d436ffd Binary files /dev/null and b/app/docs/shots/web-notes-long.png differ diff --git a/app/docs/shots/web-notes-picked.png b/app/docs/shots/web-notes-picked.png new file mode 100644 index 00000000..784a0731 Binary files /dev/null and b/app/docs/shots/web-notes-picked.png differ diff --git a/app/docs/shots/web-notes-spelling.png b/app/docs/shots/web-notes-spelling.png new file mode 100644 index 00000000..9160bff7 Binary files /dev/null and b/app/docs/shots/web-notes-spelling.png differ diff --git a/app/docs/shots/web-pictures.png b/app/docs/shots/web-pictures.png new file mode 100644 index 00000000..eaa1b3e4 Binary files /dev/null and b/app/docs/shots/web-pictures.png differ diff --git a/app/docs/shots/web-pipes.png b/app/docs/shots/web-pipes.png new file mode 100644 index 00000000..86c04b32 Binary files /dev/null and b/app/docs/shots/web-pipes.png differ diff --git a/app/docs/shots/web-prefabs-play.png b/app/docs/shots/web-prefabs-play.png new file mode 100644 index 00000000..0645a373 Binary files /dev/null and b/app/docs/shots/web-prefabs-play.png differ diff --git a/app/docs/shots/web-prefabs.png b/app/docs/shots/web-prefabs.png new file mode 100644 index 00000000..4aa546b5 Binary files /dev/null and b/app/docs/shots/web-prefabs.png differ diff --git a/app/docs/shots/web-reader-card-dates.png b/app/docs/shots/web-reader-card-dates.png new file mode 100644 index 00000000..7949d19a Binary files /dev/null and b/app/docs/shots/web-reader-card-dates.png differ diff --git a/app/docs/shots/web-reader-dates-classifiers.png b/app/docs/shots/web-reader-dates-classifiers.png new file mode 100644 index 00000000..e85759e9 Binary files /dev/null and b/app/docs/shots/web-reader-dates-classifiers.png differ diff --git a/app/docs/shots/web-s-anend.png b/app/docs/shots/web-s-anend.png new file mode 100644 index 00000000..91faee69 Binary files /dev/null and b/app/docs/shots/web-s-anend.png differ diff --git a/app/docs/shots/web-s-editor.png b/app/docs/shots/web-s-editor.png new file mode 100644 index 00000000..c494dd76 Binary files /dev/null and b/app/docs/shots/web-s-editor.png differ diff --git a/app/docs/shots/web-s-learn.png b/app/docs/shots/web-s-learn.png new file mode 100644 index 00000000..4bba667d Binary files /dev/null and b/app/docs/shots/web-s-learn.png differ diff --git a/app/docs/shots/web-s-run.png b/app/docs/shots/web-s-run.png new file mode 100644 index 00000000..a1d089e9 Binary files /dev/null and b/app/docs/shots/web-s-run.png differ diff --git a/app/docs/shots/web-scene-open-migrated.png b/app/docs/shots/web-scene-open-migrated.png new file mode 100644 index 00000000..c89cdfb2 Binary files /dev/null and b/app/docs/shots/web-scene-open-migrated.png differ diff --git a/app/docs/shots/web-scenes-combined.png b/app/docs/shots/web-scenes-combined.png new file mode 100644 index 00000000..85cab73a Binary files /dev/null and b/app/docs/shots/web-scenes-combined.png differ diff --git a/app/docs/shots/web-scenes-undo.png b/app/docs/shots/web-scenes-undo.png new file mode 100644 index 00000000..70866d73 Binary files /dev/null and b/app/docs/shots/web-scenes-undo.png differ diff --git a/app/docs/shots/web-select-box.png b/app/docs/shots/web-select-box.png new file mode 100644 index 00000000..d649dcab Binary files /dev/null and b/app/docs/shots/web-select-box.png differ diff --git a/app/docs/shots/web-settings-gpu-speed.png b/app/docs/shots/web-settings-gpu-speed.png new file mode 100644 index 00000000..23fe0d04 Binary files /dev/null and b/app/docs/shots/web-settings-gpu-speed.png differ diff --git a/app/docs/shots/web-settings-gpu.png b/app/docs/shots/web-settings-gpu.png new file mode 100644 index 00000000..547b8b4f Binary files /dev/null and b/app/docs/shots/web-settings-gpu.png differ diff --git a/app/docs/shots/web-settings-hsl.png b/app/docs/shots/web-settings-hsl.png new file mode 100644 index 00000000..7077bb31 Binary files /dev/null and b/app/docs/shots/web-settings-hsl.png differ diff --git a/app/docs/shots/web-settings-limits.png b/app/docs/shots/web-settings-limits.png new file mode 100644 index 00000000..0b7a63eb Binary files /dev/null and b/app/docs/shots/web-settings-limits.png differ diff --git a/app/docs/shots/web-settings.png b/app/docs/shots/web-settings.png new file mode 100644 index 00000000..d3db65f4 Binary files /dev/null and b/app/docs/shots/web-settings.png differ diff --git a/app/docs/shots/web-sounds.png b/app/docs/shots/web-sounds.png new file mode 100644 index 00000000..5f29fa65 Binary files /dev/null and b/app/docs/shots/web-sounds.png differ diff --git a/app/docs/shots/web-space-blocks.png b/app/docs/shots/web-space-blocks.png new file mode 100644 index 00000000..26ef8623 Binary files /dev/null and b/app/docs/shots/web-space-blocks.png differ diff --git a/app/docs/shots/web-space-chain.png b/app/docs/shots/web-space-chain.png new file mode 100644 index 00000000..1de2f7d5 Binary files /dev/null and b/app/docs/shots/web-space-chain.png differ diff --git a/app/docs/shots/web-space-copy-menu.png b/app/docs/shots/web-space-copy-menu.png new file mode 100644 index 00000000..3ddef5f9 Binary files /dev/null and b/app/docs/shots/web-space-copy-menu.png differ diff --git a/app/docs/shots/web-space-inherit.png b/app/docs/shots/web-space-inherit.png new file mode 100644 index 00000000..ba8253a0 Binary files /dev/null and b/app/docs/shots/web-space-inherit.png differ diff --git a/app/docs/shots/web-space-long-piece.png b/app/docs/shots/web-space-long-piece.png new file mode 100644 index 00000000..d8a7acbc Binary files /dev/null and b/app/docs/shots/web-space-long-piece.png differ diff --git a/app/docs/shots/web-space-note-chain.png b/app/docs/shots/web-space-note-chain.png new file mode 100644 index 00000000..567d6b2f Binary files /dev/null and b/app/docs/shots/web-space-note-chain.png differ diff --git a/app/docs/shots/web-space-searchline.png b/app/docs/shots/web-space-searchline.png new file mode 100644 index 00000000..507305d7 Binary files /dev/null and b/app/docs/shots/web-space-searchline.png differ diff --git a/app/docs/shots/web-space-size.png b/app/docs/shots/web-space-size.png new file mode 100644 index 00000000..711e0007 Binary files /dev/null and b/app/docs/shots/web-space-size.png differ diff --git a/app/docs/shots/web-space-spread.png b/app/docs/shots/web-space-spread.png new file mode 100644 index 00000000..a0e5f621 Binary files /dev/null and b/app/docs/shots/web-space-spread.png differ diff --git a/app/docs/shots/web-space-underlines.png b/app/docs/shots/web-space-underlines.png new file mode 100644 index 00000000..4b58b296 Binary files /dev/null and b/app/docs/shots/web-space-underlines.png differ diff --git a/app/docs/shots/web-space.png b/app/docs/shots/web-space.png new file mode 100644 index 00000000..9d14ecf9 Binary files /dev/null and b/app/docs/shots/web-space.png differ diff --git a/app/docs/shots/web-spec-builder-error.png b/app/docs/shots/web-spec-builder-error.png new file mode 100644 index 00000000..7bce372e Binary files /dev/null and b/app/docs/shots/web-spec-builder-error.png differ diff --git a/app/docs/shots/web-spec-builder-writer.png b/app/docs/shots/web-spec-builder-writer.png new file mode 100644 index 00000000..0a6d80c4 Binary files /dev/null and b/app/docs/shots/web-spec-builder-writer.png differ diff --git a/app/docs/shots/web-spec-builder.png b/app/docs/shots/web-spec-builder.png new file mode 100644 index 00000000..113d08bb Binary files /dev/null and b/app/docs/shots/web-spec-builder.png differ diff --git a/app/docs/shots/web-specs-training.png b/app/docs/shots/web-specs-training.png new file mode 100644 index 00000000..e099faef Binary files /dev/null and b/app/docs/shots/web-specs-training.png differ diff --git a/app/docs/shots/web-sphere.png b/app/docs/shots/web-sphere.png new file mode 100644 index 00000000..f87fb1b0 Binary files /dev/null and b/app/docs/shots/web-sphere.png differ diff --git a/app/docs/shots/web-starter-fetch-refused.png b/app/docs/shots/web-starter-fetch-refused.png new file mode 100644 index 00000000..60d967fe Binary files /dev/null and b/app/docs/shots/web-starter-fetch-refused.png differ diff --git a/app/docs/shots/web-starter-held-out.png b/app/docs/shots/web-starter-held-out.png new file mode 100644 index 00000000..e94b1206 Binary files /dev/null and b/app/docs/shots/web-starter-held-out.png differ diff --git a/app/docs/shots/web-starters.png b/app/docs/shots/web-starters.png new file mode 100644 index 00000000..04819459 Binary files /dev/null and b/app/docs/shots/web-starters.png differ diff --git a/app/docs/shots/web-stats.png b/app/docs/shots/web-stats.png new file mode 100644 index 00000000..7cda4689 Binary files /dev/null and b/app/docs/shots/web-stats.png differ diff --git a/app/docs/shots/web-superflight.png b/app/docs/shots/web-superflight.png new file mode 100644 index 00000000..4840962a Binary files /dev/null and b/app/docs/shots/web-superflight.png differ diff --git a/app/docs/shots/web-tagset.png b/app/docs/shots/web-tagset.png new file mode 100644 index 00000000..3d094f10 Binary files /dev/null and b/app/docs/shots/web-tagset.png differ diff --git a/app/docs/shots/web-taxonomy.png b/app/docs/shots/web-taxonomy.png new file mode 100644 index 00000000..33112f63 Binary files /dev/null and b/app/docs/shots/web-taxonomy.png differ diff --git a/app/docs/shots/web-textures-room.png b/app/docs/shots/web-textures-room.png new file mode 100644 index 00000000..fa1b25de Binary files /dev/null and b/app/docs/shots/web-textures-room.png differ diff --git a/app/docs/shots/web-textures-window.png b/app/docs/shots/web-textures-window.png new file mode 100644 index 00000000..7d98aa05 Binary files /dev/null and b/app/docs/shots/web-textures-window.png differ diff --git a/app/docs/shots/web-view-program.png b/app/docs/shots/web-view-program.png new file mode 100644 index 00000000..54a68709 Binary files /dev/null and b/app/docs/shots/web-view-program.png differ diff --git a/app/docs/shots/web-wires-lit.png b/app/docs/shots/web-wires-lit.png new file mode 100644 index 00000000..f60e87bd Binary files /dev/null and b/app/docs/shots/web-wires-lit.png differ diff --git a/app/docs/shots/web-wiring-lifted.png b/app/docs/shots/web-wiring-lifted.png new file mode 100644 index 00000000..0a0205f3 Binary files /dev/null and b/app/docs/shots/web-wiring-lifted.png differ diff --git a/app/docs/shots/web-wiring-ray.png b/app/docs/shots/web-wiring-ray.png new file mode 100644 index 00000000..4a04f9ce Binary files /dev/null and b/app/docs/shots/web-wiring-ray.png differ diff --git a/app/docs/shots/web-zone-window.png b/app/docs/shots/web-zone-window.png new file mode 100644 index 00000000..d06718df Binary files /dev/null and b/app/docs/shots/web-zone-window.png differ diff --git a/app/docs/shots/web-zone.png b/app/docs/shots/web-zone.png new file mode 100644 index 00000000..9d27c85e Binary files /dev/null and b/app/docs/shots/web-zone.png differ diff --git a/app/docs/shots/zone.png b/app/docs/shots/zone.png new file mode 100644 index 00000000..e0a8b799 Binary files /dev/null and b/app/docs/shots/zone.png differ diff --git a/app/src/backend/hub.rs b/app/src/backend/hub.rs new file mode 100644 index 00000000..e1583782 --- /dev/null +++ b/app/src/backend/hub.rs @@ -0,0 +1,140 @@ +//! The web build's backend: the hub's app API over a WebSocket at `/app/ws` +//! (docs/app-api.md). Calls send `{id, op, args}`; answers come back as +//! `{id, ok, data | error}`, matched by id. The socket opens on the first call and again +//! after it drops; calls made meanwhile wait in a queue. + +use std::cell::RefCell; +use std::collections::HashMap; +use std::rc::Rc; + +use futures_channel::oneshot; +use serde_json::{Value, json}; +use wasm_bindgen::JsCast; +use wasm_bindgen::closure::Closure; +use web_sys::{CloseEvent, MessageEvent, WebSocket}; + +use super::{Backend, Fut}; + +type Answer = oneshot::Sender<Result<Value, String>>; + +#[derive(Default)] +struct State { + ws: Option<WebSocket>, + open: bool, + queue: Vec<String>, + pending: HashMap<u64, Answer>, + next: u64, +} + +#[derive(Clone)] +pub struct Hub { + url: String, + st: Rc<RefCell<State>>, +} + +impl Hub { + /// the hub that served this page + pub fn here() -> Hub { + let loc = web_sys::window().map(|w| w.location()); + let (proto, host, search) = loc + .map(|l| { + ( + l.protocol().unwrap_or_default(), + l.host().unwrap_or_default(), + l.search().unwrap_or_default(), + ) + }) + .unwrap_or_default(); + let ws = if proto == "https:" { "wss" } else { "ws" }; + // `?hub=host:port` talks to a hub elsewhere (the page served apart from it) + let host = search + .trim_start_matches('?') + .split('&') + .find_map(|kv| kv.strip_prefix("hub=")) + .map(str::to_string) + .unwrap_or(host); + Hub { + url: format!("{ws}://{host}/app/ws"), + st: Default::default(), + } + } + + fn connect(&self) -> Result<(), String> { + if self.st.borrow().ws.is_some() { + return Ok(()); + } + let ws = WebSocket::new(&self.url).map_err(|e| format!("couldn't reach the hub: {e:?}"))?; + let st = self.st.clone(); + let onopen = Closure::<dyn FnMut()>::new(move || { + let mut s = st.borrow_mut(); + s.open = true; + let queued: Vec<String> = std::mem::take(&mut s.queue); + if let Some(ws) = &s.ws { + for m in queued { + let _ = ws.send_with_str(&m); + } + } + }); + let st = self.st.clone(); + let onmessage = Closure::<dyn FnMut(MessageEvent)>::new(move |e: MessageEvent| { + let Some(text) = e.data().as_string() else { return }; + let Ok(v) = serde_json::from_str::<Value>(&text) else { + return; + }; + let id = v["id"].as_u64().unwrap_or(0); + if let Some(tx) = st.borrow_mut().pending.remove(&id) { + let r = if v["ok"].as_bool() == Some(true) { + Ok(v.get("data").cloned().unwrap_or(Value::Null)) + } else { + Err(v["error"].as_str().unwrap_or("the hub said no").to_string()) + }; + let _ = tx.send(r); + } + }); + let st = self.st.clone(); + let onclose = Closure::<dyn FnMut(CloseEvent)>::new(move |_e: CloseEvent| { + let mut s = st.borrow_mut(); + s.ws = None; + s.open = false; + for (_, tx) in s.pending.drain() { + let _ = tx.send(Err("the hub dropped the connection; try again".into())); + } + }); + ws.set_onopen(Some(onopen.as_ref().unchecked_ref())); + ws.set_onmessage(Some(onmessage.as_ref().unchecked_ref())); + ws.set_onclose(Some(onclose.as_ref().unchecked_ref())); + // they live as long as the socket + onopen.forget(); + onmessage.forget(); + onclose.forget(); + self.st.borrow_mut().ws = Some(ws); + Ok(()) + } +} + +impl Backend for Hub { + fn call(&self, op: &str, args: Value) -> Fut<Value> { + let (tx, rx) = oneshot::channel(); + let sent = self.connect().map(|_| { + let mut s = self.st.borrow_mut(); + s.next += 1; + let id = s.next; + s.pending.insert(id, tx); + let msg = json!({ "id": id, "op": op, "args": args }).to_string(); + match (&s.ws, s.open) { + (Some(ws), true) => { + let _ = ws.send_with_str(&msg); + } + _ => s.queue.push(msg), + } + }); + Box::pin(async move { + sent?; + rx.await.map_err(|_| "the hub didn't answer".to_string())? + }) + } + + fn describe(&self) -> String { + format!("the hub at {}", self.url) + } +} diff --git a/app/src/backend/local.rs b/app/src/backend/local.rs new file mode 100644 index 00000000..ab91f0da --- /dev/null +++ b/app/src/backend/local.rs @@ -0,0 +1,196 @@ +//! The desktop's backend: the entry graph (core/src/graph, docs/format.md) in this +//! process. Every call runs on a worker thread and answers through a channel, so the +//! interface never waits on the disk. +//! +//! The operations are the app API's (docs/app-api.md), answered by `anend_core::ops`, the +//! same code the hub answers them with: keys are weum labels of entry ids, a note is an +//! entry of mime `text/markdown` (`# title` and markdown), lists are `member` edges, tags +//! `tag` edges. A save's classifiers live in `<save>.models` beside it +//! (`anend_core::ops::classify`), trained on threads of their own as on the hub. + +use std::path::{Path, PathBuf}; +use std::sync::Arc; + +use anend_core::ops::Saves; +use anend_core::ops::classify::Limits; +use serde_json::Value; + +use super::{Backend, Fut}; + +type Res = Result<Value, String>; + +/// the saves folder and the open save +#[derive(Clone)] +pub struct Local { + saves: Arc<Saves>, +} + +impl Local { + /// opens `save` (a path), or `main.redb` in `dir` + pub fn open(dir: &Path, save: Option<&Path>) -> Result<Local, String> { + let path = save.map(Path::to_path_buf).unwrap_or_else(|| dir.join("main.redb")); + Ok(Local { + saves: Arc::new(Saves::at(&path)?.with_models(Limits::NONE).with_folders()), + }) + } + + pub fn save_path(&self) -> PathBuf { + self.saves.current_path().unwrap_or_default() + } + + /// an op answered here and now (the command line's `run`, which has no interface to keep + /// waiting) + pub fn call_now(&self, op: &str, args: &Value) -> Res { + self.dispatch(op, args) + } + + fn dispatch(&self, op: &str, args: &Value) -> Res { + self.saves.call(op, args) + } +} + +impl Backend for Local { + fn call(&self, op: &str, args: Value) -> Fut<Value> { + let me = self.clone(); + let op = op.to_string(); + let (tx, rx) = futures_channel::oneshot::channel(); + let spawned = std::thread::Builder::new().name(format!("anend {op}")).spawn(move || { + let r = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| me.dispatch(&op, &args))) + .unwrap_or_else(|_| Err(format!("{op} failed unexpectedly"))); + let _ = tx.send(r); + }); + Box::pin(async move { + spawned.map_err(|e| format!("couldn't start a worker: {e}"))?; + rx.await.map_err(|_| "the worker stopped".to_string())? + }) + } + + fn describe(&self) -> String { + self.save_path().display().to_string() + } + + fn on_disk(&self) -> bool { + true + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::gem::Mode; + use serde_json::json; + + fn temp() -> (Local, PathBuf) { + temp_named("main") + } + + fn temp_named(tag: &str) -> (Local, PathBuf) { + let dir = std::env::temp_dir().join(format!("anend-app-test-{tag}-{}", std::process::id())); + let _ = std::fs::remove_dir_all(&dir); + (Local::open(&dir, None).unwrap(), dir) + } + + fn wait<T: 'static>(mut f: Fut<T>) -> Result<T, String> { + loop { + match futures_util::FutureExt::now_or_never(&mut f) { + Some(r) => return r, + None => std::thread::sleep(std::time::Duration::from_millis(2)), + } + } + } + + #[test] + fn texts_lists_tags_notes_backup() { + let (b, dir) = temp(); + let (k, new) = wait(b.saturate("listen")).unwrap(); + assert!(new && k == "0"); + wait(b.saturate("silent")).unwrap(); + assert_eq!(wait(b.saturate("listen")).unwrap(), ("0".to_string(), false)); + assert_eq!(wait(b.gsearch(Mode::Ordinal, "79")).unwrap().len(), 2); + assert_eq!(wait(b.gsearch(Mode::Frequency, "tinsel")).unwrap().len(), 2); + wait(b.put_memory("0", "enlist")).unwrap(); + assert_eq!(wait(b.remember("0")).unwrap().text, "enlist"); + let counts = wait(b.bucket_counts(Mode::Ordinal)).unwrap(); + assert_eq!(counts, vec![super::super::BucketCount { sum: 79, count: 2 }]); + // forget and put back: the list keeps its member + wait(b.enlist("0", "1")).unwrap(); + assert_eq!(wait(b.lists()).unwrap().lists[0].count, 1); + assert_eq!(wait(b.forget("1")).unwrap(), "silent"); + wait(b.put_memory("1", "silent")).unwrap(); + assert_eq!(wait(b.lists()).unwrap().lists[0].count, 1); + // tags on texts + wait(b.tag("0", "anagram")).unwrap(); + assert_eq!(wait(b.tagged(&["anagram".into()], false)).unwrap()[0].text, "enlist"); + // notes + let n = wait(b.save_note(&Default::default(), "# hello\n\nworld")).unwrap(); + assert_eq!(n.title, "hello"); + assert_eq!(wait(b.notes(&Default::default())).unwrap().len(), 1); + let h = wait(b.hello()).unwrap(); + assert_eq!(h.counts.notes, 1); + let backup = wait(b.call("saves.backup", json!({}))).unwrap(); + assert_eq!(backup["paths"].as_array().unwrap().len(), 2); + let im = wait(b.import_texts(r#"[["truth", [9]]]"#, "")).unwrap(); + assert_eq!(im.memories, 1); + assert_eq!(wait(b.remember("9")).unwrap().text, "truth"); + std::fs::remove_dir_all(dir).ok(); + } + + /// classifiers on the desktop: made from lists, trained in the background, asked, + /// told yes or no, and the answer taken back + #[test] + fn classifiers() { + let (b, dir) = temp_named("classify"); + let f = ["apple", "banana", "cherry", "mango", "peach", "plum", "grape", "melon"]; + let r = [ + "rock", "stone", "granite", "basalt", "flint", "slate", "quartz", "shale", + ]; + let (fruit, _) = wait(b.saturate("fruit")).unwrap(); + let (rocks, _) = wait(b.saturate("rocks")).unwrap(); + for i in 0..20 { + let (a, _) = + wait(b.saturate(&format!("{} {} {}", f[i % 8], f[(i * 3 + 1) % 8], f[(i / 8 + 4) % 8]))).unwrap(); + let (c, _) = + wait(b.saturate(&format!("{} {} {}", r[i % 8], r[(i * 5 + 2) % 8], r[(i / 8 + 4) % 8]))).unwrap(); + wait(b.enlist(&fruit, &a)).unwrap(); + wait(b.enlist(&rocks, &c)).unwrap(); + } + wait(b.create_model("kind", &[fruit.clone(), rocks.clone()], "tiny")).unwrap(); + let list = wait(b.models()).unwrap(); + assert_eq!((list[0].name.as_str(), list[0].trained), ("kind", false)); + assert_eq!(list[0].classes, ["fruit", "rocks"]); + let j = wait(b.train_model("kind", 6)).unwrap(); + assert_eq!(j.state, "running"); + let mut done = j; + for _ in 0..1200 { + done = wait(b.model_job("kind")).unwrap(); + if done.state != "running" { + break; + } + std::thread::sleep(std::time::Duration::from_millis(50)); + } + assert_eq!(done.state, "done", "{done:?}"); + assert!(wait(b.models()).unwrap()[0].trained); + let p = wait(b.run_model("kind", "granite slate flint")).unwrap(); + assert_eq!(p["results"][0]["class"], "rocks", "{p}"); + let t = "melon basalt grape"; + let prob = || { + wait(b.run_model("kind", t)).unwrap()["results"][0]["probs"][1] + .as_f64() + .unwrap() + }; + let p0 = prob(); + wait(b.model_feedback("kind", None, t, "rocks", true)).unwrap(); + let p1 = prob(); + assert!(p1 > p0, "{p0} {p1}"); + wait(b.undo_model_feedback("kind")).unwrap(); + assert_eq!(prob(), p0); + // the classifiers go with the save: copied, then deleted with it + wait(b.copy_save("main", "other")).unwrap(); + assert!(dir.join("other.models").exists()); + wait(b.delete_save("other")).unwrap(); + assert!(!dir.join("other.models").exists()); + wait(b.delete_model("kind")).unwrap(); + assert!(wait(b.models()).unwrap().is_empty()); + std::fs::remove_dir_all(dir).ok(); + } +} diff --git a/app/src/backend/mod.rs b/app/src/backend/mod.rs new file mode 100644 index 00000000..a269ea13 --- /dev/null +++ b/app/src/backend/mod.rs @@ -0,0 +1,700 @@ +//! Everything the views read and change goes through a [`Backend`]. A backend answers one +//! call: an operation of the app API (docs/app-api.md) with JSON arguments. The typed +//! methods below are what the views use; they build on that call and can be overridden. +//! +//! The backends: +//! - `local::Local` (the desktop): anend-core's `Store` on this machine, every call on a +//! worker thread so the interface never waits on the disk. +//! - `hub::Hub` (the web build): the hub's app API over a WebSocket (`/app/ws`). +//! +//! **Switching to the entry graph** (core/src/graph, being built): write a backend whose +//! `call` answers the same operations from the graph store (or make `Local` dispatch to it), +//! and pick it in `main.rs`. The views don't change. **The core in WebAssembly** slots in +//! the same way: `Local`'s dispatcher compiles to wasm32 (anend-core does), over a store on +//! OPFS/IndexedDB, picked in `main.rs` when the page has no hub. + +#[cfg(not(target_arch = "wasm32"))] +pub mod local; + +#[cfg(target_arch = "wasm32")] +pub mod hub; + +use futures_util::future::LocalBoxFuture; +use serde::{Deserialize, Serialize, de::DeserializeOwned}; +use serde_json::{Value, json}; + +use crate::gem::Mode; + +pub type Fut<T> = LocalBoxFuture<'static, Result<T, String>>; + +fn typed<T: DeserializeOwned + 'static>(f: Fut<Value>) -> Fut<T> { + Box::pin(async move { serde_json::from_value(f.await?).map_err(|e| format!("an answer that doesn't read: {e}")) }) +} + +fn field<T: DeserializeOwned + 'static>(f: Fut<Value>, name: &'static str) -> Fut<T> { + Box::pin(async move { + let mut v = f.await?; + serde_json::from_value(v.get_mut(name).map(Value::take).unwrap_or(Value::Null)) + .map_err(|e| format!("an answer that doesn't read: {e}")) + }) +} + +fn unit(f: Fut<Value>) -> Fut<()> { + Box::pin(async move { f.await.map(|_| ()) }) +} + +// ------------------------------------------------------------------ what calls answer + +/// a memory or a note as the views show it; `key` is weum's `0,12` or `note:<key>` +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct Hit { + pub key: String, + pub text: String, + #[serde(default)] + pub note: bool, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct Counts { + #[serde(default)] + pub notes: u64, + #[serde(default)] + pub memories: u64, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct Hello { + pub save: String, + #[serde(default)] + pub saves: Vec<String>, + #[serde(default)] + pub counts: Counts, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct SaveInfo { + pub name: String, + #[serde(default)] + pub open: bool, + pub notes: Option<u64>, + pub memories: Option<u64>, + #[serde(default)] + pub size: u64, + pub modified: Option<String>, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct NoteSummary { + pub key: String, + pub title: String, + #[serde(default)] + pub tags: Vec<String>, + #[serde(default)] + pub created: String, + #[serde(default)] + pub modified: String, + #[serde(default)] + pub edits: usize, + #[serde(default)] + pub preview: String, + #[serde(default)] + pub words: usize, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct Note { + #[serde(rename = "_key", default)] + pub key: String, + #[serde(default)] + pub title: String, + #[serde(default)] + pub markdown: String, + #[serde(default)] + pub tags: Vec<String>, + #[serde(default)] + pub created: String, + #[serde(default)] + pub edits: Vec<String>, + /// the note as written when it has replacements (`{{key}}` where an entry goes) + #[serde(default, skip_serializing_if = "Option::is_none")] + pub source: Option<String>, + /// its markdown with saved filters' results put in (`{{filter:name}}`) + #[serde(default, skip_serializing_if = "Option::is_none")] + pub rendered: Option<String>, +} + +/// what to find in the query model (`entries.query`) +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct EntryQuery { + #[serde(skip_serializing_if = "String::is_empty")] + pub words: String, + /// ordinal or reversed, with `from`/`to` + pub bucket: String, + pub from: Option<i64>, + pub to: Option<i64>, + #[serde(skip_serializing_if = "Option::is_none")] + pub since: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub until: Option<String>, + #[serde(skip_serializing_if = "Option::is_none")] + pub tag: Option<String>, + /// notes, memories, or anything + pub kind: String, + pub limit: usize, +} + +/// which notes: words, tags (all, or any), and a time range (RFC 3339, created) +#[derive(Debug, Clone, PartialEq, Default)] +pub struct NoteQuery { + pub q: String, + pub tags: Vec<String>, + pub any: bool, + pub since: Option<String>, + pub until: Option<String>, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct ListInfo { + pub list: String, + pub name: String, + #[serde(default)] + pub members: Vec<Hit>, + #[serde(default)] + pub count: usize, + #[serde(default)] + pub ordinal_sum: i64, + #[serde(default)] + pub reversed_sum: i64, + #[serde(default)] + pub ordinal_mean: f64, + #[serde(default)] + pub reversed_mean: f64, + #[serde(default)] + pub vector: Vec<f64>, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct Lists { + pub lists: Vec<ListInfo>, + #[serde(default)] + pub dot: Vec<Vec<f64>>, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct SpreadNode { + pub id: String, + pub x: f64, + pub y: f64, + pub z: f64, + #[serde(default)] + pub s: i64, + #[serde(default)] + pub r: i64, + #[serde(default)] + pub q: i64, + #[serde(default)] + pub hue: f64, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct Spread { + pub d: f64, + pub nodes: Vec<SpreadNode>, + #[serde(default)] + pub buckets: usize, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct Stats { + #[serde(default)] + pub notes: u64, + #[serde(default)] + pub words: u64, + #[serde(default)] + pub saves: u64, + #[serde(default)] + pub memories: u64, + #[serde(default)] + pub tags: Vec<(String, u64)>, + pub first: Option<String>, + pub latest: Option<String>, +} + +/// one sum and how many texts it holds, in a mode +#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize, Default)] +pub struct BucketCount { + pub sum: i64, + pub count: u64, +} + +/// a model (today: a classifier) as the models view lists it; the rest of its details +/// stay JSON until the declarative model spec lands (docs/models.md) +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct ModelSummary { + pub name: String, + #[serde(default)] + pub classes: Vec<String>, + #[serde(default)] + pub lists: Vec<String>, + #[serde(default)] + pub head: String, + #[serde(default)] + pub preset: String, + #[serde(default)] + pub trained: bool, + pub accuracy: Option<f64>, + pub examples: Option<u64>, + #[serde(default)] + pub training: bool, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct Job { + #[serde(default)] + pub name: String, + pub state: String, + #[serde(default)] + pub epoch: usize, + #[serde(default)] + pub step: usize, + #[serde(default)] + pub steps: usize, + #[serde(default)] + pub loss: f64, + #[serde(default)] + pub seconds: f64, + pub error: Option<String>, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct Scored { + pub key: Option<String>, + pub text: String, + #[serde(default)] + pub note: bool, + #[serde(default)] + pub prob: f64, + #[serde(default)] + pub score: f64, + pub top_class: Option<String>, + #[serde(default)] + pub member: bool, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct FilterPreset { + pub name: String, + pub expr: Value, + #[serde(default)] + pub description: String, + #[serde(default)] + pub reads: String, + pub count: Option<u64>, +} + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct FilterRun { + #[serde(default)] + pub scanned: u64, + #[serde(default)] + pub matched: u64, + #[serde(default)] + pub results: Vec<Scored>, +} + +/// what a backup wrote (the desktop: two files) or holds (the web: two downloads) +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct Backup { + /// where the files went, when the backend wrote them + #[serde(default)] + pub paths: Vec<String>, + /// every text, weum's `[[text, [key bytes]]]` + #[serde(default)] + pub texts: Value, + /// everything else: notes, lists, settings, models + #[serde(default)] + pub other: Value, +} + +/// what an import put in +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)] +pub struct Imported { + pub save: Option<String>, + #[serde(default)] + pub memories: u64, + #[serde(default)] + pub notes: u64, + #[serde(default)] + pub lists: u64, +} + +// ------------------------------------------------------------------ the backend + +/// the app's data, wherever it lives +pub trait Backend { + /// one operation of the app API (docs/app-api.md); every typed call goes through it + fn call(&self, op: &str, args: Value) -> Fut<Value>; + + /// where the data is, for the status line ("local", "hub at …") + fn describe(&self) -> String; + + /// whether the saves are files on this machine (backups go to a folder, imports read + /// paths); on the web they're downloads and uploads + fn on_disk(&self) -> bool { + false + } + + // ---- the save + fn hello(&self) -> Fut<Hello> { + typed(self.call("hello", json!({}))) + } + fn saves(&self) -> Fut<Vec<SaveInfo>> { + typed(self.call("saves.list", json!({}))) + } + fn open_save(&self, name: &str) -> Fut<()> { + unit(self.call("saves.open", json!({ "name": name }))) + } + fn new_save(&self, name: &str) -> Fut<()> { + unit(self.call("saves.new", json!({ "name": name }))) + } + fn copy_save(&self, name: &str, to: &str) -> Fut<()> { + unit(self.call("saves.copy", json!({ "name": name, "to": to }))) + } + fn rename_save(&self, name: &str, to: &str) -> Fut<()> { + unit(self.call("saves.rename", json!({ "name": name, "to": to }))) + } + fn delete_save(&self, name: &str) -> Fut<()> { + unit(self.call("saves.delete", json!({ "name": name }))) + } + /// a bundle into a save: `merge` into the open one, or a new save named `name` + fn import_bundle(&self, bundle: Value, name: &str, merge: bool) -> Fut<Imported> { + typed(self.call( + "saves.import", + json!({ "bundle": bundle, "name": name, "merge": merge }), + )) + } + /// weum's `await memory.backup`: the texts in one JSON, everything else in another; + /// on disk the backend writes the two files (their paths come back), a hub hands the + /// two documents back to be downloaded + fn backup(&self, name: &str) -> Fut<Backup> { + typed(self.call("saves.backup", json!({ "name": name }))) + } + /// weum's `all-of-it.json` (or a backup's texts.json) into the open save, or a new one + /// named `new_save` + fn import_texts(&self, json_text: &str, new_save: &str) -> Fut<Imported> { + typed(self.call("saves.import_texts", json!({ "data": json_text, "name": new_save }))) + } + + // ---- texts (memories) and sums + fn gsearch(&self, mode: Mode, key: &str) -> Fut<Vec<Hit>> { + field( + self.call("mem.gsearch", json!({ "bucket": mode.name(), "key": key })), + "hits", + ) + } + fn search(&self, q: &str, variations: bool) -> Fut<Vec<Hit>> { + typed(self.call("mem.search", json!({ "q": q, "variations": variations }))) + } + /// remembers a text unless it's there already; its key and whether it's new + fn saturate(&self, text: &str) -> Fut<(String, bool)> { + let f = self.call("mem.saturate", json!({ "text": text })); + Box::pin(async move { + let v = f.await?; + Ok(( + v["key"].as_str().unwrap_or_default().to_string(), + v["new"].as_bool().unwrap_or(false), + )) + }) + } + /// forgets a memory; its text + fn forget(&self, key: &str) -> Fut<String> { + field(self.call("mem.forget", json!({ "key": key })), "text") + } + fn remember(&self, key: &str) -> Fut<Hit> { + typed(self.call("mem.remember", json!({ "key": key }))) + } + /// a memory's text replaced, keeping its key (or a forgotten one put back) + fn put_memory(&self, key: &str, text: &str) -> Fut<()> { + unit(self.call("mem.put", json!({ "key": key, "text": text }))) + } + fn all_memories(&self, limit: usize) -> Fut<Vec<Hit>> { + typed(self.call("mem.all", json!({ "limit": limit }))) + } + /// every sum in a mode and how many texts it holds, lowest first + fn bucket_counts(&self, mode: Mode) -> Fut<Vec<BucketCount>> { + field(self.call("mem.buckets", json!({ "bucket": mode.name() })), "buckets") + } + + // ---- lists (and tags on texts, which are lists headed by the tag) + fn lists(&self) -> Fut<Lists> { + typed(self.call("lists.stats", json!({}))) + } + fn enlist(&self, list: &str, member: &str) -> Fut<()> { + unit(self.call("lists.enlist", json!({ "list": list, "member": member }))) + } + fn delist(&self, list: &str, member: &str) -> Fut<()> { + unit(self.call("lists.delist", json!({ "list": list, "member": member }))) + } + fn unlist(&self, list: &str) -> Fut<u64> { + field(self.call("lists.unlist", json!({ "list": list })), "removed") + } + + // ---- tags on any entry + fn tag(&self, key: &str, tag: &str) -> Fut<()> { + unit(self.call("tags.add", json!({ "key": key, "tag": tag }))) + } + fn untag(&self, key: &str, tag: &str) -> Fut<()> { + unit(self.call("tags.remove", json!({ "key": key, "tag": tag }))) + } + /// every tag and how many entries carry it, the most used first + fn all_tags(&self) -> Fut<Vec<(String, u64)>> { + let f = self.call("tags.all", json!({})); + Box::pin(async move { + let v = f.await?; + Ok(v.as_array() + .into_iter() + .flatten() + .map(|t| { + ( + t["tag"].as_str().unwrap_or("").to_string(), + t["count"].as_u64().unwrap_or(0), + ) + }) + .collect()) + }) + } + /// the entries carrying all (or any) of these tags + fn tagged(&self, tags: &[String], any: bool) -> Fut<Vec<Hit>> { + typed(self.call( + "tags.entries", + json!({ "tags": tags, "mode": if any { "or" } else { "and" } }), + )) + } + /// weum's notes on an entry, oldest first + fn notes_on(&self, key: &str) -> Fut<Vec<Hit>> { + typed(self.call("notes.on", json!({ "key": key }))) + } + /// the query model: words, a sum range, a creation time range, a tag, a kind + fn query(&self, q: &EntryQuery) -> Fut<(u64, Vec<Hit>)> { + let f = self.call("entries.query", serde_json::to_value(q).unwrap_or_default()); + Box::pin(async move { + let mut v = f.await?; + let hits = serde_json::from_value(v["hits"].take()).map_err(|e| e.to_string())?; + Ok((v["total"].as_u64().unwrap_or(0), hits)) + }) + } + + // ---- notes + fn notes(&self, q: &NoteQuery) -> Fut<Vec<NoteSummary>> { + let f = self.call( + "notes.list", + json!({ "q": q.q, "tags": q.tags, "mode": if q.any { "or" } else { "and" } }), + ); + let (since, until) = (q.since.clone(), q.until.clone()); + Box::pin(async move { + let mut all: Vec<NoteSummary> = + serde_json::from_value(f.await?).map_err(|e| format!("an answer that doesn't read: {e}"))?; + // the time range, here so every backend has it + all.retain(|n| { + since.as_deref().is_none_or(|s| n.created.as_str() >= s) + && until.as_deref().is_none_or(|u| n.created.as_str() <= u) + }); + Ok(all) + }) + } + fn note_tags(&self) -> Fut<Vec<(String, u64)>> { + let f = self.call("notes.tags", json!({})); + Box::pin(async move { + let v = f.await?; + Ok(v.as_array() + .into_iter() + .flatten() + .map(|t| { + ( + t["tag"].as_str().unwrap_or("").to_string(), + t["count"].as_u64().unwrap_or(0), + ) + }) + .collect()) + }) + } + fn note(&self, key: &str) -> Fut<Note> { + typed(self.call("notes.get", json!({ "key": key }))) + } + /// stores a note from the editor's text (`# title` and markdown) + fn save_note(&self, note: &Note, text: &str) -> Fut<Note> { + typed(self.call("notes.save", json!({ "note": note, "text": text }))) + } + fn delete_note(&self, key: &str) -> Fut<()> { + unit(self.call("notes.delete", json!({ "key": key }))) + } + + // ---- the space + fn spread(&self, texts: &[(String, String)], reversed: bool) -> Fut<Spread> { + let texts: Vec<Value> = texts.iter().map(|(id, t)| json!({ "id": id, "text": t })).collect(); + typed(self.call("space.spread", json!({ "texts": texts, "reversed": reversed }))) + } + + // ---- the whole app + fn stats(&self) -> Fut<Stats> { + typed(self.call("stats", json!({}))) + } + + // ---- models (classifiers today), behind this seam until the model spec lands + fn models(&self) -> Fut<Vec<ModelSummary>> { + typed(self.call("classify.list", json!({}))) + } + fn create_model(&self, name: &str, classes: &[String], preset: &str) -> Fut<()> { + unit(self.call( + "classify.create", + json!({ "name": name, "classes": classes, "preset": preset }), + )) + } + fn delete_model(&self, name: &str) -> Fut<()> { + unit(self.call("classify.delete", json!({ "name": name }))) + } + fn train_model(&self, name: &str, epochs: u32) -> Fut<Job> { + typed(self.call("classify.train", json!({ "name": name, "epochs": epochs }))) + } + fn model_job(&self, name: &str) -> Fut<Job> { + typed(self.call("classify.job", json!({ "name": name }))) + } + fn cancel_training(&self, name: &str) -> Fut<()> { + unit(self.call("classify.cancel", json!({ "name": name }))) + } + /// a model's outputs for a text: class names and probabilities + fn run_model(&self, name: &str, text: &str) -> Fut<Value> { + self.call("classify.predict", json!({ "name": name, "texts": [text] })) + } + /// the texts most likely in a class + fn model_search(&self, name: &str, class: &str, q: &str) -> Fut<Vec<Scored>> { + field( + self.call( + "classify.search", + json!({ "name": name, "class": class, "q": q, "limit": 60 }), + ), + "results", + ) + } + /// yes or no on a text for a class + fn model_feedback(&self, name: &str, key: Option<&str>, text: &str, class: &str, yes: bool) -> Fut<Value> { + let mut args = json!({ "name": name, "class": class, "yes": yes }); + match key { + Some(k) => args["key"] = json!(k), + None => args["text"] = json!(text), + } + self.call("classify.feedback", args) + } + /// takes back the latest feedback on a model (the undo of yes/no/why) + fn undo_model_feedback(&self, name: &str) -> Fut<()> { + unit(self.call("classify.unfeedback", json!({ "name": name }))) + } + fn model_enlist(&self, name: &str, class: &str) -> Fut<Value> { + self.call("classify.enlist", json!({ "name": name, "class": class })) + } + + // ---- spec models (docs/models.md; `models.*`) + fn spec_models(&self) -> Fut<Vec<Value>> { + typed(self.call("models.list", json!({}))) + } + fn spec_model(&self, name: &str) -> Fut<Value> { + self.call("models.get", json!({ "name": name })) + } + /// what making or saving a spec would say: `{ok}` or `{ok: false, path, message}` + fn check_spec(&self, spec: &str) -> Fut<Value> { + self.call("models.check", json!({ "spec": spec })) + } + fn create_spec(&self, spec: &str) -> Fut<Value> { + self.call("models.create", json!({ "spec": spec })) + } + fn update_spec(&self, name: &str, spec: &str) -> Fut<Value> { + self.call("models.update", json!({ "name": name, "spec": spec })) + } + fn delete_spec(&self, name: &str) -> Fut<()> { + unit(self.call("models.delete", json!({ "name": name }))) + } + fn train_spec(&self, name: &str, epochs: Option<u32>, fresh: bool) -> Fut<Value> { + self.call( + "models.train", + json!({ "name": name, "epochs": epochs, "fresh": fresh }), + ) + } + fn spec_job(&self, name: &str) -> Fut<Value> { + self.call("models.job", json!({ "name": name })) + } + fn cancel_spec(&self, name: &str) -> Fut<()> { + unit(self.call("models.cancel", json!({ "name": name }))) + } + /// every head's answer on a text + fn run_spec(&self, name: &str, text: &str) -> Fut<Value> { + self.call("models.run", json!({ "name": name, "text": text })) + } + /// candidates from a generator, judged by its critics; `opts` holds `candidates`, + /// `max_len`, `temperature`, `seed`, `guided` + fn generate_spec(&self, name: &str, prompt: &str, opts: Value) -> Fut<Value> { + let mut args = opts; + args["name"] = json!(name); + args["prompt"] = json!(prompt); + self.call("models.generate", args) + } + + /// the other members of the lists a word is in (synonyms, registers), with their sums + fn alternatives(&self, word: &str) -> Fut<Value> { + self.call("notes.alternatives", json!({ "word": word })) + } + + // ---- pictures (`pictures.*`) + /// the save's pictures (or a list's), each with a thumbnail fitting `thumb` pixels + fn pictures(&self, list: Option<&str>, thumb: u32) -> Fut<Vec<Value>> { + typed(self.call("pictures.list", json!({ "list": list, "thumb": thumb }))) + } + /// the lists that hold pictures: `[{list, count}]` + fn picture_lists(&self) -> Fut<Vec<Value>> { + typed(self.call("pictures.lists", json!({}))) + } + /// a picture file's bytes into the save (into `list` too, when given) + fn add_picture(&self, bytes: &[u8], name: &str, list: Option<&str>) -> Fut<Value> { + self.call( + "pictures.add", + json!({ "data": anend_core::classifiers::base64(bytes), "name": name, "list": list }), + ) + } + /// a picture file on this machine (the desktop) into the save + fn add_picture_path(&self, path: &str, list: Option<&str>) -> Fut<Value> { + self.call("pictures.add", json!({ "path": path, "list": list })) + } + fn tag_picture(&self, id: &str, list: &str, remove: bool) -> Fut<Value> { + self.call("pictures.tag", json!({ "id": id, "list": list, "remove": remove })) + } + fn delete_picture(&self, id: &str) -> Fut<()> { + unit(self.call("pictures.delete", json!({ "id": id }))) + } + + // ---- filters + fn filters(&self) -> Fut<Vec<FilterPreset>> { + typed(self.call("filters.list", json!({}))) + } + fn save_filter(&self, name: &str, expr: &Value, description: &str) -> Fut<()> { + unit(self.call( + "filters.save", + json!({ "name": name, "expr": expr, "description": description }), + )) + } + fn delete_filter(&self, name: &str) -> Fut<()> { + unit(self.call("filters.delete", json!({ "name": name }))) + } + fn run_filter(&self, expr: &Value) -> Fut<FilterRun> { + typed(self.call("filters.run", json!({ "expr": expr, "limit": 300 }))) + } + fn enlist_filter(&self, name: &str) -> Fut<Value> { + self.call("filters.enlist", json!({ "name": name })) + } + + // ---- settings kept in the save + fn setting(&self, name: &str) -> Fut<Option<String>> { + field(self.call("settings.get", json!({ "name": name })), "value") + } + fn set_setting(&self, name: &str, value: &str) -> Fut<()> { + unit(self.call("settings.set", json!({ "name": name, "value": value }))) + } +} diff --git a/app/src/fonts.rs b/app/src/fonts.rs new file mode 100644 index 00000000..cb122e55 --- /dev/null +++ b/app/src/fonts.rs @@ -0,0 +1,352 @@ +//! The Bevy app's faces, bundled: Fira Sans (regular, bold, italic) and Fira Mono, subset +//! to Latin, Greek and the common symbols (assets/fonts, from bevy_feathers; OFL). They go +//! into the page as `@font-face` rules with data URLs, so the desktop and the web look the +//! same whatever the system has installed. + +use std::sync::OnceLock; + +const FACES: [(&str, &str, &str, &[u8]); 4] = [ + ( + "Fira Sans", + "400", + "normal", + include_bytes!("../../assets/fonts/FiraSans-Regular.woff2"), + ), + ( + "Fira Sans", + "700", + "normal", + include_bytes!("../../assets/fonts/FiraSans-Bold.woff2"), + ), + ( + "Fira Sans", + "400", + "italic", + include_bytes!("../../assets/fonts/FiraSans-Italic.woff2"), + ), + ( + "Fira Mono", + "400", + "normal", + include_bytes!("../../assets/fonts/FiraMono-Medium.woff2"), + ), +]; + +pub fn base64(data: &[u8]) -> String { + const T: &[u8; 64] = b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + let mut out = String::with_capacity(data.len().div_ceil(3) * 4); + for c in data.chunks(3) { + let n = (c[0] as u32) << 16 | (*c.get(1).unwrap_or(&0) as u32) << 8 | *c.get(2).unwrap_or(&0) as u32; + out.push(T[(n >> 18) as usize & 63] as char); + out.push(T[(n >> 12) as usize & 63] as char); + out.push(if c.len() > 1 { + T[(n >> 6) as usize & 63] as char + } else { + '=' + }); + out.push(if c.len() > 2 { T[n as usize & 63] as char } else { '=' }); + } + out +} + +/// base64 back to bytes (standard alphabet, padding optional); None when it doesn't read +#[cfg_attr(not(target_arch = "wasm32"), allow(dead_code))] +pub fn unbase64(s: &str) -> Option<Vec<u8>> { + let mut out = Vec::with_capacity(s.len() / 4 * 3); + let (mut acc, mut bits) = (0u32, 0u32); + for c in s.bytes() { + let v = match c { + b'A'..=b'Z' => c - b'A', + b'a'..=b'z' => c - b'a' + 26, + b'0'..=b'9' => c - b'0' + 52, + b'+' => 62, + b'/' => 63, + b'=' | b'\n' | b'\r' => continue, + _ => return None, + }; + acc = acc << 6 | v as u32; + bits += 6; + if bits >= 8 { + bits -= 8; + out.push((acc >> bits) as u8); + acc &= (1 << bits) - 1; + } + } + Some(out) +} + +/// the `@font-face` rules, made once +pub fn css() -> &'static str { + static CSS: OnceLock<String> = OnceLock::new(); + CSS.get_or_init(|| { + FACES + .iter() + .map(|(family, weight, style, data)| { + format!( + "@font-face {{ font-family: \"{family}\"; font-weight: {weight}; font-style: {style}; font-display: block; src: url(data:font/woff2;base64,{}) format(\"woff2\"); }}\n", + base64(data) + ) + }) + .collect() + }) +} + +/// the families offered when the system's can't be listed (the web: a page can't see them) +pub const COMMON: [&str; 14] = [ + "Fira Sans", + "Inter", + "Noto Sans", + "DejaVu Sans", + "Liberation Sans", + "Ubuntu", + "Cantarell", + "Georgia", + "Times New Roman", + "Liberation Serif", + "DejaVu Serif", + "Noto Serif", + "Fira Mono", + "DejaVu Sans Mono", +]; + +#[cfg(not(target_arch = "wasm32"))] +static SYSTEM: OnceLock<Vec<String>> = OnceLock::new(); + +/// the families installed on this machine, alphabetically, once `scan_system` has found +/// them (None until then, and always on the web) +pub fn system() -> Option<&'static [String]> { + #[cfg(not(target_arch = "wasm32"))] + { + SYSTEM.get().map(Vec::as_slice) + } + #[cfg(target_arch = "wasm32")] + { + None + } +} + +/// finds the installed families on a thread of its own (the desktop's font folders, each +/// file's family name read from its `name` table) +#[cfg(not(target_arch = "wasm32"))] +pub fn scan_system() { + let _ = std::thread::Builder::new().name("anend fonts".into()).spawn(|| { + let _ = SYSTEM.set(families(&font_dirs())); + }); +} + +#[cfg(not(target_arch = "wasm32"))] +fn font_dirs() -> Vec<std::path::PathBuf> { + use std::path::PathBuf; + let home = std::env::var_os("HOME").map(PathBuf::from); + let mut dirs: Vec<PathBuf> = Vec::new(); + if cfg!(target_os = "windows") { + if let Some(w) = std::env::var_os("WINDIR") { + dirs.push(PathBuf::from(w).join("Fonts")); + } + if let Some(l) = std::env::var_os("LOCALAPPDATA") { + dirs.push(PathBuf::from(l).join("Microsoft").join("Windows").join("Fonts")); + } + } else if cfg!(target_os = "macos") { + dirs.extend(["/System/Library/Fonts", "/Library/Fonts"].map(PathBuf::from)); + dirs.extend(home.iter().map(|h| h.join("Library/Fonts"))); + } else { + dirs.extend(["/usr/share/fonts", "/usr/local/share/fonts"].map(PathBuf::from)); + let data = std::env::var_os("XDG_DATA_HOME") + .map(PathBuf::from) + .or_else(|| home.as_ref().map(|h| h.join(".local/share"))); + dirs.extend(data.map(|d| d.join("fonts"))); + dirs.extend(home.iter().map(|h| h.join(".fonts"))); + } + dirs +} + +/// every family name in the font files under `dirs` (a few levels down), alphabetically, +/// one of each ignoring case +#[cfg(not(target_arch = "wasm32"))] +pub fn families(dirs: &[std::path::PathBuf]) -> Vec<String> { + let mut found: std::collections::BTreeMap<String, String> = Default::default(); + let mut stack: Vec<(std::path::PathBuf, u32)> = dirs.iter().map(|d| (d.clone(), 0)).collect(); + let mut files = 0; + while let Some((dir, depth)) = stack.pop() { + for e in std::fs::read_dir(&dir).into_iter().flatten().flatten() { + let path = e.path(); + if e.file_type().is_ok_and(|t| t.is_dir()) { + if depth < 6 { + stack.push((path, depth + 1)); + } + continue; + } + let ext = path + .extension() + .and_then(|x| x.to_str()) + .unwrap_or("") + .to_ascii_lowercase(); + if !matches!(ext.as_str(), "ttf" | "otf" | "ttc" | "otc" | "pfb" | "pfa") || files > 20_000 { + continue; + } + files += 1; + let names = if ext.starts_with("pf") { + type1_family(&path).into_iter().collect() + } else { + file_families(&path) + }; + for name in names { + let name = name.trim().to_string(); + if !name.is_empty() && !name.starts_with('.') { + found.entry(name.to_lowercase()).or_insert(name); + } + } + } + } + found.into_values().collect() +} + +/// the family names in one font file (each face of a collection), reading only the +/// headers and the `name` table +#[cfg(not(target_arch = "wasm32"))] +fn file_families(path: &std::path::Path) -> Vec<String> { + use std::io::{Read, Seek, SeekFrom}; + let Ok(mut f) = std::fs::File::open(path) else { + return vec![]; + }; + let mut at = |off: u64, len: usize| -> Option<Vec<u8>> { + f.seek(SeekFrom::Start(off)).ok()?; + let mut b = vec![0; len]; + f.read_exact(&mut b).ok()?; + Some(b) + }; + let u16_at = |b: &[u8], i: usize| b.get(i..i + 2).map(|x| u16::from_be_bytes([x[0], x[1]])); + let u32_at = |b: &[u8], i: usize| b.get(i..i + 4).map(|x| u32::from_be_bytes([x[0], x[1], x[2], x[3]])); + let Some(head) = at(0, 12) else { return vec![] }; + let faces: Vec<u64> = if &head[0..4] == b"ttcf" { + let n = u32_at(&head, 8).unwrap_or(0).min(64) as usize; + let Some(offs) = at(12, n * 4) else { return vec![] }; + (0..n).filter_map(|i| u32_at(&offs, i * 4)).map(u64::from).collect() + } else { + vec![0] + }; + let mut out = Vec::new(); + for face in faces { + let Some(h) = at(face, 12) else { continue }; + let tables = u16_at(&h, 4).unwrap_or(0).min(200) as usize; + let Some(dir) = at(face + 12, tables * 16) else { + continue; + }; + let Some((off, len)) = (0..tables) + .find(|i| &dir[i * 16..i * 16 + 4] == b"name") + .and_then(|i| Some((u32_at(&dir, i * 16 + 8)?, u32_at(&dir, i * 16 + 12)?))) + else { + continue; + }; + let Some(t) = at(off as u64, (len as usize).min(1 << 20)) else { + continue; + }; + if let Some(name) = family_of(&t) { + out.push(name); + } + } + out +} + +/// a PostScript Type 1 font's family, from `/FamilyName (…)` in its clear-text start +#[cfg(not(target_arch = "wasm32"))] +fn type1_family(path: &std::path::Path) -> Option<String> { + use std::io::Read; + let mut b = vec![0; 8192]; + let n = std::fs::File::open(path).ok()?.read(&mut b).ok()?; + let text = String::from_utf8_lossy(&b[..n]); + let rest = &text[text.find("/FamilyName")? + 11..]; + let rest = &rest[rest.find('(')? + 1..]; + Some(rest[..rest.find(')')?].to_string()) +} + +/// a `name` table's family: the typographic family (16) when there is one, else the +/// family (1); Windows or Unicode English first, then the Mac's Roman +#[cfg(not(target_arch = "wasm32"))] +fn family_of(t: &[u8]) -> Option<String> { + let u16_at = |i: usize| t.get(i..i + 2).map(|x| u16::from_be_bytes([x[0], x[1]])); + let count = u16_at(2)? as usize; + let strings = u16_at(4)? as usize; + let mut best: Option<(u32, String)> = None; + for r in 0..count { + let b = 6 + r * 12; + let (platform, encoding, language, id, len, off) = ( + u16_at(b)?, + u16_at(b + 2)?, + u16_at(b + 4)?, + u16_at(b + 6)?, + u16_at(b + 8)?, + u16_at(b + 10)?, + ); + if id != 1 && id != 16 { + continue; + } + let Some(raw) = t.get(strings + off as usize..strings + off as usize + len as usize) else { + continue; + }; + let (text, rank) = match platform { + 0 | 3 => { + let units: Vec<u16> = raw.as_chunks::<2>().0.iter().map(|c| u16::from_be_bytes(*c)).collect(); + let english = platform == 0 || language == 0x409; + (String::from_utf16_lossy(&units), if english { 0 } else { 2 }) + } + 1 if encoding == 0 => (raw.iter().map(|&c| c as char).collect(), 1), + _ => continue, + }; + // the typographic family before the family, then the language's rank + let rank = rank + if id == 16 { 0 } else { 10 }; + if best.as_ref().is_none_or(|(r, _)| rank < *r) { + best = Some((rank, text)); + } + } + best.map(|(_, s)| s) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn encodes() { + assert_eq!(base64(b"Man"), "TWFu"); + assert_eq!(base64(b"Ma"), "TWE="); + assert_eq!(base64(b"M"), "TQ=="); + assert!(css().matches("@font-face").count() == 4); + for t in [&b""[..], b"M", b"Ma", b"Man", b"hello world \xff\x00"] { + assert_eq!(unbase64(&base64(t)).unwrap(), t); + } + assert!(unbase64("a$b").is_none()); + } + + #[cfg(not(target_arch = "wasm32"))] + #[test] + fn reads_font_families() { + // the repo's own faces are woff2 (not read); a TrueType file made by hand: one + // `name` table with a family (1) on the Mac and a typographic family (16) on Windows + let mut name = Vec::new(); + let mac = b"Plain Family"; + let win: Vec<u8> = "Típo".encode_utf16().flat_map(u16::to_be_bytes).collect(); + name.extend([0u16, 2, 6 + 2 * 12].iter().flat_map(|v| v.to_be_bytes())); + for (p, e, l, id, len, off) in [ + (1u16, 0u16, 0u16, 1u16, mac.len() as u16, 0u16), + (3, 1, 0x409, 16, win.len() as u16, mac.len() as u16), + ] { + name.extend([p, e, l, id, len, off].iter().flat_map(|v| v.to_be_bytes())); + } + name.extend(mac); + name.extend(&win); + let mut file = Vec::new(); + file.extend(0x0001_0000u32.to_be_bytes()); + file.extend([1u16, 0, 0, 0].iter().flat_map(|v| v.to_be_bytes())); + file.extend(b"name"); + file.extend([0u32, 12 + 16, name.len() as u32].iter().flat_map(|v| v.to_be_bytes())); + file.extend(&name); + let dir = std::env::temp_dir().join(format!("anend-fonts-{}", std::process::id())); + std::fs::create_dir_all(dir.join("sub")).unwrap(); + std::fs::write(dir.join("sub/a.ttf"), &file).unwrap(); + std::fs::write(dir.join("b.TTF"), &file).unwrap(); + std::fs::write(dir.join("c.txt"), b"no").unwrap(); + assert_eq!(families(std::slice::from_ref(&dir)), vec!["Típo".to_string()]); + let _ = std::fs::remove_dir_all(&dir); + } +} diff --git a/app/src/gem.rs b/app/src/gem.rs new file mode 100644 index 00000000..3c1ad5c8 --- /dev/null +++ b/app/src/gem.rs @@ -0,0 +1,321 @@ +//! The numbers the views show, computed in the app (no round trip): weum's sums, its +//! `gsum(text, 1)` line, `pfR`, `seedCLR`, the underline groups, the triangle and the byte +//! sum. weum's api.js and memory.js (docs/weum-reference) are the reference. + +use anend_core::{memory, spread, weum}; + +/// the gsearch modes (the memory view's buckets) +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "lowercase")] +pub enum Mode { + #[default] + Ordinal, + Reversed, + Frequency, +} + +impl Mode { + pub const ALL: [Mode; 3] = [Mode::Ordinal, Mode::Reversed, Mode::Frequency]; + + pub fn name(self) -> &'static str { + match self { + Mode::Ordinal => "ordinal", + Mode::Reversed => "reversed", + Mode::Frequency => "frequency", + } + } + + pub fn letter(self) -> &'static str { + match self { + Mode::Ordinal => "O", + Mode::Reversed => "R", + Mode::Frequency => "F", + } + } + + /// the sum whose shared values colour the underlines in this mode: ordinal by + /// reversed groups, reversed by ordinal groups (weum), frequency by ordinal ones + pub fn grouping(self) -> Mode { + match self { + Mode::Ordinal => Mode::Reversed, + Mode::Reversed | Mode::Frequency => Mode::Ordinal, + } + } +} + +/// a text's numbers +#[derive(Debug, Clone, PartialEq, Default)] +pub struct Measure { + pub ordinal: u64, + pub reversed: u64, + /// weum's letter table (`e1i1l1n1s1t1`) + pub frequency: String, + /// every byte counted as 1 to 256 (a separate measure, not a mode) + pub bytes: u64, +} + +impl Measure { + pub fn of(text: &str) -> Measure { + let m = memory::measure(text); + let (s, r) = spread::sums(text); + Measure { + ordinal: s.max(0) as u64, + reversed: r.max(0) as u64, + frequency: m.frequency, + bytes: byte_sum(text), + } + } + + /// weum's ⌊√(ordinal · reversed)⌋, the triangle's third side and Ctrl+right click's + /// gsearch + pub fn triangle(&self) -> u64 { + ((self.ordinal as f64) * (self.reversed as f64)).sqrt().floor() as u64 + } +} + +/// the sum of a text's bytes, each counted as its value plus one (1 to 256) +pub fn byte_sum(text: &str) -> u64 { + text.bytes().map(|b| b as u64 + 1).sum() +} + +/// weum's ordinal and reversed sums (`gsum(t, 3)`) +pub fn sums(text: &str) -> (u64, u64) { + let (s, r) = spread::sums(text); + (s.max(0) as u64, r.max(0) as u64) +} + +/// the sum a text gsearches by in a mode +pub fn sum_in(text: &str, mode: Mode) -> u64 { + match mode { + Mode::Ordinal => sums(text).0, + Mode::Reversed => sums(text).1, + Mode::Frequency => sums(text).0, + } +} + +/// weum's letter table as the letters themselves: e1i1l1n1s1t1 → eilnst +pub fn letters(freq: &str) -> String { + let mut out = String::new(); + let mut chars = freq.chars().peekable(); + while let Some(c) = chars.next() { + let mut n = String::new(); + while let Some(d) = chars.peek().filter(|d| d.is_ascii_digit()) { + n.push(*d); + chars.next(); + } + let k: usize = n.parse().unwrap_or(1); + for _ in 0..k.min(64) { + out.push(c); + } + } + out +} + +fn vowel(c: char) -> u64 { + match c { + 'a' => 1, + 'e' => 2, + 'o' => 3, + 'u' => 4, + 'i' => 5, + 'y' => 6, + _ => 0, + } +} + +fn consonant(c: char) -> u64 { + // weum's table, with t and v as separate values (t 16, v 17), as the user corrected it + match c { + 'b' => 1, + 'c' => 2, + 'd' => 3, + 'f' => 4, + 'g' => 5, + 'h' => 6, + 'j' => 7, + 'k' => 8, + 'l' => 9, + 'm' => 10, + 'n' => 11, + 'p' => 12, + 'q' => 13, + 'r' => 14, + 's' => 15, + 't' => 16, + 'v' => 17, + 'w' => 18, + 'x' => 19, + 'z' => 20, + _ => 0, + } +} + +/// weum's `gsum(text, 1)`, letter for letter: +/// `(s + r = t; * p; *sqrt(q); diff d, a b c) v vowels c consonants w words` +pub fn gsum_line(text: &str) -> String { + let (sum, r) = sums(text); + let (sum, r) = (sum as i64, r as i64); + let (mut v, mut c) = (0, 0); + for ch in text.chars().flat_map(char::to_lowercase) { + v += vowel(ch); + c += consonant(ch); + } + let words = text.split_whitespace().count().max(1); + let a = (sum + r) + (sum - r).abs(); + let b = (sum + r) + (sum - r); + format!( + "({} + {} = {}; * {}; *sqrt({:.3}); diff {}, {} {} {}) v {} c {} w {}", + sum, + r, + sum + r, + sum * r, + ((sum * r) as f64).sqrt(), + sum - r, + a, + b, + a - b, + v, + c, + words + ) +} + +/// weum's `pfR(s)` as pieces; numbers are clickable +pub fn pf_line(s: u64) -> Vec<weum::Seg> { + if s < 2 { Vec::new() } else { weum::pf_reduction(s) } +} + +/// weum's `seedCLR(m)`: a hue from the string of `m` (JavaScript's 32 bit string hash) +pub fn seed_hue(key: &str) -> u32 { + let mut hash: i32 = 0; + for c in key.encode_utf16() { + hash = (c as i32).wrapping_add(hash.wrapping_shl(5).wrapping_sub(hash)); + } + (hash % 360).unsigned_abs() +} + +/// `hsl(hue, 70%, 45%)`, weum's underline colour for a group key +pub fn seed_clr(key: &str) -> String { + format!("hsl({}, 70%, 45%)", seed_hue(key)) +} + +/// the underline colour weum's `baroeskwidjel` gives a text in a mode: the colour of its +/// grouping sum, when that sum's string is two or more characters long (weum checks the +/// key's length, so a lone text with a two digit sum is underlined too) +pub fn underline(text: &str, mode: Mode) -> Option<String> { + let key = sum_in(text, mode.grouping()).to_string(); + (key.len() >= 2).then(|| seed_clr(&key)) +} + +/// the triangle with sides s, r and t = ⌊√(s·r)⌋ as an svg polygon fitted to a box: +/// `(width, height, points, real)`. When the three can't close, the flat shape they come +/// closest to (`real` false), drawn dashed. +pub fn triangle_points(s: u64, r: u64, height: f64, max_width: f64) -> Option<(f64, f64, String, bool)> { + let t = ((s as f64) * (r as f64)).sqrt().floor(); + let (s, r) = (s as f64, r as f64); + if !(s > 0.0 && r > 0.0 && t > 0.0) { + return None; + } + let real = s < r + t && r < s + t && t < s + r; + let x = ((s * s + t * t - r * r) / (2.0 * s)).clamp(-t, t); + let y = if real { (t * t - x * x).max(0.0).sqrt() } else { 0.0 }; + let min_x = x.min(0.0); + let max_x = x.max(s); + let w = max_x - min_x; + let pad = 2.0; + let k = ((height - pad * 2.0) / y.max(1e-9)).min((max_width - pad * 2.0) / w); + let ww = w * k + pad * 2.0; + let hh = if real { y * k + pad * 2.0 } else { height }; + let base = if real { hh - pad } else { hh / 2.0 }; + let p = |px: f64, py: f64| format!("{:.1},{:.1}", (px - min_x) * k + pad, base - py * k); + Some((ww, hh, format!("{} {} {}", p(0.0, 0.0), p(s, 0.0), p(x, y)), real)) +} + +/// the triangle's angles, or why it lies flat, for its tooltip +/// the triangle in a few characters for the top line: its sides and angles, or that it +/// lies flat (the Bevy app's `s r t · a° b° c°`) +pub fn triangle_short(s: u64, r: u64) -> String { + let t = ((s as f64) * (r as f64)).sqrt().floor(); + let (sf, rf) = (s as f64, r as f64); + if !(sf < rf + t && rf < sf + t && t < sf + rf) { + return format!("{s} {r} {t} lie flat"); + } + let deg = |v: f64| v.clamp(-1.0, 1.0).acos().to_degrees(); + format!( + "{s} {r} {t} · {:.0}° {:.0}° {:.0}°", + deg((sf * sf + t * t - rf * rf) / (2.0 * sf * t)), + deg((sf * sf + rf * rf - t * t) / (2.0 * sf * rf)), + deg((rf * rf + t * t - sf * sf) / (2.0 * rf * t)), + ) +} + +pub fn triangle_title(s: u64, r: u64) -> String { + let t = ((s as f64) * (r as f64)).sqrt().floor(); + let (sf, rf) = (s as f64, r as f64); + let real = sf < rf + t && rf < sf + t && t < sf + rf; + let deg = |v: f64| v.clamp(-1.0, 1.0).acos().to_degrees(); + if real { + format!( + "s {s}, r {r}, t = ⌊√(s·r)⌋ {t}\nangles {:.1}° (facing r), {:.1}° (facing t), {:.1}° (facing s)", + deg((sf * sf + t * t - rf * rf) / (2.0 * sf * t)), + deg((sf * sf + rf * rf - t * t) / (2.0 * sf * rf)), + deg((rf * rf + t * t - sf * sf) / (2.0 * rf * t)), + ) + } else { + let m = sf.max(rf).max(t); + format!( + "s {s}, r {r}, t = ⌊√(s·r)⌋ {t}\nnot a triangle: {m} is at least the other two sides together ({}), so it lies flat", + sf + rf + t - m + ) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn weum_numbers() { + assert_eq!(sums("listen"), (79, 83)); + assert_eq!(Measure::of("listen").triangle(), 80); + // the JavaScript string hash, as weum's seedCLR + assert_eq!( + seed_hue("83"), + ("83" + .encode_utf16() + .fold(0i32, |h, c| (c as i32).wrapping_add((h << 5) - h)) + % 360) + .unsigned_abs() + ); + assert_eq!(seed_clr("345"), "hsl(276, 70%, 45%)"); + assert_eq!(letters("e1i1l1n1s1t1"), "eilnst"); + assert_eq!(byte_sum("ab"), 97 + 1 + 98 + 1); + } + + #[test] + fn gsum_like_weum() { + // weum: gsum('listen', 1) + assert_eq!( + gsum_line("listen"), + "(79 + 83 = 162; * 6557; *sqrt(80.975); diff -4, 166 158 8) v 7 c 51 w 1" + ); + } + + #[test] + fn underline_groups() { + // ordinal mode groups by reversed: listen's reversed is 83 + assert_eq!(underline("listen", Mode::Ordinal), Some(seed_clr("83"))); + assert_eq!(underline("listen", Mode::Reversed), Some(seed_clr("79"))); + // a one digit grouping sum isn't underlined ("a": reversed 26, ordinal 1) + assert_eq!(underline("a", Mode::Reversed), None); + assert!(underline("a", Mode::Ordinal).is_some()); + } + + #[test] + fn triangles() { + let (_, _, pts, real) = triangle_points(87, 48, 22.0, 64.0).unwrap(); + assert!(real && pts.split(' ').count() == 3); + assert!(!triangle_points(1, 26, 22.0, 64.0).unwrap().3); + assert!(triangle_points(0, 0, 22.0, 64.0).is_none()); + } +} diff --git a/app/src/highlight.rs b/app/src/highlight.rs new file mode 100644 index 00000000..93c4fcf8 --- /dev/null +++ b/app/src/highlight.rs @@ -0,0 +1,1018 @@ +//! Markdown highlighting in the note editor, ported from the Bevy app's highlight.rs: a +//! class for every byte of the text, line by line ([`classify`]), and the text as HTML +//! spans of those classes ([`to_html`]) for the layer painted under the editor's textarea, +//! whose own glyphs are transparent (so editing, the caret, selection and input methods +//! stay the textarea's). The colours come from the palette (theme.rs `hl_vars`), each +//! darkened or lightened until it reads on the writing pad. Spelling and grammar marks +//! (`Mark`s) are underlined over the same layer. + +/// what a stretch of markdown is +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[repr(u8)] +pub enum Class { + Plain, + /// syntax: the `#`s, `*`s, brackets and backticks around things + Mark, + Heading, + Strong, + Emph, + Strike, + Code, + Link, + Url, + /// a list item's bullet or number + List, + /// a quote's text (its `>` is a [`Class::Quote`] too) + Quote, + /// a table's pipes and its alignment row + Table, + Tag, + Rule, + /// s code (docs/s.md): a command + SCommand, + /// the suffix character of a suffix form (`x.`, `x~`, `x$`…) + SSuffix, + /// a brace or quote literal, an angle word + SLiteral, + /// a local name (`:x`) + SLocal, + SNumber, + /// a word of s's library + SLibrary, + /// an escape (`\w`) + SEscape, +} + +/// a class for every byte of `text` +pub fn classify(text: &str) -> Vec<Class> { + let mut out = vec![Class::Plain; text.len()]; + let mut fence: Option<(u8, usize)> = None; + let mut start = 0; + for line in text.split_inclusive('\n') { + let end = start + line.len(); + let body = line.trim_end_matches(['\n', '\r']); + classify_line(body, start, &mut out, &mut fence); + start = end; + } + out +} + +fn fill(out: &mut [Class], range: std::ops::Range<usize>, c: Class) { + let end = range.end.min(out.len()); + if range.start < end { + out[range.start..end].fill(c); + } +} + +/// a fence's char and length, if the line opens or closes one +fn fence_of(line: &str) -> Option<(u8, usize)> { + let t = line.trim_start(); + if line.len() - t.len() > 3 { + return None; + } + let ch = *t.as_bytes().first()?; + if ch != b'`' && ch != b'~' { + return None; + } + let n = t.bytes().take_while(|b| *b == ch).count(); + (n >= 3).then_some((ch, n)) +} + +fn classify_line(line: &str, at: usize, out: &mut [Class], fence: &mut Option<(u8, usize)>) { + let span = at..at + line.len(); + // fenced code + if let Some((ch, n)) = *fence { + fill(out, span.clone(), Class::Code); + if let Some((c2, n2)) = fence_of(line) + && c2 == ch + && n2 >= n + && line.trim().bytes().all(|b| b == ch) + { + fill(out, span, Class::Mark); + *fence = None; + } + return; + } + if let Some(f) = fence_of(line) + && !(f.0 == b'`' && line.trim_start()[f.1..].contains('`')) + { + *fence = Some(f); + fill(out, span, Class::Mark); + return; + } + let trimmed = line.trim_start(); + let indent = line.len() - trimmed.len(); + // indented code (4 spaces or a tab, not inside a list item's text) + if (line.starts_with(" ") || line.starts_with('\t')) && !trimmed.is_empty() && !is_list(trimmed) { + fill(out, span, Class::Code); + return; + } + // headings + let hashes = trimmed.bytes().take_while(|b| *b == b'#').count(); + if (1..=6).contains(&hashes) && indent < 4 && trimmed[hashes..].chars().next().is_none_or(|c| c == ' ' || c == '\t') + { + let mark_end = at + indent + hashes; + fill(out, span.clone(), Class::Heading); + fill(out, at..mark_end, Class::Mark); + inline(line, at, indent + hashes, out, Class::Heading); + // a closing run of #s is syntax too + let t = line.trim_end(); + let closing = t.bytes().rev().take_while(|b| *b == b'#').count(); + if closing > 0 && closing < t.len() - indent - hashes && t.as_bytes()[t.len() - closing - 1] == b' ' { + fill(out, at + t.len() - closing..at + t.len(), Class::Mark); + } + return; + } + // rules + let compact: String = trimmed.chars().filter(|c| !c.is_whitespace()).collect(); + if compact.len() >= 3 + && indent < 4 + && let Some(first) = compact.chars().next() + && matches!(first, '-' | '*' | '_') + && compact.chars().all(|c| c == first) + { + fill(out, span, Class::Rule); + return; + } + // quotes: each > is a mark, the rest quoted text (which can still hold a list or inline marks) + let mut i = indent; + let mut base = Class::Plain; + while line[i..].starts_with('>') { + fill(out, at + i..at + i + 1, Class::Quote); + base = Class::Quote; + i += 1; + while line[i..].starts_with(' ') { + i += 1; + } + } + if base == Class::Quote { + fill(out, at + i..span.end, Class::Quote); + } + // tables: pipes, and the alignment row + let rest = &line[i..]; + if rest.trim_start().starts_with('|') { + let is_align = rest.trim().bytes().all(|b| matches!(b, b'|' | b'-' | b':' | b' ')); + if is_align { + fill(out, at + i..span.end, Class::Table); + return; + } + inline(line, at, i, out, base); + for (j, b) in rest.bytes().enumerate() { + if b == b'|' && out[at + i + j] != Class::Code { + fill(out, at + i + j..at + i + j + 1, Class::Table); + } + } + return; + } + // list items: the bullet or number, and a task box + let lead = rest.len() - rest.trim_start().len(); + let item = &rest[lead..]; + if let Some(m) = list_marker(item) { + let s = at + i + lead; + fill(out, s..s + m, Class::List); + let mut k = i + lead + m; + let after = &line[k..]; + let t = after.trim_start(); + if t.starts_with("[ ]") || t.starts_with("[x]") || t.starts_with("[X]") { + let o = k + after.len() - t.len(); + fill(out, at + o..at + o + 3, Class::List); + k = o + 3; + } + inline(line, at, k, out, base); + return; + } + inline(line, at, i, out, base); +} + +fn is_list(t: &str) -> bool { + list_marker(t).is_some() +} + +/// the length of a list marker at the start of `t` (with its space), if there is one +fn list_marker(t: &str) -> Option<usize> { + let b = t.as_bytes(); + if b.len() >= 2 && matches!(b[0], b'-' | b'*' | b'+') && (b[1] == b' ' || b[1] == b'\t') { + return Some(1); + } + let digits = b.iter().take_while(|c| c.is_ascii_digit()).count(); + if (1..=9).contains(&digits) + && b.len() > digits + 1 + && matches!(b[digits], b'.' | b')') + && (b[digits + 1] == b' ' || b[digits + 1] == b'\t') + { + return Some(digits + 1); + } + None +} + +/// inline marks from byte `from` of the line on: code spans, links, emphasis, tags +fn inline(line: &str, at: usize, from: usize, out: &mut [Class], base: Class) { + let b = line.as_bytes(); + let n = b.len(); + let mut i = from; + // open emphasis runs: (char, run length, the position after the run) + let mut open: Vec<(u8, usize, usize)> = Vec::new(); + while i < n { + let c = b[i]; + match c { + b'\\' if i + 1 < n && b[i + 1].is_ascii_punctuation() => { + fill(out, at + i..at + i + 1, Class::Mark); + i += 2; + } + b'`' => { + let run = b[i..].iter().take_while(|x| **x == b'`').count(); + // the matching run of the same length closes it + let mut j = i + run; + let mut close = None; + while j < n { + if b[j] == b'`' { + let r = b[j..].iter().take_while(|x| **x == b'`').count(); + if r == run { + close = Some(j); + break; + } + j += r; + } else { + j += 1; + } + } + match close { + Some(j) => { + fill(out, at + i..at + j + run, Class::Code); + fill(out, at + i..at + i + run, Class::Mark); + fill(out, at + j..at + j + run, Class::Mark); + i = j + run; + } + None => i += run, + } + } + b'[' => match link_end(line, i) { + Some((text_end, url_end)) => { + let link_class = if base == Class::Heading { + Class::Heading + } else { + Class::Link + }; + fill(out, at + i..at + i + 1, Class::Mark); + fill(out, at + i + 1..at + text_end, link_class); + inline(&line[..text_end], at, i + 1, out, link_class); + fill(out, at + text_end..at + text_end + 2, Class::Mark); + fill(out, at + text_end + 2..at + url_end, Class::Url); + fill(out, at + url_end..at + url_end + 1, Class::Mark); + i = url_end + 1; + } + None => i += 1, + }, + b'<' if line[i + 1..].starts_with("http://") || line[i + 1..].starts_with("https://") => { + match line[i..].find('>') { + Some(k) => { + fill(out, at + i..at + i + k + 1, Class::Url); + i += k + 1; + } + None => i += 1, + } + } + b'h' if (line[i..].starts_with("http://") || line[i..].starts_with("https://")) + && (i == 0 || !b[i - 1].is_ascii_alphanumeric()) => + { + let len = line[i..] + .find(|c: char| c.is_whitespace() || c == ')' || c == '>') + .unwrap_or(n - i); + fill(out, at + i..at + i + len, Class::Url); + i += len; + } + b'#' if (i == 0 || b[i - 1] == b' ' || b[i - 1] == b'\t' || b[i - 1] == b'(') + && line[i + 1..] + .chars() + .next() + .is_some_and(|c| c.is_alphanumeric() || c == '_') => + { + let len = 1 + line[i + 1..] + .find(|c: char| !(c.is_alphanumeric() || matches!(c, '_' | '-' | '/' | '.'))) + .unwrap_or(n - i - 1); + // a trailing dot ends a sentence, not the tag + let len = len - usize::from(line[i..i + len].ends_with('.')); + fill(out, at + i..at + i + len, Class::Tag); + i += len; + } + b'*' | b'_' | b'~' => { + let run = b[i..].iter().take_while(|x| **x == c).count(); + let prev = if i == 0 { b' ' } else { b[i - 1] }; + let next = if i + run < n { b[i + run] } else { b' ' }; + // _ inside a word (snake_case) isn't emphasis + let intraword = c == b'_' && prev.is_ascii_alphanumeric() && next.is_ascii_alphanumeric(); + if c == b'~' && run != 2 || intraword { + i += run; + continue; + } + let can_close = !prev.is_ascii_whitespace(); + let can_open = !next.is_ascii_whitespace(); + let opener = open + .iter() + .rposition(|(oc, orun, _)| *oc == c && (*orun == run || run >= 2 && *orun >= 2)); + if can_close && let Some(k) = opener { + let (_, orun, after) = open[k]; + let used = orun.min(run); + let class = match (c, used) { + (b'~', _) => Class::Strike, + (_, 1) => Class::Emph, + _ => Class::Strong, + }; + for x in &mut out[at + after..at + i] { + // inner marks and code stay what they are + if matches!(*x, Class::Plain | Class::Quote | Class::Heading) + || (class == Class::Strong && *x == Class::Emph) + { + *x = class; + } + } + fill(out, at + after - used..at + after, Class::Mark); + fill(out, at + i..at + i + used, Class::Mark); + open.truncate(k); + i += run; + } else { + if can_open { + open.push((c, run, i + run)); + } + i += run; + } + } + _ => { + // step over a whole character + i += line[i..].chars().next().map_or(1, char::len_utf8); + } + } + } +} + +/// for a `[` at `i`: where its `](` is and where the `)` closing the url is +fn link_end(line: &str, i: usize) -> Option<(usize, usize)> { + let b = line.as_bytes(); + let mut depth = 0; + let mut j = i; + while j < b.len() { + match b[j] { + b'[' => depth += 1, + b']' => { + depth -= 1; + if depth == 0 { + break; + } + } + _ => {} + } + j += 1; + } + if j >= b.len() || b.get(j + 1) != Some(&b'(') { + return None; + } + let close = line[j + 2..].find(')')?; + Some((j, j + 2 + close)) +} + +impl Class { + /// the CSS class of a span of this class + pub fn css(self) -> &'static str { + match self { + Class::Plain => "", + Class::Mark => "h-m", + Class::Heading => "h-h", + Class::Strong => "h-s", + Class::Emph => "h-e", + Class::Strike => "h-x", + Class::Code => "h-c", + Class::Link => "h-l", + Class::Url => "h-u", + Class::List => "h-li", + Class::Quote => "h-q", + Class::Table => "h-t", + Class::Tag => "h-g", + Class::Rule => "h-r", + Class::SCommand => "h-sc", + Class::SSuffix => "h-ss", + Class::SLiteral => "h-sl", + Class::SLocal => "h-sv", + Class::SNumber => "h-sn", + Class::SLibrary => "h-sb", + Class::SEscape => "h-se", + } + } +} + +/// a stretch of the text the checker flagged: bytes `start..end`, what it is, and a title +#[derive(Clone, Debug, PartialEq)] +pub struct Flag { + pub start: usize, + pub end: usize, + pub kind: &'static str, + pub title: String, +} + +fn escape(s: &str, out: &mut String) { + for ch in s.chars() { + match ch { + '&' => out.push_str("&"), + '<' => out.push_str("<"), + '>' => out.push_str(">"), + '"' => out.push_str("""), + c => out.push(c), + } + } +} + +/// the text as HTML: runs of one class in a span each (plain text bare), flagged +/// stretches inside a `mark`; a trailing newline gets a space after it so the layer is as +/// tall as the textarea's content +/// a text cut into typing segments for the colour layer: each ends after a blank line +/// that is outside a code fence, so a segment highlights the same on its own as inside +/// the whole text (a fence is the only state that carries from line to line). The +/// segments joined are the text. +pub fn segments(text: &str) -> Vec<&str> { + segments_open(text).0 +} + +/// `segments`, and whether the text ends inside a code fence (so text after it would be +/// code too) +pub fn segments_open(text: &str) -> (Vec<&str>, bool) { + let mut out = Vec::new(); + let mut fence: Option<(u8, usize)> = None; + let (mut start, mut at) = (0, 0); + let mut prev_blank = false; + for line in text.split_inclusive('\n') { + let body = line.trim_end_matches(['\n', '\r']); + let blank = body.trim().is_empty(); + // a segment starts at the first non-blank line after blank ones + if !blank && prev_blank && fence.is_none() && at > start { + out.push(&text[start..at]); + start = at; + } + match fence { + Some((ch, n)) => { + if let Some((c2, n2)) = fence_of(body) + && c2 == ch + && n2 >= n + && body.trim().bytes().all(|b| b == ch) + { + fence = None; + } + } + None => { + if let Some(f) = fence_of(body) + && !(f.0 == b'`' && body.trim_start()[f.1..].contains('`')) + { + fence = Some(f); + } + } + } + prev_blank = blank; + at += line.len(); + } + if start < text.len() || out.is_empty() { + out.push(&text[start..]); + } + (out, fence.is_some()) +} + +/// the colour layer of a text kept as its typing segments, so an edit re-colours only +/// the segments around it. Every segment starts outside a code fence, so cutting again +/// from a segment's start is exact; an edit that leaves a fence open runs to the end. +#[derive(Default)] +pub struct Layer { + pub segs: Vec<String>, + /// the text is s code (a note tagged `s`): coloured by s's word classes, whole + pub s: bool, + /// s code's inline results, by line (dropped when the text changes) + pub notes: std::collections::BTreeMap<usize, String>, + /// the token a stepped run stopped before (dropped when the text changes) + pub at: Option<std::ops::Range<usize>>, +} + +impl Layer { + /// every segment's html, for a whole new text + pub fn full(&mut self, text: &str, colour: bool, flags: &[Flag]) -> Vec<String> { + if self.s { + self.segs = vec![text.to_string()]; + return vec![s_html_with(text, colour, &self.notes, self.at.clone())]; + } + self.segs = segments(text).into_iter().map(str::to_string).collect(); + let mut at = 0; + self.segs + .iter() + .map(|seg| { + let end = at + seg.len(); + let fl: Vec<Flag> = flags + .iter() + .filter(|f| f.start >= at && f.end <= end) + .map(|f| Flag { + start: f.start - at, + end: f.end - at, + ..f.clone() + }) + .collect(); + at = end; + part_html(seg, colour, &fl) + }) + .collect() + } + + /// bytes `a..b` of the text replaced by `ins`: the segments that changed, as (first + /// index, how many went, the new ones' html); None when there's no layer to edit + pub fn edit(&mut self, a: usize, b: usize, ins: &str, colour: bool) -> Option<(usize, usize, Vec<String>)> { + if self.segs.is_empty() { + return None; + } + if self.s { + // code is coloured whole (a brace literal may span blank lines) + let mut t = self.segs.concat(); + if b > t.len() || a > b || !t.is_char_boundary(a) || !t.is_char_boundary(b) { + return None; + } + t.replace_range(a..b, ins); + let went = self.segs.len(); + // what ran belonged to the text as it was + self.notes.clear(); + self.at = None; + let html = s_html(&t, colour); + self.segs = vec![t]; + return Some((0, went, vec![html])); + } + let n = self.segs.len(); + let mut starts = Vec::with_capacity(n); + let mut acc = 0; + for s in &self.segs { + starts.push(acc); + acc += s.len(); + } + if b > acc || a > b { + return None; + } + let within = |x: usize| starts.iter().rposition(|&st| st <= x).unwrap_or(0); + let i0 = within(a).saturating_sub(1); + let mut j1 = (within(b) + 1).min(n - 1); + let base = starts[i0]; + let mut local = self.segs[i0..=j1].concat(); + if a - base > local.len() || b - base > local.len() { + return None; + } + local.replace_range(a - base..b - base, ins); + let (mut cut, open) = segments_open(&local); + let mut owned: Vec<String>; + if open && j1 < n - 1 { + // a fence left open swallows the rest: cut again to the end + local.push_str(&self.segs[j1 + 1..].concat()); + j1 = n - 1; + cut = segments_open(&local).0; + } + owned = cut.into_iter().map(str::to_string).collect(); + let html: Vec<String> = owned.iter().map(|s| part_html(s, colour, &[])).collect(); + let went = j1 - i0 + 1; + self.segs.splice(i0..=j1, owned.drain(..)); + Some((i0, went, html)) + } + + #[cfg(test)] + pub fn text(&self) -> String { + self.segs.concat() + } +} + +/// a class for every byte of s code: commands, suffix forms (the stem plain or local, the +/// suffix marked), literals, locals, numbers, library words, escapes +pub fn s_classes(text: &str) -> Vec<Class> { + use anend_core::s::machine::{SUFFIXES, is_command}; + let library: std::collections::HashSet<&str> = + anend_core::s::lib::words().into_iter().flat_map(|(_, w)| w).collect(); + let mut out = vec![Class::Plain; text.len()]; + let b = text.as_bytes(); + let mut i = 0; + while i < b.len() { + let c = b[i]; + if c.is_ascii_whitespace() { + i += 1; + continue; + } + // a word, up to whitespace or a literal + let start = i; + while i < b.len() && !b[i].is_ascii_whitespace() && b[i] != b'{' && b[i] != b'\'' { + i += 1; + } + if i < b.len() && (b[i] == b'{' || b[i] == b'\'') { + // a literal (with its prefix) + let end = if b[i] == b'\'' { + b[i + 1..] + .iter() + .position(|&x| x == b'\'') + .map_or(b.len(), |p| i + 2 + p) + } else { + let mut depth = 0usize; + let mut j = i; + while j < b.len() { + match b[j] { + b'{' => depth += 1, + b'}' => { + depth -= 1; + if depth == 0 { + break; + } + } + _ => {} + } + j += 1; + } + (j + 1).min(b.len()) + }; + out[start..end].fill(Class::SLiteral); + i = end; + continue; + } + let w = &text[start..i]; + let class = if is_command(w) { + Class::SCommand + } else if w.len() >= 2 && w.starts_with('\\') { + Class::SEscape + } else if w.starts_with('⟨') { + Class::SLiteral + } else if library.contains(w) { + Class::SLibrary + } else if w.parse::<f64>().is_ok() { + Class::SNumber + } else if w.starts_with(':') && w.len() > 1 { + Class::SLocal + } else { + Class::Plain + }; + out[start..i].fill(class); + // a suffix form: its last character marked + if !matches!(class, Class::SCommand | Class::SEscape | Class::SLiteral) + && w.chars().count() >= 2 + && let Some(last) = w.chars().last() + && SUFFIXES.contains(&last) + { + let at = i - last.len_utf8(); + out[at..i].fill(Class::SSuffix); + } + } + out +} + +/// s code as the colour layer's html +pub fn s_html(text: &str, colour: bool) -> String { + s_html_with(text, colour, &std::collections::BTreeMap::new(), None) +} + +/// s code as the colour layer's html, with what the code editor adds: inline results at +/// the start of their lines (`notes`, by line; drawn at the pad's left edge without +/// moving the text) and the token a stepped run stopped before (`at`, marked) +pub fn s_html_with( + text: &str, + colour: bool, + notes: &std::collections::BTreeMap<usize, String>, + at: Option<std::ops::Range<usize>>, +) -> String { + let classes = if colour { + s_classes(text) + } else { + vec![Class::Plain; text.len()] + }; + let at = at.filter(|r| { + r.start < r.end && r.end <= text.len() && text.is_char_boundary(r.start) && text.is_char_boundary(r.end) + }); + let cut = |i: usize| { + at.as_ref().is_some_and(|r| r.start == i || r.end == i) || (i > 0 && text.as_bytes()[i - 1] == b'\n') + }; + let mut out = String::with_capacity(text.len() * 2); + let mut line = 0; + let mut a = 0; + if text.is_empty() + && let Some(n) = notes.get(&0) + { + note_html(n, &mut out); + } + while a < text.len() { + if a == 0 || text.as_bytes()[a - 1] == b'\n' { + if a > 0 { + line += 1; + } + if let Some(n) = notes.get(&line) { + note_html(n, &mut out); + } + } + if at.as_ref().is_some_and(|r| r.start == a) { + out.push_str("<mark class=\"s-at\">"); + } + let mut b = a + 1; + while b < text.len() && !cut(b) && (classes[b] == classes[a] || !text.is_char_boundary(b)) { + b += 1; + } + let css = classes[a].css(); + if css.is_empty() { + escape(&text[a..b], &mut out); + } else { + out.push_str("<span class=\""); + out.push_str(css); + out.push_str("\">"); + escape(&text[a..b], &mut out); + out.push_str("</span>"); + } + if at.as_ref().is_some_and(|r| r.end == b) { + out.push_str("</mark>"); + } + a = b; + } + out +} + +/// an inline result: drawn at the line's start, at the pad's left edge, taking no room +fn note_html(n: &str, out: &mut String) { + out.push_str("<span class=\"s-note\" aria-hidden=\"true\">"); + escape(n, out); + out.push_str("</span>"); +} + +#[cfg(test)] +pub fn to_html(text: &str, colour: bool, flags: &[Flag]) -> String { + let mut out = part_html(text, colour, flags); + // a last empty line keeps its height in the layer + if text.ends_with('\n') || text.is_empty() { + out.push(' '); + } + out +} + +/// `to_html` of one segment of a text (`segments`): the same, without the space a whole +/// text's empty last line gets +pub fn part_html(text: &str, colour: bool, flags: &[Flag]) -> String { + let classes = if colour { + classify(text) + } else { + vec![Class::Plain; text.len()] + }; + let mut out = String::with_capacity(text.len() * 2); + // the boundaries: where the class changes or a flag starts or ends + let mut cuts: Vec<usize> = vec![0, text.len()]; + for i in 1..text.len() { + if classes[i] != classes[i - 1] { + cuts.push(i); + } + } + for f in flags { + cuts.push(f.start.min(text.len())); + cuts.push(f.end.min(text.len())); + } + cuts.retain(|&c| text.is_char_boundary(c)); + cuts.sort_unstable(); + cuts.dedup(); + for w in cuts.windows(2) { + let (a, b) = (w[0], w[1]); + if a == b { + continue; + } + let piece = &text[a..b]; + let flag = flags.iter().find(|f| f.start <= a && b <= f.end); + if let Some(f) = flag { + out.push_str("<mark class=\"flag "); + out.push_str(f.kind); + out.push_str("\" title=\""); + escape(&f.title, &mut out); + out.push_str("\">"); + } + let css = classes[a].css(); + if css.is_empty() { + escape(piece, &mut out); + } else { + out.push_str("<span class=\""); + out.push_str(css); + out.push_str("\">"); + escape(piece, &mut out); + out.push_str("</span>"); + } + if flag.is_some() { + out.push_str("</mark>"); + } + } + out +} + +#[cfg(test)] +mod segment_tests { + use super::*; + + #[test] + fn segments_join_to_the_text_and_colour_it_the_same() { + let texts = [ + "# Title\n\nA *line* with `code`.\n\n- a list\n- more\n\n\n```rust\nfn x() {}\n\nlet y = 1;\n```\n\nafter **the** fence\n\n| a | b |\n|---|---|\n| 1 | 2 |\n\n indented\n\n> quote\n", + "", + "one line", + "\n\n\nstarts blank\n\nends blank\n\n", + "~~~\nopen fence\n\nnever closed\n\nstill code", + ]; + for t in texts { + let segs = segments(t); + assert_eq!(segs.concat(), t); + let mut joined: String = segs.iter().map(|s| part_html(s, true, &[])).collect(); + if t.ends_with('\n') || t.is_empty() { + joined.push(' '); + } + assert_eq!(joined, to_html(t, true, &[]), "{t:?} in {} segments", segs.len()); + } + assert!(segments(texts[0]).len() >= 6); + } + + #[test] + fn edits_recolour_only_around_them_and_match_a_whole_colouring() { + let mut t = String::from("# T\n\npara one\n\npara two\n\n- list\n\n```\ncode\n```\n\nend *here*\n"); + let mut l = Layer::default(); + l.full(&t, true, &[]); + // (at, delete, insert): typing, a blank line splitting a paragraph, joining two, + // opening a fence that runs to the end, closing it, deleting everything + let edits: Vec<(usize, usize, &str)> = vec![ + (9, 0, "x"), + (12, 0, "\n\nnew para "), + (8, 3, ""), + (2, 0, "\n```\n"), + (0, 0, "```\n\n"), + (0, 0, "intro\n\n"), + ]; + for (at, del, ins) in edits { + let at = at.min(t.len()); + let b = (at + del).min(t.len()); + let (i, went, html) = l.edit(at, b, ins, true).expect("an edit"); + t.replace_range(at..b, ins); + assert_eq!(l.text(), t); + assert!(went >= 1 && i < l.segs.len()); + // the layer's segments are exactly a fresh cut of the text, coloured the same + let fresh: Vec<&str> = segments(&t); + assert_eq!( + l.segs.iter().map(String::as_str).collect::<Vec<_>>(), + fresh, + "after {ins:?}" + ); + let _ = html; + } + let all = t.len(); + l.edit(0, all, "", true).unwrap(); + assert_eq!(l.text(), ""); + } +} + +#[cfg(test)] +mod tests { + use super::*; + use Class::*; + + /// the classes of `text` as a string of letters, one per byte + fn show(text: &str) -> String { + classify(text) + .iter() + .map(|c| match c { + Plain => '.', + Mark => 'm', + Heading => 'H', + Strong => 'S', + Emph => 'E', + Strike => 'x', + Code => 'c', + Link => 'L', + Url => 'u', + List => 'l', + Quote => 'q', + Table => 't', + Tag => 'g', + Rule => 'r', + SCommand => 'C', + SSuffix => '$', + SLiteral => '{', + SLocal => 'v', + SNumber => '9', + SLibrary => 'b', + SEscape => '\\', + }) + .collect() + } + + #[test] + fn headings_and_emphasis() { + assert_eq!(show("# Title"), "mHHHHHH"); + assert_eq!(show("#tag here"), "gggg....."); + assert_eq!(show("a **b** c"), "..mmSmm.."); + assert_eq!(show("*i* _j_"), "mEm.mEm"); + assert_eq!(show("snake_case_name"), "..............."); + assert_eq!(show("~~no~~"), "mmxxmm"); + assert_eq!(show("2 * 3 * 4"), "........."); + } + + #[test] + fn code_links_and_tags() { + assert_eq!(show("a `b*c*` d"), "..mccccm.."); + assert_eq!(show("[t](u)"), "mLmmum"); + assert_eq!(show("see #rust."), "....ggggg."); + assert_eq!(show("x https://a.b y"), "..uuuuuuuuuuu.."); + assert_eq!(show("```\nlet *a*\n```\nz"), "mmm.ccccccc.mmm.."); + } + + #[test] + fn blocks() { + assert_eq!(show("- item"), "l....."); + assert_eq!(show("12. x"), "lll.."); + assert_eq!(show("> q *e*"), "q.qqmEm"); + assert_eq!(show("|a|b|\n|-|-|"), "t.t.t.ttttt"); + assert_eq!(show("---"), "rrr"); + assert_eq!(show(" code"), "cccccccc"); + } + + #[test] + fn html() { + assert_eq!( + to_html("# T", true, &[]), + "<span class=\"h-m\">#</span><span class=\"h-h\"> T</span>" + ); + assert_eq!(to_html("a<b\n", false, &[]), "a<b\n "); + let f = Flag { + start: 2, + end: 5, + kind: "spell", + title: String::new(), + }; + assert_eq!( + to_html("a teh b", false, &[f]), + "a <mark class=\"flag spell\" title=\"\">teh</mark> b" + ); + // a flag never cuts a character in two + let f = Flag { + start: 1, + end: 2, + kind: "spell", + title: String::new(), + }; + assert!(to_html("é", false, &[f]).contains('é')); + } + + #[test] + fn every_byte_gets_a_class() { + for t in [ + "", + "é **ü** `ß`", + "[unclosed", + "**", + "` `", + "# ", + "> ", + "|", + "\n\n", + "- [x] done", + ] { + assert_eq!(classify(t).len(), t.len()); + } + } +} + +#[cfg(test)] +mod timing { + /// `cargo test -p anend-app --release long_text_timing -- --ignored --nocapture` + #[test] + #[ignore] + fn long_text_timing() { + let para = "The path went on past the quarry and the orchard, and the **light** fell on [[stones]] and plums. "; + let mut t = String::from("# Long\n\n"); + for i in 0..6000 { + if i % 8 == 7 { + t.push_str(&format!("\n\n## part {i}\n\n")); + } else { + t.push_str(para); + } + } + let a = std::time::Instant::now(); + let h = super::to_html(&t, true, &[]); + eprintln!("{} bytes -> {} in {:?}", t.len(), h.len(), a.elapsed()); + } + + /// s code coloured by word class: commands, suffix forms, literals, numbers, locals + #[test] + fn s_word_classes() { + use super::Class::*; + use super::{s_classes, s_html}; + let t = "{hi} 3 a# :x >"; + let c: String = s_classes(t) + .iter() + .map(|c| match c { + SCommand => 'C', + SSuffix => '$', + SLiteral => '{', + SLocal => 'v', + SNumber => '9', + _ => '.', + }) + .collect(); + assert_eq!(c, "{{{{.9..$.vv.C"); + assert!(s_html("{a} <", true).contains("h-sl")); + let mut notes = std::collections::BTreeMap::new(); + notes.insert(1, "out".to_string()); + let h = super::s_html_with("a >\nb >", true, ¬es, Some(2..3)); + assert!(h.contains("<mark class=\"s-at\">"), "{h}"); + let i = h.find("s-note").unwrap(); + assert!( + h[..i].contains('\n') && !h[..i].contains("b"), + "the note starts line 2: {h}" + ); + } +} diff --git a/app/src/hubnet.rs b/app/src/hubnet.rs new file mode 100644 index 00000000..3605a3c5 --- /dev/null +++ b/app/src/hubnet.rs @@ -0,0 +1,275 @@ +//! Talking to an anend hub over HTTP (docs/hub-api.md), as the Bevy app's hub.rs did: what +//! a hub sends is untrusted (links must stay on the hub, sizes are capped, names are +//! cleaned before they touch the disk). The desktop calls with ureq on a blocking thread; +//! the web build with the page's `fetch` (its own hub, or another that allows it). + +use serde_json::Value; + +/// the biggest save a download may be +#[cfg_attr(target_arch = "wasm32", allow(dead_code))] +pub const MAX_DOWNLOAD: u64 = 256 << 20; +/// the biggest JSON answer read +const MAX_JSON: u64 = 4 << 20; + +/// a typed hub address made tidy: `http(s)://host[:port][/path]` without the trailing `/` +pub fn base(url: &str) -> Result<String, String> { + let u = url.trim().trim_end_matches('/'); + let rest = u + .strip_prefix("http://") + .or_else(|| u.strip_prefix("https://")) + .ok_or("a hub's address starts with http:// or https://")?; + if rest.is_empty() || rest.starts_with('/') { + return Err("the hub's address needs a host".into()); + } + if u.chars().any(|c| c.is_whitespace() || c.is_control()) || u.contains(['?', '#']) { + return Err("the hub's address has odd characters in it".into()); + } + Ok(u.to_string()) +} + +/// a path on the hub; a path the hub sent can't lead anywhere else +pub fn join(hub: &str, path: &str) -> Result<String, String> { + let b = base(hub)?; + if !path.starts_with('/') + || path.starts_with("//") + || path.contains("..") + || path.contains('\\') + || path.chars().any(|c| c.is_whitespace() || c.is_control()) + { + return Err("the hub sent a bad link".into()); + } + Ok(format!("{b}{path}")) +} + +/// percent-encodes a query value +pub fn encode(s: &str) -> String { + let mut out = String::new(); + for b in s.bytes() { + if b.is_ascii_alphanumeric() || b"-_.~".contains(&b) { + out.push(b as char); + } else { + out.push_str(&format!("%{b:02X}")); + } + } + out +} + +/// a hub's ids are lowercase letters and digits +pub fn id_ok(id: &str) -> bool { + (1..=16).contains(&id.len()) && id.bytes().all(|b| b.is_ascii_lowercase() || b.is_ascii_digit()) +} + +/// a multipart/form-data body of text fields and one file, and its content type +pub fn multipart(fields: &[(&str, &str)], file: (&str, &str, &[u8])) -> (String, Vec<u8>) { + let mut seed = (crate::ui::now_ms() as u64).wrapping_mul(2654435761) | 1; + let boundary = loop { + seed ^= seed << 13; + seed ^= seed >> 7; + seed ^= seed << 17; + let b = format!("anend-{seed:016x}"); + if !file.2.windows(b.len()).any(|w| w == b.as_bytes()) { + break b; + } + }; + let q = |s: &str| -> String { + s.chars() + .map(|c| { + if c == '"' || c == '\\' || c.is_control() { + '_' + } else { + c + } + }) + .collect() + }; + let mut body = Vec::new(); + for (name, value) in fields { + body.extend_from_slice( + format!( + "--{boundary}\r\nContent-Disposition: form-data; name=\"{}\"\r\n\r\n{value}\r\n", + q(name) + ) + .as_bytes(), + ); + } + let (field, filename, bytes) = file; + body.extend_from_slice( + format!( + "--{boundary}\r\nContent-Disposition: form-data; name=\"{}\"; filename=\"{}\"\r\nContent-Type: application/octet-stream\r\n\r\n", + q(field), + q(filename) + ) + .as_bytes(), + ); + body.extend_from_slice(bytes); + body.extend_from_slice(format!("\r\n--{boundary}--\r\n").as_bytes()); + (format!("multipart/form-data; boundary={boundary}"), body) +} + +/// the hub's own words for a failed call, or its status +fn failure(status: u16, body: &[u8]) -> String { + let said = serde_json::from_slice::<Value>(body) + .ok() + .and_then(|v| v["error"].as_str().map(str::to_string)) + .unwrap_or_default(); + let said: String = said.chars().filter(|c| !c.is_control()).take(200).collect(); + match (status, said.trim()) { + (401, "") => "the hub didn't take the token (401)".into(), + (413, "") => "that's bigger than the hub takes (413)".into(), + (_, "") => format!("the hub answered {status}"), + (_, s) => format!("{s} ({status})"), + } +} + +/// one call: the status and the body (cut off past `limit`, which is an error) +#[cfg(not(target_arch = "wasm32"))] +async fn request( + method: &'static str, + url: String, + token: Option<String>, + body: Option<(String, Vec<u8>)>, + limit: u64, +) -> Result<(u16, Vec<u8>), String> { + tokio::task::spawn_blocking(move || { + use std::io::Read; + use std::time::Duration; + let agent: ureq::Agent = ureq::Agent::config_builder() + .timeout_connect(Some(Duration::from_secs(10))) + .timeout_global(Some(Duration::from_secs(15 * 60))) + .http_status_as_error(false) + .user_agent(concat!("anend/", env!("CARGO_PKG_VERSION"))) + .build() + .into(); + let auth = token.map(|t| format!("Bearer {}", t.trim())); + let resp = match (method, body) { + ("POST", Some((kind, bytes))) => { + let mut req = agent.post(&url).content_type(kind); + if let Some(a) = &auth { + req = req.header("Authorization", a); + } + req.send(&bytes[..]) + } + ("POST", None) => { + let mut req = agent.post(&url); + if let Some(a) = &auth { + req = req.header("Authorization", a); + } + req.send_empty() + } + _ => { + let mut req = agent.get(&url); + if let Some(a) = &auth { + req = req.header("Authorization", a); + } + req.call() + } + }; + let resp = resp.map_err(|e| match e { + ureq::Error::Timeout(_) => "the hub took too long to answer".to_string(), + ureq::Error::ConnectionFailed | ureq::Error::HostNotFound => "couldn't reach the hub".into(), + e => format!("couldn't reach the hub: {e}"), + })?; + let status = resp.status().as_u16(); + let mut out = Vec::new(); + resp.into_body() + .into_reader() + .take(limit + 1) + .read_to_end(&mut out) + .map_err(|e| format!("the answer broke off: {e}"))?; + if out.len() as u64 > limit { + return Err("the hub sent too much".to_string()); + } + Ok((status, out)) + }) + .await + .map_err(|e| e.to_string())? +} + +#[cfg(target_arch = "wasm32")] +async fn request( + method: &'static str, + url: String, + token: Option<String>, + body: Option<(String, Vec<u8>)>, + limit: u64, +) -> Result<(u16, Vec<u8>), String> { + // the page's fetch, the body going in and out as base64 + let b64 = body.as_ref().map(|(_, b)| crate::fonts::base64(b)).unwrap_or_default(); + let kind = body.as_ref().map(|(k, _)| k.clone()).unwrap_or_default(); + let js = format!( + r#"(async () => {{ + try {{ + const h = {{}}; + const tok = {tok}; if (tok) h['Authorization'] = 'Bearer ' + tok; + const kind = {kind}; const b64 = {b64}; + let body; + if (b64) {{ h['Content-Type'] = kind; body = Uint8Array.from(atob(b64), (c) => c.charCodeAt(0)); }} + const r = await fetch({url}, {{ method: {method}, headers: h, body, credentials: 'same-origin' }}); + const buf = new Uint8Array(await r.arrayBuffer()); + if (buf.length > {limit}) {{ dioxus.send({{ error: 'the hub sent too much' }}); return; }} + let s = ''; for (let i = 0; i < buf.length; i += 32768) s += String.fromCharCode.apply(null, buf.subarray(i, i + 32768)); + dioxus.send({{ status: r.status, body: btoa(s) }}); + }} catch (e) {{ dioxus.send({{ error: 'couldn\'t reach the hub: ' + (e && e.message || e) }}); }} +}})();"#, + tok = serde_json::to_string(&token.unwrap_or_default()).unwrap_or_default(), + kind = serde_json::to_string(&kind).unwrap_or_default(), + b64 = serde_json::to_string(&b64).unwrap_or_default(), + url = serde_json::to_string(&url).unwrap_or_default(), + method = serde_json::to_string(method).unwrap_or_default(), + ); + let mut ev = dioxus::prelude::document::eval(&js); + let v: Value = ev.recv().await.map_err(|e| format!("{e:?}"))?; + if let Some(e) = v["error"].as_str() { + return Err(e.to_string()); + } + let body = crate::fonts::unbase64(v["body"].as_str().unwrap_or("")).ok_or("the answer didn't read")?; + Ok((v["status"].as_u64().unwrap_or(0) as u16, body)) +} + +pub async fn get_json(url: String, token: Option<String>) -> Result<Value, String> { + let (s, b) = request("GET", url, token, None, MAX_JSON).await?; + if !(200..300).contains(&s) { + return Err(failure(s, &b)); + } + serde_json::from_slice(&b).map_err(|e| format!("the hub sent something odd: {e}")) +} + +#[cfg_attr(target_arch = "wasm32", allow(dead_code))] +pub async fn get_bytes(url: String, limit: u64) -> Result<Vec<u8>, String> { + let (s, b) = request("GET", url, None, None, limit).await?; + if !(200..300).contains(&s) { + return Err(failure(s, &b)); + } + Ok(b) +} + +pub async fn post(url: String, token: Option<String>, body: Option<(String, Vec<u8>)>) -> Result<Value, String> { + let (s, b) = request("POST", url, token, body, MAX_JSON).await?; + if !(200..300).contains(&s) { + return Err(failure(s, &b)); + } + Ok(serde_json::from_slice(&b).unwrap_or(Value::Null)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn urls_stay_on_the_hub() { + assert_eq!(base(" http://a.b:8080/ ").unwrap(), "http://a.b:8080"); + assert!(base("ftp://a").is_err() && base("http://").is_err() && base("http://a b").is_err()); + assert_eq!(join("http://a.b", "/api/saves").unwrap(), "http://a.b/api/saves"); + for bad in ["api", "//evil.org/x", "/../x", "/a b"] { + assert!(join("http://a.b", bad).is_err(), "{bad}"); + } + assert_eq!(encode("a b&c"), "a%20b%26c"); + assert!(id_ok("ab12") && !id_ok("AB") && !id_ok("../x")); + let (kind, body) = multipart(&[("name", "x\"y")], ("file", "f.redb", b"data")); + let s = String::from_utf8_lossy(&body); + assert!(kind.starts_with("multipart/form-data; boundary=anend-")); + assert!( + s.contains("name=\"name\"\r\n\r\nx\"y") && s.contains("filename=\"f.redb\"") && s.contains("data\r\n--") + ); + } +} diff --git a/app/src/icons.rs b/app/src/icons.rs new file mode 100644 index 00000000..2095fd94 --- /dev/null +++ b/app/src/icons.rs @@ -0,0 +1,73 @@ +//! The shared line icons (assets/icons), drawn in the text colour. The app's own icon is the window's and the web tab's, not the views'. + +/// an icon's svg by name; unknown names draw nothing +pub fn svg(name: &str) -> &'static str { + match name { + "alert" => include_str!("../../assets/icons/alert.svg"), + "and" => include_str!("../../assets/icons/and.svg"), + "bolt" => include_str!("../../assets/icons/bolt.svg"), + "bucket" => include_str!("../../assets/icons/bucket.svg"), + "check" => include_str!("../../assets/icons/check.svg"), + "chevron-left" => include_str!("../../assets/icons/chevron-left.svg"), + "chevron-right" => include_str!("../../assets/icons/chevron-right.svg"), + "classifier" => include_str!("../../assets/icons/classifier.svg"), + "close" => include_str!("../../assets/icons/close.svg"), + "copy" => include_str!("../../assets/icons/copy.svg"), + "cube" => include_str!("../../assets/icons/cube.svg"), + "delete" => include_str!("../../assets/icons/delete.svg"), + "prefab" => include_str!("../../assets/icons/prefab.svg"), + "download" => include_str!("../../assets/icons/download.svg"), + "edit" => include_str!("../../assets/icons/edit.svg"), + "editor" => include_str!("../../assets/icons/editor.svg"), + "export" => include_str!("../../assets/icons/export.svg"), + "eye-off" => include_str!("../../assets/icons/eye-off.svg"), + "filter" => include_str!("../../assets/icons/filter.svg"), + "folder" => include_str!("../../assets/icons/folder.svg"), + "font" => include_str!("../../assets/icons/font.svg"), + "forge" => include_str!("../../assets/icons/forge.svg"), + "hash" => include_str!("../../assets/icons/hash.svg"), + "help" => include_str!("../../assets/icons/help.svg"), + "home" => include_str!("../../assets/icons/home.svg"), + "hub" => include_str!("../../assets/icons/hub.svg"), + "image" => include_str!("../../assets/icons/image.svg"), + "keys" => include_str!("../../assets/icons/keys.svg"), + "link" => include_str!("../../assets/icons/link.svg"), + "list" => include_str!("../../assets/icons/list.svg"), + "memory" => include_str!("../../assets/icons/memory.svg"), + "merge" => include_str!("../../assets/icons/merge.svg"), + "near" => include_str!("../../assets/icons/near.svg"), + "new" => include_str!("../../assets/icons/new.svg"), + "not" => include_str!("../../assets/icons/not.svg"), + "open" => include_str!("../../assets/icons/open.svg"), + "or" => include_str!("../../assets/icons/or.svg"), + "palette" => include_str!("../../assets/icons/palette.svg"), + "pause" => include_str!("../../assets/icons/pause.svg"), + "pick" => include_str!("../../assets/icons/pick.svg"), + "pin" => include_str!("../../assets/icons/pin.svg"), + "play" => include_str!("../../assets/icons/play.svg"), + "reader" => include_str!("../../assets/icons/reader.svg"), + "refresh" => include_str!("../../assets/icons/refresh.svg"), + "rename" => include_str!("../../assets/icons/rename.svg"), + "save" => include_str!("../../assets/icons/save.svg"), + "search" => include_str!("../../assets/icons/search.svg"), + "settings" => include_str!("../../assets/icons/settings.svg"), + "shield" => include_str!("../../assets/icons/shield.svg"), + "sidebar" => include_str!("../../assets/icons/sidebar.svg"), + "sliders" => include_str!("../../assets/icons/sliders.svg"), + "sound" => include_str!("../../assets/icons/sound.svg"), + "sort" => include_str!("../../assets/icons/sort.svg"), + "space" => include_str!("../../assets/icons/space.svg"), + "star" => include_str!("../../assets/icons/star.svg"), + "stats" => include_str!("../../assets/icons/stats.svg"), + "sun" => include_str!("../../assets/icons/sun.svg"), + "swap" => include_str!("../../assets/icons/swap.svg"), + "tag" => include_str!("../../assets/icons/tag.svg"), + "tags" => include_str!("../../assets/icons/tags.svg"), + "text" => include_str!("../../assets/icons/text.svg"), + "undo" => include_str!("../../assets/icons/undo.svg"), + "upload" => include_str!("../../assets/icons/upload.svg"), + "view" => include_str!("../../assets/icons/view.svg"), + "zen" => include_str!("../../assets/icons/zen.svg"), + _ => "", + } +} diff --git a/app/src/keys.rs b/app/src/keys.rs new file mode 100644 index 00000000..ed1a3acd --- /dev/null +++ b/app/src/keys.rs @@ -0,0 +1,763 @@ +//! Rebindable keys, as the Bevy app had them (its keys.rs): every keyboard action has a +//! binding (a key and its modifiers) that the keys menu in the settings changes; the +//! changes are kept in the app's settings file (`Prefs::keymap`, only the ones that differ +//! from the defaults), so they stay whichever save is open, on the desktop and the web. +//! +//! Keys are named by where they sit (the `code` of a key event: `KeyW` is W on any layout), +//! like Bevy's `KeyCode`. Bindings with Ctrl or Alt work everywhere, even while typing; +//! plain keys only act while no text box has focus. Each action has a scope: global, or +//! one view; two actions only clash (and swap when one takes the other's key) when both +//! can be pressed in the same place. + +use std::collections::BTreeMap; + +use crate::ui::View; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +pub enum Action { + // everywhere + GotoMemory, + GotoSpace, + GotoLists, + GotoReader, + GotoNotes, + GotoTags, + GotoStats, + GotoModels, + GotoFilters, + OpenSettings, + OpenKeys, + FocusBar, + Undo, + ZoomIn, + ZoomOut, + ZoomReset, + // notes + Save, + NewNote, + ToggleRead, + ToggleList, + NoteClassifiers, + ToggleCheck, + // memory + BucketOrdinal, + BucketReversed, + BucketFrequency, + ToggleGsearch, + ToggleSaturate, + WhiteMode, + Letters, + ClassifierSearch, + WordTypes, + SideOrdinal, + SideReversed, + SideFrequency, + // space + FlyForward, + FlyBack, + FlyLeft, + FlyRight, + FlyUp, + FlyDown, + RollLeft, + RollRight, + Level, + BackToStart, + Slower, + Faster, + Walk, + SuperFlight, + Grapple, + Sneak, + NewText, + EditText, + DeleteText, + CopyText, + Group, + Ungroup, + WireMode, + Reversed, + Pin, + Physics, + Pause, + Settle, + SideSum, + SideReversedSum, + Help, + Hud, + Details, + Export, + SaveMap, + // reader + ReadPrev, + ReadNext, +} + +/// where an action's key works +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Scope { + Global, + In(View), +} + +impl Scope { + /// whether two actions can be pressed in the same place, so can't share a key + pub fn overlaps(self, other: Scope) -> bool { + self == other || self == Scope::Global || other == Scope::Global + } + + pub fn name(self) -> &'static str { + match self { + Scope::Global => "everywhere", + Scope::In(v) => v.name(), + } + } +} + +use Action::*; + +impl Action { + pub const ALL: [Action; 71] = [ + GotoMemory, + GotoSpace, + GotoLists, + GotoReader, + GotoNotes, + GotoTags, + GotoStats, + GotoModels, + GotoFilters, + OpenSettings, + OpenKeys, + FocusBar, + Undo, + ZoomIn, + ZoomOut, + ZoomReset, + Save, + NewNote, + ToggleRead, + ToggleList, + NoteClassifiers, + ToggleCheck, + BucketOrdinal, + BucketReversed, + BucketFrequency, + ToggleGsearch, + ToggleSaturate, + WhiteMode, + Letters, + ClassifierSearch, + WordTypes, + SideOrdinal, + SideReversed, + SideFrequency, + FlyForward, + FlyBack, + FlyLeft, + FlyRight, + FlyUp, + FlyDown, + RollLeft, + RollRight, + Level, + BackToStart, + Slower, + Faster, + Walk, + SuperFlight, + Grapple, + Sneak, + NewText, + EditText, + DeleteText, + CopyText, + Group, + Ungroup, + WireMode, + Reversed, + Pin, + Physics, + Pause, + Settle, + SideSum, + SideReversedSum, + Help, + Hud, + Details, + Export, + SaveMap, + ReadPrev, + ReadNext, + ]; + + pub fn scope(self) -> Scope { + match self { + GotoMemory | GotoSpace | GotoLists | GotoReader | GotoNotes | GotoTags | GotoStats | GotoModels + | GotoFilters | OpenSettings | OpenKeys | FocusBar | Undo | ZoomIn | ZoomOut | ZoomReset => Scope::Global, + Save | NewNote | ToggleRead | ToggleList | NoteClassifiers | ToggleCheck => Scope::In(View::Notes), + BucketOrdinal | BucketReversed | BucketFrequency | ToggleGsearch | ToggleSaturate | WhiteMode | Letters + | ClassifierSearch | WordTypes | SideOrdinal | SideReversed | SideFrequency => Scope::In(View::Memory), + ReadPrev | ReadNext => Scope::In(View::Reader), + _ => Scope::In(View::Space), + } + } + + /// the space's flying keys act while held (space.js reads them), not on a press + pub fn held(self) -> bool { + matches!( + self, + FlyForward | FlyBack | FlyLeft | FlyRight | FlyUp | FlyDown | RollLeft | RollRight | Sneak + ) + } + + /// the stable name kept in the settings file + pub fn id(self) -> &'static str { + match self { + GotoMemory => "goto_memory", + GotoSpace => "goto_space", + GotoLists => "goto_lists", + GotoReader => "goto_reader", + GotoNotes => "goto_notes", + GotoTags => "goto_tags", + GotoStats => "goto_stats", + GotoModels => "goto_models", + GotoFilters => "goto_filters", + OpenSettings => "open_settings", + OpenKeys => "open_keys", + FocusBar => "focus_bar", + Undo => "undo", + ZoomIn => "zoom_in", + ZoomOut => "zoom_out", + ZoomReset => "zoom_reset", + Save => "save", + NewNote => "new_note", + ToggleRead => "toggle_read", + ToggleList => "toggle_list", + NoteClassifiers => "note_classifiers", + ToggleCheck => "toggle_check", + BucketOrdinal => "bucket_ordinal", + BucketReversed => "bucket_reversed", + BucketFrequency => "bucket_frequency", + ToggleGsearch => "toggle_gsearch", + ToggleSaturate => "toggle_saturate", + WhiteMode => "white_mode", + Letters => "letters", + ClassifierSearch => "classifier_search", + WordTypes => "word_types", + SideOrdinal => "side_ordinal", + SideReversed => "side_reversed", + SideFrequency => "side_frequency", + FlyForward => "fly_forward", + FlyBack => "fly_back", + FlyLeft => "fly_left", + FlyRight => "fly_right", + FlyUp => "fly_up", + FlyDown => "fly_down", + RollLeft => "roll_left", + RollRight => "roll_right", + Level => "level", + BackToStart => "back_to_start", + Slower => "slower", + Faster => "faster", + Walk => "walk", + SuperFlight => "superflight", + Grapple => "grapple", + Sneak => "sneak", + NewText => "new_text", + EditText => "edit_text", + DeleteText => "delete_text", + CopyText => "copy_text", + Group => "group", + Ungroup => "ungroup", + WireMode => "wire_mode", + Reversed => "reversed", + Pin => "pin", + Physics => "physics", + Pause => "pause", + Settle => "settle", + SideSum => "side_sum", + SideReversedSum => "side_reversed_sum", + Help => "help", + Hud => "hud", + Details => "details", + Export => "export", + SaveMap => "save_map", + ReadPrev => "read_prev", + ReadNext => "read_next", + } + } + + pub fn label(self) -> &'static str { + match self { + GotoMemory => "go to memory", + GotoSpace => "go to the space", + GotoLists => "go to the lists", + GotoReader => "go to the reader", + GotoNotes => "go to the notes", + GotoTags => "go to the tags", + GotoStats => "go to stats", + GotoModels => "go to the models (classifiers)", + GotoFilters => "go to the filters", + OpenSettings => "open the settings", + OpenKeys => "open this keys menu", + FocusBar => "focus the command bar", + Undo => "take back the latest action", + ZoomIn => "zoom in", + ZoomOut => "zoom out", + ZoomReset => "zoom back to 100%", + Save => "save the note", + NewNote => "new note", + ToggleRead => "read / edit the note", + ToggleList => "slide the note list away / back", + NoteClassifiers => "the note's classifiers", + ToggleCheck => "check spelling and grammar", + BucketOrdinal => "ordinal bucket", + BucketReversed => "reversed bucket (again: back to ordinal)", + BucketFrequency => "frequency bucket (again: back to ordinal)", + ToggleGsearch => "gsearch typed text on / off", + ToggleSaturate => "saturate searches on / off", + WhiteMode => "white mode", + Letters => "the sidecar's letters", + ClassifierSearch => "search with the colouring classifier", + WordTypes => "label every text's word types", + SideOrdinal => "gsearch the bar's ordinal sum", + SideReversed => "gsearch the bar's reversed sum", + SideFrequency => "gsearch the bar's letters", + FlyForward => "fly forward (hold)", + FlyBack => "fly back (hold)", + FlyLeft => "fly left (hold)", + FlyRight => "fly right (hold)", + FlyUp => "fly up (hold)", + FlyDown => "fly down (hold)", + RollLeft => "roll left (hold)", + RollRight => "roll right (hold)", + Level => "level the horizon", + BackToStart => "back to start", + Slower => "slower flight", + Faster => "faster flight", + Walk => "walk / fly (first person: gravity, jump, crouch, lean, mantle)", + SuperFlight => "superflight / fly (collects the texts flown through)", + Grapple => "grapple: hook what's ahead / let go (the wheel reels)", + Sneak => "sneak while walking (hold)", + NewText => "new text ahead", + EditText => "edit the selected text", + DeleteText => "remove the selected text", + CopyText => "copy the selected text", + Group => "group what's selected", + Ungroup => "ungroup the selected group", + WireMode => "wiring: drag from block to block to wire them", + Reversed => "reversed on / off", + Pin => "pin / unpin the selected text", + Physics => "the physics panel", + Pause => "pause the physics", + Settle => "settle now", + SideSum => "gsearch the bar's ordinal sum", + SideReversedSum => "gsearch the bar's reversed sum", + Help => "help", + Hud => "the position card", + Details => "the details window", + Export => "export the texts to a file", + SaveMap => "save the map", + ReadPrev => "the one before", + ReadNext => "the next one", + } + } + + pub fn default_binding(self) -> Binding { + let b = |s: &str| Binding::parse(s).expect("a default binding reads"); + b(match self { + GotoMemory => "Ctrl+1", + GotoSpace => "Ctrl+2", + GotoLists => "Ctrl+3", + GotoReader => "Ctrl+4", + GotoNotes => "Ctrl+5", + GotoTags => "Ctrl+6", + GotoStats => "Ctrl+7", + GotoModels => "Ctrl+8", + GotoFilters => "Ctrl+9", + OpenSettings => "Ctrl+,", + OpenKeys => "Ctrl+K", + FocusBar => "/", + Undo => "Ctrl+Z", + ZoomIn => "Ctrl+=", + ZoomOut => "Ctrl+-", + ZoomReset => "Ctrl+0", + Save => "Ctrl+S", + NewNote => "Ctrl+N", + ToggleRead => "Ctrl+E", + ToggleList => "Ctrl+B", + NoteClassifiers => "Ctrl+I", + ToggleCheck => "Ctrl+J", + BucketOrdinal => "O", + BucketReversed => "R", + BucketFrequency => "F", + ToggleGsearch => "G", + ToggleSaturate => "S", + WhiteMode => "W", + Letters => "L", + ClassifierSearch => "C", + WordTypes => "T", + SideOrdinal => "Left", + SideReversed => "Right", + SideFrequency => "Down", + FlyForward => "W", + FlyBack => "S", + FlyLeft => "A", + FlyRight => "D", + FlyUp => "Space", + FlyDown => "C", + RollLeft => "Q", + RollRight => "E", + Level => "R", + BackToStart => "Home", + Slower => "[", + Faster => "]", + Walk => "V", + SuperFlight => "B", + Grapple => "G", + Sneak => "Z", + NewText => "N", + EditText => "Enter", + DeleteText => "Delete", + CopyText => "Ctrl+C", + Group => "Ctrl+G", + Ungroup => "Ctrl+Shift+G", + WireMode => "J", + Reversed => "F", + Pin => "U", + Physics => "O", + Pause => "P", + Settle => "K", + SideSum => "Shift+Left", + SideReversedSum => "Shift+Right", + Help => "H", + Hud => "I", + Details => "M", + Export => "X", + SaveMap => "Shift+X", + ReadPrev => "Left", + ReadNext => "Right", + }) + } + + pub fn from_id(id: &str) -> Option<Action> { + Action::ALL.into_iter().find(|a| a.id() == id) + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub struct Binding { + /// the key, by its name in [`KEYS`] + pub key: &'static str, + pub ctrl: bool, + pub shift: bool, + pub alt: bool, +} + +/// the keys that can be bound: a key event's `code`, and the name shown and kept +const KEYS: &[(&str, &str)] = &[ + ("KeyA", "A"), + ("KeyB", "B"), + ("KeyC", "C"), + ("KeyD", "D"), + ("KeyE", "E"), + ("KeyF", "F"), + ("KeyG", "G"), + ("KeyH", "H"), + ("KeyI", "I"), + ("KeyJ", "J"), + ("KeyK", "K"), + ("KeyL", "L"), + ("KeyM", "M"), + ("KeyN", "N"), + ("KeyO", "O"), + ("KeyP", "P"), + ("KeyQ", "Q"), + ("KeyR", "R"), + ("KeyS", "S"), + ("KeyT", "T"), + ("KeyU", "U"), + ("KeyV", "V"), + ("KeyW", "W"), + ("KeyX", "X"), + ("KeyY", "Y"), + ("KeyZ", "Z"), + ("Digit0", "0"), + ("Digit1", "1"), + ("Digit2", "2"), + ("Digit3", "3"), + ("Digit4", "4"), + ("Digit5", "5"), + ("Digit6", "6"), + ("Digit7", "7"), + ("Digit8", "8"), + ("Digit9", "9"), + ("F1", "F1"), + ("F2", "F2"), + ("F3", "F3"), + ("F4", "F4"), + ("F5", "F5"), + ("F6", "F6"), + ("F7", "F7"), + ("F8", "F8"), + ("F9", "F9"), + ("F10", "F10"), + ("F11", "F11"), + ("F12", "F12"), + ("ArrowLeft", "Left"), + ("ArrowRight", "Right"), + ("ArrowUp", "Up"), + ("ArrowDown", "Down"), + ("Enter", "Enter"), + ("NumpadEnter", "Enter"), + ("Tab", "Tab"), + ("Space", "Space"), + ("Backspace", "Backspace"), + ("Delete", "Delete"), + ("Insert", "Insert"), + ("Home", "Home"), + ("End", "End"), + ("PageUp", "PageUp"), + ("PageDown", "PageDown"), + ("Minus", "-"), + ("NumpadSubtract", "-"), + ("Equal", "="), + ("NumpadAdd", "="), + ("BracketLeft", "["), + ("BracketRight", "]"), + ("Backslash", "\\"), + ("Semicolon", ";"), + ("Quote", "'"), + ("Comma", ","), + ("Period", "."), + ("Slash", "/"), + ("Backquote", "`"), +]; + +/// a key's name from a key event's `code` +pub fn key_name(code: &str) -> Option<&'static str> { + KEYS.iter().find(|(c, _)| *c == code).map(|(_, n)| *n) +} + +/// a key event's `code` for a key's name (the first, where two codes share a name) +pub fn key_code(name: &str) -> Option<&'static str> { + KEYS.iter().find(|(_, n)| *n == name).map(|(c, _)| *c) +} + +fn name_of(s: &str) -> Option<&'static str> { + KEYS.iter().find(|(_, n)| n.eq_ignore_ascii_case(s)).map(|(_, n)| *n) +} + +impl std::fmt::Display for Binding { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + if self.ctrl { + f.write_str("Ctrl+")?; + } + if self.alt { + f.write_str("Alt+")?; + } + if self.shift { + f.write_str("Shift+")?; + } + f.write_str(self.key) + } +} + +impl Binding { + pub fn parse(s: &str) -> Option<Binding> { + let mut b = Binding { + key: "A", + ctrl: false, + shift: false, + alt: false, + }; + let mut rest = s.trim(); + loop { + if let Some(r) = rest.strip_prefix("Ctrl+") { + b.ctrl = true; + rest = r; + } else if let Some(r) = rest.strip_prefix("Alt+") { + b.alt = true; + rest = r; + } else if let Some(r) = rest.strip_prefix("Shift+") { + b.shift = true; + rest = r; + } else { + break; + } + } + b.key = name_of(rest)?; + Some(b) + } + + /// a key event as a binding + pub fn of(code: &str, ctrl: bool, shift: bool, alt: bool) -> Option<Binding> { + Some(Binding { + key: key_name(code)?, + ctrl, + shift, + alt, + }) + } + + /// chords work while typing, plain keys don't + pub fn is_chord(&self) -> bool { + self.ctrl || self.alt + } +} + +/// every action's binding: the defaults with the person's changes over them +#[derive(Clone, Debug, PartialEq)] +pub struct Keymap(BTreeMap<Action, Binding>); + +impl Default for Keymap { + fn default() -> Self { + Keymap(Action::ALL.iter().map(|a| (*a, a.default_binding())).collect()) + } +} + +impl Keymap { + pub fn get(&self, a: Action) -> Binding { + self.0.get(&a).copied().unwrap_or_else(|| a.default_binding()) + } + + /// binds `action`, handing its old binding to whichever action held the new one where + /// both can be pressed; returns that action + pub fn rebind(&mut self, action: Action, binding: Binding) -> Option<Action> { + let old = self.get(action); + let other = Action::ALL + .iter() + .copied() + .find(|a| *a != action && a.scope().overlaps(action.scope()) && self.get(*a) == binding); + if let Some(o) = other { + self.0.insert(o, old); + } + self.0.insert(action, binding); + other + } + + /// the person's changes, as kept in the settings file (action id → binding) + pub fn changes(&self) -> BTreeMap<String, String> { + Action::ALL + .iter() + .filter(|a| self.get(**a) != a.default_binding()) + .map(|a| (a.id().to_string(), self.get(*a).to_string())) + .collect() + } + + pub fn from_changes(map: &BTreeMap<String, String>) -> Keymap { + let mut k = Keymap::default(); + for (id, b) in map { + if let (Some(a), Some(b)) = (Action::from_id(id), Binding::parse(b)) { + k.0.insert(a, b); + } + } + k + } + + /// the action a key press fires in `view`: one of that view's, else a global one + pub fn action(&self, view: View, b: Binding, typing: bool) -> Option<Action> { + if typing && !b.is_chord() { + return None; + } + let find = |want: Scope| { + Action::ALL + .into_iter() + .find(|a| a.scope() == want && !a.held() && self.get(*a) == b) + }; + find(Scope::In(view)).or_else(|| find(Scope::Global)) + } + + /// the bindings the page's key listener should keep from the browser: chords anywhere, + /// plain keys outside text boxes (as `ctrl,shift,alt,code` strings) + pub fn taken(&self, view: View) -> Vec<String> { + Action::ALL + .into_iter() + .filter(|a| a.scope() == Scope::Global || a.scope() == Scope::In(view)) + .map(|a| { + let b = self.get(a); + format!( + "{},{},{},{}", + b.ctrl as u8, + b.shift as u8, + b.alt as u8, + key_code(b.key).unwrap_or("") + ) + }) + .collect() + } + + /// the space's held keys for space.js: action id → key code + pub fn flying(&self) -> BTreeMap<&'static str, &'static str> { + Action::ALL + .into_iter() + .filter(|a| a.held() || matches!(a, Level | BackToStart | Slower | Faster | Walk | SuperFlight | Grapple)) + .map(|a| (a.id(), key_code(self.get(a).key).unwrap_or(""))) + .collect() + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn bindings_roundtrip_and_swap() { + let mut k = Keymap::default(); + assert_eq!(k.get(Save).to_string(), "Ctrl+S"); + assert_eq!( + Binding::parse("Ctrl+Shift+Left"), + Some(Binding { + key: "Left", + ctrl: true, + shift: true, + alt: false + }) + ); + assert_eq!(Binding::parse("Nope"), None); + // taking another action's key swaps them + let swapped = k.rebind(BucketFrequency, Binding::parse("R").unwrap()); + assert_eq!(swapped, Some(BucketReversed)); + assert_eq!(k.get(BucketReversed).to_string(), "F"); + let back = Keymap::from_changes(&k.changes()); + assert_eq!(back, k); + assert!(Keymap::default().changes().is_empty()); + // every default is nameable and distinct where both can be pressed + for (i, a) in Action::ALL.iter().enumerate() { + assert!(key_code(a.default_binding().key).is_some(), "{a:?}"); + for b in &Action::ALL[i + 1..] { + assert!( + !(a.scope().overlaps(b.scope()) && a.default_binding() == b.default_binding()), + "{a:?} and {b:?} share {}", + a.default_binding() + ); + assert_ne!(a.id(), b.id()); + } + } + // the space's keys don't push the memory view's out + k.rebind(Settle, Binding::parse("G").unwrap()); + assert_eq!(k.get(ToggleGsearch).to_string(), "G"); + } + + #[test] + fn presses_find_their_action() { + let k = Keymap::default(); + let r = Binding::of("KeyR", false, false, false).unwrap(); + assert_eq!(k.action(View::Memory, r, false), Some(BucketReversed)); + assert_eq!(k.action(View::Space, r, false), Some(Level)); + assert_eq!(k.action(View::Memory, r, true), None, "plain keys wait while typing"); + let s = Binding::of("KeyS", true, false, false).unwrap(); + assert_eq!(k.action(View::Notes, s, true), Some(Save)); + assert_eq!( + k.action(View::Memory, Binding::of("Digit2", true, false, false).unwrap(), true), + Some(GotoSpace) + ); + // held keys are space.js's + assert_eq!( + k.action(View::Space, Binding::of("KeyW", false, false, false).unwrap(), false), + None + ); + assert_eq!(k.flying()["fly_forward"], "KeyW"); + } +} diff --git a/app/src/main.rs b/app/src/main.rs new file mode 100644 index 00000000..f7bca0be --- /dev/null +++ b/app/src/main.rs @@ -0,0 +1,248 @@ +//! anend's app with Dioxus: the desktop app (the system webview) and, from the same code, +//! the web app (WebAssembly). See docs/next.md, "The Dioxus app". + +mod backend; +mod fonts; +mod gem; +mod highlight; +mod hubnet; +mod icons; +mod keys; +mod md; +#[cfg(all(feature = "desktop", target_os = "linux"))] +mod native; +#[cfg(feature = "desktop")] +mod native_audio; +mod parity; +#[cfg(feature = "desktop")] +mod picture; +mod prefs; +mod shell; +mod theme; +mod ui; +mod views; + +use std::rc::Rc; + +use ui::Api; + +#[cfg(not(target_arch = "wasm32"))] +static LOCAL: std::sync::OnceLock<backend::local::Local> = std::sync::OnceLock::new(); + +/// the backend this build talks to +pub fn make_api() -> Api { + #[cfg(not(target_arch = "wasm32"))] + { + Api(Rc::new( + LOCAL.get().expect("the save is opened before the window").clone(), + )) + } + #[cfg(target_arch = "wasm32")] + { + Api(Rc::new(backend::hub::Hub::here())) + } +} + +#[cfg(not(target_arch = "wasm32"))] +/// `anend-app run <program> [arguments...] [--save path.redb]`: runs an s program on the +/// save, headless, with the app's ops a call away (`std:anend`). The program is a file, or +/// the save's s program (a note tagged `s`) of that title. What it writes goes to stdout, +/// an error to stderr; stdin, when piped, is its stdin. Its exit code is the program's. +fn run_cli(args: &[String], save: Option<&std::path::Path>) -> i32 { + use std::io::{IsTerminal, Read}; + let mut rest: Vec<String> = Vec::new(); + let mut skip = false; + for (i, a) in args.iter().enumerate().skip(2) { + if skip { + skip = false; + continue; + } + if a == "--save" || a == "--db" { + skip = true; + continue; + } + let _ = i; + rest.push(a.clone()); + } + let Some(program) = rest.first().cloned() else { + eprintln!("usage: anend-app run <program.s or a program's title> [its arguments...] [--save path.redb]"); + return 2; + }; + let dir = prefs::data_dir().join("saves"); + let local = match backend::local::Local::open(&dir, save) { + Ok(l) => l, + Err(e) => { + eprintln!("anend: couldn't open the save: {e}"); + return 1; + } + }; + let mut stdin = String::new(); + if !std::io::stdin().is_terminal() { + let _ = std::io::stdin().read_to_string(&mut stdin); + } + let mut call = serde_json::json!({ "args": rest[1..], "stdin": stdin }); + if std::path::Path::new(&program).is_file() { + match std::fs::read_to_string(&program) { + Ok(code) => call["code"] = code.into(), + Err(e) => { + eprintln!("anend: {program}: {e}"); + return 1; + } + } + } else { + let progs = local.call_now("s.programs", &serde_json::json!({})).unwrap_or_default(); + let title = program.strip_suffix(".s").unwrap_or(&program); + match progs.as_array().into_iter().flatten().find(|p| p["title"] == title) { + Some(p) => call["key"] = p["key"].clone(), + None => { + eprintln!("anend: no file {program}, and the save has no s program titled {title:?}"); + return 1; + } + } + } + match local.call_now("s.run", &call) { + Ok(r) => { + let out = r["out"].as_str().unwrap_or(""); + println!("{}", out.strip_prefix('\n').unwrap_or(out)); + if let Some(e) = r["err"].as_str() { + eprintln!("s: {e}"); + } + r["code"].as_i64().unwrap_or(0) as i32 + } + Err(e) => { + eprintln!("anend: {e}"); + 1 + } + } +} + +#[cfg(not(target_arch = "wasm32"))] +fn main() { + use dioxus::desktop::{Config, LogicalSize, WindowBuilder}; + // WebKitGTK's DMA-BUF renderer needs GBM buffers the driver may refuse ("Failed to + // create GBM buffer ... Invalid argument", NVIDIA's driver and some Wayland setups), + // which leaves the window white. Turn it off unless the person chose otherwise + // (`WEBKIT_DISABLE_DMABUF_RENDERER=0` keeps it). + #[cfg(target_os = "linux")] + if std::env::var_os("WEBKIT_DISABLE_DMABUF_RENDERER").is_none() { + // SAFETY: first thing in main, before any thread is started. + unsafe { std::env::set_var("WEBKIT_DISABLE_DMABUF_RENDERER", "1") }; + } + // `anend-app [--save path.redb]`; else the last save, else main.redb in the saves folder + let args: Vec<String> = std::env::args().collect(); + let arg_save = args + .iter() + .position(|a| a == "--save" || a == "--db") + .and_then(|i| args.get(i + 1)) + .map(std::path::PathBuf::from); + let prefs = prefs::load(); + // `anend-app run <program> [its arguments]`: an s program, headless, on the save + if args.get(1).map(String::as_str) == Some("run") { + let save = arg_save.clone().or_else(|| prefs.save.clone().map(Into::into)); + std::process::exit(run_cli(&args, save.as_deref())); + } + // the installed font families, for the settings' font fields + fonts::scan_system(); + let save = arg_save.or_else(|| prefs.save.clone().map(Into::into)); + let dir = prefs::data_dir().join("saves"); + let local = match backend::local::Local::open(&dir, save.as_deref()) { + Ok(l) => l, + Err(e) => { + eprintln!("anend: couldn't open the save: {e}"); + std::process::exit(1); + } + }; + // `--import all-of-it.json`: weum's texts into the save first + if let Some(file) = args.iter().position(|a| a == "--import").and_then(|i| args.get(i + 1)) { + let text = std::fs::read_to_string(file).unwrap_or_default(); + let mut f = backend::Backend::import_texts(&local, &text, ""); + // the worker answers on its own thread; wait for it + let r = loop { + match futures_util::FutureExt::now_or_never(&mut f) { + Some(r) => break r, + None => std::thread::sleep(std::time::Duration::from_millis(5)), + } + }; + match r { + Ok(im) => eprintln!("anend: imported {} texts", im.memories), + Err(e) => eprintln!("anend: the import failed: {e}"), + } + } + let _ = LOCAL.set(local); + // the icon goes on the window itself: `Config::with_icon` sets it on the config's own + // window, which `with_window` then replaces (so it never showed in the title bar) + let window = WindowBuilder::new() + .with_title("anend") + .with_window_icon(window_icon()) + .with_inner_size(LogicalSize::new(1200.0, 820.0)); + // the native space shows through the page: the window (and so the webview) is see-through + #[cfg(target_os = "linux")] + let window = window.with_transparent(true); + #[cfg(target_os = "linux")] + desktop_entry(); + let cfg = Config::new() + .with_window(window) + .with_menu(None) + // closing hides the window; the shell saves what's open, then ends the app + .with_close_behaviour(dioxus::desktop::WindowCloseBehaviour::WindowHides) + .with_disable_context_menu(true) + // the native room's frames, for the page (macOS, Windows: picture.rs) + .with_custom_protocol("anendframe", picture::protocol) + // the sand window's colour, so the first frame isn't a different shade + .with_background_color((0x92, 0x7a, 0x4f, 0xff)); + dioxus::LaunchBuilder::desktop().with_cfg(cfg).launch(shell::App); +} + +/// the window's icon, from assets/icon.png +#[cfg(not(target_arch = "wasm32"))] +fn window_icon() -> Option<dioxus::desktop::tao::window::Icon> { + let dec = png::Decoder::new(std::io::Cursor::new(include_bytes!("../../assets/icon.png"))); + let mut reader = dec.read_info().ok()?; + let mut buf = vec![0; reader.output_buffer_size()]; + let info = reader.next_frame(&mut buf).ok()?; + let rgba: Vec<u8> = match info.color_type { + png::ColorType::Rgba => buf[..info.buffer_size()].to_vec(), + png::ColorType::Rgb => buf[..info.buffer_size()] + .chunks(3) + .flat_map(|p| [p[0], p[1], p[2], 255]) + .collect(), + _ => return None, + }; + dioxus::desktop::tao::window::Icon::from_rgba(rgba, info.width, info.height).ok() +} + +/// Wayland desktops (GNOME, KDE) draw a window's icon from the desktop entry matching its +/// app id, not from the window: a user-level entry and icon are put in place once (never +/// overwriting one the person changed) +#[cfg(target_os = "linux")] +fn desktop_entry() { + let Some(data) = std::env::var_os("XDG_DATA_HOME") + .map(std::path::PathBuf::from) + .or_else(|| std::env::var_os("HOME").map(|h| std::path::PathBuf::from(h).join(".local/share"))) + else { + return; + }; + let icon = data.join("icons/hicolor/256x256/apps/anend.png"); + if !icon.exists() { + let _ = std::fs::create_dir_all(icon.parent().unwrap_or(&data)); + let _ = std::fs::write(&icon, include_bytes!("../../assets/icon.png")); + } + let entry = data.join("applications/anend-app.desktop"); + if !entry.exists() + && let Ok(exe) = std::env::current_exe() + { + let _ = std::fs::create_dir_all(entry.parent().unwrap_or(&data)); + let _ = std::fs::write( + &entry, + format!( + "[Desktop Entry]\nType=Application\nName=anend\nComment=notes, memory and the space\nExec=\"{}\" %F\nIcon=anend\nStartupWMClass=anend-app\nCategories=Office;Utility;\n", + exe.display() + ), + ); + } +} + +#[cfg(target_arch = "wasm32")] +fn main() { + dioxus::LaunchBuilder::web().launch(shell::App); +} diff --git a/app/src/md.rs b/app/src/md.rs new file mode 100644 index 00000000..a85468d7 --- /dev/null +++ b/app/src/md.rs @@ -0,0 +1,73 @@ +//! Markdown to HTML for reading notes: raw HTML in a note is shown as text, and links and +//! pictures only go to http(s), mailto or relative addresses. + +use pulldown_cmark::{CowStr, Event, Options, Parser, Tag, html}; + +fn safe_url(u: &str) -> bool { + let t: String = u.chars().filter(|c| !c.is_control() && !c.is_whitespace()).collect(); + let lower = t.to_ascii_lowercase(); + match lower.split_once(':') { + Some((scheme, _)) if !scheme.contains('/') => matches!(scheme, "http" | "https" | "mailto"), + _ => true, + } +} + +pub fn to_html(text: &str) -> String { + let opts = Options::ENABLE_TABLES | Options::ENABLE_STRIKETHROUGH | Options::ENABLE_TASKLISTS; + let events = Parser::new_ext(text, opts).map(|e| match e { + Event::Html(h) | Event::InlineHtml(h) => Event::Text(h), + Event::Start(Tag::Link { + link_type, + dest_url, + title, + id, + }) => Event::Start(Tag::Link { + link_type, + dest_url: if safe_url(&dest_url) { + dest_url + } else { + CowStr::from("#") + }, + title, + id, + }), + Event::Start(Tag::Image { + link_type, + dest_url, + title, + id, + }) => Event::Start(Tag::Image { + link_type, + dest_url: if safe_url(&dest_url) { + dest_url + } else { + CowStr::from("") + }, + title, + id, + }), + e => e, + }); + let mut out = String::new(); + html::push_html(&mut out, events); + out +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn safe() { + let h = to_html("# hi\n\n<script>alert(1)</script>\n\n[x](javascript:alert(1)) [y](https://a.b) **b**"); + assert!(h.contains("<h1>hi</h1>") && h.contains("<strong>b</strong>")); + assert!(!h.contains("<script>") && h.contains("<script>")); + assert!(!h.contains("javascript:") && h.contains("href=\"https://a.b\"")); + assert!( + to_html("[x](JaVa%20script:alert(1)) [y](JAVASCRIPT:x)") + .matches("href=\"#\"") + .count() + >= 1 + ); + } +} diff --git a/app/src/native.rs b/app/src/native.rs new file mode 100644 index 00000000..b0fb2b94 --- /dev/null +++ b/app/src/native.rs @@ -0,0 +1,171 @@ +//! The space drawn natively on the Linux desktop, with no JavaScript (docs/wip/questions.md +//! 114): `anend-render` draws the room on a thread of its own, and a GTK drawing area +//! *under* the (transparent) webview paints each picture where the space's element is. +//! The HTML around and over the room (bars, windows, menus) stays on top; GTK puts the two +//! together in one window. +//! +//! macOS and Windows show the same room in the page instead (picture.rs); neither space.js nor three.js is in a desktop build +//! (docs/wip/questions.md 118). + +use std::cell::RefCell; +use std::sync::mpsc::{Receiver, Sender, channel}; +use std::sync::{Arc, Mutex, OnceLock}; + +use gtk::prelude::*; + +/// a picture ready to paint: BGRA (cairo's order), where it goes in the window +struct Frame { + x: f64, + y: f64, + w: i32, + h: i32, + bgra: Vec<u8>, +} + +/// what the drawing area paints: the window's colour, then the room's picture (while shown) +#[derive(Default)] +struct Paint { + window: (f64, f64, f64), + frame: Option<Frame>, + shown: bool, +} + +fn paint() -> &'static Arc<Mutex<Paint>> { + static P: OnceLock<Arc<Mutex<Paint>>> = OnceLock::new(); + P.get_or_init(Default::default) +} + +thread_local! { + static AREA: RefCell<Option<gtk::DrawingArea>> = const { RefCell::new(None) }; +} + +/// asks GTK (on its own thread) to paint again +fn redraw() { + gtk::glib::MainContext::default().invoke(|| { + AREA.with(|a| { + if let Some(a) = a.borrow().as_ref() { + a.queue_draw(); + } + }) + }); +} + +/// puts the drawing area under the webview and makes the webview see-through; once +pub fn install(window: &dioxus::desktop::tao::window::Window, webview: &dioxus::desktop::wry::WebView) { + use dioxus::desktop::tao::platform::unix::WindowExtUnix; + if AREA.with(|a| a.borrow().is_some()) { + return; + } + let Some(vbox) = window.default_vbox() else { return }; + let Some(web) = vbox.children().into_iter().next() else { + return; + }; + vbox.remove(&web); + let overlay = gtk::Overlay::new(); + let area = gtk::DrawingArea::new(); + area.connect_draw(|_, cr| { + let p = paint().lock().unwrap_or_else(|e| e.into_inner()); + let (r, g, b) = p.window; + cr.set_source_rgb(r, g, b); + let _ = cr.paint(); + if p.shown + && let Some(f) = &p.frame + && let Ok(s) = + gtk::cairo::ImageSurface::create_for_data(f.bgra.clone(), gtk::cairo::Format::Rgb24, f.w, f.h, f.w * 4) + { + let _ = cr.set_source_surface(&s, f.x, f.y); + let _ = cr.paint(); + } + gtk::glib::Propagation::Stop + }); + overlay.add(&area); + overlay.add_overlay(&web); + vbox.pack_start(&overlay, true, true, 0); + overlay.show_all(); + // a webview at full opacity is put on screen by itself, over (and hiding) what's under + // it; just under full, GTK draws it into the window with the room showing through + web.set_opacity(0.99); + let _ = webview.set_background_color((0, 0, 0, 0)); + AREA.with(|a| *a.borrow_mut() = Some(area)); +} + +/// the window's colour (behind the see-through parts of the page), `#rrggbb` +pub fn set_window_colour(hex: &str) { + let h = |i: usize| u8::from_str_radix(hex.get(i..i + 2).unwrap_or("00"), 16).unwrap_or(0) as f64 / 255.0; + paint().lock().unwrap_or_else(|e| e.into_inner()).window = (h(1), h(3), h(5)); + redraw(); +} + +/// whether the room's picture shows (the space is the view on screen) +pub fn show(on: bool) { + paint().lock().unwrap_or_else(|e| e.into_inner()).shown = on; + redraw(); +} + +/// one picture to draw: the room, from where, into which part of the window +pub struct Job { + pub scene: anend_render::Scene, + pub camera: anend_render::Camera, + pub x: f64, + pub y: f64, + pub w: u32, + pub h: u32, +} + +fn worker() -> &'static Mutex<Sender<Job>> { + static W: OnceLock<Mutex<Sender<Job>>> = OnceLock::new(); + W.get_or_init(|| { + let (tx, rx) = channel::<Job>(); + std::thread::Builder::new() + .name("anend space".into()) + .spawn(move || draw_loop(rx)) + .expect("the space's thread"); + Mutex::new(tx) + }) +} + +/// asks for a picture; only the newest asked for is drawn +pub fn draw(job: Job) { + let _ = worker().lock().unwrap_or_else(|e| e.into_inner()).send(job); +} + +fn draw_loop(rx: Receiver<Job>) { + let mut renderer: Option<anend_render::Renderer> = None; + while let Ok(mut job) = rx.recv() { + while let Ok(newer) = rx.try_recv() { + job = newer; + } + if job.w == 0 || job.h == 0 { + continue; + } + let r = match &mut renderer { + Some(r) => { + r.resize(job.w, job.h); + r + } + None => match anend_render::Renderer::new(job.w, job.h) { + Ok(r) => renderer.insert(r), + Err(e) => { + eprintln!("anend: the space can't be drawn natively: {e}"); + return; + } + }, + }; + let mut px = r.render(&job.scene, &job.camera); + // something hidden behind came into view: drawn again, so it shows now + if r.wants_again { + px = r.render(&job.scene, &job.camera); + } + for p in px.as_chunks_mut::<4>().0 { + p.swap(0, 2); + } + paint().lock().unwrap_or_else(|e| e.into_inner()).frame = Some(Frame { + x: job.x, + y: job.y, + w: job.w as i32, + h: job.h as i32, + bgra: px, + }); + redraw(); + } +} diff --git a/app/src/native_audio.rs b/app/src/native_audio.rs new file mode 100644 index 00000000..e5f97e39 --- /dev/null +++ b/app/src/native_audio.rs @@ -0,0 +1,251 @@ +//! The native room's sounds on the Linux desktop (no Web Audio): sounds decoded once with +//! symphonia (wav, ogg, flac, mp3, mp4), mixed on cpal's output thread, each voice at the +//! gains the room says its two ears hear it with (`anend_render::room::Audio`). + +use std::collections::HashMap; +use std::sync::{Arc, Mutex, OnceLock}; + +use anend_render::room::Audio; +use cpal::traits::{DeviceTrait, HostTrait, StreamTrait}; + +/// a sound decoded: stereo frames at the output's rate +type Pcm = Arc<Vec<[f32; 2]>>; + +struct Voice { + pcm: Pcm, + at: usize, + looped: bool, + /// the gains it's heard with, and where they're easing to (no clicks) + gains: [f32; 2], + target: [f32; 2], +} + +#[derive(Default)] +struct Mix { + rate: u32, + sounds: HashMap<String, Pcm>, + voices: HashMap<String, Voice>, + /// each voice's gains as last said (they can come before it starts) + gains: HashMap<String, [f32; 2]>, + /// voices waiting on a sound still decoding: voice → (sound, looped) + pending: HashMap<String, (String, bool)>, +} + +impl Mix { + fn start(&mut self, voice: String, sound: &str, looped: bool) { + let Some(pcm) = self.sounds.get(sound).cloned() else { + self.pending.insert(voice, (sound.to_string(), looped)); + return; + }; + let g = self + .gains + .get(&voice) + .copied() + .unwrap_or(if voice.is_empty() { [1.0, 1.0] } else { [0.0, 0.0] }); + self.voices.insert( + voice, + Voice { + pcm, + at: 0, + looped, + gains: g, + target: g, + }, + ); + } +} + +fn mix() -> &'static Arc<Mutex<Mix>> { + static M: OnceLock<Arc<Mutex<Mix>>> = OnceLock::new(); + M.get_or_init(|| { + let m = Arc::new(Mutex::new(Mix { + rate: 48_000, + ..Default::default() + })); + start(m.clone()); + m + }) +} + +/// the output stream, on a thread of its own (cpal's stream isn't Send); no device, no sound +fn start(m: Arc<Mutex<Mix>>) { + std::thread::spawn(move || { + let Some(dev) = cpal::default_host().default_output_device() else { + return; + }; + let Ok(cfg) = dev.default_output_config() else { return }; + let channels = cfg.channels() as usize; + if let Ok(mut x) = m.lock() { + x.rate = cfg.sample_rate().0; + } + let fill = move |out: &mut [f32]| { + out.fill(0.0); + let Ok(mut x) = m.lock() else { return }; + x.voices.retain(|_, v| { + for frame in out.chunks_mut(channels.max(1)) { + if v.at >= v.pcm.len() { + if v.looped && !v.pcm.is_empty() { + v.at = 0; + } else { + return false; + } + } + for i in 0..2 { + v.gains[i] += (v.target[i] - v.gains[i]) * 0.002; + } + let s = v.pcm[v.at]; + v.at += 1; + if channels == 1 { + frame[0] += (s[0] * v.gains[0] + s[1] * v.gains[1]) * 0.5; + } else { + frame[0] += s[0] * v.gains[0]; + frame[1] += s[1] * v.gains[1]; + } + } + true + }); + for s in out.iter_mut() { + *s = s.clamp(-1.0, 1.0); + } + }; + let err = |_e: cpal::StreamError| {}; + let stream = match cfg.sample_format() { + cpal::SampleFormat::F32 => { + dev.build_output_stream(&cfg.config(), move |d: &mut [f32], _: &_| fill(d), err, None) + } + cpal::SampleFormat::I16 => { + let mut buf = Vec::new(); + dev.build_output_stream( + &cfg.config(), + move |d: &mut [i16], _: &_| { + buf.resize(d.len(), 0.0); + fill(&mut buf); + for (o, s) in d.iter_mut().zip(&buf) { + *o = (s * i16::MAX as f32) as i16; + } + }, + err, + None, + ) + } + _ => return, + }; + let Ok(stream) = stream else { return }; + if stream.play().is_err() { + return; + } + // the stream plays while it's kept: park here for the app's life + loop { + std::thread::park(); + } + }); +} + +/// a sound's bytes decoded to stereo at a rate (resampled straight across), or none +fn decode(bytes: Vec<u8>, rate: u32) -> Option<Vec<[f32; 2]>> { + use symphonia::core::audio::SampleBuffer; + use symphonia::core::codecs::DecoderOptions; + use symphonia::core::formats::FormatOptions; + use symphonia::core::io::MediaSourceStream; + use symphonia::core::meta::MetadataOptions; + use symphonia::core::probe::Hint; + let mss = MediaSourceStream::new(Box::new(std::io::Cursor::new(bytes)), Default::default()); + let probed = symphonia::default::get_probe() + .format( + &Hint::new(), + mss, + &FormatOptions::default(), + &MetadataOptions::default(), + ) + .ok()?; + let mut format = probed.format; + let track = format.default_track()?.clone(); + let mut dec = symphonia::default::get_codecs() + .make(&track.codec_params, &DecoderOptions::default()) + .ok()?; + let src_rate = track.codec_params.sample_rate.unwrap_or(rate); + let mut frames: Vec<[f32; 2]> = Vec::new(); + while let Ok(packet) = format.next_packet() { + if packet.track_id() != track.id { + continue; + } + let Ok(buf) = dec.decode(&packet) else { continue }; + let spec = *buf.spec(); + let ch = spec.channels.count().max(1); + let mut sb = SampleBuffer::<f32>::new(buf.capacity() as u64, spec); + sb.copy_interleaved_ref(buf); + for f in sb.samples().chunks(ch) { + frames.push(if ch == 1 { [f[0], f[0]] } else { [f[0], f[1]] }); + } + } + if frames.is_empty() { + return None; + } + if src_rate == rate { + return Some(frames); + } + let step = src_rate as f64 / rate as f64; + let n = (frames.len() as f64 / step) as usize; + Some( + (0..n) + .map(|i| { + let t = i as f64 * step; + let (a, f) = (t as usize, (t.fract()) as f32); + let (x, y) = (frames[a.min(frames.len() - 1)], frames[(a + 1).min(frames.len() - 1)]); + [x[0] + (y[0] - x[0]) * f, x[1] + (y[1] - x[1]) * f] + }) + .collect(), + ) +} + +/// does what the room said +pub fn play(cmds: Vec<Audio>) { + if cmds.is_empty() { + return; + } + let m = mix(); + for c in cmds { + match c { + Audio::Data { id, bytes } => { + let rate = m.lock().map(|x| x.rate).unwrap_or(48_000); + // decoding takes a moment: off the room's thread, then what waited starts + let m = m.clone(); + std::thread::spawn(move || { + let pcm = decode(bytes, rate).unwrap_or_default(); + if let Ok(mut x) = m.lock() { + x.sounds.insert(id.clone(), Arc::new(pcm)); + let waiting: Vec<(String, bool)> = x + .pending + .iter() + .filter(|(_, (s, _))| *s == id) + .map(|(v, (_, l))| (v.clone(), *l)) + .collect(); + for (v, l) in waiting { + x.pending.remove(&v); + x.start(v, &id, l); + } + } + }); + } + Audio::Play { voice, sound, looped } => { + if let Ok(mut x) = m.lock() { + x.start(voice, &sound, looped); + } + } + Audio::Stop { voice } => { + if let Ok(mut x) = m.lock() { + x.voices.remove(&voice); + x.pending.remove(&voice); + } + } + Audio::Gains { voice, left, right } => { + if let Ok(mut x) = m.lock() { + if let Some(v) = x.voices.get_mut(&voice) { + v.target = [left, right]; + } + x.gains.insert(voice, [left, right]); + } + } + } + } +} diff --git a/app/src/parity.rs b/app/src/parity.rs new file mode 100644 index 00000000..3672fa9e --- /dev/null +++ b/app/src/parity.rs @@ -0,0 +1,852 @@ +//! Guards for docs/parity.md: the settings keys and the views the app has. A key or a view +//! that goes away fails these tests until the expected list here and docs/parity.md are +//! changed together, saying why. + +/// every key the app's settings file holds (`prefs::Prefs`); add new ones here, and never +/// take one out without a line in docs/parity.md +#[cfg(test)] +pub const SETTINGS: &[&str] = &[ + "palette", + "colours", + "font_size", + "zoom", + "memory_font", + "spacing", + "field_width", + "mode", + "gsearch_text", + "saturate", + "letters", + "tint", + "cls_search", + "space_bg", + "space_reversed", + "space_keep", + "zen", + "zen_delay", + "hide_bar", + "collapsed", + "view", + "save", + "hub_url", + "filter_open", + "filter", + "keymap", + "highlight", + "check_spelling", + "space_search", + "hide_list", + "list_right", + "white", + "word_types", + "space", + "font", + "memory_family", + "top_bar", + "bottom_bar", + "bars_swapped", + "hub_token", + "read_device", + "piece_line", + "piece_lines", + "pipes", +]; + +/// the views, in their tab order +#[cfg(test)] +pub const VIEWS: &[&str] = &[ + "memory", "space", "lists", "reader", "notes", "tags", "stats", "models", "filters", +]; + +/// the keymap's action ids (keys.rs): every one the Bevy app had that still applies, and +/// the ones added since +#[cfg(test)] +pub const KEY_ACTIONS: &[&str] = &[ + "goto_memory", + "goto_space", + "goto_lists", + "goto_reader", + "goto_notes", + "goto_tags", + "goto_stats", + "goto_models", + "goto_filters", + "open_settings", + "open_keys", + "focus_bar", + "undo", + "zoom_in", + "zoom_out", + "zoom_reset", + "save", + "new_note", + "toggle_read", + "toggle_list", + "note_classifiers", + "toggle_check", + "bucket_ordinal", + "bucket_reversed", + "bucket_frequency", + "toggle_gsearch", + "toggle_saturate", + "white_mode", + "letters", + "classifier_search", + "word_types", + "side_ordinal", + "side_reversed", + "side_frequency", + "fly_forward", + "fly_back", + "fly_left", + "fly_right", + "fly_up", + "fly_down", + "roll_left", + "roll_right", + "level", + "back_to_start", + "slower", + "faster", + "walk", + "superflight", + "grapple", + "sneak", + "new_text", + "edit_text", + "delete_text", + "copy_text", + "group", + "ungroup", + "wire_mode", + "reversed", + "pin", + "physics", + "pause", + "settle", + "side_sum", + "side_reversed_sum", + "help", + "hud", + "details", + "export", + "save_map", + "read_prev", + "read_next", +]; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn settings_keys_stay() { + let v = serde_json::to_value(crate::prefs::Prefs::default()).unwrap(); + let have: Vec<&str> = v.as_object().unwrap().keys().map(String::as_str).collect(); + for k in SETTINGS { + assert!(have.contains(k), "the setting {k} went away: say why in docs/parity.md"); + } + for k in &have { + assert!(SETTINGS.contains(k), "a new setting {k}: add it to parity::SETTINGS"); + } + } + + #[test] + fn key_actions_stay() { + let have: Vec<&str> = crate::keys::Action::ALL.iter().map(|a| a.id()).collect(); + for k in KEY_ACTIONS { + assert!( + have.contains(k), + "the key action {k} went away: say why in docs/parity.md" + ); + } + for k in &have { + assert!( + KEY_ACTIONS.contains(k), + "a new key action {k}: add it to parity::KEY_ACTIONS" + ); + } + } + + /// the memory view's gematria underline (the colour of a text's reversed-sum group) + /// stays under word-type labels: no rule on a text or its labelled words takes the + /// underline away or draws one of its own + #[test] + fn word_types_keep_the_gematria_underline() { + let css = include_str!("style.css"); + for rule in css.split('}') { + let (sel, body) = rule.split_once('{').unwrap_or(("", "")); + if sel.contains(".art") || sel.contains("ruby.rw") { + assert!(!body.contains("text-decoration: none"), "{sel} hides the underline"); + assert!(!body.contains("border-bottom"), "{sel} draws a line of its own"); + assert!(!body.contains("text-decoration-color"), "{sel} recolours the underline"); + } + } + let mem = include_str!("views/memory.rs"); + assert!(mem.contains("text-decoration: underline; text-decoration-color: {c};")); + assert!(mem.contains("labels: true, ruby: true")); + } + + /// the space's texts carry the same gematria grouping underline as the memory view's + #[test] + fn space_keeps_the_grouping_underlines() { + let js = include_str!("space.js"); + assert!( + js.matches("borderBottomColor = t.under").count() >= 2, + "space.js must draw t.under" + ); + let rs = include_str!("views/space.rs"); + assert!( + rs.contains("\"under\": gem::underline(&h.text"), + "the space's texts must carry their underline" + ); + assert!(rs.contains("f[\"under\"] = json!(gem::underline("), "a map's texts too"); + } + + /// spatial saves: blocks keep their tiling UVs, their repeat wrapping and their gizmo, + /// and the space keeps the window that makes them + #[test] + fn blocks_tile_and_have_a_gizmo() { + let js = include_str!("space.js"); + for needle in [ + "boxGeometry(t)", + "RepeatWrapping", + "makeGizmo()", + "mode: 'scale'", + "mode: 'move'", + "kind === 'blockadd'", + "kind === 'unblock'", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + let rs = include_str!("views/space.rs"); + for needle in [ + "fn Blocks(", + "\"blocks.list\"", + "\"blocks.set\"", + "\"blocks.add\"", + "show_blocks", + ] { + assert!(rs.contains(needle), "space.rs lost {needle}"); + } + } + + /// the native room (the Linux desktop's) takes every command space.js takes, and has + /// what each of its parts does + #[test] + fn the_native_room_takes_every_command() { + let room = [ + include_str!("../../render/src/room.rs"), + include_str!("../../render/src/room/edit.rs"), + include_str!("../../render/src/room/wires.rs"), + include_str!("../../render/src/room/sounds.rs"), + include_str!("../../render/src/room/play.rs"), + ] + .concat(); + let sp = include_str!("views/space.rs"); + let mut n = 0; + for part in sp.split("c.cmd === '").skip(1) { + let cmd = &part[..part.find('\'').unwrap_or(0)]; + assert!( + room.contains(&format!("\"{cmd}\"")), + "the native room doesn't take `{cmd}`" + ); + n += 1; + } + assert!(n > 50, "space.js's commands: {n}"); + for needle in [ + "fn pick_block(", + "fn start_block_drag(", + "fn toggle_multi(", + "fn end_box(", + "fn set_groups(", + "fn pick_copy(", + "fn set_wiring(", + "fn wire_meshes(", + "fn assign_zones(", + "fn play_sound(", + "fn set_mode(", + "fn walk_step(", + "fn grapple(", + "fn superflight(", + "fn aim_ghost(", + "fn apply_anims(", + "fn thumbs(", + ] { + assert!(room.contains(needle), "the native room lost {needle}"); + } + let blocks = include_str!("../../render/src/blocks.rs"); + assert!( + blocks.contains("pub fn bend_at(") && blocks.contains("fn light_at(") && blocks.contains("fn sky_mesh(") + ); + let tiles = include_str!("../../render/src/tiles.rs"); + assert!( + tiles.contains("pub fn text_tile(") + && tiles.contains("pub fn recipe_tile(") + && tiles.contains("pub fn preview(") + ); + // and the Linux desktop's build has no space.js nor three.js in it + assert!(sp.contains("#[cfg(not(feature = \"desktop\"))]\nconst THREE")); + } + + /// wires drawn in the room and made by dragging + #[test] + fn wires_drawn_stay() { + let js = include_str!("space.js"); + for needle in [ + "drawWires() {", + "lightWires(rays) {", + "setWiring(on) {", + "startWire(e) {", + "endWire(e) {", + "u.kind === 'wired'", + "TubeGeometry", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + assert!( + include_str!("views/space.rs").contains("\"wirelink\"") + && include_str!("views/space/wirewin.rs").contains("\"connect by dragging\"") + ); + } + + /// groups: Ctrl+G, nesting, picked whole, opened, copied, made a prefab + #[test] + fn groups_stay() { + let js = include_str!("space.js"); + for needle in [ + "setGroups(list) {", + "outer(key) {", + "pickGroup(gid, add) {", + "groupMembers() {", + "openGroupAt(key) {", + "u.kind === 'grouped'", + "u.kind === 'ungrouped'", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + let sp = include_str!("views/space.rs"); + assert!( + sp.contains("fn group_copy(") + && sp.contains("fn group_prefab(") + && sp.contains("Some(Action::Group)") + && sp.contains("Some(Action::Ungroup)") + ); + } + + /// selecting many: Shift+click and boxes in the space and the memory view; notes, lists + #[test] + fn selection_of_many_stays() { + let js = include_str!("space.js"); + for needle in [ + "toggleMulti(kind, id) {", + "endBox(e) {", + "moveMulti(d) {", + "removeMulti() {", + "setBatch(on) {", + "kind: 'many'", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + assert!( + include_str!("views/space.rs").contains("\"removedmulti\"") + && include_str!("views/space.rs").contains("class: \"multibar\"") + ); + let m = include_str!("views/memory.rs"); + assert!(m.contains("BOX_SELECT") && m.contains("md.shift() || md.alt()")); + assert!( + include_str!("views/notes.rs").contains("fn ManyNotes(") + && include_str!("views/lists.rs").contains("fn ManyLists(") + ); + } + + /// a prefab's copy is one group in the room: selected, moved, copied and removed whole + #[test] + fn copies_are_groups() { + let js = include_str!("space.js"); + for needle in [ + "pickCopy(cid, quiet) {", + "openCopyAt(id) {", + "closeCopy() {", + "moveCopyParts(d) {", + "copyGone(ids, restore) {", + "kind: 'copygone'", + "'copyset'", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + let pf = include_str!("views/space/prefabwin.rs"); + assert!( + pf.contains("fn CopyMenu(") + && pf.contains("\"prefabs.duplicate\"") + && pf.contains("\"open it to edit its parts\"") + ); + } + + /// tag sets: the models view's fourth tab; English types only on English + #[test] + fn tag_sets_stay() { + let cls = include_str!("views/classifiers.rs"); + assert!( + cls.contains("(3, \"tag sets\")") + && cls.contains("models: tagsets") + && cls.contains("crate::views::tagsets::TagSets {}") + ); + let t = include_str!("views/tagsets.rs"); + for needle in [ + "\"tagsets.mark\"", + "\"tagsets.train\"", + "\"tagsets.tag\"", + "\"tagsets.score\"", + "\"tagsets.save\"", + "\"tagsets.delete\"", + "\"a checker\"", + "ts-suggest", + ] { + assert!(t.contains(needle), "tagsets.rs lost {needle}"); + } + let m = include_str!("views/memory.rs"); + assert!( + m.matches("looks_english").count() >= 2, + "the memory view's word types only on English" + ); + } + + /// views as programs: the reader's presets and view programs + #[test] + fn views_as_programs_stay() { + let r = include_str!("views/reader.rs"); + for needle in [ + "\"views.run\"", + "\"views.list\"", + "\"reader-list\"", + "\"reader-head\"", + "fn fx_style(", + ] { + assert!(r.contains(needle), "reader.rs lost {needle}"); + } + let core = include_str!("../../core/src/ops/views.rs"); + assert!( + core.contains("(\"everything\", \"everything\"") + && core.contains("(\"notes\", \"notes\"") + && core.contains("(\"texts\", \"texts\"") + ); + assert!(include_str!("../../core/src/s/lib.rs").contains("\"view\" => (&[], VIEW)")); + } + + /// pipes: the filters view's pipe editor, effects in the memory view and the space + #[test] + fn pipes_stay() { + let p = include_str!("views/pipes.rs"); + for needle in [ + "(\"colour\", \"a colour\")", + "(\"colour_by\", \"a classifier's colours\")", + "(\"underline\", \"an underline\")", + "(\"label\", \"a label\")", + "(\"size\", \"a size\")", + "(\"glow\", \"a glow\")", + "(\"gather\", \"gather in the space\")", + "(\"enlist\", \"put them in a list\")", + "(\"tag\", \"tag them\")", + "(\"run\", \"run a program on each\")", + "\"pipes.apply\"", + "\"pipes.delete\"", + "\"pipes.list\"", + ] { + assert!(p.contains(needle), "pipes.rs lost {needle}"); + } + let b = include_str!("views/flt.rs"); + assert!( + b.contains("\"pipes.save\"") + && b.contains("crate::views::pipes::Parts") + && b.contains("crate::views::pipes::KeptPipes") + ); + assert!( + include_str!("views/memory.rs").contains("\"pipes.effects\"") + && include_str!("views/memory.rs").contains("fx-label") + ); + assert!(include_str!("views/space.rs").contains("\"cmd\": \"effects\"")); + let js = include_str!("space.js"); + assert!(js.contains("effects(fx) {") && js.contains("dress(n) {") && js.contains("A.gather")); + } + + /// taxonomies: the models view's third tab, the tree editor, routing and marking + #[test] + fn taxonomies_stay() { + let cls = include_str!("views/classifiers.rs"); + assert!(cls.contains("(2, \"taxonomies\")") && cls.contains("models: taxonomies")); + assert!(cls.contains("crate::views::taxonomy::Taxonomies { bar: tax_bar }")); + let tx = include_str!("views/taxonomy.rs"); + for needle in [ + "\"taxonomy.list\"", + "\"taxonomy.get\"", + "\"taxonomy.save\"", + "\"taxonomy.delete\"", + "\"taxonomy.route\"", + "\"taxonomy.mark\"", + "\"ends here\"", + "\"none of these\"", + "fn node_view(", + ] { + assert!(tx.contains(needle), "taxonomy.rs lost {needle}"); + } + assert!(include_str!("../../core/src/s/lib.rs").contains("(\"route\", |rt|")); + } + + /// s programs: notes tagged s, the right-aligned code mode, word classes, running + #[test] + fn s_programs_stay() { + let hl = include_str!("highlight.rs"); + for needle in ["pub fn s_classes(", "pub fn s_html(", "pub s: bool"] { + assert!(hl.contains(needle), "highlight.rs lost {needle}"); + } + let rs = include_str!("views/notes.rs"); + for needle in [ + "\"run the program\"", + "\"s.run\"", + "s-run", + "ops::script::TAG", + "\"s.debug\"", + "\"step through the program\"", + "\"the program's outline\"", + "goto_req", + "__anendCompl", + ] { + assert!(rs.contains(needle), "notes.rs lost {needle}"); + } + assert!(include_str!("style.css").contains(".pad.code textarea")); + assert!(hl.contains("pub fn s_html_with(") && include_str!("views/scode.rs").contains("pub fn outline(")); + // the bar's Run and the command line's run (#11) + assert!(include_str!("views/scode.rs").contains("pub async fn run_from_bar(")); + assert!(include_str!("views/memory.rs").contains("run_from_bar")); + assert!(include_str!("views/space.rs").contains("run_from_bar")); + assert!(include_str!("main.rs").contains("fn run_cli(")); + assert!(include_str!("../../core/src/s/lib.rs").contains("\"anend\" =>")); + // classifiers and models as words (#18) + assert!(include_str!("../../core/src/s/lib.rs").contains("\"learn\" => (&[\"anend\"], LEARN)")); + } + + /// wiring: blocks that cast rays and run programs, the window, playing in the room + #[test] + fn wiring_stays() { + let js = include_str!("space.js"); + for needle in [ + "setWires(list, live)", + "wireTimers(now)", + "wireZone(zone, text, event)", + "showRays(rays)", + "this.wireFire(id, 'click')", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + let rs = include_str!("views/space/wirewin.rs"); + for needle in [ + "fn Wires(", + "\"wiring.fire\"", + "\"wiring.set\"", + "pick targets in the room", + "▶ play", + "try it", + ] { + assert!(rs.contains(needle), "wirewin.rs lost {needle}"); + } + let sp = include_str!("views/space.rs"); + assert!(sp.contains("show_wiring") && sp.contains("\"blockfire\"")); + } + + /// prefabs: grouping, the menu with pictures, a copy's controls + #[test] + fn prefabs_stay() { + let js = include_str!("space.js"); + assert!(js.contains("thumbs(list, textures)") && js.contains("part_of")); + for needle in [ + "startGhost(prefab, parts, textures, name)", + "aimGhost()", + "placeGhost()", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + let rs = include_str!("views/space/prefabwin.rs"); + for needle in [ + "fn Prefabs(", + "\"prefabs.make\"", + "\"prefabs.place\"", + "\"prefabs.apply\"", + "\"prefabs.detach\"", + "pick blocks in the room", + "…but not the other copies", + "\"prefabs.starters\"", + ] { + assert!(rs.contains(needle), "prefabwin.rs lost {needle}"); + } + let sp = include_str!("views/space.rs"); + assert!(sp.contains("show_prefabs") && sp.contains("\"prefabspot\"") && sp.contains("\"thumbs\"")); + } + + /// sounds: the window, emitters played by the room + #[test] + fn sounds_stay() { + let js = include_str!("space.js"); + for needle in [ + "playSound(blockId)", + "startLoops()", + "hushAll()", + "soundData(id, data)", + "hearFrom()", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + let rs = include_str!("views/space/soundwin.rs"); + for needle in [ + "fn Sounds(", + "\"sounds.add\"", + "\"blocks.set\"", + "sounds to add", + "the sound it plays", + ] { + assert!(rs.contains(needle), "soundwin.rs lost {needle}"); + } + let sp = include_str!("views/space.rs"); + assert!(sp.contains("show_sounds") && sp.contains("\"soundwant\"")); + } + + /// space.js defines each method of the room once: a second one replaces the first + /// without a word (an audio `listen` once shadowed the one that attaches the events) + #[test] + fn room_methods_are_unique() { + let js = include_str!("space.js"); + let mut seen = std::collections::HashSet::new(); + for line in js.lines() { + let Some(rest) = line.strip_prefix(" ") else { continue }; + if rest.starts_with(' ') || !rest.ends_with(") {") { + continue; + } + let Some((name, _)) = rest.split_once('(') else { + continue; + }; + if name.is_empty() || !name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_') { + continue; + } + if ["if", "for", "while", "switch", "catch", "constructor"].contains(&name) { + continue; + } + assert!(seen.insert(name.to_string()), "space.js defines {name} twice"); + } + assert!(seen.len() > 100); + } + + /// first-person mode: walking, the grapple, superflight and what it collects + #[test] + fn first_person_stays() { + let js = include_str!("space.js"); + for needle in [ + "setMode(mode)", + "walkStep(dt)", + "grapple()", + "superflight(dt)", + "collect(a, b)", + "BODY.mantle", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + let rs = include_str!("views/space/flightwin.rs"); + for needle in [ + "fn Collected(", + "\"mem.saturate\"", + "\"chains.make\"", + "\"lists.enlist\"", + "into the bar", + ] { + assert!(rs.contains(needle), "flightwin.rs lost {needle}"); + } + assert!(include_str!("views/space.rs").contains("\"collected\"")); + } + + /// keyframe animations: the window, the room posing blocks + #[test] + fn animations_stay() { + let js = include_str!("space.js"); + for needle in [ + "animPose(a, p)", + "applyAnims(now)", + "previewAnim(id, anim, p)", + "function cubicBezier(", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + let rs = include_str!("views/space/animwin.rs"); + for needle in [ + "fn Anims(", + "fn Curve(", + "\"anims.save\"", + "a key here", + "the selected block plays it", + ] { + assert!(rs.contains(needle), "animwin.rs lost {needle}"); + } + assert!(include_str!("views/space.rs").contains("show_anims")); + } + + /// texture recipes: the textures window's steps, faces and the sky + #[test] + fn texture_recipes_stay() { + let js = include_str!("space.js"); + for needle in [ + "recipeCanvas(about", + "recipeTexture(about", + "blockMaterial(b)", + "setSky(about)", + "preview(id, about", + "function variantOf(", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + let rs = include_str!("views/space/texwin.rs"); + for needle in [ + "fn Textures(", + "\"textures.save\"", + "\"blocks.retexture\"", + "\"space.sky\"", + "on one face:", + "as the sky", + ] { + assert!(rs.contains(needle), "texwin.rs lost {needle}"); + } + assert!(include_str!("views/space.rs").contains("show_textures")); + } + + /// lights baked onto blocks, and sphere blocks + #[test] + fn lights_and_spheres_stay() { + let js = include_str!("space.js"); + for needle in [ + "bake(o)", + "setLights(list, changed)", + "showLights(on, picked)", + "lightSpot()", + "sphereGeometry(t)", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + let rs = include_str!("views/space/lightwin.rs"); + for needle in [ + "fn Lights(", + "\"lights.add\"", + "\"lights.set\"", + "\"lights.delete\"", + "move it here", + ] { + assert!(rs.contains(needle), "lightwin.rs lost {needle}"); + } + let sp = include_str!("views/space.rs"); + for needle in [ + "show_lights", + "fn ShapeRow(", + "make it a sphere", + "fn ZoneRow(", + "a staging zone", + ] { + assert!(sp.contains(needle), "space.rs lost {needle}"); + } + } + + /// the notes editor's spelling check: asked for as one writes, its flags drawn in the + /// highlight layer, a click's suggestion put in as an undo step of its own + #[test] + fn the_spelling_check_stays() { + let rs = include_str!("views/notes.rs"); + for needle in [ + "\"grammar.check\"", + "l.layer.full(&t, colour, &flags_now)", + "fn SpellPick(", + "__anendPadSnap(p, true)", + "check_spelling", + ] { + assert!(rs.contains(needle), "notes.rs lost {needle}"); + } + } + + /// Enter in the space's bar gives the keys back to flying + #[test] + fn the_space_bar_lets_go_after_enter() { + let rs = include_str!("views/space.rs"); + let at = rs.find("\"Enter\" => {").expect("the bar's Enter"); + let arm = &rs[at..at + 700]; + assert!( + arm.contains("spawn_forever(enter(") && arm.contains("b.blur()"), + "{arm}" + ); + } + + /// the room's right-click menu, and copies that are placements, not entries + #[test] + fn space_texts_have_a_menu_and_safe_copies() { + let rs = include_str!("views/space.rs"); + for needle in [ + "fn SpaceMenu(", + "\"cmd\": \"dup\"", + "\"cmd\": \"removenode\"", + "forget the entry", + "e.shift && !t.is_empty()", + "a copy that inherits", + "a detached copy", + "edit this placement only", + "follow the entry again", + ] { + assert!(rs.contains(needle), "space.rs lost {needle}"); + } + let js = include_str!("space.js"); + for needle in [ + "placements(entry)", + "duplicate(node, det)", + "setOwn(node, text)", + "removeNode(node)", + "copyKey(entry)", + ] { + assert!(js.contains(needle), "space.js lost {needle}"); + } + } + + /// the saved scenes: listed, opened, renamed, deleted with an undo + #[test] + fn scenes_window_stays() { + let rs = include_str!("views/space.rs"); + for needle in [ + "fn Scenes(", + "show_scenes", + "renamed {n} to {to}", + "deleted the scene {n}", + "{n} is back", + ] { + assert!(rs.contains(needle), "space.rs lost {needle}"); + } + } + + /// the command bar's input spans the bar with the same room at both ends, so its + /// centred text doesn't move when what's beside it changes size + #[test] + fn the_bar_text_stays_put() { + let css = include_str!("style.css"); + assert!( + css.contains("padding: 0 var(--reserve);") && css.contains("min-width: 15.5cm"), + "the input keeps equal room at both ends" + ); + assert!( + css.contains(".cmdbar .side {\n position: absolute;"), + "the side sits over the bar, not beside the input" + ); + } + + /// the reader's note cards show when each note was written + #[test] + fn reader_cards_keep_their_dates() { + let rs = include_str!("views/reader.rs"); + assert!(rs.contains("short_date(&c)") && rs.contains("written ")); + } + + #[test] + fn views_stay() { + let have: Vec<&str> = crate::ui::View::ALL.iter().map(|v| v.name()).collect(); + assert_eq!(have, VIEWS, "the views changed: say why in docs/parity.md"); + } +} diff --git a/app/src/picture.rs b/app/src/picture.rs new file mode 100644 index 00000000..ed2a13f2 --- /dev/null +++ b/app/src/picture.rs @@ -0,0 +1,177 @@ +//! The native room's picture shown *in* the page, for desktops without GTK under the +//! webview (macOS, Windows; on Linux with `ANEND_SPACE_PICTURE=1`, to check it): each frame +//! `anend-render` draws is kept as an uncompressed bitmap, served to the page through the +//! `anendframe` custom protocol, and shown by an `img` in the space's element. No script: +//! the `img`'s address changes with each new frame (docs/wip/questions.md 118). +//! The prefab pictures (`thumbs`) are drawn here too, on every desktop. + +use std::borrow::Cow; +use std::sync::mpsc::{Receiver, Sender, channel}; +use std::sync::{Arc, Mutex, OnceLock}; + +use dioxus::desktop::wry::http::{Request, Response}; + +/// whether the room's picture goes into the page (not under it) +pub fn enabled() -> bool { + static ON: OnceLock<bool> = OnceLock::new(); + *ON.get_or_init(|| !cfg!(target_os = "linux") || std::env::var("ANEND_SPACE_PICTURE").is_ok_and(|v| v == "1")) +} + +/// the newest frame: its number and its bitmap +fn frame() -> &'static Mutex<(u64, Arc<Vec<u8>>)> { + static F: OnceLock<Mutex<(u64, Arc<Vec<u8>>)>> = OnceLock::new(); + F.get_or_init(|| Mutex::new((0, Arc::new(bmp(1, 1, &[0, 0, 0, 0]))))) +} + +/// the newest frame's number (the page asks for it by number, so each new one loads) +pub fn frame_no() -> u64 { + frame().lock().map(|f| f.0).unwrap_or(0) +} + +/// where the page fetches a frame (WebView2 serves custom protocols over http) +pub fn frame_url(n: u64) -> String { + if cfg!(target_os = "windows") { + format!("http://anendframe.localhost/{n}") + } else { + format!("anendframe://localhost/{n}") + } +} + +/// the custom protocol: the newest frame, whatever number was asked for +pub fn protocol(_: dioxus::desktop::wry::WebViewId, _req: Request<Vec<u8>>) -> Response<Cow<'static, [u8]>> { + let data = frame().lock().map(|f| f.1.clone()).unwrap_or_default(); + Response::builder() + .header("Content-Type", "image/bmp") + .header("Cache-Control", "no-store") + .body(Cow::<'static, [u8]>::Owned(data.as_ref().clone())) + .unwrap_or_else(|_| Response::new(Cow::Owned(Vec::new()))) +} + +/// RGBA rows (from the top) as a 32-bit BMP, top-down +fn bmp(w: u32, h: u32, rgba: &[u8]) -> Vec<u8> { + let size = (w * h * 4) as usize; + let mut out = Vec::with_capacity(54 + size); + let le32 = |v: u32| v.to_le_bytes(); + out.extend_from_slice(b"BM"); + out.extend_from_slice(&le32(54 + size as u32)); + out.extend_from_slice(&[0, 0, 0, 0]); + out.extend_from_slice(&le32(54)); + out.extend_from_slice(&le32(40)); + out.extend_from_slice(&le32(w)); + out.extend_from_slice(&(-(h as i32)).to_le_bytes()); + out.extend_from_slice(&1u16.to_le_bytes()); + out.extend_from_slice(&32u16.to_le_bytes()); + out.extend_from_slice(&[0; 4]); + out.extend_from_slice(&le32(size as u32)); + out.extend_from_slice(&[0; 16]); + for p in rgba.as_chunks::<4>().0 { + out.extend_from_slice(&[p[2], p[1], p[0], 255]); + } + out +} + +/// one picture to draw: the room, from where, how big +pub struct Job { + pub scene: anend_render::Scene, + pub camera: anend_render::Camera, + pub w: u32, + pub h: u32, +} + +fn worker() -> &'static Mutex<Sender<Job>> { + static W: OnceLock<Mutex<Sender<Job>>> = OnceLock::new(); + W.get_or_init(|| { + let (tx, rx) = channel::<Job>(); + std::thread::Builder::new() + .name("anend space picture".into()) + .spawn(move || draw_loop(rx)) + .expect("the space's thread"); + Mutex::new(tx) + }) +} + +/// asks for a picture; only the newest asked for is drawn +pub fn draw(job: Job) { + let _ = worker().lock().unwrap_or_else(|e| e.into_inner()).send(job); +} + +fn draw_loop(rx: Receiver<Job>) { + let mut renderer: Option<anend_render::Renderer> = None; + while let Ok(mut job) = rx.recv() { + while let Ok(newer) = rx.try_recv() { + job = newer; + } + if job.w == 0 || job.h == 0 { + continue; + } + let r = match &mut renderer { + Some(r) => { + r.resize(job.w, job.h); + r + } + None => match anend_render::Renderer::new(job.w, job.h) { + Ok(r) => renderer.insert(r), + Err(e) => { + eprintln!("anend: the space can't be drawn natively: {e}"); + return; + } + }, + }; + let mut px = r.render(&job.scene, &job.camera); + if r.wants_again { + px = r.render(&job.scene, &job.camera); + } + let b = Arc::new(bmp(job.w, job.h, &px)); + if let Ok(mut f) = frame().lock() { + *f = (f.0 + 1, b); + } + } +} + +/// the prefabs' small pictures (112 pixels square, see-through round their parts), drawn +/// on a renderer of their own: id → a PNG data URL, sent back when done +pub fn thumbs( + jobs: Vec<(serde_json::Value, anend_render::Scene, anend_render::Camera)>, + done: Sender<serde_json::Value>, +) { + if jobs.is_empty() { + return; + } + std::thread::spawn(move || { + const SIZE: u32 = 112; + let Ok(mut r) = anend_render::Renderer::new(SIZE, SIZE) else { + return; + }; + let mut out = serde_json::Map::new(); + for (id, scene, camera) in jobs { + let mut px = r.render(&scene, &camera); + // the picture's edges are blended with nothing: their colour back to full + for p in px.as_chunks_mut::<4>().0 { + let a = p[3] as f32 / 255.0; + if a > 0.0 && a < 1.0 { + for c in &mut p[..3] { + *c = ((*c as f32 / a).min(255.0)) as u8; + } + } + } + let key = id.as_str().map(String::from).unwrap_or_else(|| id.to_string()); + out.insert( + key, + serde_json::Value::String(anend_render::tiles::rgba_url(SIZE, SIZE, px)), + ); + } + let _ = done.send(serde_json::Value::Object(out)); + }); +} + +#[cfg(test)] +mod tests { + #[test] + fn frames_are_bitmaps() { + let b = super::bmp(2, 1, &[255, 0, 0, 255, 0, 0, 255, 255]); + assert_eq!(&b[..2], b"BM"); + assert_eq!(b.len(), 54 + 8); + // BGRA: the first pixel red + assert_eq!(&b[54..58], &[0, 0, 255, 255]); + } +} diff --git a/app/src/prefs.rs b/app/src/prefs.rs new file mode 100644 index 00000000..2811d08d --- /dev/null +++ b/app/src/prefs.rs @@ -0,0 +1,314 @@ +//! The app's own settings (this machine's, not the save's): colours, font size, zoom, +//! spacing, the memory view's toggles, which sections are collapsed. The desktop keeps +//! them in `app.json` beside the Bevy app's config (`ANEND_APP_CONFIG` overrides the +//! path); the web app in localStorage. + +use std::collections::{BTreeMap, BTreeSet}; + +use serde::{Deserialize, Serialize}; + +use crate::gem::Mode; + +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(default)] +pub struct Prefs { + /// sand, night, paper or sea + pub palette: String, + /// colours changed from the palette's, by role + pub colours: BTreeMap<String, String>, + /// the interface's text size in pixels + pub font_size: f32, + /// the whole page's zoom (Ctrl+= / Ctrl+−, Ctrl+PageUp / PageDown) + pub zoom: f32, + /// the memory view's text size in pixels + pub memory_font: f32, + /// the gap between texts in the memory view, in pixels + pub spacing: f32, + /// the memory view's centre field's width, in pixels (0: the whole width) + pub field_width: f32, + pub mode: Mode, + /// Enter on a text gsearches its sum (weum's gsch), not its words + pub gsearch_text: bool, + /// remember what's searched (weum's alsoSaturate) + pub saturate: bool, + /// the sidecar's frequency letters + pub letters: bool, + /// the classifier colouring the memory view's texts (empty: none) + pub tint: String, + /// Enter in the memory view searches with that classifier: a class's name finds the + /// texts most likely in it, any other text the texts it reads most like + pub cls_search: bool, + /// the pipes whose effects the memory view and the space show, stacked in this order + pub pipes: Vec<String>, + /// how the space's bar searches: normal, classifier or random + pub space_search: String, + /// the space's background colour + pub space_bg: String, + /// the space buckets by the reversed sum + pub space_reversed: bool, + /// the space adds new results to what's there + pub space_keep: bool, + /// fade the bars away while the mouse and keys rest + pub zen: bool, + /// seconds of stillness before zen fades + pub zen_delay: f32, + /// slide the top bar away until the pointer comes near it + pub hide_bar: bool, + /// sections folded shut, by name (settings, lists…) + pub collapsed: BTreeSet<String>, + pub view: String, + /// the save the desktop opens (a path) + pub save: Option<String>, + /// the hub (when built with it) + pub hub_url: String, + /// the memory view's search filter panel is open + pub filter_open: bool, + /// what the memory view's search filter keeps + pub filter: MemFilter, + /// the keys changed from their defaults: action id → binding (keys.rs) + pub keymap: BTreeMap<String, String>, + /// colour the markdown in the note editor + pub highlight: bool, + /// underline likely spelling and word-choice errors in the note editor + pub check_spelling: bool, + /// the note list slid away + pub hide_list: bool, + /// the note list at the editor's right + pub list_right: bool, + /// the memory view's white mode: dark texts on white + pub white: bool, + /// the memory view labels every text's words with their types + pub word_types: bool, + /// the space's panels, physics, history and last address + pub space: SpaceUi, + /// the interface's font family (empty: the built-in Fira Sans) + pub font: String, + /// the memory view's font family (empty: the system serif) + pub memory_family: String, + /// the top bar's and the command bar's heights in pixels + pub top_bar: f32, + pub bottom_bar: f32, + /// the top bar at the bottom, the command bar at the top + pub bars_swapped: bool, + /// an app token from the hub's profile page (sharing needs one) + pub hub_token: String, + /// where classifiers read texts: auto, cpu, gpu or gpu_fast (`classify.device`) + pub read_device: String, + /// a long text is shown piece by piece (`anend_core::pieces`): characters a line and + /// lines a piece + pub piece_line: usize, + pub piece_lines: usize, +} + +/// the space's own settings +#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] +#[serde(default)] +pub struct SpaceUi { + /// the physics panel's sliders changed from their defaults (views/space.rs `SLIDERS`) + pub physics: BTreeMap<String, f64>, + /// what the depth follows: none, ordinal, length or time + pub depth_by: String, + /// what was typed in the space's bar (↑ ↓), newest last + pub history: Vec<String>, + /// the last address (`123`, `r123` or a map's name), opened again next time + pub address: String, + pub show_physics: bool, + pub show_hud: bool, + pub show_help: bool, + pub show_details: bool, + /// the blocks window (spatial saves) + pub show_blocks: bool, + /// the saved scenes (maps) window + pub show_scenes: bool, + /// the textures window (texture recipes) + pub show_textures: bool, + /// the lights window + pub show_lights: bool, + /// the animations window + pub show_anims: bool, + /// the wiring window (blocks that cast rays and run programs) + pub show_wiring: bool, + /// the prefabs window (subassemblies and their menu) + pub show_prefabs: bool, + /// the sounds window (the save's sounds and the selected block's emitter) + pub show_sounds: bool, + /// where each movable window was left (`details`, `physics`): its left and top + pub wins: BTreeMap<String, (f64, f64)>, +} + +impl Default for SpaceUi { + fn default() -> SpaceUi { + SpaceUi { + physics: BTreeMap::new(), + depth_by: "none".into(), + history: Vec::new(), + address: String::new(), + show_physics: false, + show_hud: true, + show_help: false, + show_details: true, + show_blocks: false, + show_scenes: false, + show_textures: false, + show_lights: false, + show_anims: false, + show_wiring: false, + show_prefabs: false, + show_sounds: false, + wins: BTreeMap::new(), + } + } +} + +/// the memory view's search filter: what of the shown texts it keeps (every part empty or +/// off keeps everything) +#[derive(Debug, Clone, Default, PartialEq, Serialize, Deserialize)] +#[serde(default)] +pub struct MemFilter { + /// leave out notes / texts that aren't notes + pub no_notes: bool, + pub no_texts: bool, + /// kinds of text (core's kinds::detect) to keep; empty: all + pub kinds: BTreeSet<String>, + /// word types a text must have (each of them at least once) + pub words: BTreeSet<String>, + /// classes of the colouring classifier to keep ("unsure" for none); empty: all + pub classes: BTreeSet<String>, + /// only texts the colouring classifier was given a yes or no on + pub feedback: bool, +} + +impl MemFilter { + pub fn active(&self) -> bool { + *self != MemFilter::default() + } +} + +impl Default for Prefs { + fn default() -> Prefs { + Prefs { + palette: "sand".into(), + colours: BTreeMap::new(), + font_size: 14.0, + zoom: 1.0, + memory_font: 20.0, + spacing: 4.0, + field_width: 0.0, + mode: Mode::Ordinal, + gsearch_text: true, + saturate: true, + letters: true, + tint: String::new(), + cls_search: false, + pipes: Vec::new(), + space_search: "normal".into(), + space_bg: "#e4d4be".into(), + space_reversed: false, + space_keep: false, + zen: false, + zen_delay: 2.5, + hide_bar: false, + collapsed: ["hub".to_string()].into_iter().collect(), + view: "memory".into(), + save: None, + hub_url: String::new(), + filter_open: false, + filter: MemFilter::default(), + keymap: BTreeMap::new(), + highlight: true, + check_spelling: true, + hide_list: false, + list_right: false, + white: false, + word_types: false, + space: SpaceUi::default(), + font: String::new(), + memory_family: String::new(), + top_bar: 32.0, + bottom_bar: 32.0, + bars_swapped: false, + hub_token: String::new(), + read_device: "auto".into(), + piece_line: anend_core::pieces::LINE, + piece_lines: anend_core::pieces::LINES, + } + } +} + +impl Prefs { + pub fn folded(&self, section: &str) -> bool { + self.collapsed.contains(section) + } +} + +#[cfg(not(target_arch = "wasm32"))] +fn path() -> std::path::PathBuf { + if let Some(p) = std::env::var_os("ANEND_APP_CONFIG") { + return p.into(); + } + config_dir().join("app.json") +} + +#[cfg(not(target_arch = "wasm32"))] +fn platform_dir(xdg: &str, fallback: &str) -> std::path::PathBuf { + let base = if cfg!(target_os = "windows") { + std::env::var_os("APPDATA").map(std::path::PathBuf::from) + } else if cfg!(target_os = "macos") { + std::env::var_os("HOME").map(|h| std::path::PathBuf::from(h).join("Library/Application Support")) + } else { + std::env::var_os(xdg) + .map(std::path::PathBuf::from) + .or_else(|| std::env::var_os("HOME").map(|h| std::path::PathBuf::from(h).join(fallback))) + }; + base.unwrap_or_else(|| ".".into()).join("anend") +} + +#[cfg(not(target_arch = "wasm32"))] +pub fn config_dir() -> std::path::PathBuf { + platform_dir("XDG_CONFIG_HOME", ".config") +} + +/// where saves live unless the settings say otherwise (the Bevy app's folder) +#[cfg(not(target_arch = "wasm32"))] +pub fn data_dir() -> std::path::PathBuf { + platform_dir("XDG_DATA_HOME", ".local/share") +} + +#[cfg(not(target_arch = "wasm32"))] +pub fn load() -> Prefs { + std::fs::read(path()) + .ok() + .and_then(|b| serde_json::from_slice(&b).ok()) + .unwrap_or_default() +} + +#[cfg(not(target_arch = "wasm32"))] +pub fn store(p: &Prefs) { + let path = path(); + if let Some(d) = path.parent() { + let _ = std::fs::create_dir_all(d); + } + if let Ok(b) = serde_json::to_vec_pretty(p) { + let _ = std::fs::write(path, b); + } +} + +#[cfg(target_arch = "wasm32")] +fn storage() -> Option<web_sys::Storage> { + web_sys::window()?.local_storage().ok().flatten() +} + +#[cfg(target_arch = "wasm32")] +pub fn load() -> Prefs { + storage() + .and_then(|s| s.get_item("anend.app").ok().flatten()) + .and_then(|t| serde_json::from_str(&t).ok()) + .unwrap_or_default() +} + +#[cfg(target_arch = "wasm32")] +pub fn store(p: &Prefs) { + if let (Some(s), Ok(t)) = (storage(), serde_json::to_string(p)) { + let _ = s.set_item("anend.app", &t); + } +} diff --git a/app/src/shell.rs b/app/src/shell.rs new file mode 100644 index 00000000..a54ca795 --- /dev/null +++ b/app/src/shell.rs @@ -0,0 +1,672 @@ +//! The app's shell: the top bar (the mark, the views, the search line, the status, undo and +//! settings), the views, the dock (the strip of toggles in the memory view and the space, +//! the command bar), toasts, the right-click menu, and the keyboard. + +use dioxus::prelude::*; + +use crate::gem::Measure; +use crate::keys::{Action, Binding}; +use crate::prefs::Prefs; +use crate::ui::*; +use crate::views; + +const CSS: &str = include_str!("style.css"); + +/// the one key listener: keys the shell or the open view takes, sent to Rust; the browser +/// keeps the rest (typing, Tab, the browser's own) +const KEYS_JS: &str = r#" +const KEY = /^\d{1,3}(,\d{1,3}){0,5}$/; +// the bindings the keymap holds here (`ctrl,shift,alt,code`), set by Rust per view +window.__anendTaken = window.__anendTaken || new Set(); +// the keys menu waits for a key: every key goes to Rust +window.__anendListen = false; +window.addEventListener('keydown', (e) => { + // an input method composing (IME): its keys are its own, Enter included + if (e.isComposing || e.keyCode === 229) return; + const t = e.target || {}; + const bar = t.id === 'bar'; + const typing = t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.tagName === 'SELECT' || t.isContentEditable; + const k = e.key, c = e.ctrlKey || e.metaKey; + const send = () => dioxus.send({ key: k, code: e.code, ctrl: c, shift: e.shiftKey, alt: e.altKey, bar, typing, text: bar ? t.value : '' }); + if (window.__anendListen) { + if (!['Control', 'Shift', 'Alt', 'Meta'].includes(k)) { e.preventDefault(); send(); } + return; + } + const bound = window.__anendTaken.has(`${+c},${+e.shiftKey},${+e.altKey},${e.code}`); + // a text box keeps its own editing chords + const editing = typing && !bar && c && ['z', 'Z', 'y', 'x', 'c', 'v', 'a'].includes(k); + let take = false, prevent = false; + if (editing) return; + if (c && (k === 'z' || k === 'Z' || k === 'y') && bar) { take = true; prevent = true; } + else if (bound && (c || e.altKey)) { take = true; prevent = true; } + else if (c && (k === 'PageUp' || k === 'PageDown' || k === '+')) { take = true; prevent = true; } + else if (k === 'Escape') take = true; + else if (bar && (k === 'Enter' || k === 'ArrowUp' || k === 'ArrowDown')) { take = true; prevent = true; } + else if (bar && k === 'Delete' && KEY.test(t.value.trim()) && t.selectionStart === t.value.length) { take = true; prevent = true; } + else if (!typing && !e.altKey && !c) { take = true; if (bound || k.startsWith('Arrow') || k === ' ') prevent = true; } + if (!take) return; + if (prevent) e.preventDefault(); + send(); +}); +// zen: the bars fade while the mouse and keys rest; the top bar slides in near the top +let zenTimer = 0; +const stir = (y) => { + const app = document.querySelector('.app'); + if (!app) return; + app.classList.remove('idle'); + clearTimeout(zenTimer); + if (app.dataset.zen === '1') zenTimer = setTimeout(() => { + if (!app.querySelector('.dock:focus-within, .overlay, .menu')) app.classList.add('idle'); + }, (parseFloat(app.dataset.zenDelay) || 2.5) * 1000); + // shown from the window's top edge, kept while the pointer stays on the bar + if (y !== undefined) app.classList.toggle('peek', y < (app.classList.contains('peek') ? 36 : 8)); +}; +window.addEventListener('mousemove', (e) => stir(e.clientY), { passive: true }); +window.addEventListener('keydown', () => stir(), { passive: true }); +window.addEventListener('mousedown', (e) => stir(e.clientY), { passive: true }); +"#; + +fn measure_of(t: &str) -> Option<Measure> { + let t = t.trim(); + let key_like = !t.is_empty() && t.split(',').all(|p| p.trim().parse::<u8>().is_ok()); + (!t.is_empty() && !key_like && t.parse::<u64>().is_err()).then(|| Measure::of(t)) +} + +#[component] +pub fn App() -> Element { + let api = use_context_provider(crate::make_api); + let prefs = use_signal(crate::prefs::load); + let ui = use_context_provider(|| Ui { + view: Signal::new(View::parse(&prefs.peek().view)), + prefs, + status: Signal::new((String::new(), false, 0)), + toasts: Signal::new(Vec::new()), + bar: Signal::new(String::new()), + measure: Signal::new(None), + settings: Signal::new(false), + hello: Signal::new(Default::default()), + topline: Signal::new(None), + picks: Signal::new(Default::default()), + pending: Signal::new(Pending::None), + menu: Signal::new(None), + actions: Signal::new(Vec::new()), + bar_history: Signal::new(Default::default()), + keys: Signal::new(Vec::new()), + changed: Signal::new(0), + bar_texts: Signal::new(Default::default()), + seq: Signal::new(0), + side: Signal::new(Default::default()), + listening: Signal::new(None), + open_note: Signal::new(None), + pick_tag: Signal::new(None), + closing: Signal::new(0), + }); + // closing the window (desktop): the notes view saves the open note first; the window + // only hides when asked to close (main.rs), and the app ends here + #[cfg(not(target_arch = "wasm32"))] + { + use dioxus::desktop::tao::event::{Event, WindowEvent}; + dioxus::desktop::use_wry_event_handler(move |ev, _| { + if let Event::WindowEvent { + event: WindowEvent::CloseRequested, + .. + } = ev + { + let mut c = ui.closing; + if *c.peek() != 0 { + return; + } + c.set(1); + dioxus::dioxus_core::spawn_forever(async move { + // a view that has something to keep takes it (2) and ends the app when + // it's kept; give up waiting after a few seconds + crate::ui::sleep_ms(200).await; + if *ui.closing.peek() == 2 { + crate::ui::sleep_ms(5000).await; + } + std::process::exit(0); + }); + } + }); + } + + // where classifiers read texts, as chosen in the settings (a shared hub keeps its own) + { + let api = api.clone(); + use_hook(move || { + let device = prefs.peek().read_device.clone(); + spawn(async move { + let _ = api + .call("classify.device", serde_json::json!({ "device": device })) + .await; + }); + }); + } + + // the save's name and counts, and again whenever something changed + { + let api = api.clone(); + use_effect(move || { + let _ = (ui.changed)(); + ui.refresh(api.clone()); + }); + } + + // the bar's text measured a beat after typing stops, off the input path + use_effect(move || { + let t = ui.bar.read().clone(); + spawn(async move { + sleep_ms(110).await; + if *ui.bar.peek() == t { + let mut m = ui.measure; + m.set(measure_of(&t)); + } + }); + }); + + // the page's key listener keeps the keys bound here from the browser + use_effect(move || { + let view = (ui.view)(); + let keymap = crate::keys::Keymap::from_changes(&ui.prefs.read().keymap); + let listen = ui.listening.read().is_some(); + let taken = serde_json::to_string(&keymap.taken(view)).unwrap_or_default(); + document::eval(&format!( + "window.__anendTaken = new Set({taken}); window.__anendListen = {listen};" + )); + }); + + // the keyboard + { + let api = api.clone(); + use_hook(move || { + spawn(async move { + let mut ev = document::eval(KEYS_JS); + while let Ok(k) = ev.recv::<KeyPress>().await { + on_key(ui, api.clone(), k); + } + }); + }); + } + + let p = prefs.read(); + let vars = format!( + "{}{}", + crate::theme::css_vars(&p.palette, &p.colours), + crate::theme::hl_vars(&p.palette, &p.colours) + ); + let zoom = p.zoom; + let fs = p.font_size; + let (zen, zen_delay, hide_bar) = (p.zen, p.zen_delay, p.hide_bar); + let view = (ui.view)(); + // zoom only when it isn't 1 (WebKit's css zoom upsets the space's 3d transforms) + let zoomed = if (zoom - 1.0).abs() > 0.001 { + format!("zoom: {zoom}; height: calc(100vh / {zoom});") + } else { + String::new() + }; + // a family the person named goes before the built-in ones + let fam = |f: &str, rest: &str| { + let f = f.trim().replace(['"', ';', '{', '}'], ""); + if f.is_empty() { + String::new() + } else { + format!( + "--{rest}: \"{f}\", {};", + if rest == "font" { + "\"Fira Sans\", system-ui, sans-serif" + } else { + "\"Times New Roman\", serif" + } + ) + } + }; + let style = format!( + "{vars} --fs: {fs}px; --mfs: {}px; --mspace: {}px; --top: {}px; --barh: {}px; {}{}{zoomed}", + p.memory_font, + p.spacing, + p.top_bar.clamp(20.0, 80.0), + p.bottom_bar.clamp(20.0, 80.0), + fam(&p.font, "font"), + fam(&p.memory_family, "serif"), + ); + let swapped = p.bars_swapped; + drop(p); + rsx! { + style { {crate::fonts::css()} } + style { {CSS} } + div { + class: "app v-{view.name()}", + class: if zen { "zen" } else { "" }, + class: if hide_bar { "hide-bar" } else { "" }, + class: if swapped { "swapped" } else { "" }, + "data-zen": if zen { "1" } else { "0" }, + "data-zen-delay": "{zen_delay}", + style: "{style}", + TopBar {} + div { class: "views", + for v in View::ALL { + views::ViewHost { key: "{v.name()}", view: v } + } + } + Dock {} + Toasts {} + ContextMenu {} + if (ui.settings)() { + views::settings::Settings {} + } + } + } +} + +fn set_zoom(mut ui: Ui, z: f32) { + ui.prefs.write().zoom = (z * 20.0).round().clamp(10.0, 60.0) / 20.0; + ui.save_prefs(); + let z = ui.prefs.peek().zoom; + ui.say(format!("zoom {}%", (z * 100.0).round())); +} + +fn on_key(mut ui: Ui, api: Api, mut k: KeyPress) { + let view = *ui.view.peek(); + // the keys menu is waiting for a key + if let Some(a) = *ui.listening.peek() { + crate::views::settings::rebind(ui, a, &k); + return; + } + let keymap = ui.keymap(); + let pressed = Binding::of(&k.code, k.ctrl, k.shift, k.alt); + k.action = pressed.and_then(|b| keymap.action(view, b, k.typing || k.bar)); + let z = ui.prefs.peek().zoom; + // the bar's own undo (Ctrl+Z / Ctrl+Y / Ctrl+Shift+Z while in it) + if k.ctrl && k.bar && matches!(k.key.as_str(), "z" | "Z" | "y") { + ui.bar_undo(k.key != "z"); + return; + } + if k.ctrl && !k.alt { + match k.key.as_str() { + "PageUp" | "+" => return set_zoom(ui, z + 0.05), + "PageDown" => return set_zoom(ui, z - 0.05), + _ => {} + } + } + let global = match k.action { + Some(Action::GotoMemory) => Some(View::Memory), + Some(Action::GotoSpace) => Some(View::Space), + Some(Action::GotoLists) => Some(View::Lists), + Some(Action::GotoReader) => Some(View::Reader), + Some(Action::GotoNotes) => Some(View::Notes), + Some(Action::GotoTags) => Some(View::Tags), + Some(Action::GotoStats) => Some(View::Stats), + Some(Action::GotoModels) => Some(View::Models), + Some(Action::GotoFilters) => Some(View::Filters), + _ => None, + }; + if let Some(v) = global { + go(ui, v); + return; + } + match k.action { + Some(Action::OpenSettings) => { + let open = *ui.settings.peek(); + ui.settings.set(!open); + return; + } + Some(Action::OpenKeys) => { + crate::shell::set_pref(ui, |p| { + p.collapsed.remove("keys"); + }); + ui.settings.set(true); + return; + } + Some(Action::ZoomIn) => return set_zoom(ui, z + 0.05), + Some(Action::ZoomOut) => return set_zoom(ui, z - 0.05), + Some(Action::ZoomReset) => return set_zoom(ui, 1.0), + // the space keeps its own undo (moves, pins, removals) and falls back on this + Some(Action::Undo) if !k.typing && view != View::Space => return undo_last(ui, api), + Some(Action::FocusBar) if !*ui.settings.peek() => { + ui.focus_bar(); + return; + } + _ => {} + } + if k.key == "Escape" { + if ui.menu.peek().is_some() { + ui.menu.set(None); + } else if *ui.settings.peek() { + ui.settings.set(false); + } else if *ui.pending.peek() != Pending::None { + ui.pending.set(Pending::None); + ui.say("never mind"); + } else if k.bar { + document::eval("document.activeElement && document.activeElement.blur()"); + } else { + let handler = ui.keys.peek().iter().find(|(v, _)| *v == view).map(|(_, h)| *h); + if let Some(h) = handler { + h.call(k); + } + } + return; + } + if *ui.settings.peek() || ui.menu.peek().is_some() { + return; + } + let handler = ui.keys.peek().iter().find(|(v, _)| *v == view).map(|(_, h)| *h); + let taken = handler.map(|h| h.call(k.clone())).unwrap_or(false); + if !taken && !k.bar && !k.typing && k.key == "Enter" { + ui.focus_bar(); + } +} + +pub fn go(mut ui: Ui, v: View) { + let from = *ui.view.peek(); + if from == v { + return; + } + // each view keeps its own bar text + let now = ui.bar.peek().clone(); + ui.bar_texts.write().insert(from, now); + let back = ui.bar_texts.peek().get(&v).cloned().unwrap_or_default(); + ui.set_bar(&back); + ui.view.set(v); + ui.prefs.write().view = v.name().to_string(); + ui.save_prefs(); + ui.menu.set(None); +} + +#[component] +fn TopBar() -> Element { + let mut ui = ui(); + let api = api(); + let view = (ui.view)(); + let (status, bad, _) = (ui.status)(); + let hello = (ui.hello)(); + let line = (ui.topline)(); + let show_line = matches!(view, View::Memory | View::Space); + // the notes view counts its notes at the bar's end ("n of m notes" while narrowed), + // so the top line leaves its count out there: one notes count per view + let idle = if view == View::Notes { + format!("{} · {} texts", hello.save, hello.counts.memories) + } else { + format!( + "{} · {} texts · {} notes", + hello.save, hello.counts.memories, hello.counts.notes + ) + }; + let last = ui.actions.read().last().map(|a| a.describe()); + rsx! { + header { class: "top", role: "banner", + nav { class: "tabs", "aria-label": "views", + for (i , v) in View::ALL.into_iter().enumerate() { + button { + key: "{v.name()}", + class: if v == view { "tab on" } else { "tab" }, + class: if i == 0 { "tip-right" } else { "" }, + "data-tip": "{v.name()} · Ctrl+{i + 1}", + "aria-label": "{v.name()}", + "aria-current": if v == view { "page" } else { "false" }, + onclick: move |_| go(ui, v), + Icon { name: v.icon() } + } + } + } + if show_line { + if let Some(l) = line { + div { class: "searchline", role: "status", + b { "{l.title}" } + if !l.detail.is_empty() { + span { class: "detail", "{l.detail}" } + } + if let Some((texts, buckets)) = l.counts { + span { class: "counts", + span { title: format!("{texts} text{} in the space", if texts == 1 { "" } else { "s" }), Icon { name: "text" } b { "{texts}" } } + span { title: format!("{buckets} bucket{} in the space", if buckets == 1 { "" } else { "s" }), Icon { name: "bucket" } b { "{buckets}" } } + } + } + Triangle { s: l.s, r: l.r } + if l.s > 0 || l.r > 0 { + span { class: "detail tri", "{crate::gem::triangle_short(l.s, l.r)}" } + } + // last: the line's end gives way when the bar is narrow + if let Some(n) = l.pf { + span { class: "pfline", title: "its prime factor chain (weum's pfR); click a number to put it in the bar", crate::views::memory::PfLine { n } } + } + } + } + } + span { class: "grow" } + span { + class: if bad { "status bad" } else { "status" }, + role: "status", + "aria-live": "polite", + if status.is_empty() { "{idle}" } else { "{status}" } + } + button { + class: "side tip-left", + "data-tip": match &last { Some(d) => format!("undo {d} · Ctrl+Z"), None => "nothing to undo".to_string() }, + "aria-label": "undo", + disabled: last.is_none(), + onclick: move |_| undo_last(ui, api.clone()), + Icon { name: "undo" } + } + button { + class: "side tip-left", + "data-tip": "settings · Ctrl+,", + "aria-label": "settings", + onclick: move |_| ui.settings.set(!(ui.settings)()), + Icon { name: "settings" } + } + } + } +} + +#[component] +fn Dock() -> Element { + let ui = ui(); + let view = (ui.view)(); + let pending = (ui.pending)(); + // the bar names what Enter will do only while it does something else than search; it + // never names the view (the tabs say which one is open) + let badge = match &pending { + Pending::Edit(h) => Some(format!("editing {}", h.key)), + Pending::EditOwn { .. } => Some("this placement's own text".to_string()), + Pending::Tag(hs) => Some(format!( + "tag {} with…", + if hs.len() == 1 { + hs[0].text.clone() + } else { + format!("{} texts", hs.len()) + } + )), + Pending::None => None, + }; + rsx! { + footer { class: "dock", + div { class: "cmdbar", + if let Some(b) = badge { + label { class: "pending", r#for: "bar", "{b}" } + } + input { + id: "bar", + r#type: "text", + autocomplete: "off", + spellcheck: "false", + "aria-label": "command bar", + placeholder: view.placeholder(), + oninput: move |e| ui.typed(e.value()), + } + div { class: "side", role: "toolbar", "aria-label": "{view.name()} controls", + views::Side { view } + } + } + } + } +} + +#[component] +fn Toasts() -> Element { + let mut ui = ui(); + let toasts = (ui.toasts)(); + rsx! { + div { class: "toasts", "aria-live": "polite", + for t in toasts { + div { + key: "{t.id}", + class: "toast", + title: "click: into the bar · double click: dismiss", + onclick: { + let text = t.text.clone(); + move |_| ui.set_bar(&text) + }, + ondoubleclick: move |_| ui.toasts.write().retain(|x| x.id != t.id), + "{t.text}" + } + } + } + } +} + +#[component] +fn ContextMenu() -> Element { + let mut ui = ui(); + let api = api(); + let Some(m) = (ui.menu)() else { return rsx! {} }; + let hit = m.hit.clone(); + let selected = ui.picks.read().selected.iter().any(|h| h.key == hit.key); + let (x, y) = (m.x.min(10_000.0), m.y.min(10_000.0)); + let item = move |f: Box<dyn Fn()>| { + move |_| { + f(); + let mut menu = ui.menu; + menu.set(None); + } + }; + let h1 = hit.clone(); + let h2 = hit.clone(); + let h3 = hit.clone(); + let h4 = hit.clone(); + let h5 = hit.clone(); + let h6 = hit.clone(); + let h7 = hit.clone(); + let api2 = api.clone(); + rsx! { + div { class: "backdrop", onclick: move |_| ui.menu.set(None), oncontextmenu: move |e| { e.prevent_default(); ui.menu.set(None) } } + div { + class: "menu", + role: "menu", + style: "left: min({x}px, calc(100vw - 200px)); top: min({y}px, calc(100vh - 300px));", + onmounted: move |e| async move { let _ = e.set_focus(true).await; }, + tabindex: "-1", + div { class: "title", "{hit.text}" } + MenuKind { key: "{hit.key}", entry: hit.key.clone() } + button { role: "menuitem", onclick: item(Box::new(move || { + ui.set_bar(&h1.text); + let mut p = ui.pending; p.set(Pending::Edit(h1.clone())); + ui.focus_bar(); + ui.say("edit it in the bar; Enter puts it back under the same key, Esc leaves it"); + })), Icon { name: "edit" } "edit" kbd { "Enter keeps the key" } } + button { role: "menuitem", onclick: item(Box::new(move || { + let sel = ui.picks.peek().selected.clone(); + let targets = if sel.iter().any(|h| h.key == h2.key) { sel } else { vec![h2.clone()] }; + let mut p = ui.pending; p.set(Pending::Tag(targets)); + ui.set_bar(""); + ui.focus_bar(); + ui.say("type a tag and press Enter"); + })), Icon { name: "tag" } "tag…" } + button { role: "menuitem", onclick: item(Box::new(move || { + let mut picks = ui.picks; + let mut p = picks.write(); + if let Some(i) = p.selected.iter().position(|h| h.key == h3.key) { p.selected.remove(i); } else { p.selected.push(h3.clone()); } + })), Icon { name: "check" } if selected { "unselect" } else { "select" } kbd { "Alt+click" } } + button { role: "menuitem", onclick: item(Box::new(move || { + let mut p = ui.picks; p.write().list = Some(h4.clone()); + ui.say(format!("list: {}", h4.text)); + })), Icon { name: "list" } "make it the list" kbd { "Shift+click" } } + button { role: "menuitem", onclick: item(Box::new(move || { + let mut p = ui.picks; p.write().candidate = Some(h5.clone()); + ui.say(format!("candidate: {}", h5.text)); + })), Icon { name: "pick" } "make it the candidate" kbd { "Ctrl+click" } } + button { role: "menuitem", onclick: item(Box::new(move || { + ui.set_bar(&h6.key); + })), Icon { name: "keys" } "its key into the bar" kbd { "double click" } } + if !hit.note { + button { role: "menuitem", onclick: item(Box::new(move || { + let h = h7.clone(); + let api = api2.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.forget(&h.key).await { + Ok(text) => { + ui.did(Did::Forgot { key: h.key.clone(), text: text.clone() }); + ui.say(format!("forgot “{text}” ({}) · Ctrl+Z takes it back", h.key)); + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + })), Icon { name: "delete" } "forget" kbd { "Delete" } } + } + } + } +} + +/// in the right-click menu: when the entry was written, and its kind (told by its +/// pattern; picked here when the guess is wrong, kept in the save) +#[component] +fn MenuKind(entry: String) -> Element { + let ui = ui(); + let api = api(); + let key = entry; + let k0 = key.clone(); + let api_i = api.clone(); + let info = use_resource(move || { + let (api, k) = (api_i.clone(), k0.clone()); + async move { api.call("entries.info", serde_json::json!({ "key": k })).await } + }); + let Some(Ok(v)) = info.read().clone() else { + return rsx! {}; + }; + let kind = v["kind"].as_str().unwrap_or("text").to_string(); + let detected = v["detected"].as_str().unwrap_or("text").to_string(); + let fixed = v["fixed"] == true; + let kinds: Vec<String> = v["kinds"] + .as_array() + .into_iter() + .flatten() + .filter_map(|k| k.as_str().map(str::to_string)) + .collect(); + let written = v["created"].as_str().unwrap_or("").get(..10).unwrap_or("").to_string(); + rsx! { + div { class: "kindrow small", + label { "kind" + select { + "aria-label": "its kind", + value: "{kind}", + onchange: move |e| { + let api = api.clone(); + let k = key.clone(); + let pick = e.value(); + let det = detected.clone(); + let mut menu = ui.menu; + menu.set(None); + dioxus::dioxus_core::spawn_forever(async move { + let set = if pick == det { String::new() } else { pick.clone() }; + match api.call("entries.set_kind", serde_json::json!({ "key": k, "kind": set })).await { + Ok(_) => ui.say(format!("{k} is a {pick} now")), + Err(e) => ui.fail(e), + } + }); + }, + for k in kinds { + option { key: "{k}", value: "{k}", selected: k == kind, "{k}" } + } + } + } + span { class: "dim", if fixed { "set by hand" } else { "by its pattern" } } + if !written.is_empty() { span { class: "dim", "written {written}" } } + } + } +} + +/// the prefs, changed and kept +pub fn set_pref(mut ui: Ui, f: impl FnOnce(&mut Prefs)) { + f(&mut ui.prefs.write()); + ui.save_prefs(); +} diff --git a/app/src/space.js b/app/src/space.js new file mode 100644 index 00000000..8de12c89 --- /dev/null +++ b/app/src/space.js @@ -0,0 +1,3661 @@ +// the space: memory texts float as camera-facing labels (html laid over a webgl room at +// each text's projected place) and you fly through it. Rust sends the texts with what +// they are (their sums, length, kind, word types, lists, time, class) and the physics' +// settings; this file runs the free spread and draws, and tells Rust what happens. +// +// The spread is a free force-directed layout (no spiral, no anchors): every two texts +// repel, and attract each other as much as they are alike, where "alike" is a weighted +// sum of what the physics panel weighs (sums, bucket, length, word types, lists, class, +// time, letters), each weight from −1 (alike texts push apart) to +1 (pull together). A +// weak gravity keeps the cloud together, labels never overlap, and the integration runs +// in fixed steps with damping and cooling, so it settles whatever the frame rate. +// +// Smooth labels: each label keeps one font size and is placed and scaled with a +// sub-pixel transform every frame (no font-size steps, no whole-pixel snapping). +// +// right mouse drag looks, W A S D move, Space / C up and down, Q / E roll, Shift fast, +// [ ] or the wheel change the speed, R levels, Home goes back; the arrows ease the +// camera onto the nearest text that way. Drag a text to move it (it stays pinned), the +// wheel on a text pushes it away or pulls it near. Blocks (spatial saves) are boxes in +// the webgl room, moved and resized with a gizmo (see "blocks" below). + +import * as THREE from '__THREE__'; + +const LOOK = 0.0026; +const ROLL = 1.4; +const BASE_PX = 32; +// a block's texture repeats once per unit of its sides (core's graph::blocks::TILE) +const BLOCK_TILE = 1; +const STEP = 1 / 60; +// the flying keys by action, as the keymap binds them (Rust sends them: `keys`) +const DEFAULT_KEYS = { fly_forward: 'KeyW', fly_back: 'KeyS', fly_left: 'KeyA', fly_right: 'KeyD', fly_up: 'Space', fly_down: 'KeyC', roll_left: 'KeyQ', roll_right: 'KeyE', level: 'KeyR', back_to_start: 'Home', slower: 'BracketLeft', faster: 'BracketRight', walk: 'KeyV', superflight: 'KeyB', grapple: 'KeyG', sneak: 'KeyZ' }; +const FLYING = ['fly_forward', 'fly_back', 'fly_left', 'fly_right', 'fly_up', 'fly_down', 'roll_left', 'roll_right', 'sneak']; +// walking (first-person mode): the body's sizes, speeds (units a second) and the floor +const BODY = { r: 0.3, stand: 1.7, crouch: 1.05, walk: 3.2, run: 6, sneak: 1.4, crawl: 1.6, jump: 6.2, gravity: 20, step: 0.35, mantle: 1.3, floor: -9 }; +const FP_STEP = 1 / 120; +// the physics' settings (the panel's sliders); Rust sends changes as `physics` +export const PHYSICS = { + damping: 2.2, gravity: 0.06, repel: 9, link: 4, attract: 0.9, pad: 0.3, cool: 0.012, substeps: 2, + size: 0.5, wrap: 60, minPx: 1.2, depth: 0, flat: 1.5, qscale: 12, distance: 26, + w_ordinal: 0.6, w_reversed: 0.3, w_bucket: 0.8, w_length: 0.2, w_types: 0.3, w_lists: 0.7, w_class: 0.5, w_time: 0.2, w_letters: 0.4, + depth_by: 'none', reversed: 0, + look: 1, smooth: 14, +}; + +const typing = (e) => { + const t = e.target || {}; + return t.tagName === 'INPUT' || t.tagName === 'TEXTAREA' || t.tagName === 'SELECT' || t.isContentEditable; +}; + +const hash01 = (s, salt) => { + let h = 2166136261 ^ salt; + for (let i = 0; i < s.length; i++) h = Math.imul(h ^ s.charCodeAt(i), 16777619); + return ((h >>> 0) % 100000) / 100000; +}; + +const cosine = (a, b) => { + let d = 0, na = 0, nb = 0; + for (let i = 0; i < a.length; i++) { d += a[i] * b[i]; na += a[i] * a[i]; nb += b[i] * b[i]; } + return na && nb ? d / Math.sqrt(na * nb) : 0; +}; + +const TYPES = ['word', 'name', 'number', 'date', 'time', 'link', 'email', 'hashtag', 'noun', 'verb', 'adjective', 'adverb', 'pronoun', 'determiner', 'preposition', 'conjunction', 'interjection']; + +// a block's bend at u across its width (0 the left edge, 1 the right): how far that +// slice moves along the block's depth. The same as core's `Bend::offset`: a ripple whose +// one-period profile is the cubic bezier 0, c1, c2, 0 scaled to peak at its amount, plus +// a fold about the line `at`, each side the bezier 0, c1, c2, 1 times its amount. +export function bendAt(bend, u) { + let z = 0; + const r = bend && bend.ripple; + if (r && r.amount && r.freq > 0) { + const s = (((u * r.freq + (r.phase || 0)) % 1) + 1) % 1; + z += (r.amount * wave(s, r.c1, r.c2)) / wavePeak(r.c1, r.c2); + } + const f = bend && bend.fold; + if (f && f.amount) { + const line = 0.5 + (f.at || 0) * 0.5; + let t = u >= line ? (u - line) / Math.max(1e-6, 1 - line) : (line - u) / Math.max(1e-6, line); + t = Math.min(1, Math.max(0, t)); + z += f.amount * (3 * (1 - t) * (1 - t) * t * f.c1 + 3 * (1 - t) * t * t * f.c2 + t * t * t); + } + return z; +} +function wave(s, c1, c2) { return 3 * (1 - s) * (1 - s) * s * c1 + 3 * (1 - s) * s * s * c2; } +function wavePeak(c1, c2) { + let m = 0; + for (let i = 0; i <= 64; i++) m = Math.max(m, Math.abs(wave(i / 64, c1, c2))); + return m > 1e-6 ? m : 1; +} +// what a block's geometry depends on (its sides and bend) +function shapeKey(t) { return JSON.stringify([t.w, t.h, t.d, t.bend || null, t.shape || 'box']); } +function localAxis(i) { const a = new THREE.Vector3(); a.setComponent(i, 1); return a; } +// which variant the n-th block of a recipe shows: core's graph::textures::variant, the +// same 32-bit mix +function variantOf(seed, n, variants) { + if (!(variants > 1)) return 0; + const lo = n >>> 0, hi = Math.floor(n / 4294967296) >>> 0; + let h = ((seed >>> 0) ^ Math.imul(lo, 0x9e3779b9) ^ hi) >>> 0; + h ^= h >>> 16; h = Math.imul(h, 0x85ebca6b) >>> 0; + h ^= h >>> 13; h = Math.imul(h, 0xc2b2ae35) >>> 0; + h ^= h >>> 16; + return (h >>> 0) % variants; +} +export { variantOf }; + +// a CSS cubic-bezier timing at x (0 to 1): core's graph::anims::bezier, by bisection +function cubicBezier(t, x) { + if (x <= 0) return 0; + if (x >= 1) return 1; + const at = (a, b, s) => 3 * (1 - s) * (1 - s) * s * a + 3 * (1 - s) * s * s * b + s * s * s; + let lo = 0, hi = 1; + for (let i = 0; i < 40; i++) { const mid = (lo + hi) / 2; if (at(t[0], t[2], mid) < x) lo = mid; else hi = mid; } + return at(t[1], t[3], (lo + hi) / 2); +} + +function turnOf(b) { const r = b.rot || [0, 0, 0, 1]; return new THREE.Quaternion(r[0], r[1], r[2], r[3]); } + +export class Space { + constructor(host, send) { + this.host = host; + this.send = send; + this.nodes = new Map(); // key → node + this.order = []; // nodes, in a stable order for the pair loops + this.sim = null; // the pair weights, row-major over `order` + this.keys = new Set(); + this.bind = { ...DEFAULT_KEYS }; + this.p = { ...PHYSICS }; + this.speed = 6; + // the camera's turn as yaw (about the world's up), pitch (clamped short of straight up + // or down) and roll, kept apart: looking round in circles never builds up a roll. + // The mouse moves the targets; the camera eases onto them. + this.yaw = 0; this.pitch = 0; this.rollA = 0; + this.tyaw = 0; this.tpitch = 0; + this.running = false; + this.looking = false; + this.paused = false; + this.alpha = 0; + this.acc = 0; + this.ease = null; + this.selected = null; + this.hover = null; + this.drag = null; + this.undo = []; + // the selection of many (Shift+click, or a box drawn): kind:id → { kind, id }, kinds + // b (a block), c (a prefab's copy), t (a text's placement, by its node key), l (a light) + this.multi = new Map(); + // groups made by hand (Ctrl+G; core's ops::groups): id → members, a member's group, + // the selected group, and the groups opened (a double click) to pick inside them + this.groups = new Map(); + this.parent = new Map(); + this.selGroup = null; + this.openGroups = []; + this.freeN = 0; + this.infoAt = 0; + this.origin = new THREE.Vector3(); + this.quat = new THREE.Quaternion(); + this.scene = new THREE.Scene(); + this.camera = new THREE.PerspectiveCamera(50, 1, 0.05, 4000); + this.room = new THREE.Color('#e4d4be'); + this.scene.background = this.room; + this.scene.fog = new THREE.Fog(this.room, 60, 260); + try { + this.gl = new THREE.WebGLRenderer({ antialias: true }); + this.gl.setPixelRatio(Math.min(devicePixelRatio || 1, 2)); + this.gl.domElement.className = 'space-gl'; + host.append(this.gl.domElement); + } catch { + this.gl = null; + } + this.overlay = document.createElement('div'); + this.overlay.className = 'space-css'; + host.append(this.overlay); + this.size = { w: 1, h: 1 }; + this.grid = new THREE.GridHelper(600, 120, 0x000000, 0x000000); + this.grid.position.y = -9; + for (const m of [].concat(this.grid.material)) { + m.transparent = true; + m.opacity = 0.06; + m.depthWrite = false; + } + this.scene.add(this.grid); + this.blocks = new Map(); // id → {b, mesh, key, about} + this.mats = new Map(); // texture key (and a recipe's variant) → material + this.abouts = new Map(); // texture key → what it is (as Rust sent it) + this.sky = null; + this.lights = []; // the room's lights (core's graph::lights), baked onto the blocks + this.anims = new Map(); // animation key → the animation (core's graph::anims) + this.animT0 = performance.now(); // when the room's animations started + this.animPlaying = true; + this.lightMarks = null; // where the point and cone lights are, while the lights window is open + this.selBlock = null; + this.bdrag = null; + this.ray = new THREE.Raycaster(); + this.gizmo = this.makeGizmo(); + this.resize = this.resize.bind(this); + new ResizeObserver(this.resize).observe(host); + this.resize(); + this.listen(); + this.loop = this.loop.bind(this); + this.setFrame(); + } + + // ------------------------------------------------------------------ settings + + setKeys(map) { + this.bind = { ...DEFAULT_KEYS, ...map }; + this.keys.clear(); + } + + held(action) { + return this.keys.has(this.bind[action]); + } + + setPhysics(p) { + const old = this.p; + this.p = { ...PHYSICS, ...p }; + const weights = Object.keys(PHYSICS).filter((k) => k.startsWith('w_') || k === 'qscale' || k === 'reversed'); + if (weights.some((k) => old[k] !== this.p[k])) this.sim = null; + if (old.wrap !== this.p.wrap) for (const n of this.order) this.measure(n); + this.wake(0.6); + } + + setRoom(color, ink) { + this.room.set(color); + this.scene.fog.color.set(color); + this.host.style.setProperty('--room-bg', color); + this.host.style.setProperty('--room-ink', ink); + this.host.style.background = color; + const dark = this.room.r * 0.3 + this.room.g * 0.59 + this.room.b * 0.11 < 0.35; + for (const m of [].concat(this.grid.material)) { + m.color.set(dark ? 0xffffff : 0x000000); + m.opacity = dark ? 0.05 : 0.06; + } + this.render(); + } + + resize() { + const w = this.host.clientWidth || 1; + const h = this.host.clientHeight || 1; + this.camera.aspect = w / h; + this.camera.updateProjectionMatrix(); + this.gl?.setSize(w, h); + this.size = { w, h }; + this.render(); + } + + start() { + if (this.running) return; + this.running = true; + this.last = performance.now(); + this.resize(); + requestAnimationFrame(this.loop); + } + + stop() { + this.running = false; + this.keys.clear(); + this.looking = false; + } + + // the cloud's centre: ahead of where the camera is when a search lays texts out + setFrame() { + this.quat.copy(this.camera.quaternion); + this.origin.set(0, 0, -this.p.distance).applyQuaternion(this.quat).add(this.camera.position); + } + + world(n, out = new THREE.Vector3()) { + return out.set(n.x, n.y, n.z).applyQuaternion(this.quat).add(this.origin); + } + + local(w, n) { + const v = w.clone().sub(this.origin).applyQuaternion(this.quat.clone().invert()); + n.x = v.x; n.y = v.y; n.z = v.z; + } + + // ------------------------------------------------------------------ texts + + // texts: [{key, text, note, s, r, q, hue, chars, words, kind, types, created, lists, freq, cls, strength, colour}] + place(texts, again) { + if (!again) { + this.setFrame(); + for (const n of [...this.order]) if (!n.pinned && !n.free) this.drop(n); + } + const before = this.order.length; + for (const t of texts) { + let n = this.nodes.get(String(t.key)); + if (n) { + // a detached placement keeps the text it was detached with + const kept = n.f.text; + Object.assign(n.f, t); + if (n.det) n.f.text = kept; + this.showText(n); + const was = (n.links || []).map((c) => c.f.key + '|' + c.f.text).join('\n'); + const now = (Array.isArray(t.chain) ? t.chain : []).map((m) => m.key + '|' + m.text).join('\n'); + if (was !== now) this.link(n, t.chain); + n.el.style.borderBottomColor = t.under || 'transparent'; + this.dress(n); + continue; + } + n = this.make(t, false); + this.dress(n); + this.seed(n); + } + this.sim = null; + this.wake(1); + this.render(); + this.info(true); + return this.order.length - before; + } + + // the pipes' effects on the room's texts, by key ({colour, underline, label, size, glow, + // gather}); a text without any goes back to how it was + effects(fx) { + this.fx = fx || {}; + for (const n of this.order) this.dress(n); + this.sim = null; + this.wake(1); + } + + dress(n) { + const e = (this.fx && !n.free && this.fx[n.f.key]) || null; + const el = n.el; + n.f.gather = e && e.gather ? e.gather : null; + el.style.color = (e && e.colour) || n.f.colour || ''; + el.style.borderBottomColor = (e && e.underline) || n.f.under || 'transparent'; + el.style.textShadow = e && e.glow ? `0 0 6px ${e.glow}, 0 0 14px ${e.glow}` : ''; + n.fxSize = e && e.size ? e.size : 1; + let tag = el.querySelector(':scope > .fx-label'); + if (e && e.label) { + if (!tag) { + tag = document.createElement('span'); + tag.className = 'fx-label'; + el.append(tag); + } + tag.textContent = e.label; + } else if (tag) tag.remove(); + this.measure(n); + } + + // a placement of a text: `free` is the room's own text (no entry); `how` says how a + // copy relates to its entry: { det } detached at that version (it keeps the text it was + // copied with), { own } an inheriting copy's own text, shadowing the entry's + make(t, free, nodeKey, how) { + const el = document.createElement('div'); + el.className = 'slabel' + (free ? ' free' : '') + (t.note ? ' note' : ''); + el.textContent = t.note ? `✎ ${t.text}` : t.text; + // the gematria grouping underline (the memory view's colour), on every text that has one + el.style.borderBottomColor = t.under || 'transparent'; + if (t.colour) el.style.color = t.colour; + el.tabIndex = -1; + const n = { key: nodeKey || String(t.key), f: t, el, x: 0, y: 0, z: 0, vx: 0, vy: 0, vz: 0, hw: 1, hh: 0.4, pinned: false, free, det: 0, own: null }; + if (how && how.det) n.det = how.det; + if (how && how.own != null) n.own = how.own; + this.showText(n); + this.overlay.append(el); + this.nodes.set(n.key, n); + this.order.push(n); + this.wire(n); + this.measure(n); + if (t.isChain) el.classList.add('chain-head'); + this.link(n, t.chain); + return n; + } + + // a chain's members under its head (a chain entry's, or a note's body as a chain of + // two): nodes of their own, laid out in reading order by `follow`, never moved by the + // spread; dragging any of them drags the head + link(n, members) { + for (const c of n.links || []) this.drop(c); + n.links = []; + if (!Array.isArray(members)) return; + members.forEach((m, i) => { + const c = this.make({ key: String(m.key), text: m.text, note: !!m.note, virt: !!m.virt }, false, `${n.key}>${i}>${m.key}`); + c.head = n; + c.idx = i; + c.el.classList.add('member'); + c.x = n.x; c.y = n.y - (i + 1) * 0.9; c.z = n.z; + n.links.push(c); + }); + this.sim = null; + } + + // a chain changed (or broke, `chain` null): every head showing it takes its members + // again; a broken one becomes its title again + setChain(key, chain) { + for (const n of [...this.order]) { + if (n.head || String(n.f.key) !== String(key)) continue; + if (!chain) { + // broken: the head shows its title, and the members stay as texts where they are + n.f.key = n.f.titleKey || n.f.key; + n.f.isChain = false; + for (const c of n.links || []) { + c.head = null; + c.el.classList.remove('member'); + c.pinned = true; + c.el.classList.add('pinned'); + } + n.links = []; + n.el.classList.remove('chain-head'); + continue; + } + n.f.text = chain.title.text; + n.f.titleKey = chain.title.key; + n.f.isChain = true; + n.el.classList.add('chain-head'); + this.showText(n); + this.measure(n); + this.link(n, chain.members); + } + this.wake(0.5); + this.render(); + } + + // a text in the room becomes a chain's head (a chain just made with it as title) + chainify(node, chain) { + const n = this.nodes.get(node); + if (!n) return; + n.f.key = chain.key; + this.setChain(chain.key, chain); + } + + // a new chain (from a cut) beside the head it came from + addChain(near, chain) { + const h = this.order.find((x) => !x.head && String(x.f.key) === String(near)); + const n = this.make({ key: chain.key, text: chain.title.text, note: false, titleKey: chain.title.key, isChain: true, chain: chain.members }, false, + this.nodes.has(String(chain.key)) ? this.copyKey(chain.key) : null); + n.el.classList.add('chain-head'); + if (h) { n.x = h.x + h.hw * 2 + 1.5; n.y = h.y; n.z = h.z; } + n.pinned = true; + n.el.classList.add('pinned'); + this.render(); + } + + // members placed in reading order under their head, left-aligned, spaced by their own + // heights, eased there like a spring (so a dragged chain follows and settles) + follow(h) { + const k = Math.min(1, 10 * h); + let moved = 0; + for (const n of this.order) { + if (!n.links || !n.links.length) continue; + const gap = 0.12; + const left = n.x - n.hw; + let y = n.y - n.hh - gap; + for (const c of n.links) { + const tx = left + c.hw, ty = y - c.hh; + y -= c.hh * 2 + gap; + const dx = tx - c.x, dy = ty - c.y, dz = n.z - c.z; + c.x += dx * k; c.y += dy * k; c.z += dz * k; + c.vx = c.vy = c.vz = 0; + moved += dx * dx + dy * dy + dz * dz; + } + } + return moved; + } + + // a new text starts beside the texts most like it, or at a spot of its own + seed(n) { + const R = 2 + Math.sqrt(this.order.length) * 1.4; + const a = hash01(n.key, 1) * Math.PI * 2; + const r = R * Math.sqrt(hash01(n.key, 2)); + n.x = Math.cos(a) * r; + n.y = Math.sin(a) * r; + n.z = (hash01(n.key, 3) - 0.5) * 0.5; + } + + measure(n) { + const free = n.free; + const hidden = n.el.style.display === 'none'; + if (hidden) n.el.style.display = ''; + n.el.style.fontSize = `${BASE_PX}px`; + n.el.style.maxWidth = free ? '80ch' : `${this.p.wrap}ch`; + const w = n.el.offsetWidth || BASE_PX * 0.55 * n.f.text.length; + const h = n.el.offsetHeight || BASE_PX * 1.2; + const size = (n.size || this.p.size) * (n.fxSize || 1); + n.hw = (w / BASE_PX / 2) * size; + n.hh = (h / BASE_PX / 2) * size; + if (hidden) n.el.style.display = 'none'; + } + + drop(n) { + for (const c of n.links || []) if (c !== n) this.drop(c); + n.links = []; + n.el.remove(); + this.nodes.delete(n.key); + this.order = this.order.filter((x) => x !== n); + if (this.selected === n) this.selected = null; + if (this.hover === n) this.hover = null; + this.sim = null; + } + + clear(all) { + for (const n of [...this.order]) if (all || (!n.pinned && !n.free)) this.drop(n); + this.undo = []; + this.render(); + this.info(true); + } + + mark(list, candidate) { + for (const n of this.order) n.el.classList.toggle('picked', n.key === list || n.key === candidate); + } + + colours(map) { + for (const n of this.order) { + const c = map[n.key]; + n.el.style.color = c || ''; + } + } + + // ------------------------------------------------------------------ the spread + + wake(a) { + this.dirty = true; + this.alpha = Math.max(this.alpha, a); + } + + // how alike two texts are, from −1 to 1, by the weighted measures + alike(a, b) { + const p = this.p, A = a.f, B = b.f; + let sum = 0, w = 0; + const add = (weight, m) => { + if (!weight || m === null || m === undefined || Number.isNaN(m)) return; + sum += weight * m; + w += Math.abs(weight); + }; + add(p.w_ordinal, Math.exp(-Math.abs((A.s || 0) - (B.s || 0)) / p.qscale)); + add(p.w_reversed, Math.exp(-Math.abs((A.r || 0) - (B.r || 0)) / p.qscale)); + add(p.w_bucket, A.q === B.q ? 1 : 0); + add(p.w_length, Math.exp(-Math.abs(Math.log1p(A.chars || 1) - Math.log1p(B.chars || 1)) * 1.5)); + if (A.types && B.types) { + const va = TYPES.map((t) => A.types[t] || 0), vb = TYPES.map((t) => B.types[t] || 0); + add(p.w_types, 0.5 * cosine(va, vb) + 0.5 * (A.kind === B.kind ? 1 : 0)); + } + const la = A.lists || [], lb = B.lists || []; + if (la.length || lb.length) { + const shared = la.filter((x) => lb.includes(x)).length; + add(p.w_lists, shared / (la.length + lb.length - shared)); + } else add(p.w_lists, 0); + if (A.cls !== undefined && A.cls !== null && B.cls !== undefined && B.cls !== null) { + add(p.w_class, A.cls === B.cls ? Math.min(A.strength ?? 1, B.strength ?? 1) : 0); + } + // a pipe that gathers pulls its texts together, and apart from the rest + if (A.gather || B.gather) add(2, A.gather === B.gather ? 1 : 0); + if (A.created && B.created) add(p.w_time, Math.exp(-Math.abs(A.created - B.created) / (7 * 864e5))); + if (A.freq && B.freq) add(p.w_letters, cosine(A.freq, B.freq)); + return w ? sum / w : 0; + } + + // ------------------------------------------------------------------ staging zones + // + // A block can be a staging zone (core's graph::blocks::Zone): the texts inside it spread + // among themselves, pulled to its centre and kept inside its box, under its own physics + // (repel, attract, link, gravity, damping; each left out follows the room's). Texts + // outside and inside don't push or pull each other. Zones nest: a text belongs to the + // smallest zone it's in. Moving a zone carries its texts along. + + // the zones in the spread's own frame (texts' x y z are relative to `origin`, `quat`) + zoneFrames() { + if (!this.zoneBlocks) this.zoneBlocks = [...this.blocks.values()].filter((o) => o.b.zone).map((o) => o.b); + if (!this.zoneBlocks.length) return []; + const qi = this.quat.clone().invert(); + return this.zoneBlocks.map((b) => { + const c = new THREE.Vector3(b.x, b.y, b.z).sub(this.origin).applyQuaternion(qi); + const q = qi.clone().multiply(turnOf(b)); + return { id: b.id, c, q, qi: q.clone().invert(), half: [b.w / 2, b.h / 2, b.d / 2], vol: b.w * b.h * b.d, p: { ...this.p, ...Object.fromEntries(Object.entries(b.zone).filter(([, v]) => v != null)) } }; + }); + } + + // the smallest zone a text is in (its id), or null + zoneOf(n, frames) { + let best = null; + const v = new THREE.Vector3(); + for (const f of frames) { + v.set(n.x, n.y, n.z).sub(f.c).applyQuaternion(f.qi); + if (Math.abs(v.x) <= f.half[0] && Math.abs(v.y) <= f.half[1] && Math.abs(v.z) <= f.half[2] && (!best || f.vol < best.vol)) best = f; + } + return best ? best.id : null; + } + + // a text kept inside its zone's box (its label's half size in from the sides, at most + // half the box) + keepIn(n, f) { + const v = new THREE.Vector3(n.x, n.y, n.z).sub(f.c).applyQuaternion(f.qi); + const m = [Math.min(n.hw || 0.3, f.half[0] * 0.45), Math.min(n.hh || 0.2, f.half[1] * 0.45), Math.min(0.3, f.half[2] * 0.45)]; + const c = [v.x, v.y, v.z].map((x, i) => Math.max(-f.half[i] + m[i], Math.min(f.half[i] - m[i], x))); + if (c[0] === v.x && c[1] === v.y && c[2] === v.z) return false; + v.set(c[0], c[1], c[2]).applyQuaternion(f.q).add(f.c); + n.x = v.x; n.y = v.y; n.z = v.z; + return true; + } + + // which zone each text is in: members of a zone that moved come along first + assignZones(frames) { + const byId = new Map(frames.map((f) => [f.id, f])); + for (const n of this.order) { + const f = n.zone && byId.get(n.zone); + if (f && !n.pinned) this.keepIn(n, f); + const was = n.zone; + n.zone = frames.length ? this.zoneOf(n, frames) : null; + if (was !== n.zone && this.live) { + if (was) this.wireZone(was, n.key, 'leave'); + if (n.zone) this.wireZone(n.zone, n.key, 'enter'); + } + } + } + + weights() { + this.zonesDirty = true; + const n = this.order.length; + this.sim = new Float32Array(n * n); + for (let i = 0; i < n; i++) { + for (let j = i + 1; j < n; j++) { + const s = this.order[i].free || this.order[j].free ? 0 : this.alike(this.order[i], this.order[j]); + this.sim[i * n + j] = s; + this.sim[j * n + i] = s; + } + } + } + + // the depth a text is drawn toward: a measure, or none + depthOf(n) { + const p = this.p, f = n.f; + switch (p.depth_by) { + case 'ordinal': return ((f.s || 0) - this.mean.s) / Math.max(1, this.mean.ss); + case 'length': return Math.log1p(f.chars || 1) - this.mean.l; + case 'time': return f.created ? (f.created - this.mean.t) / Math.max(864e5, this.mean.tt) : 0; + default: return 0; + } + } + + step(h) { + const p = this.p, N = this.order; + const n = N.length; + if (!n) return; + if (!this.sim || this.sim.length !== n * n) this.weights(); + if (p.depth_by !== 'none') { + let s = 0, l = 0, t = 0, k = 0; + for (const x of N) { s += x.f.s || 0; l += Math.log1p(x.f.chars || 1); if (x.f.created) { t += x.f.created; k++; } } + const ms = s / n, ml = l / n, mt = k ? t / k : 0; + let ss = 0, tt = 0; + for (const x of N) { ss += ((x.f.s || 0) - ms) ** 2; if (x.f.created) tt += (x.f.created - mt) ** 2; } + this.mean = { s: ms, ss: Math.sqrt(ss / n), l: ml, t: mt, tt: Math.sqrt(tt / Math.max(1, k)) }; + } + const a = this.alpha; + const frames = this.zoneFrames(); + if (this.zonesDirty) { + this.assignZones(frames); + this.zonesDirty = false; + } + const zones = new Map(frames.map((f) => [f.id, f])); + const fx = new Float64Array(n), fy = new Float64Array(n), fz = new Float64Array(n); + for (let i = 0; i < n; i++) { + const A = N[i]; + // a text in a zone moves under the zone's physics, toward its centre + const zf = A.zone ? zones.get(A.zone) : null; + const pp = zf ? zf.p : p; + const L = pp.link; + for (let j = i + 1; j < n; j++) { + const B = N[j]; + // a chain's members take no part in the spread's forces: their head stands for them + if (A.head || B.head) continue; + // texts in different zones (or one in, one out) leave each other alone + if ((A.zone || null) !== (B.zone || null)) continue; + let dx = B.x - A.x, dy = B.y - A.y, dz = B.z - A.z; + let d2 = dx * dx + dy * dy + dz * dz; + if (d2 < 1e-6) { dx = (hash01(A.key + B.key, 7) - 0.5) * 0.01; dy = (hash01(B.key + A.key, 9) - 0.5) * 0.01; d2 = dx * dx + dy * dy + 1e-6; } + const d = Math.sqrt(d2); + const s = this.sim[i * n + j]; + // every two repel (more when the weights say alike texts should part), softened near + let f = -pp.repel * (1 + Math.max(0, -s) * 2) / (d2 + 0.5); + // alike texts pull toward a rest length that shrinks the more alike they are + if (s > 0) f += pp.attract * s * (d - L * (1.15 - s)); + const ux = dx / d, uy = dy / d, uz = dz / d; + fx[i] += f * ux; fy[i] += f * uy; fz[i] += f * uz; + fx[j] -= f * ux; fy[j] -= f * uy; fz[j] -= f * uz; + } + // gravity to the centre (a zone's own), and toward the depth the measure gives + if (zf) { + fx[i] -= pp.gravity * (A.x - zf.c.x); + fy[i] -= pp.gravity * (A.y - zf.c.y); + fz[i] -= p.flat * (A.z - zf.c.z); + continue; + } + fx[i] -= p.gravity * A.x; + fy[i] -= p.gravity * A.y; + const zt = p.depth_by === 'none' ? 0 : this.depthOf(A) * p.depth; + fz[i] -= p.flat * (A.z - zt); + } + let ke = 0; + for (let i = 0; i < n; i++) { + const A = N[i]; + if (A.pinned || A.head || A === this.drag?.n) { A.vx = A.vy = A.vz = 0; continue; } + const zf = A.zone ? zones.get(A.zone) : null; + const drag = Math.exp(-(zf ? zf.p.damping : p.damping) * h); + A.vx = (A.vx + a * fx[i] * h) * drag; + A.vy = (A.vy + a * fy[i] * h) * drag; + A.vz = (A.vz + a * fz[i] * h) * drag; + const v2 = A.vx * A.vx + A.vy * A.vy + A.vz * A.vz; + if (v2 > 900) { const k = 30 / Math.sqrt(v2); A.vx *= k; A.vy *= k; A.vz *= k; } + A.x += A.vx * h; A.y += A.vy * h; A.z += A.vz * h; + // bounded by its zone: the speed into a side is lost there + if (zf && this.keepIn(A, zf)) { A.vx *= 0.5; A.vy *= 0.5; A.vz *= 0.5; } + ke += v2; + } + ke += this.follow(h) * 100; + // labels never overlap: separate rectangles in the facing plane, along the shorter way + for (let pass = 0; pass < 2; pass++) { + for (let i = 0; i < n; i++) { + const A = N[i]; + for (let j = i + 1; j < n; j++) { + const B = N[j]; + if (Math.abs(A.z - B.z) > 1.5) continue; + if ((A.zone || null) !== (B.zone || null)) continue; + const ox = A.hw + B.hw + p.pad - Math.abs(B.x - A.x); + const oy = A.hh + B.hh + p.pad * 0.5 - Math.abs(B.y - A.y); + if (ox <= 0 || oy <= 0) continue; + // a chain's members aren't pushed (their head is), nor pushed off their own head + if ((A.head && (A.head === B || A.head === B.head)) || (B.head && B.head === A)) continue; + const am = A.pinned || A.head || A === this.drag?.n ? 0 : 1, bm = B.pinned || B.head || B === this.drag?.n ? 0 : 1; + if (!am && !bm) continue; + const share = am && bm ? 0.5 : 1; + if (ox / (A.hw + B.hw) < oy / (A.hh + B.hh)) { + const sgn = B.x >= A.x ? 1 : -1; + A.x -= sgn * ox * share * am; B.x += sgn * ox * share * bm; + } else { + const sgn = B.y >= A.y ? 1 : -1; + A.y -= sgn * oy * share * am; B.y += sgn * oy * share * bm; + } + } + } + } + this.alpha = Math.max(0, a - a * p.cool); + this.energy = ke / n; + } + + asleep() { + return this.alpha < 0.01 && (this.energy ?? 0) < 0.0005; + } + + settle() { + this.wake(1); + const t0 = performance.now(); + let i = 0; + while (i < 6000 && performance.now() - t0 < 400) { + this.step(STEP); + i++; + if (this.asleep()) break; + } + this.render(); + return i; + } + + // ------------------------------------------------------------------ editing + + pick(n) { + if (this.selected) this.selected.el.classList.remove('selected'); + this.selected = n; + if (n) n.el.classList.add('selected'); + if (n && this.selBlock != null) this.pickBlock(null); + if (n && this.selCopy) this.pickCopy(null); + this.send(this.ev('select', n)); + } + + // records made together (a batch) go back together, the last first + record(u) { + if (this.batch) { this.batch.push(u); return; } + this.undo.push(u); + if (this.undo.length > 300) this.undo.shift(); + } + + undoLast() { + const u = this.undo.pop(); + if (!u) return 'nothing'; + this.applyUndo(u); + this.wake(0.5); + this.render(); + return u.kind; + } + + setBatch(on) { + if (on) { this.batch = this.batch || []; return; } + const b = this.batch; + this.batch = null; + if (b && b.length) this.record(b.length === 1 ? b[0] : { kind: 'many', items: b }); + } + + applyUndo(u) { + if (u.kind === 'many') { + for (const x of [...u.items].reverse()) this.applyUndo(x); + } else if (u.kind === 'move') { + Object.assign(u.n, { x: u.x, y: u.y, z: u.z, pinned: u.pinned }); + } else if (u.kind === 'pin') { + u.n.pinned = u.was; + } else if (u.kind === 'remove') { + this.overlay.append(u.n.el); + this.nodes.set(u.n.key, u.n); + this.order.push(u.n); + this.sim = null; + } else if (u.kind === 'add') { + this.drop(u.n); + } else if (u.kind === 'text') { + this.setText(u.n, u.from); + } else if (u.kind === 'size') { + u.n.size = u.from; + this.measure(u.n); + this.send(this.ev('select', u.n)); + } else if (u.kind === 'own') { + u.n.own = u.from; + this.showText(u.n); + this.measure(u.n); + } else if (u.kind === 'blockadd') { + for (const id of u.ids) this.dropBlock(id); + this.send({ ...this.ev('blockgone', null), data: u.ids }); + } else if (u.kind === 'unblock') { + const textures = {}; + for (const i of u.items) textures[i.key] = i.about; + this.setBlocks(u.items.map((i) => i.b), textures); + this.send({ ...this.ev('blockrestore', null), data: u.items.map((i) => i.b) }); + } else if (u.kind === 'copy') { + this.send({ ...this.ev('copyset', null), data: { id: u.id, ...u.t } }); + } else if (u.kind === 'copygone') { + this.send({ ...this.ev('copyrestore', null), data: u.restore }); + } else if (u.kind === 'block') { + const o = this.blocks.get(u.id); + if (o) { + Object.assign(o.b, u.t); + this.shapeBlock(o); + this.send({ ...this.ev('blockset', null), data: this.blockOut(o) }); + } + } else if (u.kind === 'wired') { + for (const x of u.items) this.send({ ...this.ev('wireset', null), data: { id: x.id, wiring: x.before } }); + } else if (u.kind === 'grouped') { + this.send({ ...this.ev('groupbreak', null), data: { id: u.id, quiet: true } }); + } else if (u.kind === 'ungrouped') { + this.send({ ...this.ev('grouprestore', null), data: { members: u.members, name: u.name || '' } }); + } else if (u.kind === 'lightgone') { + this.send({ ...this.ev('lightrestore', null), data: u.light }); + } else if (u.kind === 'light') { + const x = this.lights.find((l) => l.id === u.id); + if (x) Object.assign(x, u.t); + this.markLights(); + this.send({ ...this.ev('lightset', null), data: { id: u.id, ...u.t } }); + } + } + + pinSelected() { + const n = this.selected; + if (!n) return null; + this.record({ kind: 'pin', n, was: n.pinned }); + n.pinned = !n.pinned; + n.el.classList.toggle('pinned', n.pinned); + this.wake(0.5); + return n.pinned ? 'pinned' : 'unpinned'; + } + + removeSelected() { + const n = this.selected; + if (!n) return null; + this.record({ kind: 'remove', n }); + this.drop(n); + this.render(); + this.info(true); + return n.key; + } + + copyKey(entry) { + let i = 2; + while (this.nodes.has(`${entry}~${i}`)) i++; + return `${entry}~${i}`; + } + + // what a placement shows: its own text, else the text it was detached with or its + // entry's (both in f.text), and its marks + showText(n) { + // a long text shows its first piece (`shown`, made by Rust); its whole text stays in f.text + const t = n.own != null ? n.own : n.det ? n.f.text : n.f.shown || n.f.text; + n.el.textContent = n.f.note && !n.f.virt ? `✎ ${t}` : t; + n.el.classList.toggle('det', !!n.det); + n.el.classList.toggle('own', n.own != null); + // the text was set afresh: a pipe's label goes back on + if (this.fx && this.fx[n.f.key] && this.fx[n.f.key].label) this.dress(n); + } + + // another placement of the selected (or named) text beside it: the same entry, not a + // new one; Ctrl+Z takes it away. `det` (the entry's edited time now, ms) makes a + // detached copy, which keeps the text as it reads now; without it the copy inherits + // (and keeps the original's own text, if it has one) + duplicate(node, det) { + const n = node ? this.nodes.get(node) : this.selected; + if (!n) return null; + const how = n.free ? null : det ? { det } : n.det ? { det: n.det } : { own: n.own }; + const f = { ...n.f }; + const c = this.make(f, n.free, n.free ? `t:${Date.now().toString(36)}${this.freeN++}` : this.copyKey(n.f.key), how); + if (n.size) { c.size = n.size; this.measure(c); } + c.x = n.x + n.hw * 2 + 0.6; c.y = n.y; c.z = n.z; + // below any copy already beside it, so copies don't land on each other + const near = (x) => x !== c && Math.abs(x.x - c.x) < c.hw && Math.abs(x.y - c.y) < c.hh * 2 && Math.abs(x.z - c.z) < 0.5; + for (let i = 0; i < 50 && this.order.some(near); i++) c.y -= c.hh * 2 + 0.25; + c.pinned = true; + c.el.classList.add('pinned'); + this.record({ kind: 'add', n: c }); + this.pick(c); + this.sim = null; + this.render(); + this.info(true); + return c.key; + } + + // takes one placement out of the room (the entry stays in the save) + removeNode(node) { + const n = this.nodes.get(node); + if (!n) return null; + this.record({ kind: 'remove', n }); + this.drop(n); + this.render(); + this.info(true); + return n.key; + } + + pinNode(node) { + const n = this.nodes.get(node); + if (!n) return null; + this.pick(n); + return this.pinSelected(); + } + + // a free text (not a memory) ahead of the camera + addFree(text) { + const key = `t:${Date.now().toString(36)}${this.freeN++}`; + const n = this.make({ key, text: text || 'text', note: false }, true); + const ahead = new THREE.Vector3(0, 0, -6).applyQuaternion(this.camera.quaternion).add(this.camera.position); + this.local(ahead, n); + n.pinned = true; + this.record({ kind: 'add', n }); + this.pick(n); + this.render(); + return key; + } + + setText(n, text) { + n.f.text = text; + // the first piece Rust made was of the old text + n.f.shown = null; + this.showText(n); + this.measure(n); + this.wake(0.3); + } + + // a text edited: a free text's own, or an entry's, which every placement inheriting + // from it shows (a detached copy keeps its text) + editFree(key, text) { + const n = this.nodes.get(key); + if (n && n.free) { + this.record({ kind: 'text', n, from: n.f.text }); + this.setText(n, text); + } else { + for (const x of this.order) { + if (!x.free && !x.det && String(x.f.key) === String(key)) this.setText(x, text); + } + } + this.render(); + } + + // a placement's font size in steps of 1/50 of a unit per em (format.md: a u8, 0 the + // default, which is the "text size" slider); `by` steps it, `to` sets it (0: default); + // Ctrl+Z undoes it + setSize(node, by, to) { + const n = node ? this.nodes.get(node) : this.selected; + if (!n) return null; + const now = n.size ? Math.round(n.size * 50) : 0; + const base = now || Math.round(this.p.size * 50); + const step = to != null ? to : Math.max(1, Math.min(255, base + by)); + this.record({ kind: 'size', n, from: n.size }); + n.size = step ? step / 50 : undefined; + this.measure(n); + this.sim = null; + this.wake(0.3); + this.render(); + this.send(this.ev('select', n)); + return step; + } + + // an inheriting copy's own text (null: it follows its entry again); Ctrl+Z undoes it + setOwn(node, text) { + const n = this.nodes.get(node); + if (!n || n.free || n.det) return null; + this.record({ kind: 'own', n, from: n.own }); + n.own = text == null || text === '' ? null : text; + this.showText(n); + this.measure(n); + this.wake(0.3); + this.render(); + return n.key; + } + + // a map: every text with its place, as the Bevy app kept them, [text, x, y, z, {size, + // key}], with how a copy relates to its entry (detached: the version it keeps; own: its + // own text) + rows() { + const w = new THREE.Vector3(); + // a chain is one row, its head's (its members are laid out from it) + return this.order.filter((n) => !n.head).map((n) => { + this.world(n, w); + const o = {}; + if (!n.free) o.key = String(n.f.key); + if (n.size) o.size = n.size; + if (!n.free && n.det) o.detached = n.det; + if (!n.free && n.own != null) o.own = n.own; + return [n.own != null ? n.own : n.f.text, +w.x.toFixed(2), +w.y.toFixed(2), +w.z.toFixed(2), o]; + }); + } + + loadRows(rows, feats) { + this.clear(true); + this.setFrame(); + const w = new THREE.Vector3(); + for (const [text, x, y, z, o] of rows) { + const key = o && o.key ? String(o.key) : `t:${Date.now().toString(36)}${this.freeN++}`; + const f = { ...((o && o.key && feats[o.key]) || { key, text, note: false }) }; + const how = o && o.key ? { det: o.detached || 0, own: o.own != null ? o.own : null } : null; + // an own text shadows the entry's, which the features carry; a detached copy keeps + // the text the row has + if (!(how && how.own != null && f.text != null)) f.text = text; + const n = this.make(f, !(o && o.key), this.nodes.has(key) ? this.copyKey(key) : null, how); + if (o && o.size) { n.size = o.size; this.measure(n); } + this.local(w.set(x, y, z), n); + n.pinned = true; + n.el.classList.add('pinned'); + } + this.sim = null; + this.render(); + this.info(true); + } + + // ------------------------------------------------------------------ blocks + // + // Spatial saves: boxes in the room (world coordinates, kept by Rust in the save's + // `graph blocks` table) showing a text, a picture or a colour. One texture and one + // material per texture key, shared by every block showing it (as the table keeps one + // key per texture); each block's geometry has its UVs scaled to its size with repeat + // wrapping, so a bigger block shows more tiles, never a stretched one. The selected + // block has a gizmo: the arrows move it along an axis, the knobs on its faces resize + // it (the opposite face stays put), the ball moves it in the view's plane; Shift snaps + // to quarter units. + + textCanvas(text, colour) { + const c = document.createElement('canvas'); + c.width = c.height = 256; + const g = c.getContext('2d'); + g.fillStyle = '#f3ead9'; + g.fillRect(0, 0, 256, 256); + // the text's grouping colour as a band at the bottom, as the labels' underline + g.fillStyle = colour || '#8a7350'; + g.fillRect(0, 244, 256, 12); + g.strokeStyle = 'rgba(60, 45, 25, 0.25)'; + g.lineWidth = 2; + g.strokeRect(1, 1, 254, 254); + g.fillStyle = '#2b2219'; + g.textAlign = 'center'; + g.textBaseline = 'middle'; + const words = String(text || '').split(/\s+/).filter(Boolean); + let size = 64; + let lines = []; + for (; size >= 12; size -= 4) { + g.font = `${size}px "Fira Sans", sans-serif`; + lines = []; + let line = ''; + for (const w of words) { + const t = line ? `${line} ${w}` : w; + if (g.measureText(t).width > 224 && line) { lines.push(line); line = w; } else line = t; + } + if (line) lines.push(line); + if (lines.length * size * 1.15 <= 220 && lines.every((l) => g.measureText(l).width <= 232)) break; + } + const top = 122 - ((lines.length - 1) * size * 1.15) / 2; + lines.slice(0, 12).forEach((l, i) => g.fillText(l, 128, top + i * size * 1.15)); + return c; + } + + // ------------------------------------------------------------------ texture recipes + // + // A recipe (core's graph::textures) is drawn into a tile: its source (a picture, a + // text drawn as a text block's is, or a colour), cropped, mirrored, turned a quarter + // at a time and tinted. The tile repeats every `scale` units, shifted by `offset`; a + // block's variant k shifts it by (k·0.381966, k·0.618034) of a tile and, with + // `turn_variants`, turns it k more quarters. The same tile shows in the textures + // window's previews (`preview`). + + // a recipe's tile; a picture's arrives later, and `redraw` is called when it has + recipeCanvas(about, extraTurns, redraw, size = 256) { + const r = about.recipe || {}; + const src = r.source || {}; + const c = document.createElement('canvas'); + c.width = c.height = size; + const draw = (img) => { + const g = c.getContext('2d'); + g.save(); + g.clearRect(0, 0, size, size); + g.translate(size / 2, size / 2); + g.rotate((((r.turn || 0) + (extraTurns || 0)) % 4) * Math.PI / 2); + if (r.mirror) g.scale(-1, 1); + g.translate(-size / 2, -size / 2); + if (src.plain) { + g.fillStyle = src.plain; + g.fillRect(0, 0, size, size); + } else if (img) { + const [l, t, rr, b] = r.crop || [0, 0, 1, 1]; + const w = img.width, h = img.height; + g.drawImage(img, l * w, t * h, Math.max(1, (rr - l) * w), Math.max(1, (b - t) * h), 0, 0, size, size); + } else { + g.fillStyle = about.gone || about.picture_gone ? '#9a8f84' : '#b8a07a'; + g.fillRect(0, 0, size, size); + } + g.restore(); + if (r.tint && r.tint_amount) { + g.globalAlpha = r.tint_amount; + g.fillStyle = r.tint; + g.fillRect(0, 0, size, size); + g.globalAlpha = 1; + } + }; + if (src.text != null) draw(this.textCanvas(about.text_gone ? '(gone)' : about.text, about.colour)); + else if (src.picture && about.src) { + draw(null); + const im = new Image(); + im.onload = () => { draw(im); if (redraw) redraw(); }; + im.src = about.src; + } else draw(null); + return c; + } + + // a recipe's texture for a block's variant (or the sky, `sky` repeats round it) + recipeTexture(about, variant, sky) { + const r = about.recipe || {}; + const v = variant || 0; + const turns = r.turn_variants ? v % 4 : 0; + let tex = null; + const canvas = this.recipeCanvas(about, turns, () => { if (tex) tex.needsUpdate = true; this.render(); }); + tex = new THREE.CanvasTexture(canvas); + tex.wrapS = tex.wrapT = THREE.RepeatWrapping; + tex.colorSpace = THREE.SRGBColorSpace; + tex.anisotropy = 4; + const [sw, sh] = r.scale || [1, 1]; + // round the sky: four tiles a turn for a one-unit tile (fewer, bigger, for a bigger one) + if (sky) tex.repeat.set(Math.max(1, Math.round(4 / sw)), Math.max(1, Math.round(2 / sh))); + else tex.repeat.set(BLOCK_TILE / sw, BLOCK_TILE / sh); + const [ou, ov] = r.offset || [0, 0]; + tex.offset.set(ou + v * 0.381966, ov + v * 0.618034); + return tex; + } + + recipeMaterial(key, about, variant) { + const k = `${key}|${variant || 0}`; + let m = this.mats.get(k); + if (m) return m; + if (!about.recipe) m = new THREE.MeshBasicMaterial({ vertexColors: true, color: new THREE.Color('#9a8f84') }); + else m = new THREE.MeshBasicMaterial({ vertexColors: true, map: this.recipeTexture(about, variant) }); + this.mats.set(k, m); + return m; + } + + // a block's material: its texture's (a recipe's for its variant), or one per face when + // some faces show recipes of their own + blockMaterial(b) { + const key = `${b.kind}:${b.texture}`; + const about = this.abouts.get(key) || {}; + const base = b.kind === 'texture' ? this.recipeMaterial(key, about, b.variant || 0) : this.material(key, about); + const all = b.shape === 'sphere' || !b.faces || !b.faces.some(Boolean) ? base : b.faces.map((f) => (f ? this.recipeMaterial(`texture:${f}`, this.abouts.get(`texture:${f}`) || {}, 0) : base)); + if (!b.zone) return all; + return Array.isArray(all) ? all.map((m) => this.seeThrough(m)) : this.seeThrough(all); + } + + // a zone shows the texts in it: its material, see-through (made once per material) + seeThrough(m) { + if (!m.userData.glass) { + const g = m.clone(); + g.transparent = true; + g.opacity = 0.22; + g.depthWrite = false; + m.userData.glass = g; + } + return m.userData.glass; + } + + // the sky: a recipe round the room, far off and following the camera (null: none) + setSky(about) { + if (this.sky) { + this.scene.remove(this.sky); + this.sky.geometry.dispose(); + this.sky.material.map?.dispose(); + this.sky.material.dispose(); + this.sky = null; + } + if (about && about.recipe) { + const m = new THREE.MeshBasicMaterial({ map: this.recipeTexture(about, 0, true), side: THREE.BackSide, fog: false, depthWrite: false }); + this.sky = new THREE.Mesh(new THREE.SphereGeometry(1800, 48, 24), m); + this.sky.renderOrder = -1000; + this.sky.userData.sky = true; + this.scene.add(this.sky); + } + this.render(); + } + + // draws a recipe's tiles into the canvas with that id on the page (the textures + // window's previews): `tiles` across, each block variant in turn when `variants` + preview(id, about, tiles, variants, tries = 0) { + const el = document.getElementById(id); + if (!el) { + if (tries < 30) requestAnimationFrame(() => this.preview(id, about, tiles, variants, tries + 1)); + return; + } + const n = Math.max(1, tiles || 1); + const W = el.width, H = el.height; + const g = el.getContext('2d'); + const r = about.recipe || {}; + const drawAll = () => { + g.clearRect(0, 0, W, H); + // a tile keeps its shape (scale w by h) + const [sw, sh] = r.scale || [1, 1]; + const cw0 = W / n, ch0 = cw0 * (sh / sw); + const rows = Math.max(1, Math.ceil(H / ch0 - 1e-6)); + for (let y = 0; y < rows; y++) for (let x = 0; x < n; x++) { + const v = variants ? (y * n + x) % Math.max(1, r.variants || 1) : 0; + const tile = tiles_[v] || tiles_[0]; + const [ou, ov] = r.offset || [0, 0]; + // as the room samples it: the tile moved left by its u offset, down by its v + const fu = (((ou + v * 0.381966) % 1) + 1) % 1, fv = (((ov + v * 0.618034) % 1) + 1) % 1; + const cw = cw0, ch = ch0, x0 = x * cw, y0 = y * ch; + g.save(); + g.beginPath(); + g.rect(x0, y0, cw, ch); + g.clip(); + for (const i of [0, 1]) for (const j of [0, 1]) g.drawImage(tile, x0 - fu * cw + i * cw, y0 + fv * ch - j * ch, cw, ch); + g.restore(); + } + }; + const kinds = variants && r.turn_variants ? 4 : 1; + const tiles_ = []; + for (let k = 0; k < Math.max(kinds, variants ? Math.max(1, r.variants || 1) : 1); k++) { + tiles_.push(this.recipeCanvas(about, r.turn_variants ? k % 4 : 0, drawAll, 128)); + } + drawAll(); + } + + // a texture key's material, made once + material(key, about) { + if (key.startsWith('texture:')) return this.recipeMaterial(key, about, 0); + let m = this.mats.get(key); + if (m) return m; + const [kind, ...rest] = key.split(':'); + const texture = rest.join(':'); + let map = null; + if (kind === 'text') map = new THREE.CanvasTexture(this.textCanvas(about.gone ? '(gone)' : about.text, about.colour)); + else if (kind === 'picture' && about.src) { + map = new THREE.TextureLoader().load(about.src, () => this.render()); + } + if (map) { + map.wrapS = map.wrapT = THREE.RepeatWrapping; + map.colorSpace = THREE.SRGBColorSpace; + map.anisotropy = 4; + } + // unlit, so a texture shows its own colours; the faces are shaded by vertex colours + m = new THREE.MeshBasicMaterial({ vertexColors: true, ...(map ? { map } : { color: new THREE.Color(kind === 'plain' ? texture : '#b8a07a') }) }); + this.mats.set(key, m); + return m; + } + + // a box whose UVs count tiles: each face's u and v run over its sides in units. A bent + // block (`bend`, core's `graph::blocks::Bend`) is cut into slices across its width + // and each slice moved along its depth by `bendAt`, so its texture, picking and ray + // hits all follow the bent shape exactly. Faces are shaded by their direction (the top + // brightest, the bottom darkest), so a box and a curve both read. + boxGeometry(t) { + if (t.shape === 'sphere') return this.sphereGeometry(t); + const bent = !!(t.bend && ((t.bend.ripple && t.bend.ripple.amount) || (t.bend.fold && t.bend.fold.amount))); + const freq = bent && t.bend.ripple && t.bend.ripple.amount ? Math.max(1, t.bend.ripple.freq || 0) : 1; + const seg = bent ? Math.min(512, Math.max(16, Math.ceil(freq * 24))) : 1; + // faces cut into cells about a unit across (at most 16 a side), so baked light has + // somewhere to land + const cells = (v) => Math.min(16, Math.max(1, Math.ceil(v - 1e-6))); + const g = new THREE.BoxGeometry(t.w, t.h, t.d, Math.max(seg, cells(t.w)), cells(t.h), cells(t.d)); + const uv = g.attributes.uv, pos = g.attributes.position, nor = g.attributes.normal; + for (let i = 0; i < uv.count; i++) { + const ax = Math.abs(nor.getX(i)), ay = Math.abs(nor.getY(i)); + const span = ax > 0.5 ? [t.d, t.h] : ay > 0.5 ? [t.w, t.d] : [t.w, t.h]; + uv.setXY(i, uv.getX(i) * span[0] / BLOCK_TILE, uv.getY(i) * span[1] / BLOCK_TILE); + } + uv.needsUpdate = true; + if (bent) { + for (let i = 0; i < pos.count; i++) { + const u = (pos.getX(i) + t.w / 2) / t.w; + pos.setZ(i, pos.getZ(i) + bendAt(t.bend, u)); + } + pos.needsUpdate = true; + g.computeVertexNormals(); + } + const col = new Float32Array(pos.count * 3); + for (let i = 0; i < pos.count; i++) { + const v = 0.86 + 0.14 * nor.getY(i) + 0.08 * Math.abs(nor.getZ(i)); + col.set([v, v, v], i * 3); + } + g.setAttribute('color', new THREE.BufferAttribute(col, 3)); + g.userData.shape = shapeKey(t); + return g; + } + + // ------------------------------------------------------------------ animations + // + // A block playing an animation (core's graph::anims) is posed every frame: its move added + // to its place, its turn after its own, its sides scaled, its texture switched from a + // key on; the block itself (its place in the save, its gizmo, picking for editing) stays + // where it was put. `animPose` follows core's `sample`. + + setAnims(list, textures) { + for (const [k, v] of Object.entries(textures || {})) this.abouts.set(k, v); + this.anims = new Map((list || []).map((x) => [x.key, x.anim])); + this.animT0 = performance.now(); + for (const o of this.blocks.values()) this.unpose(o); + this.dirty = true; + } + + // play or pause every animation (paused: each block back where it was put) + playAnims(on) { + this.animPlaying = !!on; + if (on) this.animT0 = performance.now(); + else for (const o of this.blocks.values()) this.unpose(o); + this.dirty = true; + } + + + + // ------------------------------------------------------------------ placing prefabs + // + // Placing a prefab by hand, flying or walking: a see-through copy (the ghost) follows + // where you look (where the pointer is, when it isn't locked), sitting on the face of a + // block or on the floor, snapped to a half-unit grid (Shift: free). The wheel turns it a + // quarter at a time; it shows red where it would overlap a block. A click places a copy + // there (and the ghost stays, to place more); Esc or a right click stops. + startGhost(prefab, parts, textures, name) { + this.stopGhost(); + for (const [k, v] of Object.entries(textures || {})) this.abouts.set(k, v); + const g = new THREE.Group(); + const mats = []; + for (const b of parts || []) { + const mesh = new THREE.Mesh(this.boxGeometry(b), this.blockMaterial(b)); + mesh.position.set(b.x, b.y, b.z); + const r = b.rot || [0, 0, 0, 1]; + mesh.quaternion.set(r[0], r[1], r[2], r[3]); + this.bake({ b, mesh }); + const all = Array.isArray(mesh.material) ? mesh.material : [mesh.material]; + mesh.material = all.map((m) => { const c = m.clone(); c.transparent = true; c.opacity = 0.55; c.depthWrite = false; mats.push(c); return c; }); + if (mesh.material.length === 1) mesh.material = mesh.material[0]; + g.add(mesh); + } + this.scene.add(g); + this.ghost = { prefab, g, mats, turn: 0, ok: true, name: name || 'the prefab' }; + this.dirty = true; + } + + stopGhost() { + if (!this.ghost) return; + this.scene.remove(this.ghost.g); + for (const m of this.ghost.g.children) m.geometry.dispose(); + for (const m of this.ghost.mats) m.dispose(); + this.ghost = null; + this.dirty = true; + } + + // the ghost where you look: on a block's face or the floor, snapped, turned; red if + // it would overlap + aimGhost() { + const gh = this.ghost; + if (!gh) return; + const locked = document.pointerLockElement === this.host; + const ray = this.rayFrom(locked || !this.pointer ? null : this.pointer); + const g = gh.g; + g.position.set(0, 0, 0); + g.quaternion.setFromAxisAngle(new THREE.Vector3(0, 1, 0), gh.turn * Math.PI / 2); + g.updateMatrixWorld(true); + const box = new THREE.Box3().setFromObject(g); + const meshes = [...this.blocks.values()].map((o) => o.mesh); + const hit = ray.intersectObjects(meshes, false).find((h) => h.distance <= 80); + let at, n; + if (hit) { + at = hit.point.clone(); + n = hit.face ? hit.face.normal.clone().transformDirection(hit.object.matrixWorld) : new THREE.Vector3(0, 1, 0); + } else { + // the floor, where the ray meets it (else 12 units ahead) + const o = ray.ray.origin, d = ray.ray.direction; + const t = d.y < -1e-3 ? (BODY.floor - o.y) / d.y : -1; + at = t > 0 && t < 200 ? o.clone().addScaledVector(d, t) : o.clone().addScaledVector(d, 12); + n = new THREE.Vector3(0, 1, 0); + } + // the ghost's box rests against the surface along its normal + const ax = Math.abs(n.x) > Math.abs(n.y) && Math.abs(n.x) > Math.abs(n.z) ? 'x' : Math.abs(n.y) >= Math.abs(n.z) ? 'y' : 'z'; + const sign = Math.sign(n[ax]) || 1; + const pos = at.clone(); + pos[ax] += sign > 0 ? -box.min[ax] : -box.max[ax]; + const snap = this.keys.has('ShiftLeft') || this.keys.has('ShiftRight') ? 0 : 0.5; + if (snap) for (const k of ['x', 'y', 'z']) if (k !== ax) pos[k] = Math.round(pos[k] / snap) * snap; + g.position.copy(pos); + g.updateMatrixWorld(true); + const placed = new THREE.Box3().setFromObject(g); + placed.min.addScalar(0.01); + placed.max.addScalar(-0.01); + gh.ok = !this.solids().some((s) => s.intersectsBox(placed)); + for (const m of gh.mats) m.color && m.color.set(gh.ok ? 0xb8ffc0 : 0xff6a6a); + gh.at = pos; + } + + // the click: a copy where the ghost is, if it fits + placeGhost() { + const gh = this.ghost; + if (!gh || !gh.at) return; + if (!gh.ok) { this.send({ ...this.ev('toast', null), text: 'it would overlap a block there (red); move it, or turn it with the wheel' }); return; } + const q = new THREE.Quaternion().setFromAxisAngle(new THREE.Vector3(0, 1, 0), gh.turn * Math.PI / 2); + this.send({ ...this.ev('ghostplace', null), data: { prefab: gh.prefab, x: +gh.at.x.toFixed(4), y: +gh.at.y.toFixed(4), z: +gh.at.z.toFixed(4), rot: [q.x, q.y, q.z, q.w] } }); + } + + // ------------------------------------------------------------------ first person + // + // Besides flying (the default), you can walk (V): gravity, blocks to stand on and bump + // into, run (Shift), sneak (held), crouch (C), jump (Space), lean (Q, E) and mantle (jump + // at a ledge within reach climbs onto it). The grapple (G) hooks the block or text you + // look at, to swing on, reel in and out with the wheel, and let go with G or a jump. + // Superflight (B) flies fast where you look (Shift boosts) and collects the texts you + // fly through, in order, drawn as a trail; Rust offers to make them an entry, a chain, a + // list or the bar's text. The body moves in fixed steps of 1/120 s, the same on the + // desktop and the web. Walking and superflight lock the pointer when the page allows + // (Esc lets it go); right-drag looks around as ever. + setMode(mode) { + const was = this.mode || 'fly'; + if (mode === was) return; + this.mode = mode; + this.ease = null; + if (mode === 'fly') { + this.dropRope(); + this.body = null; + this.flight = null; + if (document.pointerLockElement === this.host) document.exitPointerLock?.(); + } else { + const c = this.camera.position; + if (mode === 'walk') { + this.flight = null; + this.body = { p: new THREE.Vector3(c.x, c.y - (BODY.stand - 0.1), c.z), v: new THREE.Vector3(), ground: false, h: BODY.stand, lean: 0, acc: 0, ledge: null }; + this.rollA = 0; + } else { + this.dropRope(); + this.body = null; + this.flight = { v: new THREE.Vector3(), acc: 0, last: c.clone() }; + if (!this.collected) this.collected = []; + } + // the pointer locked, the mouse looks; not on the desktop, whose web view stops + // passing keys on while it's locked (seen under Xvfb), so right-drag looks there + try { if (!window.__anendNoLock) this.host.requestPointerLock?.(); } catch { /* right-drag still looks */ } + } + this.send({ ...this.ev('mode', null), data: mode }); + this.dirty = true; + } + + // what blocks are in the way: their boxes in the room (turned and bent), made again + // when blocks change + solids() { + if (!this.solidBoxes || this.solidsAt !== this.blocksRev) { + this.solidBoxes = []; + for (const o of this.blocks.values()) { + if (o.b.zone) continue; + o.mesh.updateMatrixWorld(true); + this.solidBoxes.push(new THREE.Box3().setFromObject(o.mesh)); + } + this.solidsAt = this.blocksRev; + } + return this.solidBoxes; + } + + // the body's box at feet `p` with height `h` + bodyBox(p, h, out) { + return (out || new THREE.Box3()).set(new THREE.Vector3(p.x - BODY.r, p.y, p.z - BODY.r), new THREE.Vector3(p.x + BODY.r, p.y + h, p.z + BODY.r)); + } + + // whether a body at feet `p`, `h` tall, would stand in a block + blocked(p, h) { + const box = this.bodyBox(p, h); + box.min.addScalar(0.001); + box.max.addScalar(-0.001); + return this.solids().some((s) => s.intersectsBox(box)); + } + + moveBody(dt) { + if (this.mode === 'super') return this.superflight(dt); + const b = this.body; + if (!b) return; + b.acc = Math.min(b.acc + dt, 0.25); + while (b.acc >= FP_STEP) { + this.walkStep(FP_STEP); + b.acc -= FP_STEP; + } + // the camera at the eyes, leaning + const c = this.camera; + const right = new THREE.Vector3(Math.cos(this.yaw), 0, -Math.sin(this.yaw)); + c.position.set(b.p.x, b.p.y + b.h - 0.1, b.p.z).addScaledVector(right, b.lean * 0.4); + this.rollA = -b.lean * 0.12; + if (this.rope) this.drawRope(); + } + + walkStep(dt) { + const b = this.body, k = this.held.bind(this); + // crouching (and staying down where there's no room to stand) + const want = k('fly_down') ? BODY.crouch : BODY.stand; + if (want > b.h && this.blocked(b.p, want)) { /* stays down */ } else b.h = want; + const lean = (k('roll_left') ? -1 : 0) + (k('roll_right') ? 1 : 0); + b.lean += (lean - b.lean) * Math.min(1, dt * 10); + // where the keys push, on the ground's plane + const fwd = new THREE.Vector3(-Math.sin(this.yaw), 0, -Math.cos(this.yaw)); + const right = new THREE.Vector3(Math.cos(this.yaw), 0, -Math.sin(this.yaw)); + const wish = new THREE.Vector3(); + if (k('fly_forward')) wish.add(fwd); + if (k('fly_back')) wish.sub(fwd); + if (k('fly_left')) wish.sub(right); + if (k('fly_right')) wish.add(right); + if (wish.lengthSq() > 0) wish.normalize(); + const shift = this.keys.has('ShiftLeft') || this.keys.has('ShiftRight'); + const speed = b.h < BODY.stand ? BODY.crawl : k('sneak') ? BODY.sneak : shift ? BODY.run : BODY.walk; + if (this.rope) { + // on the rope: a little push, gravity, the rope's pull + b.v.addScaledVector(wish, 6 * dt); + b.v.y -= BODY.gravity * dt; + } else if (b.ground) { + b.v.x = wish.x * speed; + b.v.z = wish.z * speed; + } else { + b.v.x += (wish.x * speed - b.v.x) * Math.min(1, dt * 2); + b.v.z += (wish.z * speed - b.v.z) * Math.min(1, dt * 2); + b.v.y -= BODY.gravity * dt; + } + if (b.ground && !this.rope) b.v.y = 0; + // a jump; at a ledge in reach, a mantle onto it + if (k('fly_up') && !b.jumpHeld) { + if (this.rope) this.dropRope(); + else if (b.ledge != null && b.ledge - b.p.y <= BODY.mantle && !this.blocked(new THREE.Vector3(b.p.x + fwd.x * 0.35, b.ledge + 0.01, b.p.z + fwd.z * 0.35), b.h)) { + b.p.set(b.p.x + fwd.x * 0.35, b.ledge + 0.01, b.p.z + fwd.z * 0.35); + b.v.set(0, 0, 0); + } else if (b.ground) b.v.y = BODY.jump; + } + b.jumpHeld = k('fly_up'); + // move one axis at a time, out of what's in the way + b.ledge = null; + b.ground = false; + const box = new THREE.Box3(); + for (const axis of ['x', 'z', 'y']) { + const d = b.v[axis] * dt; + if (!d) continue; + b.p[axis] += d; + for (const s of this.solids()) { + this.bodyBox(b.p, b.h, box); + if (!s.intersectsBox(box)) continue; + if (axis === 'y') { + if (d < 0) { b.p.y = s.max.y; b.ground = true; } else b.p.y = s.min.y - b.h; + b.v.y = 0; + } else { + // a low step is climbed; a higher one is a ledge to mantle + const rise = s.max.y - b.p.y; + if (rise > 0 && rise <= BODY.step && b.v.y <= 0 && !this.blocked(new THREE.Vector3(b.p.x, s.max.y + 0.001, b.p.z), b.h)) { + b.p.y = s.max.y + 0.001; + continue; + } + if (rise > 0) b.ledge = b.ledge == null ? s.max.y : Math.max(b.ledge, s.max.y); + b.p[axis] = d > 0 ? s.min[axis] - BODY.r - 0.0005 : s.max[axis] + BODY.r + 0.0005; + if (!this.rope) b.v[axis] = 0; + } + } + } + if (b.p.y <= BODY.floor) { b.p.y = BODY.floor; b.v.y = Math.max(0, b.v.y); b.ground = true; } + // standing on something (resting on its top) + if (!b.ground && b.v.y <= 0) { + const below = this.bodyBox(new THREE.Vector3(b.p.x, b.p.y - 0.01, b.p.z), 0.009); + if (this.solids().some((s) => s.intersectsBox(below))) b.ground = true; + } + // the rope keeps the hand within its length of the hook + const r = this.rope; + if (r) { + const hand = new THREE.Vector3(b.p.x, b.p.y + b.h - 0.3, b.p.z); + const d = hand.clone().sub(r.at); + const len = d.length(); + if (len > r.len) { + d.multiplyScalar(1 / len); + b.p.addScaledVector(d, r.len - len); + const out = b.v.dot(d); + if (out > 0) b.v.addScaledVector(d, -out); + b.ground = false; + } + b.v.multiplyScalar(1 - Math.min(1, dt * 0.15)); + } + } + + // the grapple: hook what's ahead, or let go + grapple() { + if (this.rope) return this.dropRope(); + if (this.mode !== 'walk') this.setMode('walk'); + const c = this.camera; + // where you look now (the room may not have drawn since the last turn) + this.applyTurn(); + c.updateMatrixWorld(true); + const ray = this.rayFrom(null); + let at = null; + const meshes = [...this.blocks.values()].map((o) => o.mesh); + const hit = ray.intersectObjects(meshes, false)[0]; + if (hit && hit.distance <= 60) at = hit.point.clone(); + // else a text near where you look + if (!at) { + const fwd = new THREE.Vector3(0, 0, -1).applyQuaternion(c.quaternion); + let best = 0.05; + const w = new THREE.Vector3(); + for (const n of this.order) { + this.world(n, w); + const d = w.clone().sub(c.position); + const dist = d.length(); + if (dist < 1 || dist > 60) continue; + const off = 1 - d.normalize().dot(fwd); + if (off < best) { best = off; at = w.clone(); } + } + } + if (!at) { this.send({ ...this.ev('toast', null), text: 'nothing to hook ahead (60 units at most)' }); return; } + const b = this.body; + const hand = new THREE.Vector3(b.p.x, b.p.y + b.h - 0.3, b.p.z); + this.rope = { at, len: Math.max(1.2, hand.distanceTo(at)) }; + if (!this.ropeLine) { + this.ropeLine = new THREE.Line(new THREE.BufferGeometry().setFromPoints([new THREE.Vector3(), new THREE.Vector3()]), new THREE.LineBasicMaterial({ color: 0x5a4632 })); + this.ropeLine.frustumCulled = false; + } + this.scene.add(this.ropeLine); + this.drawRope(); + } + + dropRope() { + if (!this.rope) return; + this.rope = null; + if (this.ropeLine) this.scene.remove(this.ropeLine); + this.dirty = true; + } + + drawRope() { + const b = this.body, r = this.rope; + if (!b || !r || !this.ropeLine) return; + const right = new THREE.Vector3(Math.cos(this.yaw), 0, -Math.sin(this.yaw)); + const hand = new THREE.Vector3(b.p.x, b.p.y + b.h - 0.35, b.p.z).addScaledVector(right, 0.25); + const pos = this.ropeLine.geometry.attributes.position; + pos.setXYZ(0, hand.x, hand.y, hand.z); + pos.setXYZ(1, r.at.x, r.at.y, r.at.z); + pos.needsUpdate = true; + } + + // superflight: thrust where you look, Shift to boost; texts flown through are collected + superflight(dt) { + const f = this.flight; + if (!f) return; + f.acc = Math.min(f.acc + dt, 0.25); + const c = this.camera, k = this.held.bind(this); + while (f.acc >= FP_STEP) { + const t = FP_STEP; + const look = new THREE.Vector3(0, 0, -1).applyQuaternion(c.quaternion); + const right = new THREE.Vector3(1, 0, 0).applyQuaternion(c.quaternion); + const boost = this.keys.has('ShiftLeft') || this.keys.has('ShiftRight') ? 3 : 1; + const thrust = new THREE.Vector3(); + if (k('fly_forward')) thrust.addScaledVector(look, 40 * boost); + if (k('fly_back')) thrust.addScaledVector(f.v, -2); + if (k('fly_left')) thrust.addScaledVector(right, -20); + if (k('fly_right')) thrust.addScaledVector(right, 20); + if (k('fly_up')) thrust.y += 20; + if (k('fly_down')) thrust.y -= 20; + f.v.addScaledVector(thrust, t); + f.v.multiplyScalar(1 - Math.min(1, 1.2 * t)); + const max = 30 * boost; + if (f.v.length() > max) f.v.setLength(max); + const from = c.position.clone(); + c.position.addScaledVector(f.v, t); + this.collect(from, c.position); + f.acc -= t; + } + } + + // the texts within reach of the path from `a` to `b`, in the order met, into the buffer + collect(a, b) { + const seg = b.clone().sub(a); + const len2 = seg.lengthSq(); + if (len2 < 1e-9) return; + const w = new THREE.Vector3(); + const met = []; + const have = new Set(this.collected.map((x) => x.key)); + for (const n of this.order) { + if (have.has(n.key)) continue; + this.world(n, w); + const t = Math.max(0, Math.min(1, w.clone().sub(a).dot(seg) / len2)); + const near = a.clone().addScaledVector(seg, t).distanceTo(w); + if (near <= 0.6 + (n.size || this.p.size)) met.push({ t, n, at: w.clone() }); + } + if (!met.length) return; + met.sort((x, y) => x.t - y.t || (x.n.key < y.n.key ? -1 : 1)); + for (const m of met) this.collected.push({ key: m.n.key, text: m.n.f.text, at: m.at }); + this.drawTrail(); + this.send({ ...this.ev('collected', null), data: this.collected.map((x) => ({ key: x.key, text: x.text })) }); + } + + // the collected texts, joined by a line in the order met + drawTrail() { + if (this.trail) { this.scene.remove(this.trail); this.trail.geometry.dispose(); this.trail = null; } + const pts = (this.collected || []).map((x) => x.at); + if (pts.length < 2) return; + this.trail = new THREE.Line(new THREE.BufferGeometry().setFromPoints(pts), new THREE.LineBasicMaterial({ color: 0xff8c1a })); + this.trail.frustumCulled = false; + this.scene.add(this.trail); + this.dirty = true; + } + + clearCollected() { + this.collected = []; + this.drawTrail(); + this.send({ ...this.ev('collected', null), data: [] }); + } + + // ------------------------------------------------------------------ prefabs + // + // A prefab's copies are drawn as their parts, ordinary blocks whose ids name their copy + // (core's graph::prefabs). The prefab menu shows each prefab as a small picture of its + // parts, drawn here on a renderer of its own: `thumbs` answers id → a PNG data URL. + thumbs(list, textures) { + for (const [k, v] of Object.entries(textures || {})) this.abouts.set(k, v); + const size = 112; + if (!this.thumbR) { + this.thumbR = new THREE.WebGLRenderer({ antialias: true, alpha: true, preserveDrawingBuffer: true }); + this.thumbR.setPixelRatio(1); + this.thumbR.setSize(size, size); + } + const out = {}; + for (const p of list || []) { + const sc = new THREE.Scene(); + const box = new THREE.Box3(); + const made = []; + for (const b of p.parts || []) { + const mesh = new THREE.Mesh(this.boxGeometry(b), this.blockMaterial(b)); + mesh.position.set(b.x, b.y, b.z); + const r = b.rot || [0, 0, 0, 1]; + mesh.quaternion.set(r[0], r[1], r[2], r[3]); + const o = { b, mesh }; + this.bake(o); + sc.add(mesh); + made.push(mesh); + box.expandByObject(mesh); + } + if (!made.length) continue; + const c = box.getCenter(new THREE.Vector3()); + const r = Math.max(0.5, box.getSize(new THREE.Vector3()).length() / 2); + const cam = new THREE.PerspectiveCamera(35, 1, 0.05, r * 20); + cam.position.copy(c).add(new THREE.Vector3(0.9, 0.7, 1.4).normalize().multiplyScalar(r / Math.sin((35 / 2) * Math.PI / 180))); + cam.lookAt(c); + this.thumbR.setClearColor(0x000000, 0); + this.thumbR.render(sc, cam); + out[p.id] = this.thumbR.domElement.toDataURL('image/png'); + for (const m of made) m.geometry.dispose(); + } + return out; + } + + // ------------------------------------------------------------------ wiring + // + // Blocks that cast rays and run programs (core's `ops::wiring`). The room only knows + // which blocks listen for what; core runs the programs and casts the rays. Playing + // (`live`), a click on a block listening for clicks fires it instead of selecting it, + // timers fire their blocks, and a zone listening for texts coming or going is told. + // The rays a cause casts show for a moment. + setWires(list, live) { + this.wires = new Map((list || []).map((w) => [w.id, w])); + this.wiresDirty = true; + // timers keep their beat across a reload of the list (a cause reloads it) + const was = this.live; + this.live = !!live; + const old = (was && this.live && this.wireT) || new Map(); + this.wireT = new Map([...old].filter(([k]) => this.wires.has(k))); + this.dirty = true; + // the looping sound emitters play while the room plays + if (this.live && !was) this.startLoops(); + if (!this.live && was) this.hushAll(); + } + + // ------------------------------------------------------------------ wires + // + // Each sticky ray is drawn as a wire from its block to each target: a sagging line, + // lit while a ray passes along it. In wiring mode (J, or the wiring window's "connect + // by dragging") every block shows a port, and a drag from one block to another makes a + // wire (or takes it away, when it's there); flying or walking alike (walking, what's + // ahead is what the drag starts and ends on). Ctrl+Z takes a wire back. + + drawWires() { + this.wiresDirty = false; + if (this.wireLines) { + this.scene.remove(this.wireLines); + this.wireLines.traverse((x) => { x.geometry?.dispose(); x.material?.dispose(); }); + this.wireLines = null; + } + const g = new THREE.Group(); + this.wireIdx = []; + const now = performance.now(); + for (const w of (this.wires || new Map()).values()) { + const a = this.blocks.get(w.id); + if (!a) continue; + for (const t of w.links || []) { + const b = this.blocks.get(t); + if (!b) continue; + const p0 = a.mesh.position, p1 = b.mesh.position; + const mid = p0.clone().add(p1).multiplyScalar(0.5); + mid.y -= Math.min(1.2, p0.distanceTo(p1) * 0.18); + const curve = new THREE.QuadraticBezierCurve3(p0.clone(), mid, p1.clone()); + const lit = this.wireLit && this.wireLit.get(`${w.id}>${t}`) > now; + // a cable with some thickness (lines are a pixel wide whatever the distance) + const line = new THREE.Mesh(new THREE.TubeGeometry(curve, 28, lit ? 0.045 : 0.028, 6, false), new THREE.MeshBasicMaterial({ color: lit ? 0xffd23f : 0x5a4a32, transparent: true, opacity: lit ? 1 : 0.85, depthTest: !lit })); + line.renderOrder = lit ? 11 : 1; + g.add(line); + this.wireIdx.push({ from: w.id, to: t }); + } + } + // the ports, while wiring + if (this.wiring) { + const mat = new THREE.MeshBasicMaterial({ color: 0x3f8cff, fog: false, depthTest: false, transparent: true, opacity: 0.9 }); + for (const o of this.blocks.values()) { + const box = new THREE.Box3().setFromObject(o.mesh); + const port = new THREE.Mesh(new THREE.SphereGeometry(0.09, 12, 8), mat.clone()); + port.position.set((box.min.x + box.max.x) / 2, box.max.y + 0.12, (box.min.z + box.max.z) / 2); + port.renderOrder = 1003; + g.add(port); + } + } + this.wireLines = g; + this.scene.add(g); + this.dirty = true; + } + + // a ray passed: the wires it went along light up for a moment + lightWires(rays) { + if (!this.wires) return; + this.wireLit = this.wireLit || new Map(); + const until = performance.now() + 700; + for (const r of rays || []) { + const from = new THREE.Vector3(...r.from); + for (const w of this.wires.values()) { + const a = this.blocks.get(w.id); + if (!a || a.mesh.position.distanceTo(from) > 0.6) continue; + for (const t of r.hits || []) if ((w.links || []).includes(t)) this.wireLit.set(`${w.id}>${t}`, until); + } + } + this.wiresDirty = true; + setTimeout(() => { this.wiresDirty = true; this.dirty = true; }, 760); + } + + setWiring(on) { + this.wiring = on == null ? !this.wiring : !!on; + this.wiresDirty = true; + this.send({ ...this.ev('wiremode', null), data: this.wiring }); + this.render(); + } + + // the block under the pointer (or ahead, walking), not the gizmo over it + blockUnder(e) { + const m = this.rayFrom(e).intersectObjects([...this.blocks.values()].map((o) => o.mesh), false)[0]; + return m ? m.object.userData.block : null; + } + + startWire(e) { + const from = this.blockUnder(e); + if (from == null) return false; + const fwd = new THREE.Vector3(0, 0, -1).applyQuaternion(this.camera.quaternion); + const at = this.blocks.get(from).mesh.position; + this.wdrag = { from, depth: at.clone().sub(this.camera.position).dot(fwd), line: null }; + try { this.host.setPointerCapture(e.pointerId); } catch { /* fine without */ } + return true; + } + + dragWire(e) { + const d = this.wdrag; + const p0 = this.blocks.get(d.from).mesh.position; + const to = this.blockUnder(e); + const p1 = to != null && to !== d.from ? this.blocks.get(to).mesh.position : this.rayAt(e.clientX, e.clientY, d.depth); + if (d.line) { this.scene.remove(d.line); d.line.geometry.dispose(); } + d.line = new THREE.Line(new THREE.BufferGeometry().setFromPoints([p0.clone(), p1.clone()]), new THREE.LineDashedMaterial({ color: 0x3f8cff, dashSize: 0.15, gapSize: 0.08, depthTest: false })); + d.line.computeLineDistances(); + d.line.renderOrder = 1004; + this.scene.add(d.line); + this.dirty = true; + } + + endWire(e) { + const d = this.wdrag; + this.wdrag = null; + if (d.line) { this.scene.remove(d.line); d.line.geometry.dispose(); } + const to = this.blockUnder(e); + if (to != null && to !== d.from) this.send({ ...this.ev('wirelink', null), data: { from: d.from, to } }); + this.render(); + } + + // ------------------------------------------------------------------ sounds + // + // Blocks can be sound emitters (core's graph::sounds): a sound of the save, a volume, + // how far it carries (it fades to nothing there) and whether it loops. While the room + // plays, looping emitters sound from the start and the others when a program prints + // `sound`; each is placed where its block is and heard from the camera (Web Audio). + // The room asks Rust for a sound's bytes the first time it needs them (`soundwant`). + audio() { + if (!this.ac) { + const AC = window.AudioContext || window.webkitAudioContext; + if (!AC) return null; + this.ac = new AC(); + this.buffers = new Map(); // sound id → AudioBuffer, or a Promise while decoding + this.voices = new Map(); // block id → { src, gain, pan } + this.waiting = new Map(); // sound id → block ids to start when it arrives + } + if (this.ac.state === 'suspended') this.ac.resume().catch(() => {}); + return this.ac; + } + + // a sound's bytes from Rust: decoded, then the blocks waiting on it start + soundData(id, data) { + const ac = this.audio(); + if (!ac) return; + const bin = atob(data); + const bytes = new Uint8Array(bin.length); + for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i); + const p = ac.decodeAudioData(bytes.buffer).then((buf) => { + this.buffers.set(id, buf); + const want = this.waiting.get(id) || []; + this.waiting.delete(id); + for (const w of want) w(); + }).catch((e) => { + this.buffers.delete(id); + this.send({ ...this.ev('toast', null), text: `that sound doesn't play here: ${e && e.message || e}` }); + }); + this.buffers.set(id, p); + } + + // runs `then` with the sound's buffer, once it's here + withSound(id, then) { + const b = this.buffers.get(id); + if (b instanceof AudioBuffer) return then(b); + const q = this.waiting.get(id) || []; + q.push(() => then(this.buffers.get(id))); + this.waiting.set(id, q); + if (!b) { + this.buffers.set(id, 'asked'); + this.send({ ...this.ev('soundwant', null), data: id }); + } + } + + // a block's sound starts (again, from the beginning) + playSound(blockId) { + const o = this.blocks.get(blockId); + const s = o && o.b.sound; + if (!s || !this.audio()) return; + this.stopSound(blockId); + this.withSound(s.id, (buf) => { + if (!(buf instanceof AudioBuffer) || !this.blocks.has(blockId)) return; + const ac = this.ac; + const src = ac.createBufferSource(); + src.buffer = buf; + src.loop = !!s.loop; + const gain = ac.createGain(); + gain.gain.value = s.volume == null ? 1 : s.volume; + const pan = ac.createPanner(); + pan.panningModel = 'equalpower'; + pan.distanceModel = 'linear'; + pan.refDistance = 1; + pan.maxDistance = Math.max(1.01, s.range || 20); + pan.rolloffFactor = 1; + src.connect(gain).connect(pan).connect(ac.destination); + const v = { src, gain, pan }; + this.voices.set(blockId, v); + this.placeVoice(blockId, v); + src.onended = () => { if (this.voices.get(blockId) === v) this.voices.delete(blockId); }; + src.start(); + this.hearFrom(); + }); + } + + stopSound(blockId) { + const v = this.voices && this.voices.get(blockId); + if (!v) return; + this.voices.delete(blockId); + try { v.src.stop(); } catch { /* ended already */ } + } + + startLoops() { + for (const [id, o] of this.blocks) if (o.b.sound && o.b.sound.loop) this.playSound(id); + } + + hushAll() { + if (!this.voices) return; + for (const id of [...this.voices.keys()]) this.stopSound(id); + } + + // what programs asked for: `[{block, play}]` + sounds(list) { + for (const s of list || []) (s.play ? this.playSound(s.block) : this.stopSound(s.block)); + } + + // a sound heard as it is, not placed (the sounds window's ▶) + previewSound(id) { + if (!this.audio()) return; + if (this.preview && this.preview.stop) { try { this.preview.stop(); } catch { /* done */ } } + this.withSound(id, (buf) => { + if (!(buf instanceof AudioBuffer)) return; + const src = this.ac.createBufferSource(); + src.buffer = buf; + src.connect(this.ac.destination); + src.start(); + this.preview = src; + }); + } + + placeVoice(id, v) { + const o = this.blocks.get(id); + if (!o) return; + const p = o.mesh.position; + const t = this.ac.currentTime; + if (v.pan.positionX) { + v.pan.positionX.setValueAtTime(p.x, t); + v.pan.positionY.setValueAtTime(p.y, t); + v.pan.positionZ.setValueAtTime(p.z, t); + } else v.pan.setPosition(p.x, p.y, p.z); + } + + // the listener is the camera; voices follow their blocks (an animation moves them). + // (Not `listen`: that's the method that attaches the room's events, once.) + hearFrom() { + if (!this.ac || !this.voices || !this.voices.size) return; + const l = this.ac.listener, c = this.camera, t = this.ac.currentTime; + const f = new THREE.Vector3(0, 0, -1).applyQuaternion(c.quaternion); + const u = new THREE.Vector3(0, 1, 0).applyQuaternion(c.quaternion); + if (l.positionX) { + l.positionX.setValueAtTime(c.position.x, t); + l.positionY.setValueAtTime(c.position.y, t); + l.positionZ.setValueAtTime(c.position.z, t); + l.forwardX.setValueAtTime(f.x, t); + l.forwardY.setValueAtTime(f.y, t); + l.forwardZ.setValueAtTime(f.z, t); + l.upX.setValueAtTime(u.x, t); + l.upY.setValueAtTime(u.y, t); + l.upZ.setValueAtTime(u.z, t); + } else { + l.setPosition(c.position.x, c.position.y, c.position.z); + l.setOrientation(f.x, f.y, f.z, u.x, u.y, u.z); + } + for (const [id, v] of this.voices) this.placeVoice(id, v); + } + + wireFire(id, event, from) { + this.send({ ...this.ev('blockfire', null), data: { id, event, from: from || '' } }); + } + + // the timers of wired blocks, on the frame's clock (playing only) + wireTimers(now) { + if (!this.live || !this.wires || !this.wires.size) return false; + let any = false; + for (const [id, w] of this.wires) { + if (!(w.on || []).includes('timer')) continue; + any = true; + const every = Math.max(0.2, w.every || 1) * 1000; + const last = this.wireT.get(id); + if (last == null) this.wireT.set(id, now); + else if (now - last >= every) { + this.wireT.set(id, now); + this.wireFire(id, 'timer'); + } + } + return any; + } + + // a text came into or left a zone: the zone's block is told, when it listens + wireZone(zone, text, event) { + if (!this.live || !zone || !this.wires) return; + const w = this.wires.get(zone); + if (w && (w.on || []).includes(event)) this.wireFire(zone, event, text); + } + + // the rays a cause cast, drawn for a moment + showRays(rays) { + if (!rays || !rays.length) return; + this.lightWires(rays); + const pts = []; + for (const r of rays) pts.push(new THREE.Vector3(...r.from), new THREE.Vector3(...r.to)); + const g = new THREE.BufferGeometry().setFromPoints(pts); + const line = new THREE.LineSegments(g, new THREE.LineBasicMaterial({ color: 0xffcc33, transparent: true, opacity: 0.95, depthTest: false })); + line.renderOrder = 10; + this.scene.add(line); + this.rayLines = (this.rayLines || []).concat([{ line, t0: performance.now() }]); + this.dirty = true; + } + + // fades the rays out over 0.8 s; whether any are left + fadeRays(now) { + if (!this.rayLines || !this.rayLines.length) return false; + this.rayLines = this.rayLines.filter((r) => { + const a = 1 - (now - r.t0) / 800; + if (a <= 0) { + this.scene.remove(r.line); + r.line.geometry.dispose(); + r.line.material.dispose(); + return false; + } + r.line.material.opacity = 0.95 * a; + return true; + }); + return true; + } + + // the animations window shows one on a block: at a phase (scrubbing), or playing + previewAnim(id, anim, p) { + const o = this.blocks.get(id); + if (!o) return; + o.preview = anim ? { anim, p: p == null ? null : p, t0: performance.now() } : null; + if (!anim) this.unpose(o); + this.dirty = true; + } + + animating() { + for (const o of this.blocks.values()) if (o.preview || (this.animPlaying && o.b.anim && this.anims.has(o.b.anim.key))) return true; + return false; + } + + unpose(o) { + o.mesh.scale.set(1, 1, 1); + o.mesh.position.set(o.b.x, o.b.y, o.b.z); + o.mesh.quaternion.copy(turnOf(o.b)); + if (o.animTex) { + o.animTex = null; + o.mesh.material = this.blockMaterial(o.b); + } + } + + // where in an animation (0 to 1) `t` seconds after it started + animPhase(a, t) { + const x = Math.max(0, t) / Math.max(0.05, a.duration || 2); + if (a.repeat === 'loop') return x % 1; + if (a.repeat === 'alternate') { const f = x % 2; return f <= 1 ? f : 2 - f; } + return Math.min(1, x); + } + + animPose(a, p) { + const keys = [...(a.keys || [])].sort((x, y) => x.at - y.at); + const timing = a.timing || [0.25, 0.1, 0.25, 1]; + const field = (name, rest) => { + const set = keys.filter((k) => k[name]); + if (!set.length) return rest; + const f = set[0]; + if (p <= f.at) { + if (f.at <= 0) return f[name]; + const u = cubicBezier(timing, p / f.at); + return rest.map((r, i) => r + (f[name][i] - r) * u); + } + for (let i = 0; i + 1 < set.length; i++) { + const k0 = set[i], k1 = set[i + 1]; + if (p <= k1.at) { + const u = cubicBezier(k0.timing || timing, (p - k0.at) / Math.max(1e-6, k1.at - k0.at)); + return k0[name].map((v, j) => v + (k1[name][j] - v) * u); + } + } + return set[set.length - 1][name]; + }; + let texture = null; + for (const k of keys) if (k.at <= p && k.texture) texture = k.texture; + return { move: field('move', [0, 0, 0]), turn: field('turn', [0, 0, 0]), scale: field('scale', [1, 1, 1]), texture }; + } + + // every playing block posed for this moment + applyAnims(now) { + const e = new THREE.Euler(), q = new THREE.Quaternion(); + for (const o of this.blocks.values()) { + let a = null, p = 0; + if (o.preview) { + a = o.preview.anim; + p = o.preview.p != null ? o.preview.p : this.animPhase(a, (now - o.preview.t0) / 1000); + } else if (this.animPlaying && o.b.anim && this.anims.has(o.b.anim.key)) { + a = this.anims.get(o.b.anim.key); + const t = ((now - this.animT0) / 1000 - (o.b.anim.delay || 0)) * (o.b.anim.speed || 1); + p = this.animPhase(a, t); + } + if (!a) continue; + const pose = this.animPose(a, p); + const b = o.b; + o.mesh.position.set(b.x + pose.move[0], b.y + pose.move[1], b.z + pose.move[2]); + e.set((pose.turn[0] * Math.PI) / 180, (pose.turn[1] * Math.PI) / 180, (pose.turn[2] * Math.PI) / 180, 'XYZ'); + o.mesh.quaternion.copy(turnOf(b)).multiply(q.setFromEuler(e)); + o.mesh.scale.set(pose.scale[0], pose.scale[1], pose.scale[2]); + if ((pose.texture || null) !== (o.animTex || null)) { + o.animTex = pose.texture; + const m = pose.texture ? this.material(pose.texture, this.abouts.get(pose.texture) || {}) : this.blockMaterial(b); + o.mesh.material = b.zone ? (Array.isArray(m) ? m.map((x) => this.seeThrough(x)) : this.seeThrough(m)) : m; + } + } + } + + // ------------------------------------------------------------------ lights + // + // The room's lights are baked: each block's vertex colours are the light reaching them + // (ambient, directional, point and cone lights summed; points and cones fade to nothing + // at their range, a cone's edge softened), worked out when a light or the block changes + // and not every frame. No shadows. With no lights, faces are shaded by their direction + // as before. Texts (html labels) aren't lit. + + // a block's vertex colours from the lights + bake(o) { + const g = o.mesh.geometry; + const pos = g.attributes.position, nor = g.attributes.normal; + let col = g.attributes.color; + if (!col || col.count !== pos.count) { + col = new THREE.BufferAttribute(new Float32Array(pos.count * 3), 3); + g.setAttribute('color', col); + } + const lights = this.lights || []; + if (!lights.length) { + const round = o.b.shape === 'sphere'; + for (let i = 0; i < pos.count; i++) { + const v = round ? 0.82 + 0.18 * nor.getY(i) + 0.06 * Math.abs(nor.getZ(i)) : 0.86 + 0.14 * nor.getY(i) + 0.08 * Math.abs(nor.getZ(i)); + col.setXYZ(i, v, v, v); + } + col.needsUpdate = true; + return; + } + o.mesh.updateMatrixWorld(true); + const m = o.mesh.matrixWorld, q = o.mesh.quaternion; + const p = new THREE.Vector3(), n = new THREE.Vector3(), l = new THREE.Vector3(); + const ls = lights.map((x) => ({ ...x, c: new THREE.Color(x.colour || '#ffffff'), d: new THREE.Vector3(...(x.dir || [0, -1, 0])).normalize(), at: new THREE.Vector3(x.x || 0, x.y || 0, x.z || 0) })); + for (let i = 0; i < pos.count; i++) { + p.fromBufferAttribute(pos, i).applyMatrix4(m); + n.fromBufferAttribute(nor, i).applyQuaternion(q).normalize(); + let r = 0, gg = 0, bb = 0; + for (const x of ls) { + let f = 0; + if (x.kind === 'ambient') f = x.intensity; + else if (x.kind === 'directional') f = x.intensity * Math.max(0, -n.dot(x.d)); + else { + l.copy(x.at).sub(p); + const dist = l.length(); + if (dist > x.range) continue; + l.divideScalar(dist || 1); + const fade = (1 - dist / x.range) ** 2; + f = x.intensity * Math.max(0, n.dot(l)) * fade; + if (x.kind === 'spot') { + const cos = -l.dot(x.d); + const outer = Math.cos((x.angle * Math.PI) / 180), inner = Math.cos((x.angle * (1 - x.softness) * Math.PI) / 180); + const t = inner > outer ? Math.min(1, Math.max(0, (cos - outer) / (inner - outer))) : cos >= outer ? 1 : 0; + f *= t * t * (3 - 2 * t); + } + } + r += x.c.r * f; gg += x.c.g * f; bb += x.c.b * f; + } + col.setXYZ(i, Math.min(r, 2), Math.min(gg, 2), Math.min(bb, 2)); + } + col.needsUpdate = true; + } + + // the lights from Rust; `changed` (ids, with where they were) bakes only the blocks they + // reach, else every block + setLights(list, changed) { + const before = new Map((this.lights || []).map((x) => [x.id, x])); + this.lights = list || []; + const now = new Map(this.lights.map((x) => [x.id, x])); + let all = !changed || (before.size === 0) !== (now.size === 0); + const reach = []; + for (const id of changed || []) { + for (const x of [before.get(id), now.get(id)]) { + if (!x) continue; + if (x.kind === 'ambient' || x.kind === 'directional') all = true; + else reach.push(x); + } + } + for (const o of this.blocks.values()) { + if (all) { this.bake(o); continue; } + const b = o.b, half = Math.hypot(b.w, b.h, b.d) / 2; + if (reach.some((x) => Math.hypot(b.x - x.x, b.y - x.y, b.z - x.z) <= x.range + half)) this.bake(o); + } + this.markLights(); + this.render(); + } + + // the lights window shows where the point and cone lights are, and which is picked + showLights(on, picked) { + this.lightsShown = !!on; + this.lightPicked = picked == null ? null : picked; + this.markLights(); + this.render(); + } + + markLights() { + if (this.lightMarks) { + this.scene.remove(this.lightMarks); + this.lightMarks.traverse((x) => { x.geometry?.dispose(); x.material?.dispose(); }); + this.lightMarks = null; + } + if (!this.lightsShown) return; + const g = new THREE.Group(); + for (const x of this.lights) { + if (x.kind !== 'point' && x.kind !== 'spot') continue; + const picked = x.id === this.lightPicked; + const mat = new THREE.MeshBasicMaterial({ color: x.colour, fog: false, depthTest: false, transparent: true, opacity: picked ? 1 : 0.8 }); + const ball = new THREE.Mesh(new THREE.SphereGeometry(picked ? 0.22 : 0.15, 16, 12), mat); + ball.position.set(x.x, x.y, x.z); + ball.userData.light = x.id; + ball.renderOrder = 998; + g.add(ball); + const ring = new THREE.Mesh(new THREE.TorusGeometry(picked ? 0.34 : 0.26, 0.02, 6, 32), new THREE.MeshBasicMaterial({ color: picked ? 0xffffff : 0x333333, fog: false, depthTest: false, transparent: true })); + ring.position.copy(ball.position); + ring.userData.facing = true; + ring.renderOrder = 998; + g.add(ring); + if (x.kind === 'spot') { + // the cone's axis, as long as its reach (up to 3 units) + const d = new THREE.Vector3(...x.dir).normalize(); + const len = Math.min(2, x.range); + const cone = new THREE.Mesh(new THREE.ConeGeometry(Math.tan((x.angle * Math.PI) / 180) * len, len, 24, 1, true), new THREE.MeshBasicMaterial({ color: x.colour, fog: false, transparent: true, opacity: 0.08, side: THREE.DoubleSide, depthWrite: false })); + cone.quaternion.setFromUnitVectors(new THREE.Vector3(0, -1, 0), d); + cone.position.copy(ball.position).add(d.clone().multiplyScalar(len / 2)); + g.add(cone); + } + } + this.lightMarks = g; + this.scene.add(g); + } + + // where a new light goes: a little ahead of the camera + lightSpot() { + const at = new THREE.Vector3(0, 0, -4).applyQuaternion(this.camera.quaternion).add(this.camera.position); + const d = new THREE.Vector3(0, 0, -1).applyQuaternion(this.camera.quaternion); + return { x: +at.x.toFixed(2), y: +at.y.toFixed(2), z: +at.z.toFixed(2), dir: [+d.x.toFixed(3), +d.y.toFixed(3), +d.z.toFixed(3)] }; + } + + // a sphere block: an ellipsoid with the block's sides as its diameters. Its texture + // tiles once per unit round its middle and from pole to pole, as a box's does over its + // faces; it neither bends nor has faces of its own (core's graph::blocks::Shape) + sphereGeometry(t) { + const g = new THREE.SphereGeometry(0.5, 48, 32); + const pos = g.attributes.position, uv = g.attributes.uv; + for (let i = 0; i < pos.count; i++) pos.setXYZ(i, pos.getX(i) * t.w, pos.getY(i) * t.h, pos.getZ(i) * t.d); + const round = (Math.PI * (t.w + t.d)) / 2, meridian = (Math.PI * t.h) / 2; + for (let i = 0; i < uv.count; i++) uv.setXY(i, (uv.getX(i) * round) / BLOCK_TILE, (uv.getY(i) * meridian) / BLOCK_TILE); + g.computeVertexNormals(); + const nor = g.attributes.normal; + const col = new Float32Array(pos.count * 3); + for (let i = 0; i < pos.count; i++) { + const v = 0.82 + 0.18 * nor.getY(i) + 0.06 * Math.abs(nor.getZ(i)); + col.set([v, v, v], i * 3); + } + g.setAttribute('color', new THREE.BufferAttribute(col, 3)); + g.userData.shape = shapeKey(t); + return g; + } + + // blocks from Rust: [{id, kind, texture, x, y, z, w, h, d}] and their textures by key + setBlocks(list, textures, replace) { + if (replace) { + for (const id of [...this.blocks.keys()]) this.dropBlock(id); + } + for (const [k, v] of Object.entries(textures || {})) this.abouts.set(k, v); + for (const b of list || []) { + const key = `${b.kind}:${b.texture}`; + const about = this.abouts.get(key) || {}; + const had = this.blocks.get(b.id); + if (had) { + had.b = b; + had.animTex = null; + had.mesh.material = this.blockMaterial(b); + this.shapeBlock(had); + continue; + } + const mesh = new THREE.Mesh(this.boxGeometry(b), this.blockMaterial(b)); + mesh.userData.block = b.id; + const o = { b, mesh, key, about }; + this.blocks.set(b.id, o); + this.shapeBlock(o); + this.scene.add(mesh); + } + if (this.selCopy) { this.copyO = this.copyBlock(this.selCopy); this.placeGizmo(); } + if (this.selCopy || this.openCopy) this.outlineCopy(); + this.render(); + } + + shapeBlock(o) { + const { b, mesh } = o; + // walking bumps into the blocks as they are now + this.blocksRev = (this.blocksRev || 0) + 1; + // a zone's place or size changed: its texts are looked at again (and come along) + if (b.zone || o.wasZone) { + this.zoneBlocks = null; + this.zonesDirty = true; + this.wake(1); + } + if (!!b.zone !== !!o.wasZone) mesh.material = this.blockMaterial(b); + o.wasZone = !!b.zone; + if (mesh.geometry.userData.shape !== shapeKey(b)) { + mesh.geometry.dispose(); + mesh.geometry = this.boxGeometry(b); + // a sphere has one face: one material, whatever faces the box had + mesh.material = this.blockMaterial(b); + } + mesh.position.set(b.x, b.y, b.z); + const r = b.rot || [0, 0, 0, 1]; + mesh.quaternion.set(r[0], r[1], r[2], r[3]); + if (!o.preview && !b.anim) mesh.scale.set(1, 1, 1); + this.bake(o); + if (this.selBlock === b.id) this.placeGizmo(); + this.wiresDirty = true; + } + + dropBlock(id) { + const o = this.blocks.get(id); + if (!o) return; + this.blocksRev = (this.blocksRev || 0) + 1; + this.stopSound(id); + if (o.b.zone) { + this.zoneBlocks = null; + this.zonesDirty = true; + this.wake(1); + } + this.scene.remove(o.mesh); + o.mesh.geometry.dispose(); + this.blocks.delete(id); + if (this.selBlock === id) this.pickBlock(null); + } + + blockOut(o) { + const { id, kind, texture, x, y, z, w, h, d, rot, bend, faces, variant, shape, zone, anim, part_of, sound } = o.b; + return { id, kind, texture, x, y, z, w, h, d, rot: rot || [0, 0, 0, 1], bend: bend || null, faces: faces || null, shape: shape || 'box', zone: zone || null, anim: anim || null, ...(variant != null ? { variant } : {}), ...(part_of ? { part_of } : {}), ...(sound ? { sound } : {}) }; + } + + pickBlock(id) { + // a part of a prefab's copy stands for its whole copy, unless that copy is open + const cid = id != null ? this.copyOf(id) : null; + if (cid && this.openCopy !== cid) return this.pickCopy(cid); + if (this.selCopy) this.pickCopy(null, true); + this.selBlock = id; + if (id != null) { + if (this.selected) this.pick(null); + this.placeGizmo(); + this.gizmo.visible = true; + } else { + this.gizmo.visible = false; + for (const k of this.gizmoKnobs) k.visible = false; + } + const o = id != null ? this.blocks.get(id) : null; + this.send({ ...this.ev('block', null), data: o ? { ...this.blockOut(o), about: o.about } : null }); + this.render(); + } + + // ------------------------------------------------------------------ copies as groups + // + // A placed prefab is one group: a click on any of its parts selects the whole copy (an + // outline round it, the gizmo at its origin), which moves, turns, copies and goes as a + // whole. A double click opens it: its parts are picked one by one (their changes kept + // as the copy's own values) until Esc or a click outside closes it again. + + copyOf(id) { + return typeof id === 'string' && id.startsWith('prefab:') && id.includes('/') ? id.slice(0, id.indexOf('/')) : null; + } + + setCopies(list) { + this.copyInfo = new Map((list || []).map((c) => [c.id, c])); + if (this.openCopy && !this.copyInfo.has(this.openCopy)) this.openCopy = null; + if (this.selCopy && !this.copyInfo.has(this.selCopy)) this.pickCopy(null); + else if (this.selCopy) { this.copyO = this.copyBlock(this.selCopy); this.placeGizmo(); } + this.outlineCopy(); + } + + partsOf(cid) { + return [...this.blocks.values()].filter((o) => this.copyOf(o.b.id) === cid); + } + + // the copy as the gizmo handles it: its origin and turn, and the parts' box + copyBlock(cid) { + const c = this.copyInfo && this.copyInfo.get(cid); + if (!c) return null; + const box = new THREE.Box3(); + for (const o of this.partsOf(cid)) box.expandByObject(o.mesh); + const size = box.isEmpty() ? new THREE.Vector3(1, 1, 1) : box.getSize(new THREE.Vector3()); + // the gizmo stands at the middle of its parts; the copy's own origin goes with it + const mid = box.isEmpty() ? new THREE.Vector3(c.x, c.y, c.z) : box.getCenter(new THREE.Vector3()); + return { + group: true, origin: new THREE.Vector3(c.x, c.y, c.z), + b: { id: cid, x: mid.x, y: mid.y, z: mid.z, rot: c.rot || [0, 0, 0, 1], w: size.x, h: size.y, d: size.z, scale: c.scale || 1 }, + name: c.name, + }; + } + + pickCopy(cid, quiet) { + this.selCopy = cid || null; + this.copyO = cid ? this.copyBlock(cid) : null; + if (cid) { + this.selBlock = null; + if (this.selected) this.pick(null); + } + this.outlineCopy(); + this.placeGizmo(); + if (!quiet) { + const o = this.copyO; + this.send({ ...this.ev('block', null), data: o ? { id: cid, copy: true, part_of: cid, name: o.name, x: o.b.x, y: o.b.y, z: o.b.z, rot: o.b.rot, scale: o.b.scale } : null }); + } + this.render(); + } + + // the outline round the selected copy, or round the open one (dashed) + outlineCopy() { + if (this.copyBox) { this.scene.remove(this.copyBox); this.copyBox.geometry.dispose(); this.copyBox = null; } + const cid = this.selCopy || this.openCopy; + if (!cid) return; + const box = new THREE.Box3(); + for (const o of this.partsOf(cid)) box.expandByObject(o.mesh); + if (box.isEmpty()) return; + box.expandByScalar(0.06); + const open = !this.selCopy && this.openCopy === cid; + const geo = new THREE.EdgesGeometry(new THREE.BoxGeometry(...box.getSize(new THREE.Vector3()).toArray())); + const mat = open + ? new THREE.LineDashedMaterial({ color: 0xe0a03f, dashSize: 0.2, gapSize: 0.12, fog: false, depthTest: false, transparent: true }) + : new THREE.LineBasicMaterial({ color: 0xe0a03f, fog: false, depthTest: false, transparent: true }); + const line = new THREE.LineSegments(geo, mat); + line.position.copy(box.getCenter(new THREE.Vector3())); + if (open) line.computeLineDistances(); + line.renderOrder = 998; + this.copyBox = line; + this.scene.add(line); + } + + // a copy Rust removed: its parts out of the room, kept for an undo + copyGone(ids, restore) { + this.record({ kind: 'copygone', restore }); + if (this.openCopy && (ids || []).some((i) => this.copyOf(i) === this.openCopy)) this.openCopy = null; + for (const id of ids || []) this.dropBlock(id); + if (this.selCopy) this.pickCopy(null); + this.outlineCopy(); + this.render(); + } + + // the copy opened from its menu: its first part selected + openCopyNamed(cid) { + const first = this.partsOf(cid)[0]; + return first ? this.openCopyAt(first.b.id) : false; + } + + // a double click on a part: its copy opens, the part selected + openCopyAt(id) { + const cid = this.copyOf(id); + if (!cid) return false; + this.openCopy = cid; + this.selCopy = null; + this.copyO = null; + this.pickBlock(id); + this.outlineCopy(); + this.send({ ...this.ev('copyopen', null), data: cid }); + return true; + } + + closeCopy() { + const cid = this.openCopy; + if (!cid) return false; + this.openCopy = null; + this.selBlock = null; + this.pickCopy(cid); + return true; + } + + // the parts follow the copy while it's dragged (Rust places them again when it ends) + moveCopyParts(d) { + const b = d.o.b; + const q0 = new THREE.Quaternion(...d.from.rot); + const q1 = new THREE.Quaternion(...b.rot); + const turn = q1.clone().multiply(q0.clone().invert()); + const p0 = new THREE.Vector3(d.from.x, d.from.y, d.from.z); + const p1 = new THREE.Vector3(b.x, b.y, b.z); + for (const s of d.parts) { + const rel = s.p.clone().sub(p0).applyQuaternion(turn); + s.o.mesh.position.copy(p1).add(rel); + s.o.mesh.quaternion.copy(turn.clone().multiply(s.q)); + } + this.outlineCopy(); + this.wiresDirty = true; + } + + // ------------------------------------------------------------------ the selection of many + // + // Shift+click adds an item to the selection or takes it out: a block, a prefab's copy, a + // text, or a light while the lights show. A box drawn on empty room selects what's in it + // (with Shift, adds to it). Selected, they're outlined (texts ringed); the gizmo at their + // middle moves and turns them all, Delete takes them all away, and Ctrl+Z takes either + // back in one step. Esc, or a click on empty room, lets them go. + + seedMulti() { + if (this.selCopy) this.multi.set(`c:${this.selCopy}`, { kind: 'c', id: this.selCopy }); + else if (this.selBlock != null) this.multi.set(`b:${this.selBlock}`, { kind: 'b', id: this.selBlock }); + if (this.selected) this.multi.set(`t:${this.selected.key}`, { kind: 't', id: this.selected.key }); + } + + toggleMulti(kind, id) { + this.selGroup = null; + // a thing in a group comes and goes with its whole group + const g = kind === 'b' || kind === 'c' ? this.outer(`${kind}:${id}`) : null; + if (g) { + if (!this.multi.size) this.seedMulti(); + const ls = this.leaves(g); + const all = ls.every((x) => this.multi.has(`${x.kind}:${x.id}`)); + for (const x of ls) { if (all) this.multi.delete(`${x.kind}:${x.id}`); else this.multi.set(`${x.kind}:${x.id}`, x); } + this.afterMulti(); + return; + } + if (!this.multi.size) this.seedMulti(); + const k = `${kind}:${id}`; + if (this.multi.has(k)) this.multi.delete(k); else this.multi.set(k, { kind, id }); + this.afterMulti(); + } + + setMulti(items, add) { + if (!add) this.multi.clear(); else if (!this.multi.size) this.seedMulti(); + for (const x of items) this.multi.set(`${x.kind}:${x.id}`, x); + this.afterMulti(); + } + + clearMulti() { + this.selGroup = null; + if (!this.multi.size) return false; + this.multi.clear(); + this.afterMulti(); + return true; + } + + itemThere(x) { + if (x.kind === 'b') return this.blocks.has(x.id); + if (x.kind === 'c') return !!(this.copyInfo && this.copyInfo.has(x.id)); + if (x.kind === 't') return this.nodes.has(x.id); + return this.lights.some((l) => l.id === x.id); + } + + // where an item is, in the room + itemAt(x) { + if (x.kind === 'b') return this.blocks.get(x.id).mesh.position.clone(); + if (x.kind === 'c') { + const box = new THREE.Box3(); + for (const o of this.partsOf(x.id)) box.expandByObject(o.mesh); + return box.isEmpty() ? new THREE.Vector3() : box.getCenter(new THREE.Vector3()); + } + if (x.kind === 't') return this.world(this.nodes.get(x.id)); + const l = this.lights.find((y) => y.id === x.id); + return new THREE.Vector3(l.x, l.y, l.z); + } + + afterMulti(quiet) { + for (const [k, x] of [...this.multi]) if (!this.itemThere(x)) this.multi.delete(k); + if (this.multi.size) { + // the one selected becomes one of many + if (this.selBlock != null || this.selCopy) { + this.selBlock = null; + this.selCopy = null; + this.copyO = null; + this.send({ ...this.ev('block', null), data: null }); + } + if (this.selected) { + this.selected.el.classList.remove('selected'); + this.selected = null; + this.send(this.ev('select', null)); + } + } + this.showMulti(); + this.multiO = this.multi.size ? this.multiBlock() : null; + this.outlineCopy(); + this.placeGizmo(); + if (!quiet) { + const n = { blocks: 0, copies: 0, texts: 0, lights: 0 }; + for (const x of this.multi.values()) n[{ b: 'blocks', c: 'copies', t: 'texts', l: 'lights' }[x.kind]]++; + const g = this.selGroup && this.groups.get(this.selGroup); + this.send({ ...this.ev('multi', null), data: { count: this.multi.size, ...n, group: g ? g.id : null, name: g ? g.name || '' : null } }); + } + this.render(); + } + + showMulti() { + for (const n of this.order) n.el.classList.toggle('multi', this.multi.has(`t:${n.key}`)); + if (this.multiLines) { + this.scene.remove(this.multiLines); + this.multiLines.traverse((x) => { x.geometry?.dispose(); x.material?.dispose(); }); + this.multiLines = null; + } + const g = new THREE.Group(); + for (const x of this.multi.values()) { + if (x.kind === 't') continue; + const box = new THREE.Box3(); + if (x.kind === 'b') box.expandByObject(this.blocks.get(x.id).mesh); + else if (x.kind === 'c') for (const o of this.partsOf(x.id)) box.expandByObject(o.mesh); + else box.setFromCenterAndSize(this.itemAt(x), new THREE.Vector3(0.5, 0.5, 0.5)); + if (box.isEmpty()) continue; + box.expandByScalar(0.05); + const line = new THREE.LineSegments( + new THREE.EdgesGeometry(new THREE.BoxGeometry(...box.getSize(new THREE.Vector3()).toArray())), + new THREE.LineBasicMaterial({ color: 0x3f8cff, fog: false, depthTest: false, transparent: true }), + ); + line.position.copy(box.getCenter(new THREE.Vector3())); + line.renderOrder = 997; + g.add(line); + } + this.multiLines = g; + this.scene.add(g); + } + + // the many as the gizmo handles them: their middle + multiBlock() { + const c = new THREE.Vector3(); + for (const x of this.multi.values()) c.add(this.itemAt(x)); + c.divideScalar(Math.max(1, this.multi.size)); + return { group: true, multi: true, b: { id: 'many', x: c.x, y: c.y, z: c.z, rot: [0, 0, 0, 1], w: 1, h: 1, d: 1 } }; + } + + // each item where it was when a drag began + multiStart() { + const out = []; + for (const x of this.multi.values()) { + if (x.kind === 'b') { + const o = this.blocks.get(x.id); + out.push({ x, o, from: { ...o.b, rot: [...(o.b.rot || [0, 0, 0, 1])] }, p: o.mesh.position.clone(), q: o.mesh.quaternion.clone() }); + } else if (x.kind === 'c') { + const c = this.copyInfo.get(x.id); + out.push({ x, origin: new THREE.Vector3(c.x, c.y, c.z), rot: c.rot || [0, 0, 0, 1], parts: this.partsOf(x.id).map((o) => ({ o, p: o.mesh.position.clone(), q: o.mesh.quaternion.clone() })) }); + } else if (x.kind === 't') { + const n = this.nodes.get(x.id); + out.push({ x, n, p: this.world(n), from: { x: n.x, y: n.y, z: n.z, pinned: n.pinned } }); + } else { + const l = this.lights.find((y) => y.id === x.id); + out.push({ x, l, p: new THREE.Vector3(l.x, l.y, l.z), from: { x: l.x, y: l.y, z: l.z } }); + } + } + return out; + } + + // the many follow the gizmo: moved, and turned about their middle + moveMulti(d) { + const b = d.o.b; + const turn = new THREE.Quaternion(...b.rot).multiply(new THREE.Quaternion(...d.from.rot).invert()); + const p0 = new THREE.Vector3(d.from.x, d.from.y, d.from.z); + const p1 = new THREE.Vector3(b.x, b.y, b.z); + const to = (p) => p.clone().sub(p0).applyQuaternion(turn).add(p1); + for (const s of d.items) { + if (s.x.kind === 'b') { + s.o.mesh.position.copy(to(s.p)); + s.o.mesh.quaternion.copy(turn.clone().multiply(s.q)); + } else if (s.x.kind === 'c') { + for (const pt of s.parts) { + pt.o.mesh.position.copy(to(pt.p)); + pt.o.mesh.quaternion.copy(turn.clone().multiply(pt.q)); + } + } else if (s.x.kind === 't') { + s.n.pinned = true; + s.n.el.classList.add('pinned'); + this.local(to(s.p), s.n); + } else { + const w = to(s.p); + Object.assign(s.l, { x: w.x, y: w.y, z: w.z }); + } + } + if (d.items.some((s) => s.x.kind === 'l')) this.markLights(); + this.wiresDirty = true; + this.showMulti(); + this.wake(0.3); + } + + // a drag of many ended: each kept where it went, one step to undo + endMulti(d) { + const b = d.o.b; + const turn = new THREE.Quaternion(...b.rot).multiply(new THREE.Quaternion(...d.from.rot).invert()); + const p0 = new THREE.Vector3(d.from.x, d.from.y, d.from.z); + const p1 = new THREE.Vector3(b.x, b.y, b.z); + const r = (v) => +v.toFixed(4); + this.setBatch(true); + for (const s of d.items) { + if (s.x.kind === 'b') { + const o = s.o; + this.record({ kind: 'block', id: o.b.id, t: s.from }); + const q = o.mesh.quaternion; + Object.assign(o.b, { x: r(o.mesh.position.x), y: r(o.mesh.position.y), z: r(o.mesh.position.z), rot: [q.x, q.y, q.z, q.w] }); + this.shapeBlock(o); + this.send({ ...this.ev('blockset', null), data: this.blockOut(o) }); + } else if (s.x.kind === 'c') { + const o1 = s.origin.clone().sub(p0).applyQuaternion(turn).add(p1); + const rot = turn.clone().multiply(new THREE.Quaternion(...s.rot)); + this.record({ kind: 'copy', id: s.x.id, t: { x: s.origin.x, y: s.origin.y, z: s.origin.z, rot: s.rot } }); + this.send({ ...this.ev('copyset', null), data: { id: s.x.id, x: r(o1.x), y: r(o1.y), z: r(o1.z), rot: [rot.x, rot.y, rot.z, rot.w] } }); + } else if (s.x.kind === 't') { + this.record({ kind: 'move', n: s.n, ...s.from }); + this.send(this.ev('moved', s.n)); + } else { + this.record({ kind: 'light', id: s.l.id, t: s.from }); + this.send({ ...this.ev('lightset', null), data: { id: s.l.id, x: r(s.l.x), y: r(s.l.y), z: r(s.l.z) } }); + } + } + this.setBatch(false); + this.afterMulti(true); + } + + // Delete with many selected: texts out of the room and blocks deleted here, the rest + // (copies, lights) by Rust, which closes the undo step when it's done + removeMulti() { + if (!this.multi.size) return null; + const items = [...this.multi.values()]; + this.multi.clear(); + this.setBatch(true); + const blocks = items.filter((x) => x.kind === 'b').map((x) => x.id); + for (const x of items.filter((y) => y.kind === 't')) this.removeNode(x.id); + if (blocks.length) { + this.unblock(blocks); + this.send({ ...this.ev('blockgone', null), data: blocks }); + } + const lights = items.filter((x) => x.kind === 'l').map((x) => this.lights.find((l) => l.id === x.id)).filter(Boolean); + for (const l of lights) this.record({ kind: 'lightgone', light: { ...l } }); + const copies = items.filter((x) => x.kind === 'c').map((x) => x.id); + const rest = { copies, lights: lights.map((l) => l.id) }; + if (!copies.length) this.setBatch(false); + this.afterMulti(); + return { count: items.length, ...rest }; + } + + drawBox(e) { + const b = this.boxSel; + if (!b.el && Math.hypot(e.clientX - b.x0, e.clientY - b.y0) < 5) return; + if (!b.el) { + b.el = document.createElement('div'); + b.el.className = 'selbox'; + document.body.append(b.el); + } + const x = Math.min(b.x0, e.clientX), y = Math.min(b.y0, e.clientY); + Object.assign(b.el.style, { left: `${x}px`, top: `${y}px`, width: `${Math.abs(e.clientX - b.x0)}px`, height: `${Math.abs(e.clientY - b.y0)}px` }); + } + + endBox(e) { + const b = this.boxSel; + this.boxSel = null; + if (!b.el) { + // a click on empty room: everything let go; a double click makes a text + if (this.openCopy) { this.openCopy = null; this.outlineCopy(); } + if (this.selCopy) this.pickCopy(null); + if (this.selBlock != null) this.pickBlock(null); + this.clearMulti(); + const now = performance.now(); + if (this.lastEmpty && now - this.lastEmpty < 450) { + this.lastEmpty = 0; + this.send(this.ev('newtext', null, b.e)); + } else this.lastEmpty = now; + if (this.selected) this.pick(null); + return; + } + const r = b.el.getBoundingClientRect(); + b.el.remove(); + const inside = (v) => { + const p = v.clone().project(this.camera); + if (p.z > 1 || p.z < -1) return false; + const host = this.host.getBoundingClientRect(); + const sx = host.left + (p.x + 1) / 2 * host.width, sy = host.top + (1 - p.y) / 2 * host.height; + return sx >= r.left && sx <= r.right && sy >= r.top && sy <= r.bottom; + }; + const items = []; + for (const n of this.order) { + if (n.el.style.display === 'none' || n.head) continue; + const er = n.el.getBoundingClientRect(); + const cx = er.left + er.width / 2, cy = er.top + er.height / 2; + if (cx >= r.left && cx <= r.right && cy >= r.top && cy <= r.bottom) items.push({ kind: 't', id: n.key }); + } + const seen = new Set(); + for (const o of this.blocks.values()) { + const c = this.copyOf(o.b.id); + if (c && this.openCopy !== c) { + if (seen.has(c)) continue; + seen.add(c); + if (inside(this.itemAt({ kind: 'c', id: c }))) items.push({ kind: 'c', id: c }); + } else if (inside(o.mesh.position)) items.push({ kind: 'b', id: o.b.id }); + } + if (this.lightsShown) for (const l of this.lights) if ((l.kind === 'point' || l.kind === 'spot') && inside(new THREE.Vector3(l.x, l.y, l.z))) items.push({ kind: 'l', id: l.id }); + if (!b.add && this.selCopy) this.pickCopy(null); + if (!b.add && this.selBlock != null) this.pickBlock(null); + this.setMulti(items, b.add); + } + + // ------------------------------------------------------------------ groups + // + // A group (Ctrl+G on what's selected) is picked as one: a click on any of its things + // selects all of it, and it moves, turns, copies and becomes a prefab as one. Groups + // nest. A double click opens a group to pick inside it; Esc closes it again. + + setGroups(list) { + this.groups = new Map((list || []).map((g) => [g.id, g])); + this.parent = new Map(); + for (const g of this.groups.values()) for (const m of g.members) this.parent.set(`${m.kind}:${m.id}`, g.id); + this.openGroups = this.openGroups.filter((id) => this.groups.has(id)); + if (this.selGroup && !this.groups.has(this.selGroup)) this.selGroup = null; + } + + // the outermost closed group a thing is in (an open group lets its things be picked) + outer(key) { + let g = this.parent.get(key), top = null; + while (g && !this.openGroups.includes(g)) { + top = g; + g = this.parent.get(`g:${g}`); + } + return top; + } + + leaves(gid, out = []) { + const g = this.groups.get(gid); + for (const m of (g && g.members) || []) { + if (m.kind === 'g') this.leaves(m.id, out); + else out.push({ kind: m.kind, id: m.id }); + } + return out; + } + + pickGroup(gid, add) { + this.setMulti(this.leaves(gid), add); + this.selGroup = add ? null : gid; + this.afterMulti(); + } + + // what Ctrl+G groups: the things selected, each as its outermost group + groupMembers() { + const out = new Map(); + for (const x of this.multi.values()) { + if (x.kind !== 'b' && x.kind !== 'c') continue; + const g = this.outer(`${x.kind}:${x.id}`); + const m = g ? { kind: 'g', id: g } : { kind: x.kind, id: x.id }; + out.set(`${m.kind}:${m.id}`, m); + } + return [...out.values()]; + } + + openGroupAt(key) { + const g = this.outer(key); + if (!g) return false; + this.openGroups.push(g); + this.clearMulti(); + this.send({ ...this.ev('groupopen', null), data: g }); + return true; + } + + // where a new block goes: ahead of the camera, or at the selected text + blockSpot() { + let at; + if (this.selected) at = this.world(this.selected); + else at = new THREE.Vector3(0, 0, -8).applyQuaternion(this.camera.quaternion).add(this.camera.position); + return { x: +at.x.toFixed(2), y: +at.y.toFixed(2), z: +at.z.toFixed(2) }; + } + + makeGizmo() { + const g = new THREE.Group(); + const axes = [new THREE.Vector3(1, 0, 0), new THREE.Vector3(0, 1, 0), new THREE.Vector3(0, 0, 1)]; + const colours = [0xd0453a, 0x3f9b4b, 0x3a6fd0]; + const mat = (c) => new THREE.MeshBasicMaterial({ color: c, fog: false, depthTest: false, depthWrite: false, transparent: true, opacity: 0.95 }); + const up = new THREE.Vector3(0, 1, 0); + this.gizmoKnobs = []; + axes.forEach((a, i) => { + const q = new THREE.Quaternion().setFromUnitVectors(up, a); + const shaft = new THREE.Mesh(new THREE.CylinderGeometry(0.025, 0.025, 0.8, 8), mat(colours[i])); + shaft.position.copy(a.clone().multiplyScalar(0.4)); + shaft.quaternion.copy(q); + const tip = new THREE.Mesh(new THREE.ConeGeometry(0.08, 0.22, 14), mat(colours[i])); + tip.position.copy(a.clone().multiplyScalar(0.9)); + tip.quaternion.copy(q); + // a fatter invisible grip, easier to hit + const grip = new THREE.Mesh(new THREE.CylinderGeometry(0.1, 0.1, 1.05, 8), new THREE.MeshBasicMaterial({ visible: false })); + grip.position.copy(a.clone().multiplyScalar(0.52)); + grip.quaternion.copy(q); + for (const m of [shaft, tip, grip]) { m.userData.handle = { mode: 'move', axis: i }; m.renderOrder = 1000; g.add(m); } + const knob = new THREE.Mesh(new THREE.BoxGeometry(0.16, 0.16, 0.16), mat(colours[i])); + knob.userData.handle = { mode: 'scale', axis: i }; + knob.renderOrder = 1001; + this.gizmoKnobs.push(knob); + this.scene.add(knob); + }); + // the rotation rings: one about each axis, dragged around the block's centre + const flat = new THREE.Vector3(0, 0, 1); + axes.forEach((a, i) => { + const q = new THREE.Quaternion().setFromUnitVectors(flat, a); + const ring = new THREE.Mesh(new THREE.TorusGeometry(1.25, 0.018, 8, 72), mat(colours[i])); + ring.material.opacity = 0.75; + ring.quaternion.copy(q); + const grip = new THREE.Mesh(new THREE.TorusGeometry(1.25, 0.09, 6, 48), new THREE.MeshBasicMaterial({ visible: false })); + grip.quaternion.copy(q); + for (const m of [ring, grip]) { m.userData.handle = { mode: 'rotate', axis: i }; m.renderOrder = 999; g.add(m); } + }); + const ball = new THREE.Mesh(new THREE.SphereGeometry(0.1, 16, 12), mat(0xf0e6d0)); + ball.userData.handle = { mode: 'plane', axis: -1 }; + ball.renderOrder = 1002; + g.add(ball); + g.visible = false; + for (const k of this.gizmoKnobs) k.visible = false; + this.scene.add(g); + return g; + } + + // the gizmo at the selected block, the same size on screen wherever it is + placeGizmo() { + const o = this.multi.size ? this.multiO : this.selCopy ? this.copyO : this.blocks.get(this.selBlock); + const on = !!o; + this.gizmo.visible = on; + // a copy is moved and turned as a whole; its size is the prefabs window's + for (const k of this.gizmoKnobs) k.visible = on && !o.group; + if (!o) return; + const b = o.b; + const c = new THREE.Vector3(b.x, b.y, b.z); + const s = Math.max(0.05, c.distanceTo(this.camera.position) * 0.11); + this.gizmo.position.copy(c); + this.gizmo.scale.setScalar(s); + const half = [b.w / 2, b.h / 2, b.d / 2]; + const q = turnOf(b); + this.gizmoKnobs.forEach((k, i) => { + // on the block's own faces, turned with it + k.position.copy(c).add(localAxis(i).applyQuaternion(q).multiplyScalar(half[i])); + k.quaternion.copy(q); + k.scale.setScalar(s); + }); + } + + rayFrom(e) { + const r = this.host.getBoundingClientRect(); + // with the pointer locked (walking, superflight) it's where you look + const ndc = document.pointerLockElement === this.host || !e ? new THREE.Vector2(0, 0) : new THREE.Vector2(((e.clientX - r.left) / r.width) * 2 - 1, -((e.clientY - r.top) / r.height) * 2 + 1); + this.ray.setFromCamera(ndc, this.camera); + return this.ray; + } + + // the gizmo handle or block under the pointer + blockHit(e) { + const ray = this.rayFrom(e); + if ((this.selBlock != null || this.selCopy || this.multi.size) && this.gizmo.visible) { + // the middle ball first, then the arrows and knobs, then the rings (a ring seen + // edge-on crosses the middle) + const hs = ray.intersectObjects([...this.gizmo.children, ...this.gizmoKnobs], false).filter((x) => x.object.visible !== false || x.object.userData.handle); + const rank = { plane: 0, move: 1, scale: 2, rotate: 3 }; + hs.sort((a, b) => rank[a.object.userData.handle.mode] - rank[b.object.userData.handle.mode] || a.distance - b.distance); + if (hs[0]) return { handle: hs[0].object.userData.handle }; + } + const meshes = [...this.blocks.values()].map((o) => o.mesh); + const h = ray.intersectObjects(meshes, false)[0]; + return h ? { block: h.object.userData.block, point: h.point } : null; + } + + // pixels on screen per unit along a world axis at a point + screenAxis(at, axis, along) { + const a = along || localAxis(axis); + return this.toPx(at.clone().add(a)).sub(this.toPx(at)); + } + + toPx(v) { + const p = v.clone().project(this.camera); + return new THREE.Vector2((p.x * 0.5 + 0.5) * this.size.w, (-p.y * 0.5 + 0.5) * this.size.h); + } + + startBlockDrag(e, hit) { + const o = this.multi.size ? this.multiO : this.selCopy ? this.copyO : this.blocks.get(this.selBlock); + if (!o) return false; + if (o.group && hit.handle && hit.handle.mode === 'scale') return false; + // many move only by the gizmo + if (o.multi && !hit.handle) return false; + const b = o.b; + const at = new THREE.Vector3(b.x, b.y, b.z); + const fwd = new THREE.Vector3(0, 0, -1).applyQuaternion(this.camera.quaternion); + const depth = at.clone().sub(this.camera.position).dot(fwd); + const mode = hit.handle ? hit.handle.mode : 'plane', axis = hit.handle ? hit.handle.axis : -1; + // a side's knob pulls along the block's own (turned) axis + const along = mode === 'scale' ? localAxis(axis).applyQuaternion(turnOf(b)) : null; + const c = this.toPx(at); + this.bdrag = { + o, mode, axis, along, + x0: e.clientX, y0: e.clientY, from: { ...b, rot: [...(b.rot || [0, 0, 0, 1])] }, depth, moved: false, + sdir: axis >= 0 && mode !== 'rotate' ? this.screenAxis(at, axis, along) : null, + off: at.clone().sub(this.rayAt(e.clientX, e.clientY, depth)), + centre: c, a0: Math.atan2(e.clientY - c.y, e.clientX - c.x), + // turning about an axis that points at the viewer turns the other way on screen + toward: localAxis(Math.max(0, axis)).dot(this.camera.position.clone().sub(at)) > 0, + // a copy's parts, where they were + parts: o.group && !o.multi ? this.partsOf(b.id).map((p) => ({ o: p, p: p.mesh.position.clone(), q: p.mesh.quaternion.clone() })) : null, + items: o.multi ? this.multiStart() : null, + }; + try { this.host.setPointerCapture(e.pointerId); } catch { /* fine without */ } + return true; + } + + dragBlock(e) { + const d = this.bdrag; + if (!d) return; + if (!d.moved && Math.hypot(e.clientX - d.x0, e.clientY - d.y0) < 3) return; + d.moved = true; + const snap = (v) => (e.shiftKey ? Math.round(v * 4) / 4 : v); + const b = d.o.b; + const f = d.from; + const keys = ['x', 'y', 'z']; + const sides = ['w', 'h', 'd']; + if (d.mode === 'plane') { + const w = this.rayAt(e.clientX, e.clientY, d.depth).add(d.off); + b.x = snap(w.x); b.y = snap(w.y); b.z = snap(w.z); + } else if (d.mode === 'rotate') { + let ang = Math.atan2(e.clientY - d.centre.y, e.clientX - d.centre.x) - d.a0; + if (d.toward) ang = -ang; + // Shift: steps of 15° + if (e.shiftKey) ang = Math.round(ang / (Math.PI / 12)) * (Math.PI / 12); + const q = new THREE.Quaternion().setFromAxisAngle(localAxis(d.axis), ang).multiply(turnOf(d.from)).normalize(); + b.rot = [q.x, q.y, q.z, q.w]; + } else { + const m = new THREE.Vector2(e.clientX - d.x0, e.clientY - d.y0); + const len2 = Math.max(1e-6, d.sdir.lengthSq()); + const units = m.dot(d.sdir) / len2; + const k = keys[d.axis]; + if (d.mode === 'move') b[k] = snap(f[k] + units); + else { + const s = sides[d.axis]; + const size = Math.max(0.05, snap(f[s] + units)); + b[s] = size; + // the opposite face stays put, along the block's own axis + const shift = (size - f[s]) / 2; + b.x = f.x + d.along.x * shift; b.y = f.y + d.along.y * shift; b.z = f.z + d.along.z * shift; + } + } + if (d.o.multi) { + this.moveMulti(d); + this.placeGizmo(); + } else if (d.o.group) { + this.moveCopyParts(d); + this.placeGizmo(); + } else this.shapeBlock(d.o); + this.render(); + } + + endBlockDrag() { + const d = this.bdrag; + this.bdrag = null; + if (!d || !d.moved) return; + if (d.o.multi) { + this.endMulti(d); + return; + } + if (d.o.group) { + // the copy's origin, carried as the middle was + const b = d.o.b; + const o0 = d.o.origin; + const turn = new THREE.Quaternion(...b.rot).multiply(new THREE.Quaternion(...d.from.rot).invert()); + const o1 = o0.clone().sub(new THREE.Vector3(d.from.x, d.from.y, d.from.z)).applyQuaternion(turn).add(new THREE.Vector3(b.x, b.y, b.z)); + const r = (v) => +v.toFixed(4); + this.record({ kind: 'copy', id: b.id, t: { x: o0.x, y: o0.y, z: o0.z, rot: d.from.rot } }); + this.send({ ...this.ev('copyset', null), data: { id: b.id, x: r(o1.x), y: r(o1.y), z: r(o1.z), rot: b.rot } }); + return; + } + this.record({ kind: 'block', id: d.o.b.id, t: d.from }); + this.send({ ...this.ev('blockset', null), data: this.blockOut(d.o) }); + this.pickBlock(d.o.b.id); + } + + // blocks Rust deleted: out of the room, kept for an undo + unblock(ids) { + const items = ids.map((id) => this.blocks.get(id)).filter(Boolean).map((o) => ({ b: this.blockOut(o), key: o.key, about: o.about })); + if (!items.length) return; + this.record({ kind: 'unblock', items }); + for (const id of ids) this.dropBlock(id); + this.render(); + } + + // a change from the window's fields + setBlockFields(id, t) { + const o = this.blocks.get(id); + if (!o) return; + this.record({ kind: 'block', id, t: { ...o.b } }); + Object.assign(o.b, t); + this.shapeBlock(o); + this.send({ ...this.ev('blockset', null), data: this.blockOut(o) }); + this.render(); + } + + // ------------------------------------------------------------------ input + + // the placements of one entry in the room (a copy is another placement of the same + // entry, never another entry) + placements(entry) { + return this.order.filter((x) => !x.free && !x.head && String(x.f.key) === String(entry)); + } + + ev(kind, n, e, extra) { + const same = n && !n.free ? this.placements(n.f.key) : []; + return { + kind, key: n ? (n.free ? n.key : String(n.f.key)) : '', node: n ? n.key : '', + copies: same.length, primary: !!(n && !n.free && same[0] === n), text: n ? (n.own != null ? n.own : n.f.text) : '', note: !!(n && n.f.note), free: !!(n && n.free), + det: n ? n.det || 0 : 0, + chain: n ? (n.head ? String(n.head.f.key) : n.f.isChain ? String(n.f.key) : '') : '', idx: n && n.head ? n.idx : -1, + members: n && n.links ? n.links.length : 0, virt: !!(n && n.f.virt), head_node: n && n.head ? n.head.key : '', font: n && n.size ? Math.round(n.size * 50) : 0, font_default: Math.round(this.p.size * 50), own: n ? n.own : null, entry_text: n ? n.f.text : '', + x: e ? e.clientX : 0, y: e ? e.clientY : 0, ctrl: !!(e && (e.ctrlKey || e.metaKey)), shift: !!(e && e.shiftKey), alt: !!(e && e.altKey), + q: n ? n.f.q || 0 : 0, hue: n ? n.f.hue || 0 : 0, pinned: !!(n && n.pinned), data: extra || '', + }; + } + + wire(n) { + const { el } = n; + el.addEventListener('pointerenter', (e) => { + if (this.looking || this.drag) return; + this.hover = n; + el.classList.add('hover'); + this.send(this.ev('hover', n, e)); + }); + el.addEventListener('pointerleave', () => { + el.classList.remove('hover'); + if (this.hover === n) this.hover = null; + }); + el.addEventListener('pointerdown', (e) => { + if (e.button !== 0) return; + e.preventDefault(); + e.stopPropagation(); + // Shift+click: one of many, in or out + // (Ctrl+Shift+click makes it the list, as a click goes) + if (e.shiftKey && !e.ctrlKey && !e.metaKey) { this.toggleMulti('t', n.key); return; } + if (this.multi.size) this.clearMulti(); + try { el.setPointerCapture(e.pointerId); } catch { /* fine without */ } + // a chain's member drags its head (the chain comes along) + const t = n.head || n; + const w = this.world(t); + const fwd = new THREE.Vector3(0, 0, -1).applyQuaternion(this.camera.quaternion); + this.drag = { n: t, el: n, x0: e.clientX, y0: e.clientY, moved: false, depth: this.world(n).sub(this.camera.position).dot(fwd), from: { x: t.x, y: t.y, z: t.z, pinned: t.pinned }, off: null }; + // where the pointer is on the text, so it doesn't jump to its centre + const hit = this.rayAt(e.clientX, e.clientY, this.drag.depth); + this.drag.off = w.clone().sub(hit); + }); + el.addEventListener('pointermove', (e) => { + const d = this.drag; + if (!d || d.el !== n) return; + if (!d.moved && Math.hypot(e.clientX - d.x0, e.clientY - d.y0) < 4) return; + d.moved = true; + const t = d.n; + t.pinned = true; + t.el.classList.add('pinned', 'dragging'); + const w = this.rayAt(e.clientX, e.clientY, d.depth).add(d.off); + this.local(w, t); + this.wake(0.3); + }); + const up = (e) => { + const d = this.drag; + if (!d || d.el !== n) return; + this.drag = null; + d.n.el.classList.remove('dragging'); + if (d.moved) { + // dropped into a zone (or out of one) + d.n.zone = this.zoneOf(d.n, this.zoneFrames()); + this.sim = null; + this.record({ kind: 'move', n: d.n, ...d.from }); + this.send(this.ev('moved', d.n, e)); + } else { + this.pick(n); + const now = performance.now(); + if (this.lastClick && this.lastClick.n === n && now - this.lastClick.t < 450) { + this.lastClick = null; + this.send(this.ev('dblclick', n, e)); + } else { + this.lastClick = { n, t: now }; + this.send(this.ev('click', n, e)); + } + } + }; + el.addEventListener('pointerup', up); + el.addEventListener('lostpointercapture', up); + el.addEventListener('contextmenu', (e) => { + e.preventDefault(); + e.stopPropagation(); + this.send(this.ev('menu', n, e)); + }); + el.addEventListener('wheel', (e) => { + e.preventDefault(); + e.stopPropagation(); + // push away or pull near, along the line from the eye + const k = Math.exp(-(e.deltaMode === 1 ? e.deltaY * 33 : e.deltaY) * 0.0015); + const w = this.world(n); + const from = w.clone().sub(this.camera.position); + const len = Math.min(2000, Math.max(0.3, from.length() * k)); + const now = performance.now(); + if (!(this.wheelUndo && this.wheelUndo.n === n && now - this.wheelUndo.t < 800)) this.record({ kind: 'move', n, x: n.x, y: n.y, z: n.z, pinned: n.pinned }); + this.wheelUndo = { n, t: now }; + this.local(this.camera.position.clone().add(from.setLength(len)), n); + n.pinned = true; + n.el.classList.add('pinned'); + this.wake(0.3); + }, { passive: false }); + } + + // the point under the pointer at a depth in front of the camera + rayAt(cx, cy, depth) { + const r = this.host.getBoundingClientRect(); + const ndc = new THREE.Vector3(((cx - r.left) / r.width) * 2 - 1, -((cy - r.top) / r.height) * 2 + 1, 0.5); + const dir = ndc.unproject(this.camera).sub(this.camera.position).normalize(); + const fwd = new THREE.Vector3(0, 0, -1).applyQuaternion(this.camera.quaternion); + const t = depth / Math.max(1e-4, dir.dot(fwd)); + return this.camera.position.clone().add(dir.multiplyScalar(t)); + } + + applyTurn() { + this.camera.quaternion.setFromEuler(new THREE.Euler(this.pitch, this.yaw, this.rollA, 'YXZ')); + } + + // yaw, pitch and roll from where an ease left the camera + syncTurn() { + const e = new THREE.Euler().setFromQuaternion(this.camera.quaternion, 'YXZ'); + this.yaw = this.tyaw = e.y; + this.pitch = this.tpitch = Math.max(-1.55, Math.min(1.55, e.x)); + this.rollA = e.z; + this.applyTurn(); + } + + home() { + this.camera.position.set(0, 0, 0); + this.yaw = this.tyaw = this.pitch = this.tpitch = this.rollA = 0; + this.ease = null; + this.applyTurn(); + this.render(); + } + + level() { + this.rollA = 0; + this.applyTurn(); + this.render(); + } + + roll() { + return (this.rollA * 180) / Math.PI; + } + + // the arrow keys: the nearest text in that direction on screen, eased onto + hop(dir) { + const cam = this.camera; + cam.updateMatrixWorld(); + let best = null; + let bestScore = Infinity; + const want = { ArrowLeft: [-1, 0], ArrowRight: [1, 0], ArrowUp: [0, 1], ArrowDown: [0, -1] }[dir]; + const w = new THREE.Vector3(); + for (const n of this.order) { + const local = this.world(n, w).applyMatrix4(cam.matrixWorldInverse); + const dist = local.length(); + if (dist < 0.5) continue; + const sx = local.x / dist; + const sy = local.y / dist; + const along = sx * want[0] + sy * want[1]; + if (along <= 0.02) continue; + const across = Math.abs(sx * want[1] - sy * want[0]); + const score = (Math.acos(Math.min(1, along)) + across * 2) * 10 + dist * 0.05 + (local.z > 0 ? 50 : 0); + if (score < bestScore) { + bestScore = score; + best = n; + } + } + if (!best) return; + const target = this.world(best); + const fwd = target.clone().sub(cam.position).normalize(); + const stand = Math.max(4, Math.min(14, best.f.text.length * 0.35)); + const toPos = target.clone().sub(fwd.clone().multiplyScalar(stand)); + const look = new THREE.Object3D(); + look.position.copy(toPos); + look.up.copy(new THREE.Vector3(0, 1, 0).applyQuaternion(cam.quaternion)); + look.lookAt(target); + // a camera looks down -z, an Object3D's lookAt points +z: turn it round + look.rotateY(Math.PI); + this.ease = { fromPos: cam.position.clone(), toPos, fromQuat: cam.quaternion.clone(), toQuat: look.quaternion.clone(), t: 0 }; + this.pick(best); + this.send(this.ev('focus', best)); + } + + listen() { + const h = this.host; + h.addEventListener('contextmenu', (e) => e.preventDefault()); + // a double click on a prefab copy's part opens the copy to edit its parts + h.addEventListener('dblclick', (e) => { + if (e.target.closest('.slabel') || !this.blocks.size) return; + // the block itself, not the gizmo over it + const m = this.rayFrom(e).intersectObjects([...this.blocks.values()].map((o) => o.mesh), false)[0]; + const id = m && m.object.userData.block; + if (id == null) return; + const c = this.copyOf(id); + if (this.outer(c && this.openCopy !== c ? `c:${c}` : `b:${id}`) && this.openGroupAt(c && this.openCopy !== c ? `c:${c}` : `b:${id}`)) return; + if (c && this.openCopy !== c) this.openCopyAt(id); + }); + h.addEventListener('pointerdown', (e) => { + if (e.target.closest('.slabel')) return; + // placing a prefab: a click places it, a right click stops + if (this.ghost && (e.button === 0 || e.button === 2)) { + e.preventDefault(); + if (e.button === 0) this.placeGhost(); else { this.stopGhost(); this.send({ ...this.ev('ghostdone', null) }); } + return; + } + // wiring: a drag from a block to another makes a wire + if (e.button === 0 && this.wiring && !this.live) { + if (this.startWire(e)) { e.preventDefault(); return; } + } + if (e.button === 0) { + // a block's gizmo, or a block: select it (and drag it in the view's plane) + // playing, a click on a block listening for clicks fires it (through the gizmo) + if (this.live && this.wires && this.wires.size) { + const m = this.rayFrom(e).intersectObjects([...this.blocks.values()].map((o) => o.mesh), false)[0]; + const id = m && m.object.userData.block; + const w = id != null && this.wires.get(id); + if (w && (w.on || []).includes('click')) { + this.wireFire(id, 'click'); + return; + } + } + // a light's marker (while the lights show): picked, or with Shift one of many + if (this.lightMarks) { + const m = this.rayFrom(e).intersectObjects(this.lightMarks.children.filter((x) => x.userData.light != null), false)[0]; + if (m) { + const id = m.object.userData.light; + if (e.shiftKey) this.toggleMulti('l', id); + else { this.clearMulti(); this.send({ ...this.ev('lightpick', null), data: id }); } + return; + } + } + const hit = this.blocks.size ? this.blockHit(e) : null; + // Shift+click on a block or a copy (the block itself, not the gizmo over it): one + // of many, in or out + if (e.shiftKey && this.blocks.size) { + const m = this.rayFrom(e).intersectObjects([...this.blocks.values()].map((o) => o.mesh), false)[0]; + const sid = m && m.object.userData.block; + if (sid != null) { + const c = this.copyOf(sid); + if (c && this.openCopy !== c) this.toggleMulti('c', c); else this.toggleMulti('b', sid); + return; + } + } + // a thing in a group: the whole group, dragged by any of it + if (hit && hit.block != null) { + const c = this.copyOf(hit.block); + const key = c && this.openCopy !== c ? `c:${c}` : `b:${hit.block}`; + const g = this.outer(key); + if (g) { + if (this.selGroup !== g) this.pickGroup(g); + this.startBlockDrag(e, { handle: { mode: 'plane', axis: -1 } }); + return; + } + } + if (hit && hit.block != null && this.multi.size) this.clearMulti(); + if (hit) { + // a click outside the open copy closes it + if (this.openCopy && hit.block != null && this.copyOf(hit.block) !== this.openCopy) this.openCopy = null; + const cid = hit.block != null ? this.copyOf(hit.block) : null; + if (cid && this.openCopy !== cid) { + if (this.selCopy !== cid) this.pickCopy(cid); + } else if (hit.block != null && hit.block !== this.selBlock) this.pickBlock(hit.block); + this.startBlockDrag(e, hit); + return; + } + // empty room: a drag draws a box to select what's in it; a click lets go + this.boxSel = { x0: e.clientX, y0: e.clientY, add: e.shiftKey, el: null, e }; + try { h.setPointerCapture(e.pointerId); } catch { /* fine without */ } + return; + } + if (e.button !== 2) return; + e.preventDefault(); + this.rdown = { x: e.clientX, y: e.clientY }; + this.looking = true; + if (this.ease) { this.ease = null; this.syncTurn(); } + h.classList.add('looking'); + try { h.setPointerCapture(e.pointerId); } catch { /* fine without */ } + }); + // the pointer locked (walking, superflight): the mouse looks around + document.addEventListener('mousemove', (e) => { + if (document.pointerLockElement !== h) return; + const k = LOOK * (this.p.look || 1); + this.tyaw -= (e.movementX || 0) * k; + this.tpitch = Math.max(-1.55, Math.min(1.55, this.tpitch - (e.movementY || 0) * k)); + }); + h.addEventListener('pointermove', (e) => { + this.pointer = { clientX: e.clientX, clientY: e.clientY }; + if (this.ghost) this.dirty = true; + if (this.bdrag) { this.dragBlock(e); return; } + if (this.boxSel) { this.drawBox(e); return; } + if (this.wdrag) { this.dragWire(e); return; } + if (!this.looking) return; + const k = LOOK * (this.p.look || 1); + this.tyaw -= (e.movementX || 0) * k; + this.tpitch = Math.max(-1.55, Math.min(1.55, this.tpitch - (e.movementY || 0) * k)); + }); + const up = (e) => { + if (this.bdrag && (e.button === 0 || e.type === 'lostpointercapture')) this.endBlockDrag(); + if (this.boxSel && (e.button === 0 || e.type === 'lostpointercapture')) this.endBox(e); + if (this.wdrag && (e.button === 0 || e.type === 'lostpointercapture')) this.endWire(e); + if (e.button === 2 || e.type === 'lostpointercapture') { + this.looking = false; + h.classList.remove('looking'); + // a right click that didn't look around, on a block: its menu + const r = this.rdown; + this.rdown = null; + if (e.button === 2 && r && Math.hypot(e.clientX - r.x, e.clientY - r.y) < 4 && this.blocks.size) { + // the block itself, not the gizmo over it + const m = this.rayFrom(e).intersectObjects([...this.blocks.values()].map((o) => o.mesh), false)[0]; + const id = m && m.object.userData.block; + if (id != null) { + this.pickBlock(id); + this.send({ ...this.ev('blockmenu', null, e), data: id }); + } + } + } + }; + h.addEventListener('pointerup', up); + h.addEventListener('lostpointercapture', up); + h.addEventListener('wheel', (e) => { + if (e.target.closest('.slabel')) return; + e.preventDefault(); + // placing a prefab, the wheel turns it a quarter + if (this.ghost) { this.ghost.turn = (this.ghost.turn + (e.deltaY > 0 ? 1 : 3)) % 4; this.dirty = true; return; } + // hanging on the grapple, the wheel reels the rope in or out + if (this.rope) { this.rope.len = Math.max(1.2, Math.min(60, this.rope.len + (e.deltaY > 0 ? 0.8 : -0.8))); return; } + this.speed = Math.min(200, Math.max(0.5, this.speed * (e.deltaY > 0 ? 0.9 : 1.1))); + this.info(true); + }, { passive: false }); + window.addEventListener('keydown', (e) => { + if (!this.running || typing(e) || e.ctrlKey || e.metaKey || e.altKey) return; + const k = e.code; + const b = this.bind; + if (FLYING.some((a) => b[a] === k) || k === 'ShiftLeft' || k === 'ShiftRight') { + this.keys.add(k); + if (this.ease) { this.ease = null; this.syncTurn(); } + e.preventDefault(); + } else if (k.startsWith('Arrow') && !e.shiftKey) { + e.preventDefault(); + this.hop(k); + } else if (k === 'Escape' && this.ghost) { this.stopGhost(); this.send({ ...this.ev('ghostdone', null) }); } + else if (k === 'Escape' && this.openCopy) this.closeCopy(); + else if (k === 'Escape' && this.multi.size) this.clearMulti(); + else if (k === 'Escape' && this.openGroups.length) { const g = this.openGroups.pop(); this.pickGroup(g); } + else if (k === b.level) this.level(); + else if (k === b.walk) this.setMode(this.mode === 'walk' ? 'fly' : 'walk'); + else if (k === b.superflight) this.setMode(this.mode === 'super' ? 'fly' : 'super'); + else if (k === b.grapple) this.grapple(); + else if (k === b.back_to_start) this.home(); + else if (k === b.slower) this.speed = Math.max(0.5, this.speed / 1.25); + else if (k === b.faster) this.speed = Math.min(200, this.speed * 1.25); + }); + window.addEventListener('keyup', (e) => this.keys.delete(e.code)); + window.addEventListener('blur', () => this.keys.clear()); + } + + // ------------------------------------------------------------------ the frame + + // a frame, and the next one asked for whatever goes wrong in this one (a fault is + // reported once, not left to stop the room) + loop(now) { + if (!this.running) return; + try { + this.frame(now); + } catch (e) { + if (!this.faulted) { + this.faulted = true; + this.send({ ...this.ev('fault', null), text: `the room: ${e && e.message || e}` }); + } + } + requestAnimationFrame(this.loop); + } + + frame(now) { + if (this.wiresDirty) this.drawWires(); + const dt = Math.min(0.1, (now - this.last) / 1000); + this.last = now; + const c = this.camera; + if (this.mode && this.mode !== 'fly') this.moveBody(dt); + else if (this.keys.size) { + const k = this.keys; + const v = this.speed * (k.has('ShiftLeft') || k.has('ShiftRight') ? 4 : 1) * dt; + if (this.held('fly_forward')) c.translateZ(-v); + if (this.held('fly_back')) c.translateZ(v); + if (this.held('fly_left')) c.translateX(-v); + if (this.held('fly_right')) c.translateX(v); + if (this.held('fly_up')) c.translateY(v); + if (this.held('fly_down')) c.translateY(-v); + if (this.held('roll_left')) this.rollA += ROLL * dt; + if (this.held('roll_right')) this.rollA -= ROLL * dt; + } + if (this.ease) { + const e = this.ease; + e.t = Math.min(1, e.t + dt / 0.6); + const s = e.t * e.t * (3 - 2 * e.t); + c.position.lerpVectors(e.fromPos, e.toPos, s); + c.quaternion.slerpQuaternions(e.fromQuat, e.toQuat, s); + if (e.t >= 1) { + this.ease = null; + this.syncTurn(); + } + } else { + // ease the turn onto where the mouse put it (frame-rate independent) + const a = 1 - Math.exp(-(this.p.smooth || 14) * dt); + this.yaw += (this.tyaw - this.yaw) * a; + this.pitch += (this.tpitch - this.pitch) * a; + this.applyTurn(); + } + // the physics in fixed steps, however long the frame was + const moving = !this.paused && this.order.length && !this.asleep(); + if (moving) { + this.acc = Math.min(this.acc + dt * this.p.substeps, 0.25); + while (this.acc >= STEP) { + this.step(STEP); + this.acc -= STEP; + } + } + // a still room isn't drawn again: nothing flies, turns, eases, drags or spreads, and + // the turn has caught up with the mouse (it keeps the page light while one types + // elsewhere) + const turning = Math.abs(this.tyaw - this.yaw) > 1e-5 || Math.abs(this.tpitch - this.pitch) > 1e-5; + const animated = this.blocks.size && this.animating(); + if (animated) this.applyAnims(now); + this.wireTimers(now); + this.hearFrom(); + if (this.ghost) this.aimGhost(); + const rays = this.fadeRays(now); + if (moving || turning || this.keys.size || this.ease || this.looking || this.drag || this.bdrag || this.dirty || animated || rays || (this.mode && this.mode !== 'fly') || this.ghost) { + this.dirty = false; + this.render(); + this.info(false); + } + } + + render() { + if (this.selBlock != null) this.placeGizmo(); + if (this.sky) this.sky.position.copy(this.camera.position); + // the lights' rings face the camera + if (this.lightMarks) for (const m of this.lightMarks.children) if (m.userData.facing) m.quaternion.copy(this.camera.quaternion); + this.gl?.render(this.scene, this.camera); + const c = this.camera; + c.updateMatrixWorld(); + const { w, h } = this.size; + const focal = h / 2 / Math.tan((c.fov * Math.PI) / 360); + const v = new THREE.Vector3(); + for (const n of this.order) { + this.world(n, v).applyMatrix4(c.matrixWorldInverse); + const dist = -v.z; + const el = n.el; + if (dist < 0.3) { + if (el.style.display !== 'none') el.style.display = 'none'; + continue; + } + const size = (n.size || this.p.size) * (n.fxSize || 1); + // a text's em on screen, in pixels + const px = (size * focal) / dist; + const x = w / 2 + (v.x / dist) * focal; + const y = h / 2 - (v.y / dist) * focal; + if (px < this.p.minPx || x < -w || x > 2 * w || y < -h || y > 2 * h) { + if (el.style.display !== 'none') el.style.display = 'none'; + continue; + } + if (el.style.display === 'none') el.style.display = ''; + const s = Math.min(px, 220) / BASE_PX; + el.style.transform = `translate3d(${x.toFixed(2)}px, ${y.toFixed(2)}px, 0) translate(-50%, -50%) scale(${s.toFixed(4)})`; + el.style.zIndex = String(100000 - Math.round(dist * 10)); + el.style.opacity = String(Math.max(0.15, Math.min(1, 1.4 - dist / 220)).toFixed(3)); + } + } + + info(now) { + const t = performance.now(); + if (!now && t - this.infoAt < 120) return; + this.infoAt = t; + const p = this.camera.position; + const state = this.paused ? 'paused' : this.asleep() ? 'still' : 'moving'; + const mode = this.mode === 'walk' ? (this.rope ? ' on the grapple' : ' walking') : this.mode === 'super' ? ` superflight ${this.flight ? this.flight.v.length().toFixed(0) : 0}` : ''; + const text = `${p.x.toFixed(1)} ${p.y.toFixed(1)} ${(-p.z).toFixed(1)} speed ${this.speed.toFixed(1)} roll ${Math.round(this.roll())}° ${this.order.length} texts spread ${state}${mode}`; + if (text === this.lastInfo) return; + this.lastInfo = text; + this.send({ ...this.ev('info', null), text }); + } +} diff --git a/app/src/style.css b/app/src/style.css new file mode 100644 index 00000000..4c18ddfe --- /dev/null +++ b/app/src/style.css @@ -0,0 +1,1002 @@ +/* anend's app: the sand look of the web and Bevy apps, written once for the desktop and the web */ +:root { + --radius: 4px; + --gap: 6px; + --frame: 6px; + --top: 32px; + --barh: 32px; + --font: "Fira Sans", "FiraGO", system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif; + --mono: "Fira Mono", "Fira Code", ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace; + --serif: "Times New Roman", Times, "Liberation Serif", "DejaVu Serif", serif; + --bad: hsl(5 60% 46%); +} +* { box-sizing: border-box; } +html, body { height: 100%; margin: 0; overflow: hidden; } +#main { height: 100%; } +/* the Bevy app's frame: the bars and the views are inset cards on the window's colour */ +.app { + height: 100vh; display: grid; grid-template-rows: var(--top) minmax(0, 1fr) auto; gap: var(--frame); + padding: var(--frame); background: var(--window); color: var(--text); + font: var(--fs, 14px)/1.45 var(--font); + text-rendering: optimizeLegibility; -webkit-font-smoothing: subpixel-antialiased; +} +button { font: inherit; } +[hidden] { display: none !important; } +.grow { flex: 1; } +.dim { color: var(--dim); } +.small { font-size: .88em; } +.bad { color: var(--bad); } +.row { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; } +h2 { font-size: 1.3em; margin: 0 0 .4em; } +h3 { font-size: 1.08em; margin: 0 0 .3em; } + +button, .btn { + display: inline-flex; align-items: center; justify-content: center; gap: 4px; + height: 24px; padding: 0 9px; border: 0; border-radius: var(--radius); + background: var(--buttons); color: var(--on-button); cursor: pointer; white-space: nowrap; font-size: .96em; +} +button:hover { filter: brightness(1.06); } +button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible, [tabindex]:focus-visible { + outline: 2px solid var(--accent); outline-offset: 1px; +} +button.on, button.primary { background: var(--accent); } +button.armed { background: var(--bad); color: #fff; } +button:disabled { opacity: .5; cursor: default; filter: none; } +button.ibtn { width: 26px; padding: 0; } +button.plain { background: none; color: var(--dim); } +button.plain:hover { background: color-mix(in srgb, var(--buttons) 40%, transparent); color: var(--text); filter: none; } +input[type=text], input[type=search], input[type=number], input[type=password], input[type=date], select, textarea { + font: inherit; color: var(--text); background: var(--pad); border: 0; border-radius: var(--radius); + padding: 3px 8px; min-width: 0; height: 26px; +} +textarea { height: auto; } +/* every select draws its own arrow, so its text sits centred and clear of it whatever the + engine (WebKitGTK clipped the text of a native select at 26px with this line height) */ +select { + appearance: none; -webkit-appearance: none; line-height: 1.2; padding: 0 26px 0 9px; cursor: pointer; + text-overflow: ellipsis; white-space: nowrap; overflow: hidden; vertical-align: middle; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 10 6'%3E%3Cpath d='M1 1l4 4 4-4' fill='none' stroke='%23777' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E"); + background-repeat: no-repeat; background-position: right 9px center; background-size: 10px 6px; +} +select option { color: var(--text); background: var(--cards); } +input[type=color] { width: 30px; height: 22px; border: 0; padding: 0; background: none; cursor: pointer; } +input[type=range] { accent-color: var(--accent); } +input::placeholder, textarea::placeholder { color: var(--dim); opacity: .8; } +.icon { display: inline-flex; width: 16px; height: 16px; flex: none; } +.icon svg { width: 100%; height: 100%; display: block; } + +/* the tooltip: a control's name and key, styled, after a short rest */ +[data-tip] { position: relative; } +[data-tip]::after { + content: attr(data-tip); position: absolute; z-index: 60; left: 50%; top: calc(100% + 6px); transform: translateX(-50%); + padding: 3px 8px; border-radius: var(--radius); white-space: pre; pointer-events: none; + background: var(--bars); color: var(--bar-text); font: 12.5px/1.35 var(--font); box-shadow: 0 3px 12px rgb(0 0 0 / .28); + opacity: 0; visibility: hidden; transition: opacity .12s; +} +[data-tip]:hover::after, [data-tip]:focus-visible::after { opacity: 1; visibility: visible; transition-delay: .35s; } +[data-tip].tip-up::after { top: auto; bottom: calc(100% + 6px); } +[data-tip].tip-left::after { left: auto; right: 0; transform: none; } +[data-tip].tip-right::after { left: 0; transform: none; } + +/* ---------------------------------------------------------------- the top bar */ +.top { + position: relative; z-index: 3; display: flex; align-items: center; gap: 2px; padding: 0 4px; min-width: 0; + background: var(--bars); color: var(--bar-text); border-radius: var(--radius); +} +.tabs { display: flex; gap: 2px; flex: none; } +.top button.tab, .top button.side { height: 26px; width: 32px; padding: 0; background: none; color: var(--bar-dim); } +.top button.tab .icon, .top button.side .icon { width: 17px; height: 17px; } +.top button.tab:hover, .top button.side:hover { color: var(--bar-text); background: color-mix(in srgb, var(--bar-text) 12%, transparent); filter: none; } +.top button.tab.on { background: var(--accent); color: var(--on-button); } +.top .status { font-size: 12.5px; color: var(--bar-dim); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 0; max-width: 34%; padding: 0 6px; } +.top .status.bad { color: hsl(8 85% 72%); } +/* the search line: centered on the bar whatever sits at its sides */ +.searchline { + position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); + display: flex; align-items: center; gap: 8px; max-width: 46%; overflow: hidden; white-space: nowrap; + height: 24px; padding: 0 10px; border-radius: var(--radius); + background: color-mix(in srgb, var(--bar-text) 13%, transparent); color: var(--bar-text); font-size: 13px; +} +.searchline b { font-weight: 700; } +.searchline .detail { font-size: 11.5px; color: var(--bar-dim); overflow: hidden; text-overflow: ellipsis; } +.searchline .detail.tri, .searchline .detail:first-of-type { flex: none; } +.searchline .counts { display: flex; align-items: center; gap: 8px; flex: none; } +.searchline .counts > span { display: inline-flex; align-items: center; gap: 3px; } +.searchline .counts .icon { width: 13px; height: 13px; } +.searchline .pfline { min-width: 0; overflow: hidden; text-overflow: ellipsis; font-size: 11.5px; color: var(--bar-dim); } +.searchline .pfline .pf { display: inline; white-space: nowrap; } +.searchline .pfline i { cursor: pointer; font-style: normal; color: var(--bar-text); } +.searchline .pfline i:hover { text-decoration: underline; } +svg.triangle { flex: none; overflow: visible; display: block; } +svg.triangle polygon { fill: color-mix(in srgb, var(--accent) 55%, transparent); stroke: var(--bar-text); stroke-width: 1; stroke-linejoin: round; } +svg.triangle.flat polygon { stroke: hsl(8 85% 72%); fill: none; } + +/* ---------------------------------------------------------------- the command bar: one bar, the view's + controls (sums, toggles, counts) at its right end */ +.dock { position: relative; z-index: 3; min-width: 0; } +/* the input spans the whole bar with the same room kept at both ends, so its centred text + never moves when what sits at the right (sums, counts, chips) changes size. The room at + each end depends only on the bar's width: whatever is left once the typing field has its + 15.5 cm (at most 520px a side), so the field is never narrower than 15.5 cm. The view's + items sit in the right-hand room on the bar's line; those that don't fit wrap upward into + a see-through bar just above it (and in a bar too narrow for a useful right-hand room, + all of them go above). */ +.dock { container-type: inline-size; } +.cmdbar { + position: relative; display: block; height: var(--barh); + --reserve: clamp(0px, calc((100cqw - 15.5cm) / 2), 520px); + background: var(--bars); color: var(--bar-text); border-radius: var(--radius); +} +.cmdbar:focus-within { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--accent) 70%, transparent); } +.cmdbar .pending { position: absolute; left: 10px; top: 0; bottom: 0; display: flex; align-items: center; font-size: 11.5px; color: var(--accent); white-space: nowrap; max-width: max(0px, calc(var(--reserve) - 20px)); overflow: hidden; text-overflow: ellipsis; pointer-events: none; } +#bar { + display: block; width: 100%; min-width: 15.5cm; height: var(--barh); background: transparent; color: var(--bar-text); text-align: center; + border: 0; outline: 0; font: inherit; font-size: 15px; padding: 0 var(--reserve); border-radius: 0; +} +#bar::placeholder { color: var(--bar-dim); opacity: .55; } +.app.v-memory #bar { font-family: var(--serif); font-size: 17px; } +.cmdbar .side { + position: absolute; right: 0; bottom: 0; width: max(0px, calc(var(--reserve) - 8px)); + display: flex; align-items: center; justify-content: flex-end; gap: 10px 12px; flex-wrap: wrap-reverse; + padding: 4px 8px calc((var(--barh) - 22px) / 2) 0; box-sizing: content-box; + color: var(--bar-dim); font-size: 12px; font-variant-numeric: tabular-nums; +} +.cmdbar .side > * { min-height: 22px; } +/* the lines that wrapped above the bar: a see-through bar of their own */ +.cmdbar .side { background: linear-gradient(to top, transparent var(--barh), color-mix(in srgb, var(--bars) 82%, transparent) var(--barh)); border-radius: var(--radius) var(--radius) 0 0; } +@container (max-width: 866px) { + .cmdbar .side { width: calc(100% - 16px); bottom: 100%; padding: 4px 8px; background: color-mix(in srgb, var(--bars) 82%, transparent); border-radius: var(--radius) var(--radius) 0 0; } +} +.cmdbar .side:empty { display: none; } +.sidenote { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.toggles { display: flex; gap: 1px; align-items: center; } +button.tchip { + min-width: 20px; height: 20px; padding: 0 3px; background: none; border: 0; color: var(--bar-dim); opacity: .55; + font: 600 12px/1 var(--font); +} +button.tchip .icon { width: 14px; height: 14px; } +button.tchip:hover { opacity: 1; filter: none; } +button.tchip.on { color: var(--bar-text); opacity: 1; } +.sidecar { color: var(--bar-text); font-family: var(--serif); font-size: 14px; white-space: nowrap; font-variant-numeric: tabular-nums; min-width: 0; overflow: hidden; text-overflow: ellipsis; } +.sidecar .extra, .sidecar .letters { margin-left: 6px; } +.sidecar .num { cursor: pointer; } +.sidecar .num:hover { color: var(--accent); } +.sidecar .num.on { text-decoration: underline; text-underline-offset: 3px; } +.sidecar .extra { color: var(--bar-dim); font-size: 12.5px; } +.sidecar .letters { font-size: 11px; color: var(--bar-dim); display: inline-block; vertical-align: bottom; max-width: 220px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } + +/* toasts (weum's): bottom right, above the bar */ +.toasts { position: fixed; right: 12px; bottom: calc(var(--barh) + 20px); z-index: 50; display: flex; flex-direction: column; gap: 4px; align-items: flex-end; } +.toast { background: var(--bars); color: var(--bar-text); padding: 4px 10px; border-radius: var(--radius); font: 13px var(--mono); cursor: pointer; box-shadow: 0 3px 12px rgb(0 0 0 / .3); max-width: 60vw; overflow-wrap: anywhere; } + +/* ---------------------------------------------------------------- views */ +.views { position: relative; min-height: 0; min-width: 0; } +.view { position: absolute; inset: 0; overflow: auto; } +.card { background: var(--cards); border-radius: var(--radius); padding: 10px 12px; } +.page { max-width: 980px; margin: 0 auto; display: flex; flex-direction: column; gap: var(--gap); padding: 0 0 6px; } +.page > .row:first-child { background: var(--cards); border-radius: 0 0 var(--radius) var(--radius); padding: 4px 10px; } +.page > .row:first-child h2 { margin: 0; } +.metrics svg.triangle polygon { stroke: var(--text); } +.chip { display: inline-flex; align-items: center; gap: 3px; height: 22px; padding: 0 7px; font-size: 13px; background: var(--buttons); color: var(--on-button); border-radius: var(--radius); border: 0; cursor: pointer; } +.chip.on { background: var(--accent); } +.empty { color: var(--dim); text-align: center; padding: 24px; } +.pager { display: flex; gap: 6px; align-items: center; justify-content: center; padding: 4px; } + +/* ---------------------------------------------------------------- the memory view (weum's black field) */ +/* the memory view: weum's black field in the frame, joined to a black command bar (Bevy's bar_look) */ +.app.v-memory .views { background: #000; border-radius: var(--radius) var(--radius) 0 0; } +.app.v-memory .dock { margin-top: calc(-1 * var(--frame)); padding-top: var(--frame); background: #000; border-radius: 0 0 var(--radius) var(--radius); } +.app.v-memory .dock, .app.v-memory .toasts { --bars: #000; --bar-text: #fff; --bar-dim: #b9a59a; } +/* weum's white line under the typing, the width of the typing box */ +.app.v-memory #bar { background: linear-gradient(#fff, #fff) center bottom 3px / calc(100% - 2 * var(--reserve) + 24px) 1px no-repeat; } +.memory { border-radius: var(--radius); background: #000; color: #fff; font-family: var(--serif); display: flex; flex-direction: column; overflow: hidden; } +.mem-head { display: flex; align-items: center; gap: 10px; padding: 3px 10px; font-size: 12.5px; color: #c9ab99; flex: none; } +.mem-head b { color: #fff; font-weight: 600; } +.mem-main { position: relative; flex: 1; min-height: 0; overflow: auto; display: flex; flex-direction: column; align-items: center; padding: 10px 26px; } +.mem-main > .spacer { flex: 1; } +.field { position: relative; width: 100%; max-width: 100%; } +.field .grip { + position: absolute; top: 0; bottom: 0; width: 8px; cursor: ew-resize; z-index: 3; + background: transparent; border-radius: 3px; +} +.field .grip:hover, .field .grip.dragging { background: color-mix(in srgb, #c9ab99 45%, transparent); } +.field .grip.l { left: -10px; } +.field .grip.r { right: -10px; } +.results-head { text-align: center; padding: 4px 4px 2px; background: #c9ab99; } +.results-head h3 { margin: 0; font-size: 26px; font-weight: 700; line-height: 1.15; color: #fff; overflow-wrap: anywhere; } +.results-head .pf { font-size: 12.5px; color: #f3ebe6; margin: 2px 0 2px; overflow-wrap: anywhere; } +.results-head .pf i { cursor: pointer; } +.results-head .pf i:hover { text-decoration: underline; } +.arts { display: flex; flex-wrap: wrap; justify-content: center; align-content: flex-start; gap: var(--mspace, 4px); padding-top: calc(var(--mspace, 4px) + 4px); } +.art { + position: relative; background: #282626; color: #fff; font-size: var(--mfs, 20px); line-height: 1.25; + padding: 2px 8px 3px; cursor: pointer; max-width: 100%; overflow-wrap: anywhere; + text-decoration-thickness: 3px; text-underline-offset: 4px; user-select: none; + max-height: 7.5em; overflow: hidden; +} +/* crisp emphasis on hover: brighter, outlined, on top; no scaling */ +.art:hover { background: #3d3838; box-shadow: 0 0 0 1px #c9ab99, 0 4px 16px rgb(0 0 0 / .8); z-index: 5; max-height: none; overflow: visible; } +.art.long:hover { position: relative; } +/* a long text: its first piece (lines at word boundaries), "more" opens the next ones */ +.art.long { max-height: none; max-width: min(100%, calc(var(--piece-ch, 80ch) + 20px)); } +.art.long .piece { white-space: pre-wrap; } +.art.long.open .piece { max-height: 60vh; overflow-y: auto; } +.art .pieces-more { display: flex; gap: 8px; align-items: center; font-size: 12px; margin-top: 2px; } +.art .pieces-more button.plain { color: #c9ab99; height: auto; padding: 0 4px; } +.art.is-list { background: #5a4636; } +.art.is-candidate { outline: 2px dashed #c9ab99; outline-offset: -2px; } +.art.selected { background: #2f4a5a; box-shadow: inset 0 0 0 2px #7fb0cf; } +.art.note::before { content: "✎ "; color: #c9ab99; } +.art .meta { display: none; } +/* word types (kinds::tag): each type a colour, its label under the word */ +.memory, .types-legend { --t-noun: #6aa6f0; --t-verb: #f07a6a; --t-adjective: #f0b34d; --t-adverb: #d38af0; --t-pronoun: #5fd0c0; --t-determiner: #a5acb8; --t-preposition: #9ccf6c; --t-conjunction: #c9b48e; --t-interjection: #f58cc0; --t-name: #f5d65a; --t-number: #6ee08a; --t-date: #7fd8f0; --t-time: #7fd8f0; --t-link: #9aa6ff; --t-email: #9aa6ff; --t-hashtag: #f0a060; } +.memory.white, .memory.white .types-legend { --t-noun: #1f62b8; --t-verb: #c0392b; --t-adjective: #a86a00; --t-adverb: #8e3fae; --t-pronoun: #138a7a; --t-determiner: #5f6672; --t-preposition: #4f7d22; --t-conjunction: #7d6440; --t-interjection: #b5306e; --t-name: #8a6d00; --t-number: #1d8a3c; --t-date: #1b7d9a; --t-time: #1b7d9a; --t-link: #3d4bc7; --t-email: #3d4bc7; --t-hashtag: #b05a10; } +/* a labelled word: the word over its type's short name, a bar of its colour between */ +.tw { display: inline-flex; flex-direction: column; align-items: center; vertical-align: top; line-height: 1.1; } +.tw .w { border-bottom: 2px solid var(--tc, currentColor); padding-bottom: 1px; } +.tw .l { font: 700 max(10px, .5em)/1.15 var(--font); color: var(--tc); letter-spacing: .02em; margin-top: 1px; } +.tw.t-noun { --tc: var(--t-noun); } .tw.t-verb { --tc: var(--t-verb); } .tw.t-adjective { --tc: var(--t-adjective); } +.tw.t-adverb { --tc: var(--t-adverb); } .tw.t-pronoun { --tc: var(--t-pronoun); } .tw.t-determiner { --tc: var(--t-determiner); } +.tw.t-preposition { --tc: var(--t-preposition); } .tw.t-conjunction { --tc: var(--t-conjunction); } .tw.t-interjection { --tc: var(--t-interjection); } +.tw.t-name { --tc: var(--t-name); } .tw.t-number { --tc: var(--t-number); } .tw.t-date, .tw.t-time { --tc: var(--t-date); } +.tw.t-link, .tw.t-email { --tc: var(--t-link); } .tw.t-hashtag { --tc: var(--t-hashtag); } +/* in a text (an article) the words stay inline under its own gematria underline; each + type is only the coloured label under its word (ruby), so the two never mix */ +.art .tagged { display: inline; } +.art:has(.tagged) { max-height: none; line-height: 1.9; } +ruby.rw { ruby-position: under; ruby-align: center; } +ruby.rw rt { font: 700 max(10px, .5em)/1.2 var(--font); letter-spacing: .02em; color: var(--tc); } +ruby.rw.t-noun { --tc: var(--t-noun); } ruby.rw.t-verb { --tc: var(--t-verb); } ruby.rw.t-adjective { --tc: var(--t-adjective); } +ruby.rw.t-adverb { --tc: var(--t-adverb); } ruby.rw.t-pronoun { --tc: var(--t-pronoun); } ruby.rw.t-determiner { --tc: var(--t-determiner); } +ruby.rw.t-preposition { --tc: var(--t-preposition); } ruby.rw.t-conjunction { --tc: var(--t-conjunction); } ruby.rw.t-interjection { --tc: var(--t-interjection); } +ruby.rw.t-name { --tc: var(--t-name); } ruby.rw.t-number { --tc: var(--t-number); } ruby.rw.t-date, ruby.rw.t-time { --tc: var(--t-date); } +ruby.rw.t-link, ruby.rw.t-email { --tc: var(--t-link); } ruby.rw.t-hashtag { --tc: var(--t-hashtag); } +.types-legend .tw { flex-direction: row; gap: 4px; color: var(--tc); align-items: baseline; } +.mem-types { text-align: center; font: 17px/2 var(--serif); padding: 0 10px 4px; flex: none; color: #ddd; } +.mem-types .tw .w { color: #fff; } +.memory.white .mem-types .tw .w { color: #111; } +.types-legend { display: flex; flex-wrap: wrap; gap: 3px 12px; justify-content: center; padding: 4px 6px 0; font: 12.5px var(--font); } +.types-legend b { font-weight: 700; margin-right: 2px; } +/* white mode (W): dark texts on white, as weum's */ +.memory.white { background: #fff; color: #111; } +.app.v-memory:has(.memory.white) .views, .app.v-memory:has(.memory.white) .dock { background: #fff; } +.app.v-memory:has(.memory.white) .dock { --bars: #fff; --bar-text: #111; --bar-dim: #6b5d55; } +.app.v-memory:has(.memory.white) #bar { background-image: linear-gradient(#111, #111); } +.memory.white .art { background: #fff; color: #111; box-shadow: inset 0 0 0 1px #ddd; } +.memory.white .art:hover { background: #f2ece8; } + +.memory.white .results-head { background: #fff; } +.memory.white .results-head h3 { color: #111; } +.memory.white .results-head .pf, .memory.white .mem-hover, .memory.white .mem-types, .memory.white .mem-intro { color: #333; } +.mem-intro { max-width: 520px; margin: auto; text-align: center; color: #c9ab99; font-size: 17px; } +.mem-intro p { margin: .4em 0; } +.mem-hover { min-height: 1.5em; text-align: center; font: 12.5px var(--mono); color: #bbb; padding: 4px; flex: none; overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } +.selbar { display: flex; gap: 6px; align-items: center; justify-content: center; padding: 4px; color: #ddd; font-size: 13px; flex: none; flex-wrap: wrap; } +.selbar button { height: 22px; font-size: 12.5px; } +.listpick { display: flex; flex-wrap: wrap; gap: 4px; justify-content: center; max-height: 30vh; overflow: auto; padding: 4px; } +.listpick button { background: #3a3030; color: #fff; } +.listpick button:hover { background: #5a4636; } +/* the left edge: the sum buckets as circles, shown on hover */ +.edge { position: absolute; left: 0; top: 0; bottom: 0; width: 14px; z-index: 8; } +.buckets { + position: absolute; left: 0; top: 0; bottom: 0; width: 64px; z-index: 9; overflow-y: auto; overflow-x: hidden; + opacity: 0; pointer-events: none; transition: opacity .25s; scrollbar-width: none; + background: linear-gradient(90deg, rgb(0 0 0 / .92), rgb(0 0 0 / .6) 70%, transparent); +} +.buckets::-webkit-scrollbar { display: none; } +.edge:hover + .buckets, .buckets:hover { opacity: 1; pointer-events: auto; } +.buckets .line { position: absolute; left: 20px; top: 0; bottom: 0; width: 1px; background: #5b4f48; } +.buckets .b { position: relative; display: flex; align-items: center; gap: 4px; margin: 1px 0; cursor: pointer; color: #c9ab99; font: 10px var(--font); } +.buckets .b .dot { display: inline-block; border-radius: 50%; background: #c9ab99; flex: none; margin-left: calc(20px - var(--r)); width: calc(var(--r) * 2); height: calc(var(--r) * 2); } +.buckets .b:hover .dot, .buckets .b.on .dot { background: #fff; } +.buckets .b:hover { color: #fff; } +.buckets .label { position: fixed; left: 70px; z-index: 20; background: #1b1818; color: #fff; padding: 2px 8px; border-radius: 3px; font-size: 12px; pointer-events: none; } +/* the right-click menu */ +.menu { + position: fixed; z-index: 70; min-width: 170px; background: var(--cards); color: var(--text); border-radius: var(--radius); + box-shadow: 0 6px 22px rgb(0 0 0 / .35); padding: 4px; display: flex; flex-direction: column; font: 13.5px var(--font); +} +.menu .title { padding: 3px 8px 5px; color: var(--dim); font-size: 12px; max-width: 280px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; border-bottom: 1px solid color-mix(in srgb, var(--dim) 30%, transparent); margin-bottom: 3px; } +.menu button { justify-content: flex-start; background: none; color: var(--text); height: 26px; gap: 8px; } +.menu button:hover, .menu button:focus-visible { background: color-mix(in srgb, var(--accent) 35%, transparent); filter: none; } +.menu kbd { margin-left: auto; font: 11px var(--mono); color: var(--dim); } +.backdrop { position: fixed; inset: 0; z-index: 65; } + +/* ---------------------------------------------------------------- settings: a dialog, closed by a click outside */ +.overlay { position: fixed; inset: 0; z-index: 40; background: rgb(0 0 0 / .35); display: flex; justify-content: center; align-items: flex-start; padding-top: calc(var(--top) + 8px); } +.dialog { + position: relative; width: min(760px, calc(100vw - 16px)); max-height: calc(100vh - var(--top) - 24px); overflow-y: auto; overflow-x: hidden; + background: var(--cards); color: var(--text); border-radius: var(--radius); box-shadow: 0 10px 40px rgb(0 0 0 / .4); padding: 8px 14px 12px; +} +.dialog .head { display: flex; align-items: center; gap: 8px; position: sticky; top: -8px; background: var(--cards); padding: 4px 0; z-index: 2; } +.dialog .head h2 { margin: 0; } +.dialog .close { flex: none; } +.dialog hr { border: 0; border-top: 1px solid color-mix(in srgb, var(--dim) 35%, transparent); margin: 6px 0; } +.section > .shead { display: flex; align-items: center; gap: 6px; width: 100%; background: none; color: var(--text); justify-content: flex-start; height: 28px; padding: 0 2px; font-weight: 600; font-size: 1.05em; } +.section > .shead .icon { transition: transform .15s; transform: rotate(90deg); } +.section.folded > .shead .icon { transform: none; } +.section .body { display: grid; grid-template-columns: minmax(130px, 200px) 1fr; gap: 6px 12px; align-items: center; padding: 4px 4px 8px; } +.section .body > .wide { grid-column: 1 / -1; } +.section .body label { color: var(--dim); } +.swatches { display: flex; gap: 8px; flex-wrap: wrap; } +.swatches label { display: inline-flex; align-items: center; gap: 4px; font-size: 12.5px; color: var(--text); } +table.saves { width: 100%; border-collapse: collapse; font-size: 13px; } +table.saves td, table.saves th { padding: 3px 6px; text-align: left; border-bottom: 1px solid color-mix(in srgb, var(--dim) 20%, transparent); } +table.saves tr.open td:first-child { font-weight: 700; } +table.keys td { padding: 2px 8px 2px 0; font-size: 13px; } +.keymap { display: grid; grid-template-columns: repeat(auto-fill, minmax(320px, 1fr)); gap: 4px 18px; } +.keygroup h4 { margin: 8px 0 2px; font-size: 12.5px; color: var(--dim); font-weight: 600; text-transform: none; } +.keyrow { display: flex; align-items: center; gap: 8px; padding: 1px 0; font-size: 13px; } +.keyrow .what { flex: 1; min-width: 0; } +button.keycap { min-width: 74px; height: 22px; font: 12px var(--mono); background: var(--pad); color: var(--text); } +button.keycap.changed { box-shadow: inset 0 0 0 1px var(--accent); } +button.keycap.on { background: var(--accent); color: var(--on-button); } +kbd { font: 12px var(--mono); border: 1px solid color-mix(in srgb, var(--dim) 50%, transparent); border-radius: 3px; padding: 0 4px; } +.import { background: var(--pad); border-radius: var(--radius); padding: 8px; display: flex; flex-direction: column; gap: 6px; } +.steps { display: flex; gap: 6px; font-size: 12px; color: var(--dim); } +.steps .on { color: var(--text); font-weight: 700; } + +/* ---------------------------------------------------------------- lists */ +.lists-head { display: flex; flex-direction: column; gap: 6px; } +.listcard { display: flex; flex-direction: column; gap: 6px; } +.listcard.chosen { box-shadow: inset 0 0 0 2px var(--accent); } +.listcard .lname { height: auto; padding: 0 4px; color: var(--text); } +.listcard .lname h3 { margin: 0; font-size: 1.25em; } +.mono { font-family: var(--mono); } +.figures-row { display: flex; flex-wrap: wrap; gap: 4px 22px; } +.figures-row div { display: flex; flex-direction: column; } +.figures-row b { font-size: 1.3em; line-height: 1.1; } +.figures-row span { font-size: 12px; color: var(--dim); } +.memberchips { display: flex; flex-wrap: wrap; gap: 4px; } +.mchip { display: inline-flex; align-items: center; gap: 5px; padding: 1px 2px 1px 8px; background: var(--pad); border-radius: 3px; font-size: 13px; } +.mchip .mt { cursor: pointer; } +.mchip .mt:hover { color: var(--link); } +.mchip .ms { color: var(--dim); font-size: 12px; font-variant-numeric: tabular-nums; } +.mchip button.mx { height: 18px; width: 18px; padding: 0; font-size: 14px; } +.alike { display: grid; gap: 2px; margin-top: 6px; overflow-x: auto; font-size: 12px; } +.alike-col { color: var(--dim); text-align: center; overflow: hidden; white-space: nowrap; } +.alike-row { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } +.alike-cell { height: 22px; display: flex; align-items: center; justify-content: center; border-radius: 2px; font-variant-numeric: tabular-nums; } +.list-page .pf, .listcard .pf { font-size: 12px; color: var(--dim); overflow-wrap: anywhere; } +.listcard .pf i { cursor: pointer; color: var(--link); } +.list-grid { flex: none; display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: var(--gap); } +.list-tile { height: auto; white-space: normal; display: flex; flex-direction: column; gap: 4px; cursor: pointer; border: 0; text-align: left; font: inherit; color: var(--text); background: var(--cards); } +.list-tile:hover { outline: 2px solid var(--accent); } +.list-tile h3 { margin: 0; overflow-wrap: anywhere; } +.list-page .name { font-size: 1.6em; font-weight: 700; margin: 0; overflow-wrap: anywhere; } +.members { display: flex; flex-direction: column; gap: 3px; } +.member { display: flex; gap: 6px; align-items: center; } +.member input { flex: 1; } +.member .key { font: 11.5px var(--mono); color: var(--dim); width: 74px; flex: none; } +.figures { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 4px 14px; font-size: 13px; } +.figures div b { display: block; font-size: 1.25em; } +.letterbars { display: grid; grid-template-columns: repeat(26, 1fr); gap: 2px; height: 46px; align-items: end; } +.letterbars .col { display: flex; flex-direction: column; justify-content: flex-end; height: 100%; } +.letterbars .bar { display: block; background: var(--accent); border-radius: 3px 3px 0 0; min-height: 1px; } +.letterbars .l { font-size: 9.5px; color: var(--dim); text-align: center; line-height: 12px; } + +/* ---------------------------------------------------------------- reader */ +.reader-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(var(--cell, 220px), 1fr)); gap: var(--gap); } +.reader-grid.tiny { --cell: 120px; } +.rcard { overflow: hidden; display: flex; flex-direction: column; gap: 4px; min-height: 0; max-height: 260px; cursor: pointer; } +.rcard:hover { outline: 2px solid var(--accent); } +.rcard h3 { margin: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; } +.rcard .body { font-size: .95em; overflow: hidden; white-space: pre-wrap; overflow-wrap: anywhere; } +.rcard.tiny { max-height: 90px; padding: 6px 8px; } +.expand { max-width: 820px; margin: 0 auto; padding: 18px 22px; } +.expand h2 { font-size: 1.8em; margin-bottom: .1em; } +.expand { display: flex; flex-direction: column; gap: 8px; } +.expand .dates b { font-weight: 600; color: var(--text); } +.expand .text { white-space: pre-wrap; font-size: 1.12em; line-height: 1.6; overflow-wrap: anywhere; } +.md h1 { font-size: 1.5em; } .md h2 { font-size: 1.3em; } .md pre { background: var(--code); padding: 8px; border-radius: var(--radius); overflow: auto; } +.md code { font-family: var(--mono); background: var(--code); padding: 0 3px; border-radius: 3px; } +.md blockquote { margin: .4em 0; padding-left: 10px; border-left: 4px solid var(--accent); color: var(--dim); } + +/* ---------------------------------------------------------------- notes */ +/* the view never scrolls itself (its list and its pad do), so nothing drags it sideways */ +.view.notes { overflow: hidden; } +.notes { position: absolute; inset: 0; display: grid; grid-template-columns: 250px minmax(0, 1fr); gap: var(--gap); min-width: 0; } +.notes.no-list { grid-template-columns: minmax(0, 1fr); } +.notes.list-right { grid-template-columns: minmax(0, 1fr) 250px; } +.notes.list-right .notelist { order: 2; } +/* slid away: the list waits off its edge and slides in while the pointer is near it */ +.notes.no-list .list-edge { position: absolute; top: 0; bottom: 0; left: 0; width: 10px; z-index: 5; } +.notes.no-list.list-right .list-edge { left: auto; right: 0; } +.notes.no-list .notelist { position: absolute; top: 0; bottom: 0; left: 0; width: 250px; z-index: 6; + transform: translateX(calc(-100% - 16px)); transition: transform .15s ease; box-shadow: 0 4px 18px rgb(0 0 0 / .25); } +.notes.no-list.list-right .notelist { left: auto; right: 0; transform: translateX(calc(100% + 16px)); } +.notes.no-list .list-edge:hover + .notelist, .notes.no-list .notelist:hover, .notes.no-list .notelist:focus-within { transform: none; } +.notelist { display: flex; flex-direction: column; gap: 6px; padding: 6px; overflow: hidden; min-height: 0; } +.notelist ul { list-style: none; margin: 0; padding: 0; overflow-y: auto; overflow-x: hidden; flex: 1; min-height: 0; display: flex; flex-direction: column; gap: 2px; } +.notelist li { padding: 4px 8px; border-radius: var(--radius); cursor: pointer; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; flex: none; } +.notelist li .when { display: block; font-size: 11px; color: var(--dim); } +.notelist li:hover { background: color-mix(in srgb, var(--buttons) 35%, transparent); } +.notelist li:focus-visible { outline: 2px solid var(--accent); outline-offset: -2px; } +.notelist li.on { background: var(--accent); color: var(--on-button); } +.notelist li.on .when { color: inherit; opacity: .8; } +.editor { display: flex; flex-direction: column; gap: 6px; padding: 8px; min-height: 0; min-width: 0; overflow: hidden; } +.editor .head { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; min-width: 0; } +.editor .title { font-weight: 700; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 60px; max-width: 40%; } +.tagchips { flex: 1; display: flex; flex-wrap: wrap; gap: 4px; align-items: center; min-width: 120px; } +.tagchips .chip .x { margin-left: 4px; opacity: .7; } +.tagchips input.taginput { width: 110px; height: 22px; font-size: 13px; } +button.plain.on { background: var(--accent); color: var(--on-button); } +/* the pad: a transparent-glyph textarea over the highlighting layer, both the same box */ +.pad { position: relative; flex: 1; min-height: 0; background: var(--pad); border-radius: 5px; overflow: hidden; } +.pad textarea, .pad pre.hl { + position: absolute; inset: 0; margin: 0; padding: 10px; border: 0; border-radius: 5px; + font: 15px/1.45 var(--mono); letter-spacing: 0; tab-size: 4; white-space: pre-wrap; overflow-wrap: anywhere; word-break: normal; +} +.pad textarea { width: 100%; height: 100%; resize: none; background: transparent; color: var(--text); z-index: 1; } +/* both always keep the same scrollbar room, so their lines wrap alike; the layer's is invisible */ +.pad textarea, .pad pre.hl { overflow-y: scroll; overflow-x: hidden; scrollbar-width: thin; } +.pad textarea::-webkit-scrollbar, .pad pre.hl::-webkit-scrollbar { width: 10px; } +.pad textarea::-webkit-scrollbar-thumb { background: color-mix(in srgb, var(--dim) 45%, transparent); border-radius: 5px; border: 2px solid transparent; background-clip: padding-box; } +.pad pre.hl { scrollbar-color: transparent transparent; } +.pad pre.hl::-webkit-scrollbar-thumb, .pad pre.hl::-webkit-scrollbar-track { background: transparent; } +.pad.hl-on textarea { color: transparent; caret-color: var(--text); } +.pad.hl-on textarea::selection { background: color-mix(in srgb, var(--accent) 45%, transparent); color: transparent; } +.pad pre.hl { color: var(--text); pointer-events: none; z-index: 0; background: none; } +/* the layer's typing segments are blocks, so a changed one lays out on its own (a + block's last line break draws no line, and the next block starts a new one: the lines + are the same as the text's) */ +.pad pre.hl > span { display: block; contain: layout style; } +.pad:not(.hl-on) pre.hl { visibility: hidden; } +.hl .h-m { color: var(--hl-mark); } +.hl .h-h { color: var(--hl-heading); font-weight: 700; } +.hl .h-s { font-weight: 700; } +.hl .h-e { color: var(--hl-emph); font-style: italic; } +.hl .h-x { color: var(--hl-strike); text-decoration: line-through; } +.hl .h-c { color: var(--hl-code); background: color-mix(in srgb, var(--code) 70%, transparent); border-radius: 2px; } +.hl .h-l { color: var(--hl-link); text-decoration: underline; } +.hl .h-u { color: var(--hl-url); } +.hl .h-li, .hl .h-t { color: var(--hl-list); font-weight: 700; } +.hl .h-q { color: var(--hl-quote); } +.hl .h-g { color: var(--hl-tag); } +.hl .h-r { color: var(--hl-rule); } +/* a flagged stretch (spelling, grammar): a wavy underline under the glyphs */ +.hl mark.flag { background: none; color: inherit; text-decoration: underline wavy; text-decoration-thickness: 1.5px; text-underline-offset: 3px; } +.hl mark.flag.spell { text-decoration-color: hsl(2 75% 52%); } +.hl mark.flag.grammar { text-decoration-color: hsl(215 75% 52%); } +.spell-pick { position: fixed; z-index: 60; min-width: 160px; display: flex; flex-direction: column; gap: 2px; padding: 6px; background: var(--cards); color: var(--text); border-radius: var(--radius); box-shadow: 0 4px 18px rgb(0 0 0 / .22); } +.spell-pick button { justify-content: space-between; display: flex; gap: 12px; text-align: left; } +.spell-note { margin-top: 4px; } +/* what classifiers say of an entry (views/judge.rs) */ +.judge { display: flex; flex-direction: column; gap: 6px; background: var(--code); border-radius: 5px; padding: 8px 10px; flex: none; max-height: 40%; overflow: auto; } +.judge-pick { gap: 4px; } +.judge .chip:not(.on) { background: color-mix(in srgb, var(--buttons) 45%, transparent); color: var(--text); } +.verdict { display: flex; flex-direction: column; gap: 3px; padding-top: 4px; border-top: 1px solid color-mix(in srgb, var(--dim) 25%, transparent); } +.verdict .probs { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 2px 14px; } +.prob { display: flex; align-items: center; gap: 8px; font-size: 12.5px; } +.prob .c { width: 90px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.prob.best .c { font-weight: 700; } +.prob .p { width: 46px; text-align: right; color: var(--dim); font-variant-numeric: tabular-nums; } + +/* ---------------------------------------------------------------- tags, stats, models, filters */ +.taglist { display: flex; flex-wrap: wrap; gap: 4px; } +.stats-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: var(--gap); } +.stat b { display: block; font-size: 1.8em; line-height: 1.1; } +.stat span { font-size: .85em; color: var(--dim); } +.bars { display: grid; gap: 3px; } +.hbar { display: grid; grid-template-columns: minmax(80px, 180px) 1fr 50px; gap: 8px; align-items: center; font-size: 13px; } +.hbar .track { height: 8px; } +.hbar .fill { display: block; height: 100%; background: var(--accent); border-radius: 0 4px 4px 0; min-width: 3px; } +.hbar .n { text-align: right; color: var(--dim); font-variant-numeric: tabular-nums; } +.results { display: flex; flex-direction: column; gap: 2px; } +.result { display: flex; gap: 8px; align-items: center; padding: 2px 4px; border-radius: 3px; } +.result:hover { background: color-mix(in srgb, var(--buttons) 25%, transparent); } +.result .p { width: 52px; text-align: right; font-variant-numeric: tabular-nums; color: var(--dim); font-size: 12.5px; flex: none; } +.result .t { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.probbar { width: 80px; height: 6px; background: var(--pad); border-radius: 3px; flex: none; overflow: hidden; } +.probbar span { display: block; height: 100%; background: var(--accent); } +.builder { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: var(--gap); } +.builder .card h3 { display: flex; align-items: center; gap: 6px; } +.cond { display: flex; gap: 4px; align-items: center; flex-wrap: wrap; padding: 3px 0; } + +/* ---------------------------------------------------------------- the space */ +/* the space fills the window behind the bars, as the Bevy app's 3D view did; its panels sit + between the bars */ +.app.v-space { background: transparent; } +.view.space { position: fixed; inset: 0; z-index: 0; overflow: hidden; } +.space { overflow: hidden; background: var(--room-bg, #e4d4be); --over-top: calc(var(--top) + 2 * var(--frame)); --over-bottom: calc(var(--barh) + 2 * var(--frame)); } +.space-host { position: absolute; inset: 0; overflow: hidden; outline: 0; } +.space-host.looking { cursor: none; } +.space-gl, .space-css { position: absolute !important; inset: 0; } +.space-css { pointer-events: none; overflow: hidden; z-index: 1; } +.space-css .slabel { position: absolute; left: 0; top: 0; transform-origin: 50% 50%; } +.slabel { + pointer-events: auto; cursor: grab; line-height: 1.15; padding: 0 3px; text-align: center; white-space: pre-wrap; width: max-content; + color: var(--room-ink); font-family: var(--font); border-bottom: .12em solid transparent; user-select: none; + text-shadow: 0 0 2px var(--room-bg); backface-visibility: hidden; +} +.slabel.dragging { cursor: grabbing; } +/* hovered and selected texts take the Bevy space's accent */ +.slabel.hover, .slabel.selected { color: #e811a0 !important; } +.slabel.selected { text-decoration: underline dotted; text-decoration-thickness: .06em; } +.slabel.picked { background: color-mix(in srgb, var(--accent) 40%, transparent); } +.slabel.pinned::after { content: "•"; font-size: .5em; vertical-align: super; color: var(--accent); margin-left: 2px; } +.slabel.free { font-style: italic; } +/* a detached copy (keeps the text it was copied with) and a copy with its own text */ +.slabel.det::before, .slabel.own::before { font-size: .5em; vertical-align: super; color: var(--accent); margin-right: 2px; } +.slabel.det::before { content: "◇"; } +.slabel.own::before { content: "◆"; } +.poscard { position: absolute; top: calc(var(--over-top) + 2px); left: calc(var(--frame) + 2px); z-index: 2; pointer-events: none; white-space: pre; background: color-mix(in srgb, var(--cards) 92%, transparent); color: var(--text); font: 12px var(--mono); padding: 2px 8px; border-radius: var(--radius); } +/* the space's windows: moved by their title bar, their close button showing on hover */ +.space { --win-w: min(320px, calc(100vw - 16px)); } +.win { + position: absolute; z-index: 4; width: var(--win-w); max-height: calc(100vh - var(--over-top) - var(--over-bottom) - 8px); + display: flex; flex-direction: column; background: color-mix(in srgb, var(--cards) 94%, transparent); color: var(--text); + border-radius: var(--radius); box-shadow: 0 4px 18px rgb(0 0 0 / .22); font: 13px/1.4 var(--font); +} +.win-head { display: flex; align-items: center; gap: 6px; padding: 5px 6px 4px 10px; cursor: move; user-select: none; touch-action: none; border-bottom: 1px solid color-mix(in srgb, var(--dim) 18%, transparent); } +.win-title { flex: 1; font-weight: 700; font-size: 14px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; display: flex; align-items: center; gap: 4px; } +.win-head .win-title, .win-head .win-title * { pointer-events: none; } +.win-head .close { opacity: 0; transition: opacity .15s; height: 20px; width: 22px; } +.win:hover .win-head .close, .win-head .close:focus-visible { opacity: 1; } +.win-body { padding: 6px 10px 8px; overflow: hidden auto; min-height: 0; } +.scene-open { min-width: 0; } +.blocks-add { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; margin-bottom: 8px; } +.blocks-add .row, .blocks-sel .row { display: inline-flex; gap: 4px; align-items: center; } +.blocks-add select { max-width: 120px; } +.blocks-add input[type=color] { width: 30px; height: 24px; padding: 0 2px; border: 0; background: none; cursor: pointer; } +.blocks-sel { border-top: 1px solid color-mix(in srgb, var(--dim) 18%, transparent); padding-top: 6px; display: flex; flex-direction: column; gap: 6px; } +.bfields { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px 8px; } +.bfield { display: flex; align-items: center; gap: 4px; font: 12px var(--mono); color: var(--dim); } +.bfield input { width: 100%; min-width: 0; font: 12px var(--mono); padding: 2px 4px; } +.win-drag { position: fixed; inset: 0; z-index: 90; cursor: move; touch-action: none; user-select: none; } +.metrics-table { border-collapse: collapse; font-variant-numeric: tabular-nums; } +.metrics-table th { text-align: left; font-weight: 400; color: var(--dim); padding: 0 6px 0 0; white-space: nowrap; } +.metrics-table td { padding: 0 12px 0 0; } +.win .num { cursor: pointer; color: var(--link); } +.win .num:hover { text-decoration: underline; } +.win .gsum { font: 11.5px var(--mono); margin: 4px 0; overflow-wrap: anywhere; } +.win .pf { font-size: 11.5px; color: var(--dim); overflow-wrap: anywhere; } +.win .pf i { cursor: pointer; color: var(--link); } +.win svg.triangle polygon { stroke: var(--text); } +/* the physics panel */ +.win .physics { display: flex; flex-direction: column; gap: 6px; } +.pgroup h4 { margin: 2px 0 2px; font-size: 12px; color: var(--dim); font-weight: 600; } +.pslider { display: grid; grid-template-columns: 1fr 92px 38px; gap: 6px; align-items: center; font-size: 12px; } +.pslider .pname { cursor: default; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.pslider input[type=range] { width: 100%; } +.pslider .pval { text-align: right; color: var(--dim); font-variant-numeric: tabular-nums; } +.pslider select { height: 22px; font-size: 12px; } +.space-empty { position: absolute; left: 50%; top: 40%; transform: translate(-50%, -50%); z-index: 1; pointer-events: none; width: min(440px, calc(100% - 32px)); text-align: center; color: var(--room-ink); font-size: 15px; } +.space-help { position: absolute; left: 50%; transform: translateX(-50%); top: calc(var(--over-top) + 4px); width: min(980px, calc(100vw - 24px)); max-height: calc(100vh - var(--over-top) - var(--over-bottom) - 12px); overflow: auto; z-index: 5; font-size: 12.5px; background: color-mix(in srgb, var(--cards) 96%, transparent); color: var(--text); padding: 8px 14px; border-radius: var(--radius); box-shadow: 0 4px 18px rgb(0 0 0 / .22); } +.space-help .close { position: absolute; right: 6px; top: 6px; } +.help-cols { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 4px 20px; } +.help-cols h4 { margin: 4px 0 2px; font-size: 12.5px; color: var(--dim); } +.help-cols td { padding: 1px 8px 1px 0; vertical-align: top; } + +/* zen: the bars fade while you rest (the views keep their room); the top bar can slide away + and come back when the pointer nears the top */ +.app .top, .app .dock, .app .mem-head, .app .mem-hover { transition: opacity .6s, transform .25s ease; } +.app.zen.idle .top, .app.zen.idle .dock, .app.zen.idle .mem-hover { opacity: 0; } +.app.zen.idle { cursor: none; } +.app.zen.idle.peek .top { opacity: 1; } +.app.hide-bar { grid-template-rows: minmax(0, 1fr) auto; } +.app.hide-bar .top { position: fixed; left: 0; right: 0; top: 0; height: var(--top); z-index: 30; transform: translateY(-100%); box-shadow: 0 2px 10px rgb(0 0 0 / .3); } +.app.hide-bar.peek .top, .app.hide-bar .top:focus-within { transform: none; } + +/* markdown read: the reader's expanded note and the notes view's reading mode */ +.md.rendered { flex: 1; overflow: auto; padding: 4px 10px; min-height: 0; } +.md { line-height: 1.55; overflow-wrap: anywhere; } +.md ul, .md ol { padding-left: 1.6em; } +.md li::marker { color: var(--accent); } +.md table { border-collapse: collapse; } +.md th, .md td { padding: 3px 8px; border-bottom: 1px solid color-mix(in srgb, var(--accent) 45%, transparent); } +.md img { max-width: 100%; } +.md a { color: var(--link); } +.import input[type=text] { background: var(--cards); } + +/* ---------------------------------------------------------------- classifiers */ +.page.wide { max-width: 1180px; } +.cls-layout { display: grid; grid-template-columns: 230px minmax(0, 1fr); gap: var(--gap); align-items: start; } +.cls-list { display: flex; flex-direction: column; gap: 2px; padding: 6px; position: sticky; top: 0; max-height: calc(100vh - var(--top) - var(--barh) - 60px); overflow: auto; } +button.cls-item { display: flex; flex-direction: column; align-items: flex-start; height: auto; padding: 4px 8px; gap: 0; background: none; color: var(--text); text-align: left; white-space: normal; } +button.cls-item:hover { background: color-mix(in srgb, var(--buttons) 35%, transparent); filter: none; } +button.cls-item.on { background: var(--accent); color: var(--on-button); } +button.cls-item .small { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; max-width: 100%; opacity: .85; } +button.cls-item .state { font-size: 11px; opacity: .7; } +.cls-main, .cls-page { display: flex; flex-direction: column; gap: var(--gap); min-width: 0; } +.cls-head h2 { margin: 0 6px 0 0; overflow-wrap: anywhere; } +.chip.cls-class { background: hsl(var(--hue) 40% 52%); color: #fff; } +.form { display: grid; grid-template-columns: minmax(110px, 170px) minmax(0, 1fr); gap: 6px 12px; align-items: center; padding: 4px 0 8px; } +.form > label { color: var(--dim); } +.form .col { display: flex; flex-direction: column; gap: 4px; } +.card h3 { display: flex; align-items: center; gap: 6px; } +.progress { height: 10px; background: var(--pad); border-radius: 5px; overflow: hidden; margin: 6px 0 4px; } +.progress span { display: block; height: 100%; background: var(--accent); transition: width .3s; } +svg.spark { display: block; margin-top: 4px; overflow: visible; } +svg.spark polyline { fill: none; stroke: var(--accent); stroke-width: 1.5; stroke-linejoin: round; } +table.confusion { border-collapse: collapse; font-size: 12.5px; margin-top: 6px; font-variant-numeric: tabular-nums; } +table.confusion th, table.confusion td { padding: 2px 8px; text-align: right; border-bottom: 1px solid color-mix(in srgb, var(--dim) 20%, transparent); } +table.confusion th:first-child { text-align: left; } +table.confusion thead th { font-weight: 400; color: var(--dim); } +table.confusion td.hit { font-weight: 700; } +table.confusion td.miss { color: var(--bad); } +.result.best .t { font-weight: 700; } +.cls-new .chip.on, .cls-page .chip.on { box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--text) 60%, transparent); font-weight: 600; } +.result .t .swatch { display: inline-block; width: 9px; height: 9px; border-radius: 50%; background: hsl(var(--hue) 45% 55%); margin-right: 6px; } +.probbar.wide { width: min(260px, 34%); height: 8px; } +.num { font: 12px var(--mono); color: var(--dim); width: 44px; text-align: right; flex: none; } +.t.dim.small { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0; } +.starters .starter { padding: 10px 0; border-top: 1px solid var(--pad); display: flex; flex-direction: column; gap: 4px; } +.starters .starter .row { flex-wrap: wrap; gap: 6px; align-items: center; } +.held-out .big { font-size: 1.6em; } +@media (max-width: 700px) { .cls-layout { grid-template-columns: 1fr; } .cls-list { position: static; max-height: 30vh; } } +/* the page's controls sit at the right: their tips open leftwards, inside the window */ +.page.wide [data-tip]::after { left: auto; right: 0; transform: none; } +/* a classifier's colours in the memory view */ +.tint-legend { display: flex; flex-wrap: wrap; gap: 4px 12px; justify-content: center; padding: 3px; font: 12.5px var(--font); color: #ddd; } +.tint-legend .dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; margin-right: 5px; } +.tintpick { gap: 4px; margin-left: 6px; } +.tintpick .icon-l { display: inline-flex; color: var(--bar-dim); } +.tintpick select { border-radius: var(--radius); height: 20px; padding: 0 18px 0 6px; background-position: right 5px center; font-size: 12px; background: transparent; color: var(--bar-text); border: 1px solid color-mix(in srgb, var(--bar-dim) 45%, transparent); } +.tintpick select option { color: #000; background: #fff; } + +/* ---------------------------------------------------------------- spec models */ +.mtabs { display: flex; gap: 0; flex: none; border-radius: var(--radius); overflow: hidden; margin-right: 6px; } +.mtabs button.mtab { border-radius: 0; background: color-mix(in srgb, var(--buttons) 40%, transparent); color: var(--text); font-size: 1.05em; font-weight: 600; } +.mtabs button.mtab.on { background: var(--accent); color: var(--on-button); } +.spec-editor { display: flex; flex-direction: column; gap: 4px; } +.spec-editor textarea.spec-text { width: 100%; font: 13px/1.45 var(--mono); padding: 8px 10px; resize: vertical; tab-size: 2; white-space: pre; overflow: auto; } +.spec-err { display: flex; gap: 6px; align-items: baseline; color: var(--bad); overflow-wrap: anywhere; } +.spec-err code { font: 12px var(--mono); background: color-mix(in srgb, var(--bad) 14%, transparent); padding: 0 4px; border-radius: 3px; flex: none; } +.spec-ok { color: var(--dim); display: flex; gap: 4px; align-items: center; } +.spec-head h4 { margin: 8px 0 2px; font-size: 13px; color: var(--dim); font-weight: 600; } +.spec-out { font: 14px/1.45 var(--mono); white-space: pre-wrap; overflow-wrap: anywhere; background: var(--pad); padding: 6px 8px; border-radius: var(--radius); } +.spec-img { image-rendering: pixelated; width: 192px; border-radius: var(--radius); } +.row.wrap { flex-wrap: wrap; } +.cands { gap: 6px; margin-top: 6px; } +.cand { padding: 4px 6px; border-radius: var(--radius); background: color-mix(in srgb, var(--pad) 60%, transparent); } +.cand.broken { opacity: .6; } +.cand .cand-text { flex: 1; font: 13.5px/1.4 var(--mono); white-space: pre-wrap; overflow-wrap: anywhere; min-width: 0; } +.cand .p { width: 38px; text-align: right; color: var(--dim); font-variant-numeric: tabular-nums; flex: none; } +.cand .chip { font-size: 11.5px; } +.menu .kindrow { display: flex; gap: 8px; align-items: center; padding: 2px 10px 6px; flex-wrap: wrap; } +.menu .kindrow label { display: flex; gap: 6px; align-items: center; } +.menu .kindrow select { height: 24px; } + +/* the pictures panel (views/pictures.rs) */ +.pictures { flex: none; display: flex; flex-direction: column; gap: 8px; } +.pictures.over { box-shadow: inset 0 0 0 2px var(--accent); } +.pictures label.button { display: inline-flex; align-items: center; gap: 4px; height: 24px; padding: 0 9px; border-radius: var(--radius); background: var(--buttons); color: var(--on-button); cursor: pointer; } +.pictures .chips { flex-wrap: wrap; gap: 4px; } +.pic-drop { border: 1px dashed color-mix(in srgb, var(--dim) 60%, transparent); border-radius: var(--radius); padding: 18px; text-align: center; } +.pic-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: var(--gap); } +.pic { display: flex; flex-direction: column; gap: 4px; background: var(--pad); border-radius: var(--radius); padding: 6px; min-width: 0; } +.pic img { width: 100%; height: 128px; object-fit: contain; image-rendering: auto; background: color-mix(in srgb, var(--dim) 12%, transparent); border-radius: var(--radius); } +.pic-name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.pic-lists { display: flex; flex-wrap: wrap; gap: 3px; min-height: 0; } +.pic-lists .chip button.plain { height: 16px; width: 16px; padding: 0; } +.pic-tools input { flex: 1; height: 24px; } + +/* the memory view's search filter (views/memory.rs) */ +.filter-panel { position: fixed; right: 12px; bottom: 84px; font-family: var(--font); z-index: 40; width: min(420px, calc(100vw - 24px)); max-height: 60vh; overflow: auto; background: var(--cards); color: var(--text); border-radius: var(--radius); padding: 8px 10px; box-shadow: 0 4px 18px rgba(0,0,0,.35); display: flex; flex-direction: column; gap: 6px; font-size: 13px; } +.filter-panel .fgroup { display: flex; flex-wrap: wrap; gap: 4px; align-items: center; } +.filter-panel .fgroup > span:first-child { min-width: 64px; } +.filter-panel .chip:not(.on) { background: color-mix(in srgb, var(--buttons) 35%, transparent); color: var(--text); } +.filter-note { text-align: center; color: #bbb; font-size: 12px; padding: 2px; } +.filter-square { margin-left: 6px; } + +/* the editor's replacements (views/notes.rs) */ +.editor .replace { gap: 6px; flex-wrap: wrap; } +.editor .replace select { max-width: 280px; } +.editor .replace input { width: min(260px, 100%); } + +/* the classifier page's tabs and extras (views/clsmore.rs) */ +.cls-tabs { display: flex; gap: 4px; padding: 4px 6px; } +.cls-tabs button { gap: 6px; } +table.growth { border-collapse: collapse; font-size: 12.5px; width: 100%; font-variant-numeric: tabular-nums; } +table.growth th { text-align: left; font-weight: 400; color: var(--dim); padding: 2px 8px 2px 0; } +table.growth td { padding: 2px 8px 2px 0; border-top: 1px solid color-mix(in srgb, var(--dim) 15%, transparent); } +.bgrid { display: grid; grid-template-columns: minmax(110px, 180px) 46px 1fr; gap: 4px 10px; align-items: center; margin: 6px 0; } +.bscale { display: flex; justify-content: space-between; } +button.bclass { justify-content: flex-start; gap: 6px; color: var(--text); height: 26px; } +.bclass .dot { width: 10px; height: 10px; border-radius: 2px; display: inline-block; } +.bands { display: grid; grid-template-columns: repeat(10, 1fr); gap: 3px; height: 30px; } +button.band { height: 30px; padding: 0; background: color-mix(in srgb, var(--pad) 70%, transparent); border-radius: 3px; display: flex; align-items: flex-end; overflow: hidden; } +button.band span { display: block; width: 100%; min-height: 0; border-radius: 0 0 3px 3px; } +button.band:hover { box-shadow: inset 0 0 0 1px var(--accent); } +.bucket-texts { border-top: 1px solid color-mix(in srgb, var(--dim) 25%, transparent); padding-top: 6px; margin-top: 4px; max-height: 360px; overflow: auto; } +.result .t { cursor: pointer; } +.wide-label { margin-top: 6px; font-weight: 600; color: var(--text) !important; } +h3 .dim.small, h3 .small { font-weight: 400; } + +/* the filters' builder (views/flt.rs) */ +.fgroup { display: flex; flex-direction: column; gap: 4px; padding: 6px 8px; border-left: 3px solid color-mix(in srgb, var(--accent) 60%, transparent); background: color-mix(in srgb, var(--pad) 45%, transparent); border-radius: var(--radius); margin: 2px 0; } +.fgroup.root { border-left-color: var(--accent); } +.fgroup .cond { gap: 6px; padding: 2px 0; } +.fgroup select { height: 24px; } +.kept { padding: 3px 0; border-top: 1px solid color-mix(in srgb, var(--dim) 15%, transparent); } + +/* the bars swapped: the command bar at the top, the top bar at the bottom */ +.app.swapped { grid-template-rows: auto minmax(0, 1fr) var(--top); } +.app.swapped .dock { order: -1; } +.app.swapped .views { order: 0; } +.app.swapped .top { order: 1; } +.app.swapped [data-tip].tip-up::after { bottom: auto; top: calc(100% + 6px); } +/* the forge (views/forge.rs) */ +.dialog.forge { width: min(1100px, calc(100vw - 16px)); } +.forge-cols { display: grid; grid-template-columns: 1fr 1fr 1.4fr; gap: 12px; } +.fcol { display: flex; flex-direction: column; gap: 4px; min-width: 0; } +.fcol h3 { margin: 4px 0; } +.fsave button { width: 26px; padding: 0; font-weight: 700; } +.fsample { max-height: 180px; overflow: auto; background: var(--pad); border-radius: var(--radius); padding: 4px 8px; } +a.btn { text-decoration: none; } +.top .side, .top .status { z-index: 1; } +@media (max-width: 800px) { .forge-cols { grid-template-columns: 1fr; } } +.hbar button.tag-open { justify-content: flex-start; height: 20px; padding: 0 4px; color: var(--link); } + +/* the hub section (views/hubui.rs) */ +.hub-list { display: flex; flex-direction: column; gap: 4px; max-height: 340px; overflow: auto; background: var(--pad); border-radius: var(--radius); padding: 6px 8px; } +.hub-item { padding: 3px 0; border-bottom: 1px solid color-mix(in srgb, var(--dim) 18%, transparent); } +.progress + .row .device { color: var(--accent); font-weight: 600; } +/* the room never selects as text when dragged across */ +.space-host, .space-host * { user-select: none; -webkit-user-select: none; } + +.menu.smenu { max-height: calc(100vh - 16px); overflow-y: auto; } +.scenes { display: flex; flex-direction: column; gap: 3px; } +.scene { display: flex; align-items: center; gap: 4px; } +.scene.on .scene-open b { color: var(--link); } +.scene-open { flex: 1; justify-content: flex-start; text-align: left; overflow: hidden; } +.scene-name { flex: 1; min-width: 0; } +.scene-save { margin-top: 6px; gap: 4px; } +.scene-save input { flex: 1; min-width: 0; } +.scenes input { font: 13px var(--font); background: var(--pad, #ddd); color: var(--text); border: 0; border-radius: var(--radius); padding: 3px 6px; } +.cmdbar select.search-mode { height: 22px; font-size: 11.5px; padding: 0 18px 0 6px; background-color: color-mix(in srgb, var(--bar-text) 10%, transparent); color: var(--bar-text); border: 0; } +.checkpoints { display: flex; flex-direction: column; gap: 3px; padding: 2px 0 6px 12px; border-left: 2px solid color-mix(in srgb, var(--accent) 50%, transparent); } +.checkpoints .checkpoint { gap: 8px; align-items: center; } +.checkpoints .grow { flex: 1; } +/* a placement's size: − value + (the space's menu and details window) */ +.size-row { flex-wrap: nowrap; gap: 4px; padding: 2px 0; } +.size-row > * { flex: none; } +.smenu .size-row { padding: 4px 12px; } +.size-row .num { white-space: nowrap; width: 14ch; text-align: center; } +.size-row button.btn.small { width: auto; min-width: 26px; padding: 1px 8px; justify-content: center; } +/* chains in the space: the members hang under their head, a rule at their left */ +.slabel.member { border-left: 2px solid color-mix(in srgb, var(--accent) 80%, transparent); padding-left: 5px; } +.slabel.chain-head { font-weight: 600; } +.menu .rot-up { transform: rotate(-90deg); } +.menu .rot-down { transform: rotate(90deg); } +/* a block's turn and bend (the blocks window) */ +.turn-row { gap: 4px; margin: 4px 0; } +.blocks-sel details.bend { margin: 4px 0 6px; } +.blocks-sel details.bend summary { cursor: pointer; font-weight: 600; } +.bend-editor { display: flex; flex-direction: column; gap: 8px; margin-top: 4px; } +.bend-part { display: flex; flex-direction: column; gap: 2px; } +.bend-curve { background: color-mix(in srgb, var(--pad, #ddd) 70%, transparent); border-radius: var(--radius); touch-action: none; } +.bend-curve .axis { stroke: color-mix(in srgb, var(--dim) 50%, transparent); stroke-dasharray: 3 3; } +.bend-curve .handle { stroke: color-mix(in srgb, var(--accent) 70%, transparent); } +.bend-curve .curve { fill: none; stroke: var(--text); stroke-width: 2; } +.bend-curve .ctl { fill: var(--accent); stroke: var(--text); cursor: ns-resize; } +.bend-curve .catch { fill: transparent; cursor: ns-resize; } +.bend-slider { display: grid; grid-template-columns: 9em 1fr 3.5em; gap: 6px; align-items: center; font-size: 12px; } +.bend-slider .num { width: auto; } + +/* a colour as hue, saturation, lightness and hex (settings, looks) */ +.hsl-edit { display: flex; flex-direction: column; gap: 6px; } +.hsl-sliders { display: grid; gap: 4px; } +.hsl-sliders label { display: grid; grid-template-columns: 6.5em 1fr 3.5em; gap: 8px; align-items: center; font-size: 12.5px; } +.hsl-sliders .num { width: auto; } +.hsl-swatch { display: block; height: 18px; border-radius: var(--radius); border: 1px solid color-mix(in srgb, var(--text) 25%, transparent); } +.hsl-sliders input.hue { accent-color: var(--accent); } +/* the textures window: saved recipes, then the pipeline's steps from source to use */ +.tx-saved { display: flex; flex-wrap: wrap; gap: 6px; margin-bottom: 8px; } +.tx-item { display: flex; flex-direction: column; align-items: center; gap: 2px; width: 64px; } +.tx-item canvas { width: 56px; height: 56px; border-radius: 4px; cursor: pointer; box-shadow: 0 0 0 1px color-mix(in srgb, var(--dim) 30%, transparent); } +.tx-item span { max-width: 64px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.tx-item button { padding: 0 4px; height: 18px; } +.tx-steps { display: flex; flex-direction: column; } +.tx-step { border: 1px solid color-mix(in srgb, var(--dim) 22%, transparent); border-radius: 6px; padding: 6px 8px; display: flex; flex-direction: column; gap: 6px; } +.tx-step-head { display: flex; align-items: center; gap: 6px; min-width: 0; } +.tx-step-head .dim { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.tx-n { display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 50%; background: var(--accent); color: var(--on-button); font-size: 11px; font-weight: 700; flex: none; } +.tx-arrow { text-align: center; color: var(--dim); line-height: 14px; } +.tx-step .row { display: flex; gap: 6px; align-items: center; } +.tx-step .row.wrap { flex-wrap: wrap; } +.tx-step select { max-width: 150px; } +.tx-step input[type=color] { width: 30px; height: 24px; padding: 0 2px; border: 0; background: none; cursor: pointer; } +.tx-crop { position: relative; align-self: center; touch-action: none; } +.tx-crop canvas { width: 100%; height: 100%; display: block; border-radius: 3px; } +.tx-cropbox { position: absolute; border: 2px solid var(--accent); box-shadow: 0 0 0 9999px rgba(0, 0, 0, .35); pointer-events: none; box-sizing: border-box; } +.tx-crop { overflow: hidden; } +.tx-crop-grip { position: absolute; inset: 0; cursor: crosshair; } +.tx-tile-row { display: flex; gap: 8px; align-items: center; } +.tx-tile-row canvas { width: 96px; height: 96px; flex: none; border-radius: 3px; } +.tx-sliders { display: flex; flex-direction: column; gap: 2px; flex: 1; min-width: 0; } +.tx-sliders label { display: flex; align-items: center; gap: 6px; font-size: 12px; } +.tx-sliders label span { width: 46px; color: var(--dim); } +.tx-sliders input { flex: 1; min-width: 0; } +.tx-patch { width: 200px; height: 200px; align-self: center; border-radius: 3px; } +.win:has(.tx-steps) { --win-w: min(360px, calc(100vw - 16px)); } +.tx-name { flex: 1; min-width: 0; height: 24px; } +.tx-faces button { padding: 0 6px; } +/* the lights window */ +.lt-add { display: flex; gap: 6px; align-items: center; flex-wrap: wrap; margin-bottom: 6px; } +.lt-list { display: flex; flex-direction: column; gap: 2px; margin-bottom: 6px; } +.lt-row { display: flex; justify-content: flex-start; width: 100%; align-items: center; gap: 8px; padding: 3px 6px; border-radius: 4px; background: none; border: 0; text-align: left; color: inherit; cursor: pointer; } +.lt-row:hover { background: color-mix(in srgb, var(--dim) 12%, transparent); } +.lt-row.on { background: color-mix(in srgb, var(--accent) 30%, transparent); } +.lt-swatch { width: 14px; height: 14px; border-radius: 50%; box-shadow: 0 0 0 1px color-mix(in srgb, var(--dim) 40%, transparent); flex: none; } +.lt-edit { display: flex; flex-direction: column; gap: 4px; border-top: 1px solid color-mix(in srgb, var(--dim) 18%, transparent); padding-top: 6px; } +.lt-edit .row { display: flex; gap: 6px; align-items: center; } +.lt-edit .row.wrap { flex-wrap: wrap; } +.lt-edit input[type=color] { width: 30px; height: 24px; padding: 0 2px; border: 0; background: none; cursor: pointer; } +.lt-slider { display: flex; align-items: center; gap: 6px; font-size: 12px; } +.lt-slider > span:first-child { width: 62px; color: var(--dim); flex: none; } +.lt-slider input { flex: 1; min-width: 0; } +.lt-slider .dim { width: 64px; text-align: right; flex: none; } +.zone-row { display: flex; flex-direction: column; gap: 3px; margin: 4px 0; } +.zone-row .lt-slider > span:first-child { width: 84px; } +.zone-row .lt-slider button { width: 76px; padding: 0 4px; flex: none; } +.zone-row .lt-slider .dim { width: 76px; text-align: center; } +/* the spec builder: the spec's parts as controls, beside the JSON view */ +.sb-tabs { gap: 4px; margin: 6px 0; } +.sb-tabs .tab { border: 0; background: none; padding: 3px 10px; border-radius: var(--radius); color: var(--text); display: inline-flex; gap: 4px; align-items: center; cursor: pointer; } +.sb-tabs .tab.on { background: var(--accent); color: var(--on-button); } +.sb { display: flex; flex-direction: column; gap: 10px; } +.sb-top-err { display: flex; gap: 6px; align-items: center; } +.sb-sec { border: 1px solid color-mix(in srgb, var(--dim) 22%, transparent); border-radius: 6px; padding: 8px 10px; display: flex; flex-direction: column; gap: 6px; } +.sb-sec h4 { margin: 0 0 2px; font-size: 13.5px; } +.sb-sec h4.sb-sub { margin-top: 6px; } +.sb-row { display: grid; grid-template-columns: 120px 1fr; gap: 8px; align-items: center; } +.sb-row.bad .sb-label { color: var(--bad); } +.sb-label { font-size: 12.5px; color: var(--dim); } +.sb-ctl { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; min-width: 0; } +.sb-help { font-size: 11.5px; color: var(--dim); } +.sb-err { font-size: 12px; color: var(--bad); display: inline-flex; gap: 4px; align-items: center; flex-basis: 100%; } +.sb-num { width: 110px; height: 26px; } +.sb-text { min-width: 140px; flex: 1; height: 26px; } +.sb-short { flex: none; min-width: 0; width: 60px; } +.sb-pick { height: 26px; max-width: 260px; } +.sb-slide { display: inline-flex; gap: 6px; align-items: center; flex: 1; min-width: 200px; } +.sb-slide input { flex: 1; } +.sb-val { width: 54px; font-size: 12px; text-align: right; } +.sb-pair { display: inline-flex; gap: 6px; align-items: center; } +.sb-ticks { display: inline-flex; flex-wrap: wrap; gap: 10px; } +.sb-tick { display: inline-flex; gap: 4px; align-items: center; font-size: 12.5px; } +.sb-chips { display: inline-flex; flex-wrap: wrap; gap: 4px; align-items: center; } +.sb-chips .chip { display: inline-flex; gap: 2px; align-items: center; } +.sb-chips .chip button { padding: 0 3px; height: 16px; line-height: 1; } +.sb-chip-in { width: 120px; height: 24px; } +.sb-values { display: inline-flex; flex-wrap: wrap; gap: 6px; } +.sb-value { display: inline-flex; gap: 4px; align-items: center; } +.sb-value .sb-num { width: 80px; } +.sb-item { border-left: 3px solid color-mix(in srgb, var(--accent) 60%, transparent); padding: 4px 0 4px 8px; display: flex; flex-direction: column; gap: 5px; } +.sb-item-head { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; } +.sb-n { display: inline-grid; place-items: center; width: 18px; height: 18px; border-radius: 50%; background: color-mix(in srgb, var(--accent) 40%, transparent); font-size: 11px; font-weight: 700; flex: none; } +.sb-inline { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; } +.sb-more summary { cursor: pointer; font-size: 12.5px; color: var(--dim); margin-bottom: 4px; } +.sb-sec > button.btn, .sb-sec > button.plain { align-self: flex-start; } +.sb-diagram { display: block; font-size: 10.5px; } +.sb-diagram text { fill: var(--text); } +.sb-diagram rect { stroke: color-mix(in srgb, var(--text) 35%, transparent); stroke-width: 1; } +.sb-d-in { fill: color-mix(in srgb, var(--accent) 22%, transparent); } +.sb-d-trunk { fill: color-mix(in srgb, var(--accent) 45%, transparent); } +.sb-d-head { fill: color-mix(in srgb, hsl(140 40% 50%) 30%, transparent); } +.sb-d-data { fill: color-mix(in srgb, hsl(210 50% 55%) 25%, transparent); } +.sb-d-critic { fill: color-mix(in srgb, hsl(0 50% 55%) 25%, transparent); } +.sb-d-line { stroke: color-mix(in srgb, var(--text) 45%, transparent); stroke-width: 1.2; } +.sb-d-teach { fill: none; stroke: hsl(210 50% 55%); stroke-width: 1.2; stroke-dasharray: 4 3; } +.sb-d-judge { stroke: hsl(0 50% 55%); stroke-width: 1.2; stroke-dasharray: 2 2; } +@media (max-width: 560px) { .sb-row { grid-template-columns: 1fr; } } +/* the animations window */ +.anim-list { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 6px; } +.anim-edit { display: flex; flex-direction: column; gap: 6px; } +.anim-edit .row { display: flex; gap: 6px; align-items: center; } +.anim-edit .row.wrap { flex-wrap: wrap; } +.anim-timing { display: flex; gap: 8px; align-items: flex-start; } +.anim-named { display: flex; flex-direction: column; gap: 2px; align-items: flex-start; } +.anim-curve .anim-box { fill: none; stroke: color-mix(in srgb, var(--dim) 30%, transparent); stroke-dasharray: 2 3; } +.anim-track { position: relative; height: 40px; margin: 0 8px; } +.anim-key { position: absolute; top: 0; transform: translateX(-50%); background: none; border: 0; padding: 0; font-size: 15px; line-height: 16px; color: var(--dim); cursor: pointer; } +.anim-key, .anim-key.on, .anim-key:hover { background: none !important; box-shadow: none; width: auto; height: auto; min-width: 0; } +.anim-key.on { color: var(--accent); font-size: 18px; } +.anim-scrub { position: absolute; left: 0; right: 0; bottom: 0; width: 100%; } +.anim-keyed { display: flex; flex-direction: column; gap: 4px; border-top: 1px solid color-mix(in srgb, var(--dim) 18%, transparent); padding-top: 6px; } +.anim-vec { display: flex; flex-direction: column; gap: 2px; } +.anim-vec .lt-slider > span:first-child { width: 20px; } +.anim-use { display: flex; flex-direction: column; gap: 3px; border-top: 1px solid color-mix(in srgb, var(--dim) 18%, transparent); padding-top: 6px; } +/* s code in the notes view: right-aligned, so the acting words stand in a column */ +.pad.code textarea, .pad.code .hl { text-align: right; } +.hl .h-sc { color: var(--hl-heading); font-weight: 700; } +.hl .h-ss { color: var(--hl-mark); font-weight: 700; } +.hl .h-sl { color: var(--hl-code); } +.hl .h-sv { color: var(--hl-tag); } +.hl .h-sn { color: var(--hl-link); } +.hl .h-sb { color: var(--hl-url); } +.hl .h-se { color: var(--hl-mark); font-style: italic; } +.s-run { margin-top: 6px; border: 1px solid color-mix(in srgb, var(--dim) 25%, transparent); border-radius: 6px; padding: 6px 10px; } +.s-run .row { display: flex; align-items: center; gap: 6px; } +.s-out { font: 13px/1.45 var(--mono); white-space: pre-wrap; margin: 4px 0 0; max-height: 240px; overflow: auto; } +.s-err { font: 13px/1.45 var(--mono); color: var(--bad); white-space: pre-wrap; margin: 4px 0 0; } + +/* the wiring window: blocks that cast rays and run programs */ +.wire-sec { display: flex; flex-direction: column; gap: 4px; padding: 6px 0; border-top: 1px solid color-mix(in srgb, var(--dim) 25%, transparent); } +.wire-sec .check { display: inline-flex; align-items: center; gap: 3px; margin-right: 6px; cursor: pointer; } +.wire-sec select, .wire-sec input[type="text"], .wire-sec input[type="number"] { min-width: 0; flex: 1; } +.wire-targets { display: flex; flex-wrap: wrap; gap: 4px; } +.wire-targets .chip button { padding: 0 2px; } +.wire-log { display: flex; flex-direction: column; gap: 3px; padding-top: 6px; border-top: 1px solid color-mix(in srgb, var(--dim) 25%, transparent); max-height: 180px; overflow: auto; } +.wire-log pre { margin: 2px 0 0; } + +/* the prefabs window: the menu's cards, each with its picture */ +.pf-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(124px, 1fr)); gap: 8px; } +.pf-card { display: flex; flex-direction: column; gap: 3px; min-width: 0; } +.pf-card b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.pf-card input { min-width: 0; } +.pf-thumb { width: 100%; height: auto; min-height: 0; aspect-ratio: 1; padding: 0; overflow: hidden; display: grid; place-items: center; background: color-mix(in srgb, var(--dim) 12%, transparent); border-radius: var(--radius); } +.pf-thumb img { display: block; width: 100%; height: 100%; object-fit: contain; } +.pf-copy { border-top: 0; } + +/* the sounds window */ +.snd-row { gap: 6px; align-items: center; } +.snd-name { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; cursor: default; } + +/* s code: inline results, the stepped token, completion, the outline, the debugger */ +.pad pre.hl .s-note { position: absolute; left: 10px; max-width: 42%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--dim); font-style: italic; font-size: .88em; text-align: left; pointer-events: none; } +.pad pre.hl mark.s-at { background: color-mix(in srgb, var(--accent) 45%, transparent); color: inherit; border-radius: 2px; } +.s-compl { gap: 4px; padding: 4px 2px 0; } +.s-outline { display: flex; flex-direction: column; gap: 2px; padding: 6px 8px; border-radius: 5px; background: var(--card); max-height: 220px; overflow: auto; } +.s-outline .s-item { justify-content: flex-start; gap: 4px; height: auto; padding: 2px 4px; } +.s-dbg .s-stack { gap: 4px; padding: 4px 0; } +.s-dbg .s-vals { display: grid; grid-template-columns: repeat(auto-fill, minmax(140px, 1fr)); gap: 2px 10px; padding: 4px 0; } +.s-dbg .s-unit { font-size: .9em; } + +/* ---------------------------------------------------------------- taxonomies */ +.tax-node { display: flex; flex-direction: column; gap: 4px; } +.tax-node > .row { gap: 8px; align-items: center; flex-wrap: wrap; } +.tax-route { display: flex; flex-direction: column; gap: 4px; margin-left: 14px; } +.tax-route > .row { gap: 8px; align-items: center; flex-wrap: wrap; } +.tax-class { font-weight: 600; overflow-wrap: anywhere; } +.tax-sub { margin-left: 10px; padding: 4px 0 4px 12px; border-left: 2px solid color-mix(in srgb, var(--accent) 55%, transparent); } +input.tax-title { font-size: 1.2em; font-weight: 700; min-width: 0; flex: 1 1 200px; } +.tax-step .t { white-space: normal; } +.tax-which { flex-wrap: wrap; gap: 6px; align-items: center; margin: 0 0 6px 52px; } +input.tax-about { width: 100%; } + +/* ---------------------------------------------------------------- pipes */ +.pipe-parts { display: flex; flex-direction: column; gap: 4px; padding: 6px 0; border-top: 1px solid var(--pad); margin-top: 6px; } +.pipe-parts > .row { gap: 8px; align-items: center; flex-wrap: wrap; } +.pipe-n { display: inline-grid; place-items: center; min-width: 16px; height: 16px; border-radius: 8px; background: var(--accent); color: var(--on-button); font-size: 11px; font-weight: 700; } +.fx-label { display: inline-block; margin-left: 6px; padding: 0 5px; border-radius: 7px; font-size: 0.6em; vertical-align: middle; background: color-mix(in srgb, var(--accent) 80%, transparent); color: var(--on-button); text-decoration: none; } +/* the reader's views of one's own */ +.chip.own { font-style: italic; } +.reader-head { margin: 12px 0 4px; grid-column: 1 / -1; display: flex; gap: 6px; align-items: baseline; } +.reader-list { display: flex; flex-direction: column; gap: 2px; } +.reader-list .reader-head { margin: 10px 0 2px; } +.rrow { padding: 4px 8px; border-radius: var(--radius); background: var(--cards); cursor: pointer; display: flex; gap: 8px; align-items: baseline; } +.rrow:hover { background: color-mix(in srgb, var(--buttons) 30%, var(--cards)); } +.rrow h3 { margin: 0; font-size: 1em; } +.rrow .body { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } +.view-title { font-style: italic; } + +/* ---------------------------------------------------------------- tag sets */ +.chip.ts-type { background: color-mix(in srgb, var(--c) 30%, var(--cards)); box-shadow: inset 3px 0 0 var(--c); } +.swatch-dot { display: inline-block; width: 9px; height: 9px; border-radius: 50%; } +.ts-words { display: flex; flex-wrap: wrap; gap: 6px 4px; padding: 8px 0; align-items: flex-start; } +.ts-word { display: inline-flex; flex-direction: column; align-items: center; gap: 2px; } +.ts-word > button.plain { display: inline-flex; flex-direction: column; align-items: center; height: auto; padding: 2px 6px; border-radius: var(--radius); border-bottom: 3px solid var(--c); } +.ts-word .w { font-size: 1.15em; } +.ts-word .l { font-size: 11px; color: var(--dim); } +.ts-word.flagged .w { text-decoration: underline wavy #d6453d; } +.ts-pick, .ts-suggest { display: flex; gap: 3px; flex-wrap: wrap; justify-content: center; } +.row.wrap { flex-wrap: wrap; } + +/* ---------------------------------------------------------------- the selection of many */ +.slabel.multi { outline: 2px solid #3f8cff; outline-offset: 2px; border-radius: 3px; } +.selbox { position: fixed; z-index: 50; border: 1px solid #3f8cff; background: rgba(63, 140, 255, 0.12); pointer-events: none; } +.multibar { position: absolute; left: 50%; transform: translateX(-50%); bottom: 64px; z-index: 30; display: flex; gap: 10px; align-items: center; padding: 6px 10px; border-radius: 8px; background: var(--cards); box-shadow: 0 2px 12px rgb(0 0 0 / .25); max-width: calc(100% - 32px); flex-wrap: wrap; } +.notelist li.picked { box-shadow: inset 3px 0 0 #3f8cff; background: color-mix(in srgb, #3f8cff 14%, transparent); } +.many { display: flex; flex-direction: column; gap: 4px; padding: 6px; margin: 4px 0; border-radius: var(--radius); background: color-mix(in srgb, #3f8cff 12%, var(--cards)); } +.many .row { gap: 4px; flex-wrap: wrap; } +.many input { min-width: 0; flex: 1; } +.listcard.picked { box-shadow: inset 4px 0 0 #3f8cff; } +/* the space drawn natively under the page: the page is see-through over it */ +.app:has(.space-host.native) { background: transparent; } +.space-host.native { background: transparent; } + +/* the native room's picture in the page (macOS, Windows): under everything in the space */ +.space-frame { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; user-select: none; } diff --git a/app/src/theme.rs b/app/src/theme.rs new file mode 100644 index 00000000..6c0702e3 --- /dev/null +++ b/app/src/theme.rs @@ -0,0 +1,233 @@ +//! The colours: every one has a role (as in the web and Bevy apps) and a CSS variable. +//! Sand is the old admin panel's; night, paper and sea start from it. + +use std::collections::BTreeMap; + +pub const ROLES: [(&str, &str); 13] = [ + ("window", "--window"), + ("bars", "--bars"), + ("bar text", "--bar-text"), + ("bar labels", "--bar-dim"), + ("cards", "--cards"), + ("writing pad", "--pad"), + ("buttons", "--buttons"), + ("accent", "--accent"), + ("text", "--text"), + ("dim text", "--dim"), + ("links", "--link"), + ("code", "--code"), + ("space room", "--room"), +]; + +const SAND: [&str; 13] = [ + "#927a4f", "#404040", "#ebebeb", "#9e9e9e", "#ffffff", "#dbd4c8", "#c4b28f", "#c4a265", "#2e2e2e", "#6b6b6b", + "#86592a", "#e9e5de", "#e4d4be", +]; +const NIGHT: [&str; 13] = [ + "#1d1b19", "#2b2825", "#e8e2d8", "#9a9184", "#2f2c29", "#3a3632", "#6b5d48", "#a8875a", "#e6dfd4", "#a39a8d", + "#d9a066", "#26231f", "#26221e", +]; +const PAPER: [&str; 13] = [ + "#e9e6df", "#d9d4ca", "#2e2b27", "#77706a", "#fbfaf7", "#f2efe8", "#d6cfc2", "#b9a688", "#2b2926", "#7a746c", + "#8a4f22", "#ece8df", "#f1ede4", +]; +const SEA: [&str; 13] = [ + "#4d6e78", "#2c3b40", "#ebebeb", "#9e9e9e", "#f6fafa", "#d5e2e4", "#9dbcc2", "#6f9ea7", "#2e2e2e", "#6b6b6b", + "#2d6470", "#e3eced", "#d8e4e3", +]; + +pub const PALETTES: [&str; 4] = ["sand", "night", "paper", "sea"]; + +pub fn palette(name: &str) -> &'static [&'static str; 13] { + match name { + "night" => &NIGHT, + "paper" => &PAPER, + "sea" => &SEA, + _ => &SAND, + } +} + +/// a role's colour: the custom one, else the palette's +pub fn colour(name: &str, own: &BTreeMap<String, String>, role: &str) -> String { + if let Some(c) = own.get(role) { + return c.clone(); + } + ROLES + .iter() + .position(|(r, _)| *r == role) + .map(|i| palette(name)[i].to_string()) + .unwrap_or_default() +} + +pub fn rgb(hex: &str) -> (f64, f64, f64) { + let h = hex.trim_start_matches('#'); + let n = u32::from_str_radix(h.get(..6).unwrap_or("000000"), 16).unwrap_or(0); + (((n >> 16) & 255) as f64, ((n >> 8) & 255) as f64, (n & 255) as f64) +} + +/// whether dark ink reads on it +pub fn light(hex: &str) -> bool { + let (r, g, b) = rgb(hex); + 0.2126 * r + 0.7152 * g + 0.0722 * b > 140.0 +} + +/// the CSS variables for a palette and its custom colours +pub fn css_vars(name: &str, own: &BTreeMap<String, String>) -> String { + let mut out = String::new(); + for (role, var) in ROLES { + out.push_str(&format!("{var}: {};", colour(name, own, role))); + } + let buttons = colour(name, own, "buttons"); + out.push_str(&format!( + "--on-button: {};", + if light(&buttons) { "#1f1f1f" } else { "#f1ebe2" } + )); + let cards = colour(name, own, "cards"); + out.push_str(&format!( + "color-scheme: {};", + if light(&cards) { "light" } else { "dark" } + )); + out +} + +pub fn hsl_of(hex: &str) -> (f64, f64, f64) { + let (r, g, b) = rgb(hex); + let (r, g, b) = (r / 255.0, g / 255.0, b / 255.0); + let (mx, mn) = (r.max(g).max(b), r.min(g).min(b)); + let l = (mx + mn) / 2.0; + if mx == mn { + return (0.0, 0.0, l); + } + let d = mx - mn; + let s = if l > 0.5 { d / (2.0 - mx - mn) } else { d / (mx + mn) }; + let h = if mx == r { + (g - b) / d + if g < b { 6.0 } else { 0.0 } + } else if mx == g { + (b - r) / d + 2.0 + } else { + (r - g) / d + 4.0 + }; + (h * 60.0, s, l) +} + +pub fn hex_of_hsl(h: f64, s: f64, l: f64) -> String { + let c = (1.0 - (2.0 * l - 1.0).abs()) * s; + let hp = h.rem_euclid(360.0) / 60.0; + let x = c * (1.0 - (hp % 2.0 - 1.0).abs()); + let (r, g, b) = match hp as u32 { + 0 => (c, x, 0.0), + 1 => (x, c, 0.0), + 2 => (0.0, c, x), + 3 => (0.0, x, c), + 4 => (x, 0.0, c), + _ => (c, 0.0, x), + }; + let m = l - c / 2.0; + let to = |v: f64| ((v + m).clamp(0.0, 1.0) * 255.0).round() as u8; + format!("#{:02x}{:02x}{:02x}", to(r), to(g), to(b)) +} + +/// relative luminance (WCAG) +fn luminance(hex: &str) -> f64 { + let (r, g, b) = rgb(hex); + let lin = |v: f64| { + let v = v / 255.0; + if v <= 0.03928 { + v / 12.92 + } else { + ((v + 0.055) / 1.055).powf(2.4) + } + }; + 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b) +} + +fn contrast(a: &str, b: &str) -> f64 { + let (la, lb) = (luminance(a), luminance(b)); + (la.max(lb) + 0.05) / (la.min(lb) + 0.05) +} + +/// `c`, darkened or lightened (away from `bg`) until it stands out from it by `ratio` +pub fn readable(c: &str, bg: &str, ratio: f64) -> String { + let darker = luminance(bg) > 0.18; + let (h, s, mut l) = hsl_of(c); + let mut out = hex_of_hsl(h, s, l); + for _ in 0..40 { + if contrast(&out, bg) >= ratio { + break; + } + l = if darker { + (l - 0.025).max(0.0) + } else { + (l + 0.025).min(1.0) + }; + out = hex_of_hsl(h, s, l); + } + out +} + +fn mix(a: &str, b: &str, t: f64) -> String { + let (a, b) = (rgb(a), rgb(b)); + let m = |x: f64, y: f64| (x + (y - x) * t).round() as u8; + format!("#{:02x}{:02x}{:02x}", m(a.0, b.0), m(a.1, b.1), m(a.2, b.2)) +} + +/// the editor's highlighting colours (highlight.rs's classes), as the Bevy app made them: +/// from the palette, each readable on the writing pad, the hues the palette doesn't name +/// turned from its link colour so they suit any preset +pub fn hl_vars(name: &str, own: &BTreeMap<String, String>) -> String { + let pad = colour(name, own, "writing pad"); + let text = colour(name, own, "text"); + let dim = colour(name, own, "dim text"); + let link = colour(name, own, "links"); + let accent = colour(name, own, "accent"); + let (lh, ls, ll) = hsl_of(&link); + let turn = |deg: f64, sat: f64| hex_of_hsl(lh + deg, (ls * sat).clamp(0.25, 0.75), ll); + let heading = readable(&link, &pad, 5.0); + let mark = readable(&mix(&dim, &pad, 0.2), &pad, 2.2); + let vars = [ + ("--hl-mark", mark.clone()), + ("--hl-heading", heading.clone()), + ("--hl-emph", readable(&mix(&text, &heading, 0.4), &pad, 5.0)), + ("--hl-strike", readable(&dim, &pad, 2.6)), + ("--hl-code", readable(&turn(140.0, 0.8), &pad, 4.2)), + ("--hl-link", readable(&turn(200.0, 1.0), &pad, 4.5)), + ("--hl-url", readable(&turn(190.0, 0.6), &pad, 3.0)), + ("--hl-list", readable(&accent, &pad, 3.0)), + ("--hl-quote", readable(&dim, &pad, 3.4)), + ("--hl-tag", readable(&turn(-40.0, 1.0), &pad, 4.0)), + ("--hl-rule", mark), + ]; + vars.iter().map(|(k, v)| format!("{k}: {v};")).collect() +} + +/// readable ink for texts on a background (the space's room): dark on light, light on dark +pub fn ink_on(bg: &str) -> &'static str { + if light(bg) { "hsl(0 0% 12%)" } else { "hsl(35 30% 92%)" } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn palettes() { + let own = BTreeMap::from([("accent".to_string(), "#ff0000".to_string())]); + assert_eq!(colour("night", &own, "accent"), "#ff0000"); + assert_eq!(colour("night", &own, "window"), "#1d1b19"); + assert!(css_vars("sand", &BTreeMap::new()).contains("--window: #927a4f")); + assert!(light("#ffffff") && !light("#1d1b19")); + assert_eq!(ink_on("#000000"), "hsl(35 30% 92%)"); + // the sand window is hsl(39 30% 44%), the Bevy app's MOOD_DARK + assert_eq!(hex_of_hsl(39.0, 0.30, 0.44), "#927a4f"); + let (h, s, l) = hsl_of("#927a4f"); + assert!((h - 39.0).abs() < 1.0 && (s - 0.30).abs() < 0.01 && (l - 0.44).abs() < 0.01); + // every highlighting colour reads on the pad + for p in PALETTES { + let pad = colour(p, &BTreeMap::new(), "writing pad"); + for part in hl_vars(p, &BTreeMap::new()).split(';').filter(|x| !x.is_empty()) { + let c = part.split(": ").nth(1).unwrap(); + assert!(contrast(c, &pad) >= 2.2, "{p} {part}"); + } + } + } +} diff --git a/app/src/ui.rs b/app/src/ui.rs new file mode 100644 index 00000000..a43c6612 --- /dev/null +++ b/app/src/ui.rs @@ -0,0 +1,497 @@ +//! The state every view shares (signals in a context), and the small pieces they all use: +//! the status line, toasts, the command bar, picks (the list, its candidate and a +//! selection), the right-click menu, and undo. + +use std::rc::Rc; + +use dioxus::prelude::*; + +use crate::backend::{Backend, Hello, Hit}; +use crate::gem::{Measure, Mode}; +use crate::prefs::Prefs; + +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +pub enum View { + Memory, + Space, + Lists, + Reader, + Notes, + Tags, + Stats, + Models, + Filters, +} + +impl View { + pub const ALL: [View; 9] = [ + View::Memory, + View::Space, + View::Lists, + View::Reader, + View::Notes, + View::Tags, + View::Stats, + View::Models, + View::Filters, + ]; + + pub fn name(self) -> &'static str { + match self { + View::Memory => "memory", + View::Space => "space", + View::Lists => "lists", + View::Reader => "reader", + View::Notes => "notes", + View::Tags => "tags", + View::Stats => "stats", + View::Models => "models", + View::Filters => "filters", + } + } + + pub fn icon(self) -> &'static str { + match self { + View::Memory => "memory", + View::Space => "space", + View::Lists => "list", + View::Reader => "reader", + View::Notes => "editor", + View::Tags => "tags", + View::Stats => "stats", + View::Models => "classifier", + View::Filters => "filter", + } + } + + pub fn parse(s: &str) -> View { + View::ALL.into_iter().find(|v| v.name() == s).unwrap_or(View::Memory) + } + + /// what the command bar asks for in this view + pub fn placeholder(self) -> &'static str { + match self { + View::Memory => "a number, a text, or a key", + View::Space => "a number, a text, or a key (Esc to fly)", + View::Lists => "a text for the chosen list, a list's name, or a new list's (Enter)", + View::Reader | View::Notes => "words to find notes by", + View::Tags => "a tag (Enter picks the first match)", + View::Stats => "", + View::Models => "a text to try the model on (or to route, in a taxonomy)", + View::Filters => "words, or a sum like 79 or 70-90", + } + } +} + +/// a key press the shell hands to the open view: from the bar (`bar`), or anywhere else +/// that isn't typing +#[derive(Debug, Clone, PartialEq, serde::Deserialize)] +pub struct KeyPress { + pub key: String, + pub code: String, + pub ctrl: bool, + pub shift: bool, + pub alt: bool, + pub bar: bool, + /// a text box (the bar or another) has the focus + #[serde(default)] + pub typing: bool, + pub text: String, + /// the action the keymap gives this press here (set by the shell) + #[serde(skip)] + pub action: Option<crate::keys::Action>, +} + +#[derive(Debug, Clone, PartialEq)] +pub struct Toast { + pub id: u64, + pub text: String, +} + +/// the search line in the top bar: what was searched and its triangle +#[derive(Debug, Clone, PartialEq, Default)] +pub struct TopLine { + pub title: String, + pub detail: String, + pub s: u64, + pub r: u64, + /// the space: texts in the room and the buckets they make + pub counts: Option<(usize, usize)>, + /// a gsearched number's prime factor chain (weum's pfR line), shown after it + pub pf: Option<u64>, +} + +/// the list (Ctrl+Shift+click), its candidate (Ctrl+click) and a selection of texts +#[derive(Debug, Clone, PartialEq, Default)] +pub struct Picks { + pub list: Option<Hit>, + pub candidate: Option<Hit>, + pub selected: Vec<Hit>, + /// the chain texts are being added to in the space (its key, its title) + pub chain: Option<Hit>, +} + +/// what the next Enter in the bar does instead of a search +#[derive(Debug, Clone, PartialEq, Default)] +pub enum Pending { + #[default] + None, + /// the bar holds the text; Enter puts it back under the same key + Edit(Hit), + /// the bar holds a placement's text in the space; Enter makes it that placement's + /// own text (the entry and its other placements stay as they are) + EditOwn { node: String, text: String }, + /// the next text typed tags these + Tag(Vec<Hit>), +} + +/// the right-click menu on a text +#[derive(Debug, Clone, PartialEq)] +pub struct Menu { + pub hit: Hit, + pub x: f64, + pub y: f64, +} + +/// a recent action that can be taken back +#[derive(Debug, Clone, PartialEq)] +pub enum Did { + Forgot { key: String, text: String }, + Remembered { key: String, text: String }, + Edited { key: String, old: String }, + Enlisted { list: String, member: String }, + Delisted { list: String, member: String }, + Unlisted { list: String, members: Vec<String> }, + Feedback { model: String }, +} + +impl Did { + pub fn describe(&self) -> String { + match self { + Did::Forgot { text, .. } => format!("forgetting “{text}”"), + Did::Remembered { text, .. } => format!("remembering “{text}”"), + Did::Edited { old, .. } => format!("the edit of “{old}”"), + Did::Enlisted { .. } => "adding to a list".into(), + Did::Delisted { .. } => "taking out of a list".into(), + Did::Unlisted { .. } => "deleting a list".into(), + Did::Feedback { model } => format!("the verdict given to {model}"), + } + } +} + +/// the bar's own undo: states it was in, coalesced while typing +#[derive(Debug, Clone, PartialEq, Default)] +pub struct BarHistory { + pub back: Vec<String>, + pub forth: Vec<String>, + pub last_push: f64, +} + +#[derive(Clone)] +pub struct Api(pub Rc<dyn Backend>); + +impl PartialEq for Api { + fn eq(&self, other: &Api) -> bool { + Rc::ptr_eq(&self.0, &other.0) + } +} + +impl std::ops::Deref for Api { + type Target = dyn Backend + 'static; + fn deref(&self) -> &(dyn Backend + 'static) { + &*self.0 + } +} + +#[derive(Clone, Copy)] +pub struct Ui { + pub view: Signal<View>, + pub prefs: Signal<Prefs>, + pub status: Signal<(String, bool, u64)>, + pub toasts: Signal<Vec<Toast>>, + /// the command bar's text, mirrored on every input (the input itself isn't bound to it, + /// so typing never waits on a render) + pub bar: Signal<String>, + /// the bar's text measured, a beat after typing stops + pub measure: Signal<Option<Measure>>, + pub settings: Signal<bool>, + pub hello: Signal<Hello>, + pub topline: Signal<Option<TopLine>>, + pub picks: Signal<Picks>, + pub pending: Signal<Pending>, + pub menu: Signal<Option<Menu>>, + pub actions: Signal<Vec<Did>>, + pub bar_history: Signal<BarHistory>, + /// each view's key handler + pub keys: Signal<Vec<(View, Callback<KeyPress, bool>)>>, + /// bumped when the save's data changed (views reload) + pub changed: Signal<u64>, + /// what the bar held in each view, put back when you return to it + pub bar_texts: Signal<std::collections::HashMap<View, String>>, + pub seq: Signal<u64>, + /// what each view says at the command bar's right end (its counts, what Enter does) + pub side: Signal<std::collections::HashMap<View, String>>, + /// the keys menu waits for a key for this action + pub listening: Signal<Option<crate::keys::Action>>, + /// a note another view asked the notes view to open + pub open_note: Signal<Option<String>>, + /// a tag another view asked the tags view to show + pub pick_tag: Signal<Option<String>>, + /// the window is closing (desktop): 1 asked, 2 a view is saving and closes it after + pub closing: Signal<u8>, +} + +pub fn ui() -> Ui { + use_context::<Ui>() +} + +pub fn api() -> Api { + use_context::<Api>() +} + +pub fn now_ms() -> f64 { + #[cfg(target_arch = "wasm32")] + { + js_sys::Date::now() + } + #[cfg(not(target_arch = "wasm32"))] + { + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .map(|d| d.as_secs_f64() * 1000.0) + .unwrap_or(0.0) + } +} + +pub async fn sleep_ms(ms: u64) { + #[cfg(target_arch = "wasm32")] + { + let p = js_sys::Promise::new(&mut |ok, _| { + if let Some(w) = web_sys::window() { + let _ = w.set_timeout_with_callback_and_timeout_and_arguments_0(&ok, ms as i32); + } + }); + let _ = wasm_bindgen_futures::JsFuture::from(p).await; + } + #[cfg(not(target_arch = "wasm32"))] + { + tokio::time::sleep(std::time::Duration::from_millis(ms)).await; + } +} + +impl Ui { + /// the keymap: the defaults with the person's changes + pub fn keymap(self) -> crate::keys::Keymap { + crate::keys::Keymap::from_changes(&self.prefs.peek().keymap) + } + + /// what the key bound to an action is called, for tooltips + pub fn key_of(self, a: crate::keys::Action) -> String { + self.keymap().get(a).to_string() + } + + /// what the view says at the command bar's right end + pub fn side_note(mut self, view: View, text: impl Into<String>) { + let t = text.into(); + if self.side.peek().get(&view) != Some(&t) { + self.side.write().insert(view, t); + } + } + + fn next(mut self) -> u64 { + let n = *self.seq.peek() + 1; + self.seq.set(n); + n + } + + /// a message in the top bar; errors stay a while longer + pub fn say(mut self, msg: impl Into<String>) { + let n = self.next(); + self.status.set((msg.into(), false, n)); + dioxus::dioxus_core::spawn_forever(async move { + sleep_ms(4000).await; + if self.status.peek().2 == n { + self.status.set((String::new(), false, n)); + } + }); + } + + pub fn fail(mut self, msg: impl Into<String>) { + let n = self.next(); + self.status.set((msg.into(), true, n)); + dioxus::dioxus_core::spawn_forever(async move { + sleep_ms(8000).await; + if self.status.peek().2 == n { + self.status.set((String::new(), false, n)); + } + }); + } + + /// weum's toast: 15 seconds, click puts it in the bar, double click dismisses + pub fn toast(mut self, text: impl Into<String>) { + let id = self.next(); + self.toasts.write().push(Toast { id, text: text.into() }); + dioxus::dioxus_core::spawn_forever(async move { + sleep_ms(15_000).await; + self.toasts.write().retain(|t| t.id != id); + }); + } + + /// puts a text in the command bar (and its undo history) + pub fn set_bar(mut self, text: &str) { + let old = self.bar.peek().clone(); + if old != text { + let mut h = self.bar_history.write(); + h.back.push(old); + h.forth.clear(); + h.last_push = now_ms(); + } + self.bar.set(text.to_string()); + let js = format!( + "const b = document.getElementById('bar'); if (b) b.value = {};", + serde_json::to_string(text).unwrap_or_default() + ); + document::eval(&js); + } + + pub fn focus_bar(self) { + document::eval("const b = document.getElementById('bar'); if (b) { b.focus(); }"); + } + + /// the bar's input, as typed: coalesced into undo states + pub fn typed(mut self, text: String) { + let old = self.bar.peek().clone(); + let t = now_ms(); + { + let mut h = self.bar_history.write(); + // a new undo state after a pause or at a word's end + if t - h.last_push > 700.0 || old.ends_with(' ') && !text.ends_with(' ') || h.back.is_empty() { + h.back.push(old); + if h.back.len() > 200 { + h.back.remove(0); + } + h.forth.clear(); + } + h.last_push = t; + } + self.bar.set(text); + } + + pub fn bar_undo(mut self, redo: bool) { + let cur = self.bar.peek().clone(); + let to = { + let mut h = self.bar_history.write(); + let t = if redo { h.forth.pop() } else { h.back.pop() }; + if t.is_some() { + if redo { + h.back.push(cur); + } else { + h.forth.push(cur); + } + h.last_push = 0.0; + } + t + }; + if let Some(t) = to { + self.bar.set(t.clone()); + document::eval(&format!( + "const b = document.getElementById('bar'); if (b) b.value = {};", + serde_json::to_string(&t).unwrap_or_default() + )); + } + } + + pub fn did(mut self, a: Did) { + let mut all = self.actions.write(); + all.push(a); + if all.len() > 50 { + all.remove(0); + } + } + + pub fn touched(mut self) { + let n = *self.changed.peek() + 1; + self.changed.set(n); + } + + pub fn mode(self) -> Mode { + self.prefs.read().mode + } + + pub fn save_prefs(self) { + crate::prefs::store(&self.prefs.peek()); + } + + /// counts and the save's name again + pub fn refresh(mut self, api: Api) { + dioxus::dioxus_core::spawn_forever(async move { + match api.hello().await { + Ok(h) => self.hello.set(h), + Err(e) => self.fail(e), + } + }); + } +} + +/// takes back the latest action +pub fn undo_last(ui: Ui, api: Api) { + let mut actions = ui.actions; + let Some(a) = actions.write().pop() else { + ui.say("nothing to undo"); + return; + }; + dioxus::dioxus_core::spawn_forever(async move { + let r = match &a { + Did::Forgot { key, text } => api.put_memory(key, text).await, + Did::Remembered { key, .. } => api.forget(key).await.map(|_| ()), + Did::Edited { key, old } => api.put_memory(key, old).await, + Did::Enlisted { list, member } => api.delist(list, member).await, + Did::Delisted { list, member } => api.enlist(list, member).await, + Did::Unlisted { list, members } => { + let mut r = Ok(()); + for m in members { + r = r.and(api.enlist(list, m).await); + } + r + } + Did::Feedback { model } => api.undo_model_feedback(model).await, + }; + match r { + Ok(()) => { + ui.say(format!("took back {}", a.describe())); + ui.touched(); + ui.refresh(api); + } + Err(e) => ui.fail(format!("couldn't take back {}: {e}", a.describe())), + } + }); +} + +/// an icon from the shared set +#[component] +pub fn Icon(name: String, #[props(default)] class: String) -> Element { + rsx! { + span { class: "icon {class}", "aria-hidden": "true", dangerous_inner_html: crate::icons::svg(&name) } + } +} + +/// the triangle with sides s, r and ⌊√(s·r)⌋, with its angles as the tooltip +#[component] +pub fn Triangle(s: u64, r: u64, #[props(default = 22.0)] height: f64) -> Element { + let Some((w, h, pts, real)) = crate::gem::triangle_points(s, r, height, height * 3.0) else { + return rsx! {}; + }; + let title = crate::gem::triangle_title(s, r); + rsx! { + svg { + class: if real { "triangle" } else { "triangle flat" }, + width: "{w:.1}", + height: "{h:.1}", + view_box: "0 0 {w:.1} {h:.1}", + role: "img", + "aria-label": "{title}", + title { "{title}" } + polygon { points: "{pts}", stroke_dasharray: if real { "none" } else { "2 2" } } + } + } +} diff --git a/app/src/views/classifiers.rs b/app/src/views/classifiers.rs new file mode 100644 index 00000000..dd255134 --- /dev/null +++ b/app/src/views/classifiers.rs @@ -0,0 +1,1374 @@ +//! Classifiers: models trained on the save's lists, one class per list (docs/app-api.md, +//! `classify.*`). The same view on the desktop and the web, through the backend. +//! +//! The left column lists them; a classifier's page has its training (epochs, progress, +//! cancel, the metrics), a try card (the command bar's text, each class's probability, +//! yes/no, texts like it), its steering (bias, temperature, threshold), a search by class +//! (yes/no on each, the class as a list), and its recent verdicts. Every yes/no can be +//! taken back with Ctrl+Z. "new" makes one from lists; "import" takes a classifier file +//! (`.anendcls`), and each page exports its own. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use crate::backend::{ListInfo, ModelSummary, Scored}; +use crate::ui::*; +use crate::views::clsmore::Tab; +use crate::views::use_keys; + +/// what the open classifier's page is showing +#[derive(Clone, Copy, PartialEq)] +enum Side { + None, + New, + Import, + Starters, +} + +pub(crate) fn strs(v: &Value) -> Vec<String> { + v.as_array() + .into_iter() + .flatten() + .filter_map(|x| x.as_str().map(str::to_string)) + .collect() +} + +pub(crate) fn nums(v: &Value) -> Vec<f64> { + v.as_array().into_iter().flatten().filter_map(Value::as_f64).collect() +} + +pub(crate) fn pct(p: f64) -> String { + format!("{:.0}%", p * 100.0) +} + +#[component] +pub fn Models() -> Element { + let ui = ui(); + let api = api(); + let mut chosen: Signal<Option<String>> = use_signal(|| None); + let mut side = use_signal(|| Side::None); + let mut rev = use_signal(|| 0u64); + // the classifiers (0), the spec models (1), the taxonomies (2) or the tag sets (3) + let mut tab = use_signal(|| { + let p = ui.prefs.peek(); + if p.folded("models: tagsets") { + 3u8 + } else if p.folded("models: taxonomies") { + 2 + } else if p.folded("models: specs") { + 1 + } else { + 0 + } + }); + let specs_tab = use_memo(move || tab() == 1); + // the bar's text, sent to a taxonomy's try card by Enter + let mut tax_bar = use_signal(|| (0u64, String::new())); + let specs = use_hook(crate::views::specs::SpecState::new); + let api_r = api.clone(); + let models = use_resource(move || { + let api = api_r.clone(); + let _ = ((ui.changed)(), rev()); + async move { api.models().await } + }); + use_keys(View::Models, move |k: KeyPress| { + if *tab.peek() == 3 { + return false; + } + if *tab.peek() == 2 { + if k.bar && k.key == "Enter" { + let n = tax_bar.peek().0 + 1; + tax_bar.set((n, k.text.trim().to_string())); + return true; + } + return false; + } + if *specs_tab.peek() { + if k.bar && k.key == "Enter" { + let mut e = specs.enter; + e += 1; + return true; + } + if !k.bar && k.key == "Escape" { + specs.escape(); + return true; + } + return false; + } + if k.bar && k.key == "Enter" { + // the try card runs as you type + if chosen.peek().is_none() + && models + .peek() + .as_ref() + .and_then(|r| r.as_ref().ok()) + .is_none_or(|l| l.is_empty()) + { + ui.fail("make a classifier first (new)"); + } + return true; + } + if !k.bar && k.key == "Escape" { + if *side.peek() != Side::None { + side.set(Side::None); + } else { + chosen.set(None); + } + return true; + } + false + }); + let (list, note): (Vec<ModelSummary>, Option<String>) = match &*models.read() { + Some(Ok(v)) => (v.clone(), None), + Some(Err(e)) => (vec![], Some(e.clone())), + None => (vec![], None), + }; + // the first one is open until another is picked + let open = chosen().or_else(|| { + (side() == Side::None) + .then(|| list.first().map(|m| m.name.clone())) + .flatten() + }); + let on_made = move |name: String| { + side.set(Side::None); + chosen.set(Some(name)); + rev += 1; + }; + rsx! { + div { class: "page wide", + div { class: "row", + div { class: "mtabs", role: "tablist", "aria-label": "kinds of model", + for (on , label) in [(0u8, "classifiers"), (1, "spec models"), (2, "taxonomies"), (3, "tag sets")] { + button { key: "{label}", role: "tab", "aria-selected": "{tab() == on}", + class: if tab() == on { "mtab on" } else { "mtab" }, + onclick: move |_| { + tab.set(on); + crate::shell::set_pref(ui, |p| { + p.collapsed.remove("models: specs"); + p.collapsed.remove("models: taxonomies"); + p.collapsed.remove("models: tagsets"); + match on { + 1 => { p.collapsed.insert("models: specs".into()); } + 2 => { p.collapsed.insert("models: taxonomies".into()); } + 3 => { p.collapsed.insert("models: tagsets".into()); } + _ => {} + } + }); + }, + "{label}" } + } + } + if tab() == 3 { + span { class: "dim small", "word types of your own, learned from words you mark" } + } else if tab() == 2 { + span { class: "dim small", "classifiers in a tree: each answer picks the next classifier" } + } else if specs_tab() { + span { class: "dim small", "described as data: what they read, their heads, what they learn from" } + } else { + span { class: "dim small", "learn classes from example lists, then read any text" } + } + span { class: "grow" } + if tab() == 0 { + button { class: if side() == Side::New { "on" } else { "" }, onclick: move |_| side.set(if side() == Side::New { Side::None } else { Side::New }), + Icon { name: "new" } "new" } + button { class: if side() == Side::Starters { "on" } else { "" }, "data-tip": "ready-made classifiers whose answers a rule can check", + onclick: move |_| side.set(if side() == Side::Starters { Side::None } else { Side::Starters }), + Icon { name: "star" } "starters" } + button { class: if side() == Side::Import { "on" } else { "" }, "data-tip": "a classifier file (.anendcls)", + onclick: move |_| side.set(if side() == Side::Import { Side::None } else { Side::Import }), + Icon { name: "upload" } "import" } + } + } + if tab() == 3 { + crate::views::tagsets::TagSets {} + } else if tab() == 2 { + crate::views::taxonomy::Taxonomies { bar: tax_bar } + } else if specs_tab() { + crate::views::specs::SpecModels { state: specs } + } else { + if let Some(n) = note { + div { class: "card bad", "{n}" } + } + div { class: "cls-layout", + div { class: "card cls-list", role: "listbox", "aria-label": "classifiers", + if list.is_empty() { + span { class: "dim small", "none yet" } + } + for m in list.iter().cloned() { + button { + key: "{m.name}", + role: "option", + "aria-selected": "{open.as_deref() == Some(m.name.as_str())}", + class: if open.as_deref() == Some(m.name.as_str()) && side() == Side::None { "cls-item on" } else { "cls-item" }, + onclick: { let n = m.name.clone(); move |_| { chosen.set(Some(n.clone())); side.set(Side::None); } }, + b { "{m.name}" } + span { class: "small", + {m.classes.join(" · ")} + } + span { class: "small state", + if m.training { "training…" } + else if m.trained { {format!("trained{}", m.accuracy.map(|a| format!(" · {}", pct(a))).unwrap_or_default())} } + else { "not trained yet" } + } + } + } + } + div { class: "cls-main", + match side() { + Side::New => rsx! { NewClassifier { on_made } }, + Side::Import => rsx! { ImportClassifier { on_made } }, + Side::Starters => rsx! { Starters { on_made } }, + Side::None => match open { + Some(name) => rsx! { ClassifierPage { key: "{name}", name: name.clone(), on_gone: move |_| { chosen.set(None); rev += 1; } } }, + None => rsx! { + div { class: "card empty", + p { "A classifier learns from examples, given as lists (each list a class, its members the examples), and then reads any text, in the save or newly typed: it orders classifier search, colours the memory and the space, and answers in the reader and the notes. Classifiers are one use of the project's transformer engine, which also runs spec models (taggers, generators, critics)." } + p { "Make two or more lists (in the memory view: Ctrl+Shift+click a text to make it a list's head, then Shift+click texts and put them in it), then press " b { "new" } "." } + p { "Or begin with a starter: ready-made texts whose classes a rule knows for certain, so how well a classifier learned them is measured on texts it never saw. " + button { onclick: move |_| side.set(Side::Starters), Icon { name: "star" } "starters" } } + } + }, + }, + } + } + } + } + } + } +} + +// ------------------------------------------------------------------ making one + +#[component] +fn NewClassifier(on_made: EventHandler<String>) -> Element { + let ui = ui(); + let api = api(); + let mut name = use_signal(String::new); + let mut classes: Signal<Vec<String>> = use_signal(Vec::new); + let mut not = use_signal(String::new); + let mut preset = use_signal(|| "compact".to_string()); + let mut multi = use_signal(|| false); + let mut gematria = use_signal(|| false); + let mut busy = use_signal(|| false); + let mut q = use_signal(String::new); + let api_l = api.clone(); + let lists = use_resource(move || { + let api = api_l.clone(); + async move { api.lists().await } + }); + let all: Vec<ListInfo> = match &*lists.read() { + Some(Ok(l)) => l.lists.clone(), + Some(Err(e)) => return rsx! { div { class: "card bad", "{e}" } }, + None => return rsx! { div { class: "card dim", "…" } }, + }; + let usable: Vec<ListInfo> = all.iter().filter(|l| l.count > 0).cloned().collect(); + let ql = q().to_lowercase(); + let shown: Vec<ListInfo> = usable + .iter() + .filter(|l| ql.is_empty() || l.name.to_lowercase().contains(&ql) || classes.read().contains(&l.list)) + .cloned() + .collect(); + let picked = classes(); + let ready = !name().trim().is_empty() && (picked.len() >= 2 || (picked.len() == 1 && !not().is_empty())); + let create = move |_| { + let api = api.clone(); + let args = json!({ + "name": name.peek().trim(), + "classes": *classes.peek(), + "not": *not.peek(), + "preset": *preset.peek(), + "head": if *multi.peek() { "multi" } else { "single" }, + "gematria": *gematria.peek(), + }); + busy.set(true); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("classify.create", args).await { + Ok(v) => { + let n = v["name"].as_str().unwrap_or("").to_string(); + ui.say(format!("made {n}; train it next")); + on_made.call(n); + } + Err(e) => ui.fail(e), + } + busy.set(false); + }); + }; + rsx! { + div { class: "card cls-new", + h3 { Icon { name: "new" } "a new classifier" } + if usable.len() < 2 { + p { class: "dim", "It needs at least two lists with members (or one list and a list of texts that are not in it). This save has {usable.len()}." } + } + div { class: "form", + label { r#for: "cls-name", "name" } + input { id: "cls-name", r#type: "text", placeholder: "kind, author, mood…", oninput: move |e| name.set(e.value()) } + label { "classes" } + div { class: "col", + if usable.len() > 12 { + input { r#type: "text", placeholder: "find a list", oninput: move |e| q.set(e.value()) } + } + div { class: "taglist", + for l in shown { + button { + key: "{l.list}", + class: if picked.contains(&l.list) { "chip on" } else { "chip" }, + "aria-pressed": "{picked.contains(&l.list)}", + title: l.members.iter().take(5).map(|m| m.text.clone()).collect::<Vec<_>>().join(" · "), + onclick: { let k = l.list.clone(); move |_| { + let mut c = classes.write(); + if let Some(i) = c.iter().position(|x| *x == k) { c.remove(i); } else { c.push(k.clone()); } + } }, + "{l.name}" span { class: "dim", " {l.count}" } + } + } + } + span { class: "dim small", "each list picked is a class; its members are the examples" } + } + label { r#for: "cls-not", "none of them" } + select { id: "cls-not", onchange: move |e| not.set(e.value()), + option { value: "", "no such list" } + for l in usable.iter().filter(|l| !picked.contains(&l.list)) { + option { key: "{l.list}", value: "{l.list}", "{l.name} ({l.count})" } + } + } + label { r#for: "cls-preset", "size" } + select { id: "cls-preset", value: "{preset}", onchange: move |e| preset.set(e.value()), + option { value: "tiny", "tiny: trains in seconds" } + option { value: "compact", "compact: the default" } + option { value: "small", "small: more to learn, slower" } + option { value: "base", "base: the largest" } + } + label { "options" } + div { class: "col", + label { class: "row", input { r#type: "checkbox", checked: multi(), onchange: move |e| multi.set(e.checked()) } "a text can be in several classes at once" } + label { class: "row", input { r#type: "checkbox", checked: gematria(), onchange: move |e| gematria.set(e.checked()) } "read the letters' values and word sums too (gematria inputs)" } + } + } + div { class: "row", + span { class: "grow" } + button { class: "primary", disabled: !ready || busy(), onclick: create, Icon { name: "check" } "make it" } + } + } + } +} + +#[component] +fn ImportClassifier(on_made: EventHandler<String>) -> Element { + let ui = ui(); + let api = api(); + let mut path = use_signal(String::new); + let mut as_name = use_signal(String::new); + let on_disk = api.on_disk(); + let take = { + let api = api.clone(); + move |bytes: Vec<u8>| { + let api = api.clone(); + let n = as_name.peek().trim().to_string(); + dioxus::dioxus_core::spawn_forever(async move { + let data = anend_core::classifiers::base64(&bytes); + match api.call("classify.import", json!({ "data": data, "as": n })).await { + Ok(v) => { + let name = v["name"].as_str().unwrap_or("").to_string(); + let lists = v["lists"].as_array().map_or(0, |l| l.len()); + ui.say(format!("took in {name} ({lists} lists for its classes)")); + ui.touched(); + on_made.call(name); + } + Err(e) => ui.fail(e), + } + }); + } + }; + let take2 = take.clone(); + rsx! { + div { class: "card", + h3 { Icon { name: "upload" } "a classifier file" } + p { class: "dim small", "A .anendcls file exported from anend (here, another save, or the hub). Each class goes to the list of its name, made when there's none." } + div { class: "form", + label { r#for: "imp-as", "as" } + input { id: "imp-as", r#type: "text", placeholder: "the name it came with", oninput: move |e| as_name.set(e.value()) } + label { "the file" } + input { r#type: "file", accept: ".anendcls", + onchange: move |e: FormEvent| { + let take = take.clone(); + async move { + let Some(f) = e.files().into_iter().next() else { return }; + match f.read_bytes().await { + Ok(b) => take(b.to_vec()), + Err(e) => ui.fail(format!("couldn't read it: {e}")), + } + } + }, + } + if on_disk { + label { r#for: "imp-path", "or its path" } + div { class: "row", + input { id: "imp-path", r#type: "text", style: "flex: 1;", placeholder: "/home/you/Downloads/kind.anendcls", oninput: move |e| path.set(e.value()) } + button { onclick: move |_| { + #[cfg(not(target_arch = "wasm32"))] + match std::fs::read(path().trim()) { + Ok(b) => take2(b), + Err(e) => ui.fail(format!("couldn't read {}: {e}", path().trim())), + } + #[cfg(target_arch = "wasm32")] + { let _ = &take2; } + }, "take it in" } + } + } + } + } + } +} + +// ------------------------------------------------------------------ one classifier + +#[component] +fn ClassifierPage(name: String, on_gone: EventHandler<()>) -> Element { + let ui = ui(); + let api = api(); + let mut rev = use_signal(|| 0u64); + let mut armed = use_signal(|| false); + let mut job: Signal<Option<Value>> = use_signal(|| None); + let mut watching = use_signal(|| true); + let tab = use_signal(|| Tab::Learn); + let api_all = api.clone(); + let all = use_resource(move || { + let api = api_all.clone(); + let _ = (ui.changed)(); + async move { api.call("classify.list", json!({})).await.ok() } + }); + let all_names: Vec<String> = all + .read() + .clone() + .flatten() + .and_then(|v| v.as_array().cloned()) + .unwrap_or_default() + .iter() + .filter_map(|c| c["name"].as_str().map(str::to_string)) + .collect(); + let n0 = name.clone(); + let api_d = api.clone(); + let details = use_resource(move || { + let (api, n) = (api_d.clone(), n0.clone()); + let _ = ((ui.changed)(), rev()); + async move { api.call("classify.get", json!({ "name": n })).await } + }); + // the training's progress, while there is one + { + let (api, n) = (api.clone(), name.clone()); + use_future(move || { + let (api, n) = (api.clone(), n.clone()); + async move { + let mut was_running = false; + loop { + if *watching.peek() { + match api.call("classify.job", json!({ "name": n })).await { + Ok(j) => { + let running = j["state"] == "running"; + if !running { + watching.set(false); + if was_running { + match j["state"].as_str() { + Some("done") => ui.say(format!("{n} is trained")), + Some("failed") => ui.fail(format!( + "{n}: {}", + j["error"].as_str().unwrap_or("training failed") + )), + Some(s) => ui.say(format!("{n}: {s}")), + None => {} + } + ui.touched(); + } + } + was_running = running; + job.set(Some(j)); + } + Err(_) => watching.set(false), + } + } + sleep_ms(if was_running { 350 } else { 600 }).await; + } + } + }); + } + let d = match &*details.read() { + Some(Ok(v)) => v.clone(), + Some(Err(e)) => return rsx! { div { class: "card bad", "{e}" } }, + None => return rsx! { div { class: "card dim", "…" } }, + }; + let classes = strs(&d["classes"]); + let trained = d["trained"].as_bool().unwrap_or(false); + let running = job().is_some_and(|j| j["state"] == "running"); + let api_x = api.clone(); + let api_del = api.clone(); + let n_x = name.clone(); + let n_del = name.clone(); + let size = &d["size"]; + let inputs: Vec<String> = d["inputs"] + .as_array() + .into_iter() + .flatten() + .filter_map(|i| i["from"].as_str().map(str::to_string)) + .collect(); + rsx! { + div { class: "cls-page", + div { class: "card cls-head", + div { class: "row", + h2 { "{name}" } + for (i , c) in classes.iter().enumerate() { + span { key: "{c}", class: "chip cls-class", style: "--hue: {hue(i, classes.len())};", "{c}" } + } + if let Some(n) = d["not"]["name"].as_str() { + span { class: "chip", title: "texts that are none of the classes", Icon { name: "not" } "{n}" } + } + span { class: "grow" } + button { class: "plain", "data-tip": "export it as a file (.anendcls)", "aria-label": "export", + onclick: move |_| export(ui, api_x.clone(), n_x.clone()), + Icon { name: "download" } } + button { + class: if armed() { "armed" } else { "plain" }, + "data-tip": "delete it (its lists stay); click twice", + "aria-label": "delete the classifier", + disabled: running, + onclick: move |_| { + if !armed() { armed.set(true); return; } + let (api, n) = (api_del.clone(), n_del.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.delete_model(&n).await { + Ok(()) => { ui.say(format!("deleted {n}")); on_gone.call(()); } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "delete" } + if armed() { "delete it?" } + } + } + div { class: "dim small", + {format!( + "{} · {} head{}{} · version {}", + d["preset"].as_str().unwrap_or(""), + d["head"].as_str().unwrap_or(""), + if d["gematria"].as_bool() == Some(true) { " · gematria inputs" } else { "" }, + if size.is_object() { format!(" · {} weights, {} wide, {} blocks", size["weights"], size["d_model"], size["layers"]) } else { String::new() }, + d["version"], + )} + if !inputs.is_empty() { + {format!(" · builds on {}", inputs.join(", "))} + } + if let Some(s) = d["starter"].as_str() { + {format!(" · from the starter {s:?}")} + } + } + } + crate::views::clsmore::Tabs { tab } + match tab() { + Tab::Learn => rsx! { + Train { name: name.clone(), details: d.clone(), job: job(), on_start: move |j: Value| { job.set(Some(j)); watching.set(true); } } + if trained && d["starter"].is_string() { + HeldOut { name: name.clone(), version: d["version"].as_u64().unwrap_or(0) } + } + if trained { + Steer { name: name.clone(), details: d.clone() } + } + crate::views::clsmore::Growth { details: d.clone() } + Verdicts { name: name.clone(), details: d.clone(), on_change: move |_| rev += 1 } + }, + _ if !trained => rsx! { + div { class: "card dim", if running { "It's training: the learn tab shows how it goes." } else { "Train it first (the learn tab): then try it on texts, search with it, file the save into its buckets and check it with other classifiers." } } + }, + Tab::Use => rsx! { + Try { name: name.clone(), classes: classes.clone() } + crate::views::clsmore::Why { name: name.clone() } + Search { name: name.clone(), classes: classes.clone(), outputs: d["outputs"].clone() } + }, + Tab::Buckets => rsx! { crate::views::clsmore::Buckets { name: name.clone() } }, + Tab::Checks => rsx! { crate::views::clsmore::Checks { name: name.clone(), all: all_names.clone() } }, + } + } + } +} + +// ------------------------------------------------------------------ starters + +/// the starters: each one's classes, where its texts come from and on what terms; making +/// one writes its training texts as lists and trains a classifier on them +#[component] +fn Starters(on_made: EventHandler<String>) -> Element { + let ui = ui(); + let api = api(); + let mut rev = use_signal(|| 0u64); + let mut busy: Signal<Option<String>> = use_signal(|| None); + let api_l = api.clone(); + let all = use_resource(move || { + let api = api_l.clone(); + let _ = rev(); + async move { api.call("classify.starters", json!({})).await } + }); + let list: Vec<Value> = match &*all.read() { + Some(Ok(v)) => v.as_array().cloned().unwrap_or_default(), + Some(Err(e)) => return rsx! { div { class: "card bad", "{e}" } }, + None => return rsx! { div { class: "card dim", "…" } }, + }; + rsx! { + div { class: "card starters", + h3 { "starters" } + p { class: "dim small", + "Texts whose classes are known for certain: made by a rule, or taken from public-domain books. Making one writes its training texts into this save as lists, one per class (400 texts a class for the rule-made ones), and trains a classifier on them; its page then scores it on texts held out from training, which it never saw." + } + for s in list { + { + let id = s["id"].as_str().unwrap_or("").to_string(); + let classes = strs(&s["classes"]); + let source = match s["source"].as_str() { + Some("rules") => "made by rules", + Some("bundled") => "public domain, comes with the app", + _ => "public domain, fetched when asked", + }; + let needs_fetch = s["fetched"] == false; + let this_busy = busy().as_deref() == Some(id.as_str()); + let (api_m, id_m) = (api.clone(), id.clone()); + let make = move |_| { + let (api, id) = (api_m.clone(), id_m.clone()); + busy.set(Some(id.clone())); + spawn(async move { + let r = api.call("classify.starter", json!({ "id": id })).await; + busy.set(None); + match r { + Ok(v) => { + let n = v["classifier"]["name"].as_str().unwrap_or("").to_string(); + ui.say(format!("{n}: {} texts in its lists; training", v["texts"])); + ui.touched(); + on_made.call(n); + } + Err(e) => ui.fail(e), + } + }); + }; + let (api_f, id_f) = (api.clone(), id.clone()); + let fetch = move |_| { + let (api, id) = (api_f.clone(), id_f.clone()); + busy.set(Some(id.clone())); + spawn(async move { + let r = api.call("classify.starter_fetch", json!({ "id": id })).await; + busy.set(None); + match r { + Ok(v) => { ui.say(format!("fetched {} books", v["got"])); rev += 1; } + Err(e) => ui.fail(e), + } + }); + }; + rsx! { + div { key: "{id}", class: "starter", + div { class: "row", + b { {s["title"].as_str().unwrap_or("")} } + for (i , c) in classes.iter().enumerate() { + span { key: "{c}", class: "chip cls-class", style: "--hue: {hue(i, classes.len())};", "{c}" } + } + span { class: "grow" } + if needs_fetch { + button { disabled: busy().is_some(), onclick: fetch, Icon { name: "download" } if this_busy { "fetching…" } else { "fetch its books" } } + } else { + button { disabled: busy().is_some(), onclick: make, Icon { name: "new" } if this_busy { "making…" } else { "make and train it" } } + } + } + div { class: "small", {s["about"].as_str().unwrap_or("")} } + div { class: "dim small", "{source}: " {s["licence"].as_str().unwrap_or("")} } + } + } + } + } + } + } +} + +/// a starter classifier's score on the starter's held-out texts, read again when its +/// weights change +#[component] +fn HeldOut(name: String, version: u64) -> Element { + let api = api(); + let mut again = use_signal(|| 0u64); + let n0 = name.clone(); + let score = use_resource(move || { + let (api, n) = (api.clone(), n0.clone()); + let _ = (again(), version); + async move { api.call("classify.starter_score", json!({ "name": n })).await } + }); + let body = match &*score.read() { + Some(Ok(v)) => { + let per: Vec<String> = v["classes"] + .as_array() + .into_iter() + .flatten() + .map(|c| format!("{} {}/{}", c["class"].as_str().unwrap_or(""), c["right"], c["texts"])) + .collect(); + let dev = match v["device"]["device"].as_str() { + Some("cpu") | None => "the CPU".to_string(), + Some(_) => format!("the GPU ({})", v["device"]["gpu"].as_str().unwrap_or("")), + }; + rsx! { + div { class: "row", + b { class: "big", {format!("{:.1}%", 100.0 * v["accuracy"].as_f64().unwrap_or(0.0))} } + span { {format!("right on {} of {} held-out texts it never trained on", v["right"], v["texts"])} } + } + div { class: "dim small", {per.join(" · ")} } + div { class: "dim small", {format!("read on {dev} in {:.2} s", v["seconds"].as_f64().unwrap_or(0.0))} } + } + } + Some(Err(e)) => rsx! { div { class: "bad small", "{e}" } }, + None => rsx! { div { class: "dim small", "scoring on the held-out texts…" } }, + }; + rsx! { + div { class: "card held-out", + div { class: "row", + h3 { "held-out score" } + span { class: "grow" } + button { class: "plain", "data-tip": "score it again", onclick: move |_| again += 1, Icon { name: "refresh" } } + } + {body} + } + } +} + +/// a class's hue, spread round the wheel (the memo palette's order) +pub(crate) fn hue(i: usize, n: usize) -> f64 { + (i as f64 * 360.0 / n.max(1) as f64 + 24.0) % 360.0 +} + +/// the classifier as a file: written to Downloads on the desktop, a download on the web +fn export(ui: Ui, api: Api, name: String) { + dioxus::dioxus_core::spawn_forever(async move { + let v = match api.call("classify.export", json!({ "name": name })).await { + Ok(v) => v, + Err(e) => return ui.fail(e), + }; + let file = v["file"].as_str().unwrap_or("classifier.anendcls").to_string(); + let data = v["data"].as_str().unwrap_or("").to_string(); + if api.on_disk() { + #[cfg(not(target_arch = "wasm32"))] + { + let Some(bytes) = anend_core::classifiers::unbase64(&data) else { + return ui.fail("the export didn't read"); + }; + let home = std::env::var_os("HOME").or_else(|| std::env::var_os("USERPROFILE")); + let downloads = home + .map(|h| std::path::PathBuf::from(h).join("Downloads")) + .filter(|d| d.is_dir()); + let dir = downloads.unwrap_or_else(|| { + std::path::PathBuf::from(api.describe()) + .parent() + .map(|p| p.join("exports")) + .unwrap_or_default() + }); + let _ = std::fs::create_dir_all(&dir); + let path = dir.join(&file); + match std::fs::write(&path, bytes) { + Ok(()) => ui.say(format!("exported to {}", path.display())), + Err(e) => ui.fail(format!("couldn't write {}: {e}", path.display())), + } + } + } else { + let js = format!( + "const b = Uint8Array.from(atob({}), c => c.charCodeAt(0)); const a = document.createElement('a'); a.href = URL.createObjectURL(new Blob([b], {{type: 'application/octet-stream'}})); a.download = {}; a.click(); setTimeout(() => URL.revokeObjectURL(a.href), 4000);", + serde_json::to_string(&data).unwrap_or_default(), + serde_json::to_string(&file).unwrap_or_default() + ); + document::eval(&js); + ui.say(format!("exported {file}")); + } + }); +} + +// ------------------------------------------------------------------ training + +#[component] +fn Train(name: String, details: Value, job: Option<Value>, on_start: EventHandler<Value>) -> Element { + let ui = ui(); + let api = api(); + let mut epochs = use_signal(|| 8u32); + let mut fresh = use_signal(|| false); + let device = use_signal(|| "cpu".to_string()); + let state = job + .as_ref() + .and_then(|j| j["state"].as_str()) + .unwrap_or("idle") + .to_string(); + let running = state == "running"; + let trained = details["trained"].as_bool().unwrap_or(false); + let last = details["history"] + .as_array() + .and_then(|h| h.iter().rev().find(|e| e["kind"] == "train")) + .cloned() + .unwrap_or(Value::Null); + let (api_t, n_t, api_c, n_c) = (api.clone(), name.clone(), api.clone(), name.clone()); + let start = move |_| { + let (api, n) = (api_t.clone(), n_t.clone()); + let args = json!({ "name": n, "epochs": *epochs.peek(), "fresh": *fresh.peek(), "device": *device.peek() }); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("classify.train", args).await { + Ok(j) => { + ui.say(format!("training {n}…")); + on_start.call(j); + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + }; + let cancel = move |_| { + let (api, n) = (api_c.clone(), n_c.clone()); + dioxus::dioxus_core::spawn_forever(async move { + if let Err(e) = api.cancel_training(&n).await { + ui.fail(e); + } + }); + }; + rsx! { + div { class: "card", + div { class: "row", + h3 { Icon { name: "play" } "training" } + span { class: "grow" } + if !running { + label { class: "row small", "epochs" + input { r#type: "number", min: "1", max: "200", style: "width: 64px;", initial_value: "{epochs}", + oninput: move |e| if let Ok(v) = e.value().parse::<u32>() { epochs.set(v.clamp(1, 200)) } } + } + if trained { + label { class: "row small", title: "from new weights instead of going on from these", + input { r#type: "checkbox", checked: fresh(), onchange: move |e| fresh.set(e.checked()) } "from scratch" } + } + DevicePick { device } + button { class: "primary", onclick: start, Icon { name: "play" } if trained { "train more" } else { "train" } } + } else { + button { onclick: cancel, Icon { name: "pause" } "cancel" } + } + } + if let Some(j) = job.as_ref().filter(|_| running) { + Progress { job: j.clone() } + } else { + if state == "failed" { + div { class: "bad small", {j_err(&job)} } + } + if let Some(j) = job.as_ref().filter(|j| j["state"] == "done") { + div { class: "dim small", "the last run: " {format!("{:.1} s {}", j["seconds"].as_f64().unwrap_or(0.0), device_words(j["device"].as_str().unwrap_or("")))} + if let Some(n) = j["device_note"].as_str() { span { class: "bad", " · {n}" } } } + } + if state == "cancelled" { + div { class: "dim small", "the last run was cancelled; nothing was written" } + } + if last.is_object() { + Metrics { event: last.clone(), classes: strs(&details["classes"]) } + } else if !trained { + div { class: "dim small", "It learns from its lists' members as they are when training starts. A tiny classifier trains in seconds; compact in a minute or so." } + } + } + } + } +} + +fn j_err(job: &Option<Value>) -> String { + job.as_ref() + .and_then(|j| j["error"].as_str()) + .unwrap_or("it failed") + .to_string() +} + +/// where a training runs: the CPU (the reference, bit for bit the same everywhere), the GPU +/// in exact precision, or the GPU fast (plain operators, within a hair of the CPU) +#[component] +pub(crate) fn DevicePick(device: Signal<String>) -> Element { + let mut device = device; + rsx! { + label { class: "row small", title: "where it trains: without a GPU (or on a hub that keeps members on its CPU) it falls back to the CPU and says so", + "on" + select { "aria-label": "where it trains", value: "{device}", onchange: move |e| device.set(e.value()), + option { value: "cpu", selected: device() == "cpu", "the CPU" } + option { value: "gpu", selected: device() == "gpu", "the GPU" } + option { value: "gpu_fast", selected: device() == "gpu_fast", "the GPU, fast" } + } + } + } +} + +/// a job's device in words +pub(crate) fn device_words(d: &str) -> &'static str { + match d { + "gpu" => "on the GPU", + "gpu_fast" => "on the GPU (fast)", + "cpu" => "on the CPU", + _ => "", + } +} + +#[component] +pub(crate) fn Progress(job: Value) -> Element { + let steps = job["steps"].as_f64().unwrap_or(0.0).max(1.0); + let step = job["step"].as_f64().unwrap_or(0.0); + let rounds = job["rounds"].as_u64().unwrap_or(1); + let done = (step / steps).clamp(0.0, 1.0); + let losses: Vec<(f64, f64)> = job["losses"] + .as_array() + .into_iter() + .flatten() + .filter_map(|p| Some((p.get(0)?.as_f64()?, p.get(1)?.as_f64()?))) + .collect(); + let line = spark(&losses, 240.0, 34.0); + rsx! { + div { class: "progress", role: "progressbar", "aria-valuenow": "{(done * 100.0).round()}", "aria-valuemin": "0", "aria-valuemax": "100", + span { style: "width: {done * 100.0:.1}%;" } + } + div { class: "row small", + span { {format!("{:.0}%", done * 100.0)} } + span { class: "dim", {format!("epoch {} · step {} of {}", job["epoch"].as_u64().unwrap_or(0) + 1, step as u64, steps as u64)} } + if rounds > 1 { span { class: "dim", {format!("round {} of {rounds}", job["round"].as_u64().unwrap_or(0) + 1)} } } + span { class: "dim", {format!("loss {:.3}", job["loss"].as_f64().unwrap_or(0.0))} } + span { class: "dim", {format!("{:.0} tokens/s · {:.0} s · {} texts", job["tokens_per_sec"].as_f64().unwrap_or(0.0), job["seconds"].as_f64().unwrap_or(0.0), job["examples"])} } + span { class: "device", {device_words(job["device"].as_str().unwrap_or(""))} } + } + if let Some(n) = job["device_note"].as_str() { + div { class: "small bad", "{n}" } + } + if !line.is_empty() { + svg { class: "spark", width: "240", height: "34", view_box: "0 0 240 34", role: "img", "aria-label": "the loss as it trains", + polyline { points: "{line}" } + } + } + } +} + +/// points of a line through (x, y) pairs fitted to w × h +pub(crate) fn spark(p: &[(f64, f64)], w: f64, h: f64) -> String { + if p.len() < 2 { + return String::new(); + } + let (x0, x1) = (p[0].0, p[p.len() - 1].0.max(p[0].0 + 1.0)); + let lo = p.iter().map(|q| q.1).fold(f64::INFINITY, f64::min); + let hi = p.iter().map(|q| q.1).fold(f64::NEG_INFINITY, f64::max).max(lo + 1e-9); + p.iter() + .map(|(x, y)| { + format!( + "{:.1},{:.1}", + (x - x0) / (x1 - x0) * w, + h - 2.0 - (y - lo) / (hi - lo) * (h - 4.0) + ) + }) + .collect::<Vec<_>>() + .join(" ") +} + +#[component] +pub(crate) fn Metrics(event: Value, classes: Vec<String>) -> Element { + let m = &event["metrics"]; + let on = event["measured_on"].as_str().unwrap_or(""); + let per = m["classes"].as_array().cloned().unwrap_or_default(); + let confusion: Vec<Vec<u64>> = m["confusion"] + .as_array() + .into_iter() + .flatten() + .map(|r| r.as_array().into_iter().flatten().filter_map(Value::as_u64).collect()) + .collect(); + rsx! { + div { class: "figures", + div { b { {pct(m["accuracy"].as_f64().unwrap_or(0.0))} } "accuracy" } + div { b { {format!("{:.2}", m["macro_f1"].as_f64().unwrap_or(0.0))} } "macro F1" } + div { b { {format!("{:.3}", m["log_loss"].as_f64().unwrap_or(0.0))} } "log loss" } + div { b { "{event[\"examples\"]}" } "texts" } + div { b { {format!("{:.0} s", event["seconds"].as_f64().unwrap_or(0.0))} } "{event[\"steps\"]} steps" } + } + div { class: "dim small", {format!("measured on {} texts {}", m["n"], if on.is_empty() { "held out".to_string() } else { on.to_string() })} " · " {event["note"].as_str().unwrap_or("").to_string()} } + if !per.is_empty() { + table { class: "confusion", + thead { tr { th { "" } th { "F1" } th { "texts" } for c in classes.iter() { th { key: "{c}", title: "said {c}", "→ {c}" } } } } + tbody { + for (i , c) in classes.iter().enumerate() { + tr { key: "{c}", + th { "{c}" } + td { {format!("{:.2}", per.get(i).and_then(|s| s["f1"].as_f64()).unwrap_or(0.0))} } + td { {per.get(i).map(|s| s["support"].to_string()).unwrap_or_default()} } + for (j , n) in confusion.get(i).cloned().unwrap_or_default().into_iter().enumerate() { + td { key: "{j}", class: if i == j { "hit" } else if n > 0 { "miss" } else { "" }, "{n}" } + } + } + } + } + } + } + } +} + +// ------------------------------------------------------------------ trying it + +#[component] +fn Try(name: String, classes: Vec<String>) -> Element { + let ui = ui(); + let api = api(); + let mut similar: Signal<Option<Vec<Value>>> = use_signal(|| None); + let n0 = name.clone(); + let api_p = api.clone(); + let out = use_resource(move || { + let (api, n) = (api_p.clone(), n0.clone()); + let t = ui.bar.read().trim().to_string(); + let shown = (ui.view)() == View::Models; + let _ = (ui.changed)(); + async move { + if t.is_empty() || !shown { + return None; + } + // a beat after typing stops + sleep_ms(180).await; + Some(api.run_model(&n, &t).await) + } + }); + let v = match &*out.read() { + Some(Some(Ok(v))) => v.clone(), + Some(Some(Err(e))) => return rsx! { div { class: "card bad", "{e}" } }, + _ => { + return rsx! { + div { class: "card", + h3 { Icon { name: "text" } "try it" } + div { class: "dim", "Type a text in the command bar below: each class's probability shows here as you type." } + } + }; + } + }; + let r = v["results"][0].clone(); + let text = r["text"].as_str().unwrap_or("").to_string(); + let probs = nums(&r["probs"]); + let members = strs(&r["members"]); + let top = r["class"].as_str().unwrap_or("").to_string(); + let api_s = api.clone(); + let (n_s, t_s) = (name.clone(), text.clone()); + rsx! { + div { class: "card", + div { class: "row", + h3 { Icon { name: "text" } "try it" } + span { class: "dim small t", "“{text}”" } + span { class: "grow" } + button { class: "plain", "data-tip": "the texts it reads most like this one", "aria-label": "texts like this", + onclick: move |_| { + let (api, n, t) = (api_s.clone(), n_s.clone(), t_s.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("classify.similar", json!({ "name": n, "text": t, "limit": 12 })).await { + Ok(v) => similar.set(Some(v["results"].as_array().cloned().unwrap_or_default())), + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "near" } "texts like this" } + } + div { class: "results", + for (i , c) in classes.iter().cloned().enumerate() { + ClassRow { key: "{c}", name: name.clone(), class: c.clone(), prob: probs.get(i).copied().unwrap_or(0.0), + top: c == top, member: members.contains(&c), hue: hue(i, classes.len()), key_: None, text: text.clone() } + } + } + if let Some(found) = similar() { + div { class: "row small", span { class: "dim", "most like it:" } button { class: "plain", "aria-label": "close", onclick: move |_| similar.set(None), Icon { name: "close" } } } + div { class: "results", + for h in found { + div { key: "{h[\"key\"]}", class: "result", + span { class: "p", {format!("{:.2}", h["cosine"].as_f64().unwrap_or(0.0))} } + span { class: "t", title: "{h[\"text\"].as_str().unwrap_or(\"\")}", {h["text"].as_str().unwrap_or("").to_string()} } + button { class: "plain", "aria-label": "into the bar", "data-tip": "into the bar", + onclick: { let t = h["text"].as_str().unwrap_or("").to_string(); move |_| ui.set_bar(&t) }, Icon { name: "text" } } + } + } + } + } + } + } +} + +/// a class's probability for a text, with yes and no (Ctrl+Z takes either back) +#[component] +fn ClassRow( + name: String, + class: String, + prob: f64, + top: bool, + member: bool, + hue: f64, + key_: Option<String>, + text: String, +) -> Element { + let ui = ui(); + let api = api(); + rsx! { + div { class: if top { "result best" } else { "result" }, + span { class: "t", style: "--hue: {hue};", span { class: "swatch" } "{class}" if member { span { class: "dim small", " · in it" } } } + span { class: "probbar wide", span { style: "width: {prob * 100.0:.1}%; background: hsl({hue} 45% 55%);" } } + span { class: "p", {pct(prob)} } + for yes in [true, false] { + button { class: "plain", "aria-label": if yes { "yes, it is {class}" } else { "no, it isn't {class}" }, "data-tip": if yes { "yes, it is" } else { "no, it isn't" }, + onclick: { let (api, n, t, c, k) = (api.clone(), name.clone(), text.clone(), class.clone(), key_.clone()); move |_| { + let (api, n, t, c, k) = (api.clone(), n.clone(), t.clone(), c.clone(), k.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.model_feedback(&n, k.as_deref(), &t, &c, yes).await { + Ok(v) => { + let e = &v["entry"]; + ui.did(Did::Feedback { model: n }); + ui.say(format!("told it {}: {c} {} → {} · Ctrl+Z takes it back", if yes { "yes" } else { "no" }, + pct(e["before"].as_f64().unwrap_or(0.0)), pct(e["after"].as_f64().unwrap_or(0.0)))); + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + } }, + Icon { name: if yes { "check" } else { "close" } } } + } + } + } +} + +// ------------------------------------------------------------------ steering + +#[component] +fn Steer(name: String, details: Value) -> Element { + let ui = ui(); + let api = api(); + let classes = strs(&details["classes"]); + let h = &details["steer"]["heads"][0]; + let mut bias = use_signal(|| nums(&h["bias"])); + let mut temperature = use_signal(|| h["temperature"].as_f64().unwrap_or(1.0)); + let mut threshold = use_signal(|| h["threshold"].as_f64().unwrap_or(0.5)); + let g0 = &details["steer"]["gains"]; + let mut gains = use_signal(|| ["letter", "word", "side", "extra"].map(|k| g0[k].as_f64().unwrap_or(1.0))); + let mut report: Signal<Option<Value>> = use_signal(|| None); + let mut form = use_signal(|| 0u64); + let apply = { + let (api, n) = (api.clone(), name.clone()); + move |reset: bool| { + let (api, n) = (api.clone(), n.clone()); + let steer = if reset { + json!({ "reset": true }) + } else { + { + let g = *gains.peek(); + json!({ "bias": *bias.peek(), "temperature": *temperature.peek(), "threshold": *threshold.peek(), + "gains": { "letter": g[0], "word": g[1], "side": g[2], "extra": g[3] } }) + } + }; + dioxus::dioxus_core::spawn_forever(async move { + match api.call("classify.steer", json!({ "name": n, "steer": steer })).await { + Ok(v) => { + let h = &v["steer"]["heads"][0]; + if reset { + bias.set(nums(&h["bias"])); + temperature.set(h["temperature"].as_f64().unwrap_or(1.0)); + threshold.set(h["threshold"].as_f64().unwrap_or(0.5)); + let g = &v["steer"]["gains"]; + gains.set(["letter", "word", "side", "extra"].map(|k| g[k].as_f64().unwrap_or(1.0))); + form += 1; + } + report.set(Some(v["bias"].clone())); + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + } + }; + let (a1, a2, a3, a4) = (apply.clone(), apply.clone(), apply.clone(), apply.clone()); + let b = bias(); + rsx! { + div { class: "card", + div { class: "row", + h3 { Icon { name: "sliders" } "steering" } + span { class: "dim small", "your hand on its answers; training never changes these" } + span { class: "grow" } + button { class: "plain", onclick: move |_| a4(true), Icon { name: "refresh" } "reset" } + } + for g in [form()] { + div { key: "{g}", class: "form", + for (i , c) in classes.iter().enumerate() { + label { "towards {c}" } + div { class: "row", + input { r#type: "range", min: "-4", max: "4", step: "0.1", style: "flex: 1;", "aria-label": "bias towards {c}", + initial_value: "{b.get(i).copied().unwrap_or(0.0)}", + oninput: move |e| if let (Ok(v), Some(x)) = (e.value().parse::<f64>(), bias.write().get_mut(i)) { *x = v; }, + onchange: { let a = a1.clone(); move |_| a(false) } } + span { class: "num", {format!("{:+.1}", b.get(i).copied().unwrap_or(0.0))} } + } + } + label { "temperature" } + div { class: "row", + input { r#type: "range", min: "0.2", max: "4", step: "0.05", style: "flex: 1;", "aria-label": "temperature", + initial_value: "{temperature}", oninput: move |e| if let Ok(v) = e.value().parse() { temperature.set(v) }, + onchange: { let a = a2.clone(); move |_| a(false) } } + span { class: "num", {format!("{:.2}", temperature())} } + } + label { "counts as in at" } + div { class: "row", + input { r#type: "range", min: "0", max: "1", step: "0.01", style: "flex: 1;", "aria-label": "threshold", + initial_value: "{threshold}", oninput: move |e| if let Ok(v) = e.value().parse() { threshold.set(v) }, + onchange: { let a = a3.clone(); move |_| a(false) } } + span { class: "num", {pct(threshold())} } + } + label { class: "wide-label", "channel gains" } + div { class: "dim small", "how much each kind of input counts: the letters, the words' sums, the text's own measures, other classifiers" } + for (i , what) in ["letters", "word sums", "the text's measures", "other classifiers"].into_iter().enumerate() { + label { key: "gl{i}", "{what}" } + div { class: "row", + input { r#type: "range", min: "0", max: "3", step: "0.05", style: "flex: 1;", "aria-label": "the gain of {what}", + initial_value: "{gains()[i]}", oninput: move |e| if let Ok(v) = e.value().parse::<f64>() { gains.write()[i] = v; }, + onchange: { let a = a1.clone(); move |_| a(false) } } + span { class: "num", {format!("{:.2}", gains()[i])} } + } + } + } + } + if let Some(r) = report().filter(|r| r.is_object()) { + div { class: "dim small", + {format!("on {} texts: {} change their answer, mean shift {:.3} nats (largest {:.3})", + r["texts"], pct(r["flipped"].as_f64().unwrap_or(0.0)), r["mean_kl"].as_f64().unwrap_or(0.0), r["max_kl"].as_f64().unwrap_or(0.0))} + } + } + } + } +} + +// ------------------------------------------------------------------ searching with it + +#[component] +fn Search(name: String, classes: Vec<String>, outputs: Value) -> Element { + let ui = ui(); + let api = api(); + let mut class = use_signal(|| 0usize); + let mut words = use_signal(String::new); + let mut found: Signal<Option<Vec<Scored>>> = use_signal(|| None); + let mut busy = use_signal(|| false); + let run = { + let (api, n, classes) = (api.clone(), name.clone(), classes.clone()); + move || { + let (api, n) = (api.clone(), n.clone()); + let c = classes.get(*class.peek()).cloned().unwrap_or_default(); + let q = words.peek().trim().to_string(); + busy.set(true); + dioxus::dioxus_core::spawn_forever(async move { + match api.model_search(&n, &c, &q).await { + Ok(r) => found.set(Some(r)), + Err(e) => ui.fail(e), + } + busy.set(false); + }); + } + }; + let (r1, r2) = (run.clone(), run.clone()); + let api_e = api.clone(); + let n_e = name.clone(); + let cur = classes.get(class()).cloned().unwrap_or_default(); + let as_list = outputs[cur.as_str()].as_str().map(str::to_string); + let c_e = cur.clone(); + rsx! { + div { class: "card", + div { class: "row", + h3 { Icon { name: "search" } "search by class" } + for (i , c) in classes.iter().enumerate() { + button { key: "{c}", class: if class() == i { "chip on" } else { "chip" }, onclick: { let mut r = r1.clone(); move |_| { class.set(i); r(); } }, "{c}" } + } + input { r#type: "text", placeholder: "and these words (optional)", style: "flex: 1; min-width: 120px;", + oninput: move |e| words.set(e.value()), + onkeydown: { let mut r = r2.clone(); move |e: KeyboardEvent| if e.key() == Key::Enter { r() } } } + button { class: "primary", disabled: busy(), onclick: { let mut r = run.clone(); move |_| r() }, Icon { name: "search" } "find" } + button { "data-tip": if as_list.is_some() { "write the list again from its answers now" } else { "its answers for this class as a list, for lists and other classifiers" }, + onclick: move |_| { + let (api, n, c) = (api_e.clone(), n_e.clone(), c_e.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.model_enlist(&n, &c).await { + Ok(v) => { ui.say(format!("“{}”: {} texts", v["name"].as_str().unwrap_or(""), v["members"])); ui.touched(); } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "list" } if as_list.is_some() { "list again" } else { "as a list" } } + } + if let Some(hits) = found() { + if hits.is_empty() { + div { class: "dim", "nothing found" } + } + div { class: "results", + for h in hits { + SearchRow { key: "{h.key.clone().unwrap_or_default()}", name: name.clone(), class: cur.clone(), hit: h } + } + } + } + } + } +} + +#[component] +fn SearchRow(name: String, class: String, hit: Scored) -> Element { + let ui = ui(); + let api = api(); + let t = hit.text.clone(); + rsx! { + div { class: "result", + span { class: "p", {pct(hit.prob)} } + span { class: "probbar", span { style: "width: {hit.prob * 100.0:.1}%;" } } + span { class: "t", title: "{hit.text}", if hit.note { "✎ " } "{hit.text}" } + if hit.top_class.as_deref().is_some_and(|c| c != class) { + span { class: "dim small", "reads as {hit.top_class.clone().unwrap_or_default()}" } + } + for yes in [true, false] { + button { class: "plain", "aria-label": if yes { "yes" } else { "no" }, "data-tip": if yes { "yes, it is {class}" } else { "no, it isn't {class}" }, + onclick: { let (api, n, c, k, t) = (api.clone(), name.clone(), class.clone(), hit.key.clone(), hit.text.clone()); move |_| { + let (api, n, c, k, t) = (api.clone(), n.clone(), c.clone(), k.clone(), t.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.model_feedback(&n, k.as_deref(), &t, &c, yes).await { + Ok(_) => { ui.did(Did::Feedback { model: n }); ui.say("told it; Ctrl+Z takes it back"); ui.touched(); } + Err(e) => ui.fail(e), + } + }); + } }, + Icon { name: if yes { "check" } else { "close" } } } + } + button { class: "plain", "aria-label": "into the bar", "data-tip": "into the bar", onclick: move |_| ui.set_bar(&t), Icon { name: "text" } } + } + } +} + +// ------------------------------------------------------------------ verdicts given + +#[component] +fn Verdicts(name: String, details: Value, on_change: EventHandler<()>) -> Element { + let ui = ui(); + let api = api(); + let fb = details["feedback"].as_array().cloned().unwrap_or_default(); + let count = details["feedback_count"].as_u64().unwrap_or(0); + let undo = details["undo"].as_u64().unwrap_or(0); + if count == 0 { + return rsx! {}; + } + let n = name.clone(); + rsx! { + div { class: "card", + div { class: "row", + h3 { Icon { name: "check" } "yes and no given" } + span { class: "dim small", "{count} in all; kept and replayed when it trains" } + span { class: "grow" } + button { class: "plain", disabled: undo == 0, "data-tip": if undo == 0 { "nothing to take back since it last trained".to_string() } else { format!("take back the latest ({undo} can be)") }, + onclick: move |_| { + let (api, n) = (api.clone(), n.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.undo_model_feedback(&n).await { + Ok(()) => { ui.say("took it back"); ui.touched(); on_change.call(()); } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "undo" } "take back" } + } + div { class: "results", + for (i , e) in fb.into_iter().take(8).enumerate() { + div { key: "{i}", class: "result", + span { class: "p", Icon { name: if e["yes"] == true { "check" } else { "close" } } } + span { class: "small", style: "flex: none;", {e["class"].as_str().unwrap_or("").to_string()} } + span { class: "t dim", {e["text"].as_str().unwrap_or("").to_string()} } + span { class: "p", {format!("{} → {}", pct(e["before"].as_f64().unwrap_or(0.0)), pct(e["after"].as_f64().unwrap_or(0.0)))} } + } + } + } + } + } +} diff --git a/app/src/views/clsmore.rs b/app/src/views/clsmore.rs new file mode 100644 index 00000000..f2c17974 --- /dev/null +++ b/app/src/views/clsmore.rs @@ -0,0 +1,461 @@ +//! More of the classifiers view, as the Bevy app had it (classify_ui.rs, cls_more.rs): the +//! page's tabs (learn, use, buckets, checks); the buckets (every text filed by class and +//! sureness in tenths, a column or a class opening its texts, index again); texts near a +//! text by meaning or by verdict; "why" (each classifier's part in a verdict); the checks +//! (validators: other classifiers that must say a class for a verdict to stand, and the +//! texts they disagree on); the growth it went through. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use crate::ui::*; +use crate::views::classifiers::{nums, strs}; + +#[derive(Clone, Copy, PartialEq, Eq, Debug)] +pub enum Tab { + Learn, + Use, + Buckets, + Checks, +} + +impl Tab { + pub const ALL: [Tab; 4] = [Tab::Learn, Tab::Use, Tab::Buckets, Tab::Checks]; + pub fn name(self) -> &'static str { + match self { + Tab::Learn => "learn", + Tab::Use => "use", + Tab::Buckets => "buckets", + Tab::Checks => "checks", + } + } + pub fn icon(self) -> &'static str { + match self { + Tab::Learn => "sliders", + Tab::Use => "search", + Tab::Buckets => "bucket", + Tab::Checks => "shield", + } + } + pub fn tip(self) -> &'static str { + match self { + Tab::Learn => "training, steering and what it was told", + Tab::Use => "try it, why it says so, search by class, texts near a text", + Tab::Buckets => "every text filed by class and sureness, and near texts", + Tab::Checks => "other classifiers that check this one, and where they disagree", + } + } +} + +#[component] +pub fn Tabs(tab: Signal<Tab>) -> Element { + let mut tab = tab; + rsx! { + div { class: "card cls-tabs", role: "tablist", + for t in Tab::ALL { + button { + key: "{t.name()}", + role: "tab", + class: if tab() == t { "plain on" } else { "plain" }, + "aria-selected": "{tab() == t}", + "data-tip": "{t.tip()}", + onclick: move |_| tab.set(t), + Icon { name: t.icon() } + "{t.name()}" + } + } + } + } +} + +/// the growth and training it went through, newest first +#[component] +pub fn Growth(details: Value) -> Element { + let hist: Vec<Value> = details["history"].as_array().cloned().unwrap_or_default(); + if hist.is_empty() { + return rsx! {}; + } + rsx! { + div { class: "card", + h3 { Icon { name: "stats" } "growth" span { class: "dim small", " what it went through, newest first" } } + table { class: "growth", + thead { tr { th { "when" } th { "what" } th { "accuracy" } th { "F1" } th { "on" } th { "steps" } th { "" } } } + for (i , e) in hist.iter().rev().take(30).enumerate() { + tr { key: "{i}", + td { class: "dim", {e["time"].as_str().unwrap_or("").get(..16).unwrap_or("").replace('T', " ")} } + td { "{e[\"kind\"].as_str().unwrap_or(\"\")}" } + td { {e["metrics"]["accuracy"].as_f64().map(|a| format!("{:.1}%", a * 100.0)).unwrap_or_default()} } + td { {e["metrics"]["macro_f1"].as_f64().map(|a| format!("{a:.3}")).unwrap_or_default()} } + td { class: "dim", {format!("{} {}", e["examples"].as_u64().unwrap_or(0), e["measured_on"].as_str().unwrap_or(""))} } + td { "{e[\"steps\"].as_u64().unwrap_or(0)}" } + td { class: "dim small", "{e[\"note\"].as_str().unwrap_or(\"\")}" } + } + } + } + } + } +} + +/// each classifier's part in what this one says of a text (`classify.contributions`) +#[component] +pub fn Why(name: String) -> Element { + let ui = ui(); + let api = api(); + let mut text = use_signal(String::new); + let mut got: Signal<Option<Value>> = use_signal(|| None); + let ask = move |_| { + let (api, n, t) = (api.clone(), name.clone(), text()); + if t.trim().is_empty() { + ui.say("a text to ask about, please"); + return; + } + spawn(async move { + match api + .call("classify.contributions", json!({ "name": n, "text": t })) + .await + { + Ok(v) => got.set(Some(v)), + Err(e) => ui.fail(e), + } + }); + }; + let v = got(); + rsx! { + div { class: "card", + h3 { Icon { name: "help" } "why" span { class: "dim small", " each classifier's part in a verdict, end to end through the couplings" } } + div { class: "row", + input { r#type: "text", style: "flex: 1;", placeholder: "a text", "aria-label": "a text to ask why about", oninput: move |e| text.set(e.value()) } + button { onclick: ask, "why?" } + } + if let Some(v) = v { + div { class: "dim small", "it says “{v[\"class\"].as_str().unwrap_or(\"\")}”: who had a part in it" } + div { class: "results", + for (i , r) in v["results"].as_array().cloned().unwrap_or_default().into_iter().enumerate() { + div { key: "{i}", class: "result", + span { class: "p", {format!("{:.0}%", r["share"].as_f64().unwrap_or(0.0) * 100.0)} } + span { class: "probbar", span { style: "width: {(r[\"share\"].as_f64().unwrap_or(0.0) * 100.0).clamp(0.0, 100.0):.0}%;" } } + span { class: "t", b { "{r[\"name\"].as_str().unwrap_or(\"\")}" } if r["judged"] == true { " (this one)" } " says {r[\"top_class\"].as_str().unwrap_or(\"\")}" } + span { class: "dim small", {format!("inputs {:.0}%", r["input_share"].as_f64().unwrap_or(0.0) * 100.0)} } + } + } + } + } + } + } +} + +/// the texts filed nearest a text, by what the classifier represents them as (meaning) or +/// by how it judges them (verdict) +#[component] +pub fn Near(name: String) -> Element { + let ui = ui(); + let api = api(); + let mut text = use_signal(String::new); + let mut by = use_signal(|| "embedding"); + let mut got: Signal<Option<Value>> = use_signal(|| None); + let ask = move |_| { + let (api, n, t, b) = (api.clone(), name.clone(), text(), by()); + if t.trim().is_empty() { + return; + } + // a key as it is, else a text + let args = if anend_core::graph::record::parse_label(t.trim().trim_start_matches("note:")).is_some() { + json!({ "name": n, "key": t.trim(), "by": b, "limit": 30 }) + } else { + json!({ "name": n, "text": t, "by": b, "limit": 30 }) + }; + spawn(async move { + match api.call("classify.near", args).await { + Ok(v) => got.set(Some(v)), + Err(e) => ui.fail(e), + } + }); + }; + rsx! { + div { class: "card", + h3 { Icon { name: "near" } "near texts" span { class: "dim small", " the filed texts closest to a text: by meaning (what it represents it as) or by verdict (how it judges it)" } } + div { class: "row", + span { class: "mtabs", + button { class: if by() == "embedding" { "mtab on" } else { "mtab" }, onclick: move |_| by.set("embedding"), "meaning" } + button { class: if by() == "outputs" { "mtab on" } else { "mtab" }, onclick: move |_| by.set("outputs"), "verdict" } + } + input { r#type: "text", style: "flex: 1;", placeholder: "a text, or a key like 0,12", "aria-label": "a text to find near texts of", oninput: move |e| text.set(e.value()) } + button { onclick: ask, Icon { name: "near" } "find them" } + } + if let Some(v) = got() { + div { class: "dim small", "{v[\"indexed\"]} texts filed" } + div { class: "results", + for (i , r) in v["results"].as_array().cloned().unwrap_or_default().into_iter().enumerate() { + div { key: "{i}", class: "result", + span { class: "p", {format!("{:.3}", r["cosine"].as_f64().unwrap_or(0.0))} } + span { class: "t", title: "{r[\"key\"].as_str().unwrap_or(\"\")}", onclick: { let t = r["text"].as_str().unwrap_or("").to_string(); move |_| ui.set_bar(&t) }, + if r["note"] == true { "✎ " } "{r[\"text\"].as_str().unwrap_or(\"\")}" } + } + } + } + } + } + } +} + +/// every text filed by class and sureness, in tenths; a cell opens its texts +#[component] +pub fn Buckets(name: String) -> Element { + let ui = ui(); + let api = api(); + let mut again = use_signal(|| 0u64); + let mut open: Signal<Option<(String, Option<u32>)>> = use_signal(|| None); + let mut job: Signal<Option<Value>> = use_signal(|| None); + let (n0, api0) = (name.clone(), api.clone()); + let b = use_resource(move || { + let (api, n) = (api0.clone(), n0.clone()); + let _ = (again(), (ui.changed)()); + async move { api.call("classify.buckets", json!({ "name": n })).await } + }); + let (n1, api1) = (name.clone(), api.clone()); + let texts = use_resource(move || { + let (api, n) = (api1.clone(), n1.clone()); + let o = open(); + async move { + let (c, band) = o?; + let mut args = json!({ "name": n, "class": c, "limit": 200 }); + if let Some(b) = band { + args["band"] = json!(b); + } + api.call("classify.bucket", args).await.ok() + } + }); + let (n2, api2) = (name.clone(), api.clone()); + let index = move |_| { + let (api, n) = (api2.clone(), n2.clone()); + spawn(async move { + match api.call("classify.index", json!({ "name": n })).await { + Ok(j) => { + job.set(Some(j)); + loop { + sleep_ms(400).await; + match api.call("classify.index_job", json!({ "name": n })).await { + Ok(j) => { + let running = j["state"] == "running"; + job.set(Some(j)); + if !running { + break; + } + } + Err(_) => break, + } + } + again += 1; + ui.say(format!("{n}: the save is filed again")); + } + Err(e) => ui.fail(e), + } + }); + }; + let v = match &*b.read() { + Some(Ok(v)) => v.clone(), + Some(Err(e)) => return rsx! { div { class: "card dim", "{e}" } }, + None => return rsx! { div { class: "card dim", "…" } }, + }; + let palette = strs(&v["palette"]); + let buckets: Vec<Value> = v["buckets"].as_array().cloned().unwrap_or_default(); + let max = buckets.iter().flat_map(|b| nums(&b["bands"])).fold(1.0f64, f64::max); + let total: u64 = buckets.iter().map(|b| b["count"].as_u64().unwrap_or(0)).sum(); + let running = job().is_some_and(|j| j["state"] == "running"); + rsx! { + div { class: "card", + div { class: "row", + h3 { Icon { name: "bucket" } "buckets" } + span { class: "dim small", "{total} of {v[\"indexed\"]} texts filed" } + span { class: "grow" } + if running { + span { class: "dim small", {format!("filing {} of {}", job().map(|j| j["done"].clone()).unwrap_or_default(), job().map(|j| j["total"].clone()).unwrap_or_default())} } + } + button { disabled: running, "data-tip": "file every text again (after training or new texts)", onclick: index, Icon { name: "bolt" } "index again" } + } + div { class: "bgrid", + span { class: "dim small", "class" } + span {} + span { class: "dim small bscale", span { "0%" } span { "sureness →" } span { "100%" } } + for (i , bk) in buckets.iter().enumerate() { + { + let cname = bk["class"].as_str().unwrap_or("").to_string(); + let colour = if bk["index"].is_null() { "#8a8580".to_string() } else { palette.get(i).cloned().unwrap_or_default() }; + let bands = nums(&bk["bands"]); + let c2 = cname.clone(); + rsx! { + button { key: "c{i}", class: "plain bclass", onclick: move |_| open.set(Some((c2.clone(), None))), + span { class: "dot", style: "background: {colour};" } "{cname}" } + span { class: "dim num", "{bk[\"count\"]}" } + div { class: "bands", + for (j , n) in bands.iter().enumerate() { + { + let c3 = cname.clone(); + let h = (n / max * 100.0).clamp(0.0, 100.0); + rsx! { + button { key: "{j}", class: "band", title: "{cname}: {n} texts {j}0–{j + 1}0% sure", + onclick: move |_| open.set(Some((c3.clone(), Some(j as u32)))), + span { style: "height: {h:.0}%; background: {colour};" } + } + } + } + } + } + } + } + } + } + div { class: "dim small", "each class's texts by how sure it is, in tenths; “uncertain” holds the texts it puts in no class. Click a class or a cell for its texts. What's filed is kept until training, feedback or steering changes it." } + if let Some((c, band)) = open() { + div { class: "bucket-texts", + div { class: "row", + b { "{c}" } + if let Some(bd) = band { span { class: "dim small", " {bd}0–{bd + 1}0% sure" } } + span { class: "grow" } + button { class: "plain ibtn", "aria-label": "close", onclick: move |_| open.set(None), Icon { name: "close" } } + } + match texts.read().clone().flatten() { + Some(t) => rsx! { + if t["stale"].as_u64().unwrap_or(0) > 0 { div { class: "dim small", "{t[\"stale\"]} filed before the last change: index again" } } + div { class: "results", + for (i , h) in t["hits"].as_array().cloned().unwrap_or_default().into_iter().enumerate() { + div { key: "{i}", class: "result", + span { class: "p", {format!("{:.0}%", h["prob"].as_f64().unwrap_or(0.0) * 100.0)} } + span { class: "t", onclick: { let t = h["text"].as_str().unwrap_or("").to_string(); move |_| ui.set_bar(&t) }, + if h["note"] == true { "✎ " } "{h[\"text\"].as_str().unwrap_or(\"\")}" } + span { class: "dim small", "{h[\"ordinal\"]}·{h[\"reversed\"]}" } + } + } + } + }, + None => rsx! { div { class: "dim", "…" } }, + } + } + } + } + Near { name: name.clone() } + } +} + +/// the validators (classifiers that check this one) and the texts they disagree on +#[component] +pub fn Checks(name: String, all: Vec<String>) -> Element { + let ui = ui(); + let api = api(); + let mut again = use_signal(|| 0u64); + let (n0, api0) = (name.clone(), api.clone()); + let vals = use_resource(move || { + let (api, n) = (api0.clone(), n0.clone()); + let _ = again(); + async move { api.call("classify.validators", json!({ "name": n })).await } + }); + let (n1, api1) = (name.clone(), api.clone()); + let dis = use_resource(move || { + let (api, n) = (api1.clone(), n1.clone()); + let _ = again(); + async move { + api.call("classify.disagreements", json!({ "name": n, "limit": 40 })) + .await + } + }); + let mut by = use_signal(String::new); + let mut class = use_signal(String::new); + let mut min = use_signal(|| 0.5f64); + let mut mode = use_signal(|| "gate".to_string()); + // the classes of the classifier picked as a validator + let api_c = api.clone(); + let by_classes = use_resource(move || { + let api = api_c.clone(); + let b = by(); + async move { + if b.is_empty() { + return vec![]; + } + api.call("classify.get", json!({ "name": b })) + .await + .map(|v| strs(&v["classes"])) + .unwrap_or_default() + } + }); + let current: Vec<Value> = match &*vals.read() { + Some(Ok(v)) => v["validators"].as_array().cloned().unwrap_or_default(), + _ => vec![], + }; + let set = { + let (api, n) = (api.clone(), name.clone()); + move |list: Vec<Value>| { + let (api, n) = (api.clone(), n.clone()); + spawn(async move { + match api.call("classify.validators", json!({ "name": n, "set": list })).await { + Ok(_) => { + again += 1; + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + } + }; + let set2 = set.clone(); + let cur2 = current.clone(); + let others: Vec<String> = all.into_iter().filter(|x| *x != name).collect(); + rsx! { + div { class: "card", + h3 { Icon { name: "shield" } "validators" span { class: "dim small", " other classifiers that check this one: a verdict stands when its validator says the class it must" } } + if current.is_empty() { div { class: "dim", "none yet" } } + for (i , v) in current.iter().enumerate() { + div { key: "{i}", class: "row", + b { "{v[\"by\"].as_str().unwrap_or(\"\")}" } + span { "must say “{v[\"class\"].as_str().unwrap_or(\"\")}” at least {v[\"min\"].as_f64().unwrap_or(0.5) * 100.0:.0}% ({v[\"mode\"].as_str().unwrap_or(\"gate\")})" } + button { class: "plain", "data-tip": "take this validator off", + onclick: { let s = set.clone(); let cur = current.clone(); move |_| { let mut l = cur.clone(); l.remove(i); s(l); } }, + Icon { name: "close" } } + } + } + if others.is_empty() { + div { class: "dim small", "train another classifier to check this one with" } + } else { + div { class: "row", + select { "aria-label": "the validator", onchange: move |e| { by.set(e.value()); class.set(String::new()); }, + option { value: "", "a classifier…" } + for o in others { option { key: "{o}", value: "{o}", "{o}" } } + } + select { "aria-label": "the class it must say", onchange: move |e| class.set(e.value()), + option { value: "", "the class it must say…" } + for c in by_classes.read().clone().unwrap_or_default() { option { key: "{c}", value: "{c}", "{c}" } } + } + label { class: "row small", "at least" input { r#type: "number", min: "0", max: "1", step: "0.05", value: "{min}", style: "width: 70px;", oninput: move |e| if let Ok(x) = e.value().parse() { min.set(x) } } } + select { "aria-label": "how it checks", value: "{mode}", onchange: move |e| mode.set(e.value()), + option { value: "gate", "gate: no class unless it passes" } + option { value: "weigh", "weigh: multiply by its sureness" } + } + button { disabled: by().is_empty() || class().is_empty(), + onclick: move |_| { let mut l = cur2.clone(); l.push(json!({ "by": by(), "class": class(), "min": min(), "mode": mode() })); set2(l); }, + Icon { name: "new" } "add it" } + } + } + } + div { class: "card", + h3 { Icon { name: "alert" } "disagreements" span { class: "dim small", " texts it puts in a class its validators don't let stand" } } + match &*dis.read() { + Some(Ok(d)) => { + let rs = d["results"].as_array().cloned().unwrap_or_default(); + rsx! { + if rs.is_empty() { div { class: "dim", "they agree on every text" } } + div { class: "results", + for (i , r) in rs.into_iter().enumerate() { + div { key: "{i}", class: "result", + span { class: "p", {format!("{:.0}%", r["prob"].as_f64().unwrap_or(0.0) * 100.0)} } + span { class: "t", onclick: { let t = r["text"].as_str().unwrap_or("").to_string(); move |_| ui.set_bar(&t) }, "{r[\"text\"].as_str().unwrap_or(\"\")}" } + span { class: "dim small", "“{r[\"class\"].as_str().unwrap_or(\"\")}”, checked by " {r["checks"].as_array().cloned().unwrap_or_default().iter().map(|c| format!("{} {:.0}%", c[0].as_str().unwrap_or(""), c[1].as_f64().unwrap_or(0.0) * 100.0)).collect::<Vec<_>>().join(", ")} } + } + } + } + } + } + Some(Err(e)) => rsx! { div { class: "dim", "{e}" } }, + None => rsx! { div { class: "dim", "…" } }, + } + } + } +} diff --git a/app/src/views/flt.rs b/app/src/views/flt.rs new file mode 100644 index 00000000..5b562059 --- /dev/null +++ b/app/src/views/flt.rs @@ -0,0 +1,500 @@ +//! The filters view's builder, as the Bevy app's filters_ui.rs had it: include and exclude +//! texts by what classifiers say of them, by words, sums, lists, tags and kind, nested in +//! "all of" and "any of" groups (each condition can be turned round: "not"); run over the +//! classifiers' memoized buckets (`filters.run`), kept as presets that can include each +//! other (`filters.save`), and written out as lists (`filters.enlist`). +//! +//! The expression is core's `filters::Expr` as JSON, edited in place by paths into it. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use crate::backend::FilterRun; +use crate::ui::*; +use crate::views::classifiers::strs; + +/// what the builder offers to add +const ADD: [(&str, &str); 8] = [ + ("class", "a classifier says"), + ("words", "words"), + ("sum", "a sum"), + ("list", "in a list"), + ("tags", "tags"), + ("kind", "texts or notes"), + ("preset", "a kept filter"), + ("group", "a group"), +]; + +fn blank(kind: &str) -> Value { + match kind { + "class" => json!({ "op": "class", "classifier": "", "class": "" }), + "words" => json!({ "op": "words", "q": "" }), + "sum" => json!({ "op": "sum", "bucket": "ordinal" }), + "list" => json!({ "op": "list", "list": "" }), + "tags" => json!({ "op": "tags", "tags": [] }), + "kind" => json!({ "op": "kind", "kind": "memories" }), + "preset" => json!({ "op": "preset", "name": "" }), + _ => json!({ "op": "or", "of": [] }), + } +} + +/// the node at a path (indices into `of`) +fn at<'a>(root: &'a mut Value, path: &[usize]) -> Option<&'a mut Value> { + let mut v = root; + for &i in path { + v = v.get_mut("of")?.get_mut(i)?; + } + Some(v) +} + +/// a condition without its "not" +fn inner(v: &Value) -> (&Value, bool) { + if v["op"] == "not" { (&v["of"], true) } else { (v, false) } +} + +#[derive(Clone, PartialEq)] +struct Ctx { + classifiers: Vec<(String, Vec<String>)>, + lists: Vec<(String, String)>, + presets: Vec<String>, +} + +#[component] +pub fn Builder() -> Element { + let ui = ui(); + let api = api(); + let mut expr = use_signal(|| json!({ "op": "and", "of": [] })); + let mut name = use_signal(String::new); + // a pipe's effects and actions on what the filter lets through + let mut effects: Signal<Vec<Value>> = use_signal(Vec::new); + let mut actions: Signal<Vec<Value>> = use_signal(Vec::new); + // the kept pipe being edited, and the kept pipes' revision + let mut editing: Signal<Option<String>> = use_signal(|| None); + let mut pipes_rev = use_signal(|| 0u64); + let mut found: Signal<Option<FilterRun>> = use_signal(|| None); + let api_c = api.clone(); + let ctx = use_resource(move || { + let api = api_c.clone(); + let _ = (ui.changed)(); + async move { + let mut classifiers = Vec::new(); + for c in api + .call("classify.list", json!({})) + .await + .ok() + .and_then(|v| v.as_array().cloned()) + .unwrap_or_default() + { + let n = c["name"].as_str().unwrap_or("").to_string(); + let classes = api + .call("classify.get", json!({ "name": n })) + .await + .map(|d| strs(&d["classes"])) + .unwrap_or_default(); + classifiers.push((n, classes)); + } + let lists = api + .lists() + .await + .map(|l| l.lists.into_iter().map(|x| (x.list, x.name)).collect()) + .unwrap_or_default(); + let presets = api.filters().await.unwrap_or_default(); + ( + Ctx { + classifiers, + lists, + presets: presets.iter().map(|p| p.name.clone()).collect(), + }, + presets, + ) + } + }); + let Some((cx, presets)) = ctx.read().clone() else { + return rsx! { div { class: "card dim", "…" } }; + }; + use_context_provider(|| cx.clone()); + let api_r = api.clone(); + let run = move |_| { + let api = api_r.clone(); + let e = prune(&expr()); + if e.is_null() { + ui.say("add a condition first"); + return; + } + spawn(async move { + match api.run_filter(&e).await { + Ok(r) => found.set(Some(r)), + Err(e) => ui.fail(e), + } + }); + }; + let api_s = api.clone(); + let save = move |_| { + let (api, n, e) = (api_s.clone(), name().trim().to_string(), prune(&expr())); + spawn(async move { + match api.save_filter(&n, &e, "").await { + Ok(()) => { + ui.say(format!( + "kept the filter “{n}”: it can be part of other filters, and written as a list" + )); + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + }; + let api_p = api.clone(); + let keep_pipe = move |_| { + let api = api_p.clone(); + let n = name().trim().to_string(); + let e = prune(&expr()); + let pipe = json!({ "name": n, "from": e, "effects": effects(), "actions": actions() }); + let was = editing(); + spawn(async move { + let mut args = json!({ "pipe": pipe }); + match &was { + Some(w) => args["was"] = json!(w), + None => args["new"] = json!(true), + } + match api.call("pipes.save", args).await { + Ok(_) => { + ui.say(format!( + "kept the pipe “{n}”: turn it on below to see its effects in the memory view and the space" + )); + if let Some(w) = was.filter(|w| *w != n) { + crate::shell::set_pref(ui, |p| { + for x in p.pipes.iter_mut() { + if *x == w { + *x = n.clone(); + } + } + }); + } + editing.set(Some(n)); + pipes_rev += 1; + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + }; + let classifier_names: Vec<String> = cx.classifiers.iter().map(|c| c.0.clone()).collect(); + rsx! { + div { class: "card", + h3 { Icon { name: "classifier" } "by what classifiers say, and pipes" span { class: "dim small", " conditions in groups: all of them, or any; each can be turned round. With effects, it's a pipe." } } + Group { expr, path: vec![], depth: 0 } + crate::views::pipes::Parts { effects, actions, classifiers: classifier_names } + div { class: "row", + button { class: "primary", onclick: run, Icon { name: "play" } "run" } + input { r#type: "text", placeholder: "a name to keep it", value: "{name}", oninput: move |e| name.set(e.value()) } + button { disabled: name().trim().is_empty(), "data-tip": "keep the filter, to use in other filters", onclick: save, Icon { name: "save" } "keep the filter" } + button { disabled: name().trim().is_empty(), "data-tip": "keep the filter with its effects and actions", + onclick: keep_pipe, Icon { name: "save" } if editing().is_some() { "save the pipe" } else { "keep as a pipe" } } + if let Some(w) = editing() { + span { class: "dim small", "editing the pipe “{w}”" } + button { class: "plain", onclick: move |_| { editing.set(None); effects.set(vec![]); actions.set(vec![]); expr.set(json!({ "op": "and", "of": [] })); name.set(String::new()); }, + Icon { name: "close" } "new" } + } + } + if let Some(r) = found() { + div { class: "dim small", "{r.matched} of {r.scanned} texts" } + div { class: "results", + for (i , h) in r.results.iter().cloned().enumerate() { + div { key: "{i}", class: "result", + span { class: "p", {if h.prob > 0.0 { format!("{:.0}%", h.prob * 100.0) } else { String::new() }} } + span { class: "t", title: "{h.text}", onclick: { let t = h.text.clone(); move |_| ui.set_bar(&t) }, if h.note { "✎ " } "{h.text}" } + } + } + } + } + } + crate::views::pipes::KeptPipes { rev: pipes_rev, on_open: move |p: Value| { + let from = p["from"].clone(); + expr.set(if from.is_null() { json!({ "op": "and", "of": [] }) } else if from["op"] == "and" || from["op"] == "or" { from } else { json!({ "op": "and", "of": [from] }) }); + effects.set(p["effects"].as_array().cloned().unwrap_or_default()); + actions.set(p["actions"].as_array().cloned().unwrap_or_default()); + let n = p["name"].as_str().unwrap_or("").to_string(); + name.set(n.clone()); + editing.set(Some(n)); + } } + if !presets.is_empty() { + div { class: "card", + h3 { Icon { name: "save" } "kept filters" } + for p in presets { + Kept { key: "{p.name}", name: p.name.clone(), reads: p.reads.clone(), count: p.count, expr: p.expr.clone(), on_open: { let mut expr = expr; move |e: Value| { expr.set(e); } } } + } + } + } + } +} + +#[component] +fn Kept(name: String, reads: String, count: Option<u64>, expr: Value, on_open: EventHandler<Value>) -> Element { + let ui = ui(); + let api = api(); + let mut armed = use_signal(|| false); + let (api1, api2, n1, n2) = (api.clone(), api.clone(), name.clone(), name.clone()); + rsx! { + div { class: "row kept", + b { "{name}" } + span { class: "dim small grow", "{reads}" if let Some(c) = count { " · {c} found last time" } } + button { class: "plain", "data-tip": "into the builder", onclick: move |_| on_open.call(expr.clone()), Icon { name: "edit" } } + button { class: "plain", "data-tip": "write its texts as a list", + onclick: move |_| { + let (api, n) = (api1.clone(), n1.clone()); + spawn(async move { + match api.enlist_filter(&n).await { + Ok(v) => { ui.say(format!("the list “{}” holds its {} texts", v["name"].as_str().unwrap_or(""), v["members"])); ui.touched(); } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "list" } "as a list" } + button { class: if armed() { "armed" } else { "plain" }, "data-tip": "delete it (click twice)", + onclick: move |_| { + if !armed() { armed.set(true); return; } + let (api, n) = (api2.clone(), n2.clone()); + spawn(async move { match api.delete_filter(&n).await { Ok(()) => ui.touched(), Err(e) => ui.fail(e) } }); + }, + Icon { name: "delete" } } + } + } +} + +#[component] +fn Group(expr: Signal<Value>, path: Vec<usize>, depth: usize) -> Element { + let mut expr = expr; + let node = { + let mut root = expr(); + at(&mut root, &path).cloned().unwrap_or(Value::Null) + }; + let (g, not) = inner(&node); + let op = g["op"].as_str().unwrap_or("and").to_string(); + let items: Vec<Value> = g["of"].as_array().cloned().unwrap_or_default(); + let p1 = path.clone(); + let p2 = path.clone(); + let p3 = path.clone(); + rsx! { + div { class: if depth == 0 { "fgroup root" } else { "fgroup" }, + div { class: "row", + span { class: "mtabs", + button { class: if op == "and" { "mtab on" } else { "mtab" }, onclick: { let p = p1.clone(); move |_| set_op(expr, &p, "and") }, "all of" } + button { class: if op == "or" { "mtab on" } else { "mtab" }, onclick: { let p = p1.clone(); move |_| set_op(expr, &p, "or") }, "any of" } + } + if not { span { class: "bad small", "not" } } + span { class: "grow" } + select { + key: "{items.len()}", + "aria-label": "add a condition", + value: "", + onchange: move |e| { + let k = e.value(); + if k.is_empty() { return; } + let mut root = expr(); + if let Some(n) = at(&mut root, &p2) { + let g = if n["op"] == "not" { &mut n["of"] } else { n }; + if let Some(a) = g["of"].as_array_mut() { a.push(blank(&k)); } + } + expr.set(root); + }, + option { value: "", "add a condition…" } + for (k , label) in ADD { option { key: "{k}", value: "{k}", "{label}" } } + } + if depth > 0 { + Turn { expr, path: p3.clone() } + } + } + if items.is_empty() { div { class: "dim small", "no conditions yet: every text passes" } } + for (i , it) in items.iter().enumerate() { + { + let mut p = path.clone(); + p.push(i); + let (c, _) = inner(it); + let group = c["op"] == "and" || c["op"] == "or"; + rsx! { + if group { + Group { key: "{i}", expr, path: p, depth: depth + 1 } + } else { + Cond { key: "{i}", expr, path: p } + } + } + } + } + } + } +} + +/// the expression without empty groups (a group with nothing in it lets everything by) +fn prune(v: &Value) -> Value { + match v["op"].as_str() { + Some("and") | Some("or") => { + let of: Vec<Value> = v["of"] + .as_array() + .into_iter() + .flatten() + .map(prune) + .filter(|x| !x.is_null()) + .collect(); + if of.is_empty() { + Value::Null + } else { + json!({ "op": v["op"], "of": of }) + } + } + Some("not") => { + let i = prune(&v["of"]); + if i.is_null() { + Value::Null + } else { + json!({ "op": "not", "of": i }) + } + } + _ => v.clone(), + } +} + +fn set_op(mut expr: Signal<Value>, path: &[usize], op: &str) { + let mut root = expr(); + if let Some(n) = at(&mut root, path) { + let g = if n["op"] == "not" { &mut n["of"] } else { n }; + g["op"] = json!(op); + } + expr.set(root); +} + +/// "not" and remove, for a condition or a nested group +#[component] +fn Turn(expr: Signal<Value>, path: Vec<usize>) -> Element { + let mut expr = expr; + let p1 = path.clone(); + let p2 = path.clone(); + let not = { + let mut root = expr(); + at(&mut root, &path).is_some_and(|n| n["op"] == "not") + }; + rsx! { + button { class: if not { "chip on" } else { "chip" }, "data-tip": "turn it round: the texts it doesn't let through", + onclick: move |_| { + let mut root = expr(); + if let Some(n) = at(&mut root, &p1) { + *n = if n["op"] == "not" { n["of"].clone() } else { json!({ "op": "not", "of": n.clone() }) }; + } + expr.set(root); + }, + "not" } + button { class: "plain ibtn", "aria-label": "remove it", + onclick: move |_| { + let mut root = expr(); + if let Some((last, parent)) = p2.split_last() + && let Some(pn) = at(&mut root, parent) + { + let g = if pn["op"] == "not" { &mut pn["of"] } else { pn }; + if let Some(a) = g["of"].as_array_mut() && *last < a.len() { a.remove(*last); } + } + expr.set(root); + }, + Icon { name: "close" } } + } +} + +#[component] +fn Cond(expr: Signal<Value>, path: Vec<usize>) -> Element { + let cx = use_context::<Ctx>(); + let mut expr = expr; + let node = { + let mut root = expr(); + at(&mut root, &path).cloned().unwrap_or(Value::Null) + }; + let (c, _) = inner(&node); + let c = c.clone(); + let p = path.clone(); + // writes a field of the condition (inside its "not", if any) + let set = move |k: &'static str, v: Value| { + let mut root = expr(); + if let Some(n) = at(&mut root, &p) { + let c = if n["op"] == "not" { &mut n["of"] } else { n }; + if v.is_null() { + if let Some(o) = c.as_object_mut() { + o.remove(k); + } + } else { + c[k] = v; + } + } + expr.set(root); + }; + let s = |k: &str| c[k].as_str().unwrap_or("").to_string(); + let op = s("op"); + let classes: Vec<String> = cx + .classifiers + .iter() + .find(|(n, _)| *n == s("classifier")) + .map(|x| x.1.clone()) + .unwrap_or_default(); + rsx! { + div { class: "cond row", + match op.as_str() { + "class" => rsx! { + Icon { name: "classifier" } + select { "aria-label": "the classifier", onchange: { let mut set = set.clone(); move |e: FormEvent| { set("classifier", json!(e.value())); set("class", json!("")); } }, + option { value: "", "a classifier…" } + for (n , _) in cx.classifiers.iter() { option { key: "{n}", value: "{n}", selected: *n == s("classifier"), "{n}" } } + } + "says" + select { "aria-label": "the class", onchange: { let mut set = set.clone(); move |e: FormEvent| set("class", json!(e.value())) }, + option { value: "", "a class…" } + for k in classes { option { key: "{k}", value: "{k}", selected: k == s("class"), "{k}" } } + } + "at least" + input { r#type: "number", min: "0", max: "1", step: "0.05", style: "width: 70px;", placeholder: "its own", + initial_value: c["min"].as_f64().map(|x| x.to_string()).unwrap_or_default(), + oninput: { let mut set = set.clone(); move |e: FormEvent| set("min", e.value().parse::<f64>().map(|x| json!(x)).unwrap_or(Value::Null)) } } + label { class: "row small", input { r#type: "checkbox", checked: c["top"] == true, onchange: { let mut set = set.clone(); move |e: FormEvent| set("top", if e.checked() { json!(true) } else { Value::Null }) } } "its top class" } + }, + "words" => rsx! { + Icon { name: "search" } "words" + input { r#type: "text", initial_value: "{s(\"q\")}", oninput: { let mut set = set.clone(); move |e: FormEvent| set("q", json!(e.value())) } } + }, + "sum" => rsx! { + Icon { name: "hash" } + select { "aria-label": "which sum", onchange: { let mut set = set.clone(); move |e: FormEvent| set("bucket", json!(e.value())) }, + for b in ["ordinal", "reversed"] { option { key: "{b}", value: "{b}", selected: b == s("bucket"), "{b}" } } + } + "from" input { r#type: "number", style: "width: 80px;", initial_value: c["from"].as_i64().map(|x| x.to_string()).unwrap_or_default(), oninput: { let mut set = set.clone(); move |e: FormEvent| set("from", e.value().parse::<i64>().map(|x| json!(x)).unwrap_or(Value::Null)) } } + "to" input { r#type: "number", style: "width: 80px;", initial_value: c["to"].as_i64().map(|x| x.to_string()).unwrap_or_default(), oninput: { let mut set = set.clone(); move |e: FormEvent| set("to", e.value().parse::<i64>().map(|x| json!(x)).unwrap_or(Value::Null)) } } + }, + "list" => rsx! { + Icon { name: "list" } "in" + select { "aria-label": "the list", onchange: { let mut set = set.clone(); move |e: FormEvent| set("list", json!(e.value())) }, + option { value: "", "a list…" } + for (k , n) in cx.lists.iter() { option { key: "{k}", value: "{k}", selected: *k == s("list"), "{n}" } } + } + }, + "tags" => rsx! { + Icon { name: "tag" } "tagged" + input { r#type: "text", placeholder: "tags, comma separated", + initial_value: c["tags"].as_array().map(|a| a.iter().filter_map(|t| t.as_str()).collect::<Vec<_>>().join(", ")).unwrap_or_default(), + oninput: { let mut set = set.clone(); move |e: FormEvent| set("tags", json!(e.value().split(',').map(|t| t.trim().to_string()).filter(|t| !t.is_empty()).collect::<Vec<_>>())) } } + label { class: "row small", input { r#type: "checkbox", checked: c["any"] == true, onchange: { let mut set = set.clone(); move |e: FormEvent| set("any", if e.checked() { json!(true) } else { Value::Null }) } } "any of them" } + }, + "kind" => rsx! { + Icon { name: "filter" } + select { "aria-label": "texts or notes", onchange: { let mut set = set.clone(); move |e: FormEvent| set("kind", json!(e.value())) }, + option { value: "memories", selected: s("kind") == "memories", "texts only" } + option { value: "notes", selected: s("kind") == "notes", "notes only" } + } + }, + "preset" => rsx! { + Icon { name: "save" } "the kept filter" + select { "aria-label": "a kept filter", onchange: { let mut set = set.clone(); move |e: FormEvent| set("name", json!(e.value())) }, + option { value: "", "which…" } + for n in cx.presets.iter() { option { key: "{n}", value: "{n}", selected: *n == s("name"), "{n}" } } + } + }, + _ => rsx! { span { class: "dim", "{op}" } }, + } + span { class: "grow" } + Turn { expr, path: path.clone() } + } + } +} diff --git a/app/src/views/forge.rs b/app/src/views/forge.rs new file mode 100644 index 00000000..f4ce5654 --- /dev/null +++ b/app/src/views/forge.rs @@ -0,0 +1,168 @@ +//! The forge, as the Bevy app laid it out (forge_ui.rs, after Oblivion's spellmaking +//! altar): your saves on the left, the ingredients chosen in the middle (each with its +//! effect: add, take away, keep shared), and the result on the right: what it holds, a few +//! of its texts with their sums, filters to narrow it (words, ordinal and reversed ranges, +//! texts, notes, lists), a name, and the forge. Forging makes a new save; pouring puts the +//! result into the open one (`forge.preview`, `forge.make`, `forge.pour`). + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use crate::ui::*; + +const EFFECTS: [(&str, &str); 3] = [("add", "+"), ("take away", "−"), ("keep shared", "∩")]; + +#[component] +pub fn Forge(on_close: EventHandler<()>) -> Element { + let ui = ui(); + let api = api(); + let mut parts: Signal<Vec<(String, String)>> = use_signal(Vec::new); + let mut words = use_signal(String::new); + let mut o_from = use_signal(String::new); + let mut o_to = use_signal(String::new); + let mut r_from = use_signal(String::new); + let mut r_to = use_signal(String::new); + let mut keep = use_signal(|| [true, true, true]); + let mut name = use_signal(String::new); + let api_s = api.clone(); + let saves = use_resource(move || { + let api = api_s.clone(); + let _ = (ui.changed)(); + async move { api.saves().await.unwrap_or_default() } + }); + let args = move || { + let n = |s: Signal<String>| s.peek().trim().parse::<i64>().ok(); + let k = *keep.peek(); + json!({ + "ingredients": parts.peek().iter().map(|(s, e)| json!({ "save": s, "effect": e })).collect::<Vec<_>>(), + "filter": { "words": words.peek().clone(), "ordinal_from": n(o_from), "ordinal_to": n(o_to), + "reversed_from": n(r_from), "reversed_to": n(r_to), "memories": k[0], "notes": k[1], "lists": k[2] }, + }) + }; + let api_p = api.clone(); + let preview = use_resource(move || { + let api = api_p.clone(); + let _ = (parts(), words(), o_from(), o_to(), r_from(), r_to(), keep()); + let a = args(); + async move { + if a["ingredients"].as_array().is_none_or(|x| x.is_empty()) { + return None; + } + Some(api.call("forge.preview", a).await) + } + }); + let api_m = api.clone(); + let make = move |_| { + let api = api_m.clone(); + let mut a = args(); + let n = name().trim().to_string(); + a["name"] = json!(n); + spawn(async move { + match api.call("forge.make", a).await { + Ok(v) => { + ui.say(format!( + "forged {}: {} texts, {} notes, {} lists", + v["save"].as_str().unwrap_or(""), + v["memories"], + v["notes"], + v["lists"] + )); + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + }; + let api_o = api.clone(); + let pour = move |_| { + let api = api_o.clone(); + let a = args(); + spawn(async move { + match api.call("forge.pour", a).await { + Ok(v) => { + ui.say(format!( + "poured in {} texts, {} notes, {} lists", + v["memories"], v["notes"], v["lists"] + )); + ui.touched(); + ui.refresh(api); + } + Err(e) => ui.fail(e), + } + }); + }; + let all = saves.read().clone().unwrap_or_default(); + let pv: Option<Result<Value, String>> = preview.read().clone().flatten(); + rsx! { + div { class: "overlay", onclick: move |_| on_close.call(()), + div { class: "dialog forge", role: "dialog", "aria-label": "the forge", onclick: move |e| e.stop_propagation(), + div { class: "head", + h2 { Icon { name: "forge" } " the forge" } + span { class: "dim small", "saves in, a save out: + adds one, − takes it away, ∩ keeps only what they share" } + span { class: "grow" } + button { class: "plain ibtn", "aria-label": "close", onclick: move |_| on_close.call(()), Icon { name: "close" } } + } + div { class: "forge-cols", + div { class: "fcol", + h3 { "your saves" } + for s in all { + div { key: "{s.name}", class: "row fsave", + span { class: "grow", "{s.name}" if s.open { span { class: "dim small", " (open)" } } } + for (e , sym) in EFFECTS { + button { key: "{e}", class: "plain", "data-tip": "{e}", + onclick: { let n = s.name.clone(); move |_| parts.write().push((n.clone(), e.to_string())) }, + "{sym}" } + } + } + } + } + div { class: "fcol", + h3 { "ingredients" } + if parts().is_empty() { div { class: "dim small", "pick saves on the left with + − ∩" } } + for (i , (s , e)) in parts().into_iter().enumerate() { + div { key: "{i}", class: "row", + b { {EFFECTS.iter().find(|x| x.0 == e).map(|x| x.1).unwrap_or("+")} } + span { class: "grow", "{s}" span { class: "dim small", " · {e}" } } + button { class: "plain ibtn", "aria-label": "take it out", onclick: move |_| { parts.write().remove(i); }, Icon { name: "close" } } + } + } + } + div { class: "fcol", + h3 { "the result" } + match pv { + Some(Ok(v)) => rsx! { + div { "{v[\"memories\"]} texts · {v[\"notes\"]} notes · {v[\"lists\"]} list links" } + div { class: "fsample", + for (i , t) in v["sample"].as_array().cloned().unwrap_or_default().into_iter().enumerate() { + div { key: "{i}", class: "small", "{t[\"text\"].as_str().unwrap_or(\"\")} " span { class: "dim", "{t[\"ordinal\"]}·{t[\"reversed\"]}" } } + } + for (i , t) in v["titles"].as_array().cloned().unwrap_or_default().into_iter().enumerate() { + div { key: "n{i}", class: "small", "✎ {t.as_str().unwrap_or(\"\")}" } + } + } + }, + Some(Err(e)) => rsx! { div { class: "bad small", "{e}" } }, + None => rsx! { div { class: "dim small", "nothing yet" } }, + } + div { class: "form", + label { "words" } input { r#type: "text", placeholder: "word -notword", oninput: move |e| words.set(e.value()) } + label { "ordinal" } div { class: "row", input { r#type: "number", style: "width: 80px;", oninput: move |e| o_from.set(e.value()) } "to" input { r#type: "number", style: "width: 80px;", oninput: move |e| o_to.set(e.value()) } } + label { "reversed" } div { class: "row", input { r#type: "number", style: "width: 80px;", oninput: move |e| r_from.set(e.value()) } "to" input { r#type: "number", style: "width: 80px;", oninput: move |e| r_to.set(e.value()) } } + label { "keep" } + div { class: "row", + for (i , what) in ["texts", "notes", "lists"].into_iter().enumerate() { + label { key: "{what}", class: "row small", input { r#type: "checkbox", checked: keep()[i], onchange: move |e| keep.write()[i] = e.checked() } "{what}" } + } + } + label { "name" } input { r#type: "text", placeholder: "the new save's name", oninput: move |e| name.set(e.value()) } + } + div { class: "row", + button { class: "primary", disabled: parts().is_empty() || name().trim().is_empty(), onclick: make, Icon { name: "forge" } "forge" } + button { disabled: parts().is_empty(), "data-tip": "put the result into the open save", onclick: pour, Icon { name: "merge" } "pour into the open save" } + } + } + } + } + } + } +} diff --git a/app/src/views/hubui.rs b/app/src/views/hubui.rs new file mode 100644 index 00000000..a7c38983 --- /dev/null +++ b/app/src/views/hubui.rs @@ -0,0 +1,395 @@ +//! The settings' hub section (the Bevy app's hub_ui.rs and the JS client's hub pages): +//! connect to an anend hub (its address and an app token from your profile there), browse +//! the saves and classifiers people share, take one in, and share the open save or a +//! classifier. On the desktop a taken save lands in the saves folder and opens; on the web +//! the app's own hub takes it into your workspace (`POST /app/hub/{id}`). + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use crate::hubnet; +use crate::shell::set_pref; +use crate::ui::*; +use crate::views::Fold; + +#[derive(Clone, Copy, PartialEq)] +enum What { + Saves, + Classifiers, +} + +/// the hub's address: the setting, else (on the web) the page's own +fn address(ui: Ui) -> String { + let a = ui.prefs.peek().hub_url.trim().to_string(); + if !a.is_empty() { + return a; + } + #[cfg(target_arch = "wasm32")] + { + web_sys::window() + .and_then(|w| w.location().origin().ok()) + .unwrap_or_default() + } + #[cfg(not(target_arch = "wasm32"))] + { + String::new() + } +} + +#[component] +pub fn Hub() -> Element { + let ui = ui(); + let api = api(); + let p = ui.prefs.read().clone(); + let mut info: Signal<Option<String>> = use_signal(|| None); + let mut what = use_signal(|| What::Saves); + let mut q = use_signal(String::new); + let mut sort = use_signal(|| "new"); + let mut page = use_signal(|| 0u32); + let mut found: Signal<Option<Value>> = use_signal(|| None); + let mut share_name = use_signal(String::new); + let mut share_desc = use_signal(String::new); + let mut share_tags = use_signal(String::new); + let mut share_cls = use_signal(String::new); + let connect = move |_| { + let hub = address(ui); + let tok = ui.prefs.peek().hub_token.clone(); + spawn(async move { + let url = match hubnet::join(&hub, "/api/hub") { + Ok(u) => u, + Err(e) => return ui.fail(e), + }; + match hubnet::get_json(url, None).await { + Ok(v) => { + let mut line = format!( + "{} · {} saves · {} classifiers · {} people", + v["name"].as_str().unwrap_or("a hub"), + v["saves"], + v["classifiers"], + v["users"] + ); + if !tok.trim().is_empty() + && let Ok(u) = hubnet::join(&hub, "/api/me") + { + match hubnet::get_json(u, Some(tok)).await { + Ok(me) => line.push_str(&format!(" · you're {}", me["username"].as_str().unwrap_or("?"))), + Err(e) => line.push_str(&format!(" · the token: {e}")), + } + } + info.set(Some(line)); + } + Err(e) => ui.fail(e), + } + }); + }; + let browse = move || { + let hub = address(ui); + let path = match what() { + What::Saves => "/api/saves", + What::Classifiers => "/api/classifiers", + }; + let url = hubnet::join( + &hub, + &format!( + "{path}?q={}&sort={}&page={}", + hubnet::encode(q().trim()), + sort(), + page() + ), + ); + spawn(async move { + match url { + Ok(u) => match hubnet::get_json(u, None).await { + Ok(v) => found.set(Some(v)), + Err(e) => ui.fail(e), + }, + Err(e) => ui.fail(e), + } + }); + }; + let b1 = browse; + let api_t = api.clone(); + let take = move |item: Value| { + let api = api_t.clone(); + let hub = address(ui); + let kind = what(); + spawn(async move { + let id = item["id"].as_str().unwrap_or("").to_string(); + if !hubnet::id_ok(&id) { + return ui.fail("the hub sent an odd id"); + } + let name = item["name"].as_str().unwrap_or("hub").to_string(); + let r: Result<String, String> = async { + match kind { + What::Saves => take_save(&api, &hub, &id, &name, &item).await, + What::Classifiers => { + #[cfg(target_arch = "wasm32")] + { + let u = hubnet::join(&hub, &format!("/app/classifiers/{id}/take"))?; + hubnet::post(u, None, Some(("application/json".into(), b"{}".to_vec()))).await?; + Ok(format!("took in the classifier {name}")) + } + #[cfg(not(target_arch = "wasm32"))] + { + let u = hubnet::join(&hub, &format!("/classifiers/{id}/download"))?; + let bytes = hubnet::get_bytes(u, 64 << 20).await?; + api.call( + "classify.import", + json!({ "data": crate::fonts::base64(&bytes), "name": name }), + ) + .await?; + Ok(format!("took in the classifier {name}")) + } + } + } + } + .await; + match r { + Ok(m) => { + ui.say(m); + ui.touched(); + ui.refresh(api); + } + Err(e) => ui.fail(e), + } + }); + }; + let api_s = api.clone(); + let share_save = move |_| { + let api = api_s.clone(); + let hub = address(ui); + let tok = ui.prefs.peek().hub_token.clone(); + let (n, d, t) = (share_name(), share_desc(), share_tags()); + spawn(async move { + let r: Result<Value, String> = async { + let name = if n.trim().is_empty() { + ui.hello.peek().save.clone() + } else { + n.trim().to_string() + }; + let bytes = open_save_bytes(&api, &ui.hello.peek().save).await?; + let (kind, body) = hubnet::multipart( + &[("name", &name), ("description", d.trim()), ("tags", t.trim())], + ("file", &format!("{name}.redb"), &bytes), + ); + hubnet::post(hubnet::join(&hub, "/api/saves")?, Some(tok), Some((kind, body))).await + } + .await; + match r { + Ok(v) => ui.say(format!( + "shared: {} ({})", + v["url"].as_str().unwrap_or(""), + v["status"].as_str().unwrap_or("") + )), + Err(e) => ui.fail(e), + } + }); + }; + let api_c = api.clone(); + let share_classifier = move |_| { + let api = api_c.clone(); + let hub = address(ui); + let tok = ui.prefs.peek().hub_token.clone(); + let n = share_cls(); + spawn(async move { + let r: Result<Value, String> = async { + if n.trim().is_empty() { + return Err("pick a classifier to share".to_string()); + } + #[cfg(target_arch = "wasm32")] + { + let _ = (&api, &tok); + hubnet::post( + hubnet::join(&hub, "/app/classifiers/share")?, + None, + Some(("application/json".into(), json!({ "name": n }).to_string().into_bytes())), + ) + .await + } + #[cfg(not(target_arch = "wasm32"))] + { + let v = api.call("classify.export", json!({ "name": n })).await?; + let bytes = + crate::fonts::unbase64(v["data"].as_str().unwrap_or("")).ok_or("the export didn't read")?; + let (kind, body) = hubnet::multipart( + &[("name", &n)], + ("file", v["file"].as_str().unwrap_or("c.anendcls"), &bytes), + ); + hubnet::post(hubnet::join(&hub, "/api/classifiers")?, Some(tok), Some((kind, body))).await + } + } + .await; + match r { + Ok(v) => ui.say(format!("shared {n}: {}", v["status"].as_str().unwrap_or("done"))), + Err(e) => ui.fail(e), + } + }); + }; + let api_l = api.clone(); + let mine = use_resource(move || { + let api = api_l.clone(); + async move { + api.call("classify.list", json!({})) + .await + .ok() + .and_then(|v| v.as_array().cloned()) + .unwrap_or_default() + .iter() + .filter_map(|c| c["name"].as_str().map(str::to_string)) + .collect::<Vec<_>>() + } + }); + let items: Vec<Value> = found() + .map(|v| { + v[if what() == What::Saves { "saves" } else { "classifiers" }] + .as_array() + .cloned() + .unwrap_or_default() + }) + .unwrap_or_default(); + let more = found().is_some_and(|v| v["more"] == true); + let take2 = take.clone(); + rsx! { + Fold { name: "hub", title: "the hub", + label { r#for: "hub", "its address" } + div { class: "row", + input { id: "hub", r#type: "text", style: "flex: 1;", placeholder: if cfg!(target_arch = "wasm32") { "this page's own hub" } else { "http://localhost:8080" }, initial_value: "{p.hub_url}", + oninput: move |e| set_pref(ui, |p| p.hub_url = e.value()) } + button { onclick: connect, Icon { name: "hub" } "connect" } + } + label { r#for: "hubtok", "an app token" } + div { class: "row", + input { id: "hubtok", r#type: "password", style: "flex: 1;", placeholder: "from your profile on the hub (sharing needs one)", initial_value: "{p.hub_token}", + oninput: move |e| set_pref(ui, |p| p.hub_token = e.value()) } + } + if let Some(i) = info() { div { class: "wide dim small", "{i}" } } + div { class: "wide row", + span { class: "mtabs", + button { class: if what() == What::Saves { "mtab on" } else { "mtab" }, onclick: move |_| { what.set(What::Saves); found.set(None); }, "saves" } + button { class: if what() == What::Classifiers { "mtab on" } else { "mtab" }, onclick: move |_| { what.set(What::Classifiers); found.set(None); }, "classifiers" } + } + input { r#type: "text", style: "flex: 1;", placeholder: "names, tags, authors", oninput: move |e| q.set(e.value()), + onkeydown: move |e: KeyboardEvent| if e.key() == Key::Enter { page.set(0); b1() } } + select { "aria-label": "order", onchange: move |e| sort.set(match e.value().as_str() { "stars" => "stars", "downloads" => "downloads", "featured" => "featured", _ => "new" }), + for s in ["new", "stars", "downloads", "featured"] { option { key: "{s}", value: "{s}", "{s}" } } + } + button { onclick: move |_| { page.set(0); browse() }, Icon { name: "search" } "browse" } + } + if found().is_some() { + div { class: "wide hub-list", + if items.is_empty() { div { class: "dim", "nothing shared there yet (or nothing matches)" } } + for (i , it) in items.into_iter().enumerate() { + div { key: "{i}", class: "row hub-item", + div { class: "grow", + b { "{it[\"name\"].as_str().unwrap_or(\"\")}" } + span { class: "dim small", " by {it[\"author\"].as_str().unwrap_or(\"?\")}" } + div { class: "dim small", + {it["description"].as_str().unwrap_or("").chars().take(160).collect::<String>()} + if what() == What::Saves { " · {it[\"memories\"]} texts · {it[\"notes\"]} notes" } else { " · {it[\"classes\"].as_array().map(|a| a.iter().filter_map(|c| c.as_str()).collect::<Vec<_>>().join(\", \")).unwrap_or_default()}" } + " · ★ {it[\"stars\"]} · ↓ {it[\"downloads\"]}" + } + } + button { onclick: { let t = take2.clone(); let it = it.clone(); move |_| t(it.clone()) }, Icon { name: "download" } "take it" } + } + } + div { class: "row", + button { disabled: page() == 0, onclick: move |_| { page -= 1; browse() }, Icon { name: "chevron-left" } } + span { class: "dim small", "page {page() + 1}" } + button { disabled: !more, onclick: move |_| { page += 1; browse() }, Icon { name: "chevron-right" } } + } + } + } + label { "share this save" } + div { class: "row", + if cfg!(target_arch = "wasm32") { + span { class: "dim small", "from the desktop app (the web app's saves stay on this hub; export a bundle to move one)" } + } else { + input { r#type: "text", placeholder: "its name there", oninput: move |e| share_name.set(e.value()) } + input { r#type: "text", placeholder: "a line about it", oninput: move |e| share_desc.set(e.value()) } + input { r#type: "text", placeholder: "tags, comma separated", oninput: move |e| share_tags.set(e.value()) } + button { onclick: share_save, Icon { name: "upload" } "share" } + } + } + label { "share a classifier" } + div { class: "row", + select { "aria-label": "the classifier to share", onchange: move |e| share_cls.set(e.value()), + option { value: "", "a classifier…" } + for n in mine.read().clone().unwrap_or_default() { option { key: "{n}", value: "{n}", "{n}" } } + } + button { onclick: share_classifier, Icon { name: "upload" } "share" } + } + } + } +} + +/// a hub save into this app: the desktop downloads it into the saves folder and opens it; +/// the web asks its own hub to take it into the workspace +async fn take_save(api: &Api, hub: &str, id: &str, name: &str, item: &Value) -> Result<String, String> { + #[cfg(target_arch = "wasm32")] + { + let _ = (api, item); + let u = hubnet::join(hub, &format!("/app/hub/{id}"))?; + hubnet::post(u, None, None).await?; + Ok(format!("took {name} into your saves")) + } + #[cfg(not(target_arch = "wasm32"))] + { + let link = item["download_url"] + .as_str() + .map(str::to_string) + .unwrap_or(format!("/saves/{id}/download")); + let bytes = hubnet::get_bytes(hubnet::join(hub, &link)?, hubnet::MAX_DOWNLOAD).await?; + if !bytes.starts_with(b"redb\x1A\x0A\xA9\x0D\x0A") { + return Err("the hub sent something that isn't a save".into()); + } + let clean: String = name + .chars() + .map(|c| { + if c.is_alphanumeric() || " -_.".contains(c) { + c + } else { + '-' + } + }) + .collect::<String>() + .trim_matches('.') + .trim() + .chars() + .take(80) + .collect(); + let clean = if clean.is_empty() { + "hub save".to_string() + } else { + clean + }; + let dir = crate::prefs::data_dir().join("saves"); + let mut n = clean.clone(); + let mut i = 2; + while dir.join(format!("{n}.redb")).exists() { + n = format!("{clean} {i}"); + i += 1; + } + std::fs::create_dir_all(&dir).map_err(|e| e.to_string())?; + std::fs::write(dir.join(format!("{n}.redb")), &bytes).map_err(|e| format!("couldn't keep it: {e}"))?; + api.open_save(&n).await.map_err(|e| { + let _ = std::fs::remove_file(dir.join(format!("{n}.redb"))); + format!("the app can't open it ({e}); deleted it") + })?; + Ok(format!("took {name} and opened it")) + } +} + +/// the open save's file, to share +async fn open_save_bytes(api: &Api, name: &str) -> Result<Vec<u8>, String> { + #[cfg(not(target_arch = "wasm32"))] + { + let _ = api; + let path = crate::prefs::data_dir().join("saves").join(format!("{name}.redb")); + std::fs::read(&path).map_err(|e| format!("couldn't read {}: {e}", path.display())) + } + #[cfg(target_arch = "wasm32")] + { + let _ = (api, name); + Err("sharing a save goes from the desktop app".into()) + } +} diff --git a/app/src/views/judge.rs b/app/src/views/judge.rs new file mode 100644 index 00000000..59bf3ae3 --- /dev/null +++ b/app/src/views/judge.rs @@ -0,0 +1,149 @@ +//! What classifiers say of one entry (the Bevy app's index panel, index_panel.rs): pick +//! which classifiers the entry is indexed on (kept in the save, `classify.set_index`), and +//! see how it measures on each: every class's probability as a bar in that classifier's +//! colours, the class it's put in, and a yes or a no that teaches it. Used by the notes +//! editor (the classifier button, Ctrl+I) and the reader's opened item. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use crate::ui::*; + +/// `key` is an entry's key (`0,12` or `note:…`; a bare note key is taken as a note's) +#[component] +pub fn Judge(entry: String, #[props(default)] title: String) -> Element { + let ui = ui(); + let api = api(); + let key = if entry.contains(',') || entry.starts_with("note:") { + entry + } else { + format!("note:{entry}") + }; + let mut again = use_signal(|| 0u64); + let k0 = key.clone(); + let api0 = api.clone(); + let info = use_resource(move || { + let (api, k) = (api0.clone(), k0.clone()); + let _ = (again(), (ui.changed)()); + async move { api.call("classify.indexed", json!({ "key": k })).await } + }); + let v = match &*info.read() { + Some(Ok(v)) => v.clone(), + Some(Err(e)) => return rsx! { div { class: "judge dim small", "{e}" } }, + None => return rsx! { div { class: "judge dim small", "reading what the classifiers say…" } }, + }; + let all: Vec<(String, bool, bool)> = v["classifiers"] + .as_array() + .into_iter() + .flatten() + .map(|c| { + ( + c["name"].as_str().unwrap_or("").to_string(), + c["trained"] == true, + c["chosen"] == true, + ) + }) + .collect(); + let chosen: Vec<String> = all.iter().filter(|c| c.2).map(|c| c.0.clone()).collect(); + let verdicts: Vec<Value> = v["verdicts"].as_array().cloned().unwrap_or_default(); + rsx! { + div { class: "judge", + div { class: "row judge-pick", + Icon { name: "classifier" } + if title.is_empty() { span { class: "dim small", "classifiers to measure it on:" } } else { span { class: "dim small", "{title}" } } + if all.is_empty() { + span { class: "dim small", "none yet: make one in the models view (Ctrl+8)" } + } + for (name , trained , on) in all.clone() { + button { + key: "{name}", + class: if on { "chip on" } else { "chip" }, + "aria-pressed": "{on}", + "data-tip": if trained { "measure it on {name}" } else { "{name} isn't trained yet" }, + onclick: { + let (api, key, chosen, name) = (api.clone(), key.clone(), chosen.clone(), name.clone()); + move |_| { + let mut names = chosen.clone(); + if on { names.retain(|n| *n != name); } else { names.push(name.clone()); } + let (api, key) = (api.clone(), key.clone()); + spawn(async move { + match api.call("classify.set_index", json!({ "key": key, "names": names })).await { + Ok(_) => again += 1, + Err(e) => ui.fail(e), + } + }); + } + }, + "{name}" + } + } + } + for v in verdicts { + Verdict { key: "{v[\"name\"]}", entry: key.clone(), v, on_change: move |_| again += 1 } + } + } + } +} + +#[component] +fn Verdict(entry: String, v: Value, on_change: EventHandler<()>) -> Element { + let ui = ui(); + let api = api(); + let name = v["name"].as_str().unwrap_or("").to_string(); + let classes = crate::views::classifiers::strs(&v["classes"]); + if v["trained"] != true { + return rsx! { + div { class: "verdict dim small", b { "{name}" } " isn't trained yet: train it in the models view" } + }; + } + let probs = crate::views::classifiers::nums(&v["probs"]); + let palette = crate::views::classifiers::strs(&v["palette"]); + let top = v["top"].as_u64().unwrap_or(0) as usize; + let members = crate::views::classifiers::strs(&v["members"]); + let confidence = v["confidence"].as_f64().unwrap_or(0.0); + let valid = v["valid"] != false; + let top_class = classes.get(top).cloned().unwrap_or_default(); + let teach = move |yes: bool| { + let (api, name, entry, class) = (api.clone(), name.clone(), entry.clone(), top_class.clone()); + move |_| { + let (api, name, entry, class) = (api.clone(), name.clone(), entry.clone(), class.clone()); + spawn(async move { + match api.model_feedback(&name, Some(&entry), "", &class, yes).await { + Ok(_) => { + ui.did(Did::Feedback { model: name.clone() }); + ui.say(format!( + "{name} learns that {} “{class}”; Ctrl+Z takes it back", + if yes { "it is" } else { "it isn't" } + )); + on_change.call(()); + } + Err(e) => ui.fail(e), + } + }); + } + }; + let (yes, no) = (teach(true), teach(false)); + rsx! { + div { class: "verdict", + div { class: "row", + b { "{v[\"name\"].as_str().unwrap_or(\"\")}" } + span { class: "chip cls-class", style: "background: {palette.get(top).cloned().unwrap_or_default()};", "{classes.get(top).cloned().unwrap_or_default()}" } + span { class: "dim small", {format!("{:.0}% sure", confidence * 100.0)} } + if members.len() > 1 { span { class: "dim small", "also {members.iter().filter(|m| **m != classes[top.min(classes.len().saturating_sub(1))]).cloned().collect::<Vec<_>>().join(\", \")}" } } + if !valid { span { class: "bad small", "its validators disagree" } } + span { class: "grow" } + button { class: "plain", "data-tip": "yes, it is that", "aria-label": "yes", onclick: yes, Icon { name: "check" } } + button { class: "plain", "data-tip": "no, it isn't that", "aria-label": "no", onclick: no, Icon { name: "close" } } + } + div { class: "probs", + for (i , c) in classes.iter().enumerate() { + div { key: "{c}", class: if i == top { "prob best" } else { "prob" }, + span { class: "c", "{c}" } + span { class: "probbar wide", span { style: "width: {(probs.get(i).copied().unwrap_or(0.0) * 100.0).clamp(0.0, 100.0):.1}%; background: {palette.get(i).cloned().unwrap_or_default()};" } } + span { class: "p", {format!("{:.1}%", probs.get(i).copied().unwrap_or(0.0) * 100.0)} } + } + } + } + } + } +} diff --git a/app/src/views/lists.rs b/app/src/views/lists.rs new file mode 100644 index 00000000..76da898d --- /dev/null +++ b/app/src/views/lists.rs @@ -0,0 +1,519 @@ +//! Lists, as the Bevy app had them (lists_ui.rs): every list as a card with its figures, +//! the list read as one text, its letters as a vector and its members as chips with their +//! sums (× takes one out); how alike every two lists are (the cosine of their letter +//! vectors); a chosen list the bar fills (Enter adds what's typed, remembering it when +//! new), or, with none chosen, Enter chooses a list by its name or starts one. A list's +//! own page (its name clicked) renames it, edits its members a page at a time, and holds +//! its pictures. Unlisting takes two clicks, and Ctrl+Z brings a list back. + +use dioxus::prelude::*; + +use crate::backend::{Hit, ListInfo}; +use crate::gem; +use crate::ui::*; +use crate::views::use_keys; + +const PAGE: usize = 40; + +#[component] +pub fn Lists() -> Element { + let ui = ui(); + let api = api(); + let mut open: Signal<Option<String>> = use_signal(|| None); + // the list the bar fills (the Bevy app's "chosen"): Enter adds what's typed to it + let mut chosen: Signal<Option<Hit>> = use_signal(|| None); + // lists picked with Shift+click on their names + let mut picked: Signal<Vec<String>> = use_signal(Vec::new); + let api_r = api.clone(); + let lists = use_resource(move || { + let api = api_r.clone(); + let _ = (ui.changed)(); + async move { api.lists().await } + }); + { + let api = api.clone(); + use_keys(View::Lists, move |k: KeyPress| { + if k.bar && k.key == "Enter" { + let typed = k.text.trim().to_string(); + if typed.is_empty() { + return true; + } + let api = api.clone(); + let list = chosen.peek().clone(); + let exact = lists + .peek() + .as_ref() + .and_then(|r| r.as_ref().ok()) + .and_then(|l| l.lists.iter().find(|x| x.name.eq_ignore_ascii_case(&typed)).cloned()); + dioxus::dioxus_core::spawn_forever(async move { + match (list, exact) { + // a list is chosen: the text joins it (remembered when it's new) + (Some(l), _) => match api.saturate(&typed).await { + Ok((key, _)) if key == l.key => ui.fail("a list can't hold itself"), + Ok((key, _)) => match api.enlist(&l.key, &key).await { + Ok(()) => { + ui.did(Did::Enlisted { + list: l.key.clone(), + member: key, + }); + ui.say(format!("added “{typed}” to {}", l.text)); + ui.set_bar(""); + ui.touched(); + } + Err(e) => ui.fail(e), + }, + Err(e) => ui.fail(e), + }, + // a list by that name: choose it + (None, Some(l)) => { + chosen.set(Some(Hit { + key: l.list.clone(), + text: l.name.clone(), + note: false, + })); + ui.set_bar(""); + ui.say(format!("Enter adds to “{}” now", l.name)); + } + // else a new list headed by the text, chosen + (None, None) => match api.saturate(&typed).await { + Ok((key, _)) => { + let h = Hit { + key, + text: typed.clone(), + note: false, + }; + chosen.set(Some(h.clone())); + let mut picks = ui.picks; + picks.write().list = Some(h); + ui.set_bar(""); + ui.say(format!("a new list “{typed}”: type its members, Enter after each")); + ui.touched(); + } + Err(e) => ui.fail(e), + }, + } + }); + return true; + } + if !k.bar && k.key == "Escape" { + if open.peek().is_some() { + open.set(None); + } else { + chosen.set(None); + } + return true; + } + false + }); + } + use_effect(move || { + let note = match chosen() { + Some(l) => format!("Enter adds to “{}”", l.text), + None => "Enter chooses a list by its name, or starts one".to_string(), + }; + ui.side_note(View::Lists, note); + }); + let q = ui.bar.read().trim().to_lowercase(); + let (all, dot): (Vec<ListInfo>, Vec<Vec<f64>>) = match &*lists.read() { + Some(Ok(l)) => (l.lists.clone(), l.dot.clone()), + Some(Err(e)) => return rsx! { div { class: "page", div { class: "card bad", "{e}" } } }, + None => return rsx! { div { class: "page", div { class: "card dim", "…" } } }, + }; + let names: Vec<String> = all.iter().map(|l| l.name.clone()).collect(); + if let Some(key) = open() + && let Some(l) = all.iter().find(|l| l.list == key).cloned() + { + return rsx! { ListPage { list: l, back: move |_| open.set(None) } }; + } + let finding = chosen().is_none() && !q.is_empty(); + let shown: Vec<ListInfo> = all + .iter() + .filter(|l| !finding || l.name.to_lowercase().contains(&q)) + .cloned() + .collect(); + let cur = chosen(); + rsx! { + div { class: "page lists-page", + div { class: "card lists-head", + div { class: "row", + h2 { "lists" } + span { class: "dim small", "{all.len()} lists" if finding { " · {shown.len()} named like “{q}”" } } + } + match &cur { + Some(l) => rsx! { + div { class: "row", + span { "Typing in the bar adds to " b { "“{l.text}”" } ". Choose another list below, or let go of it to start a new one." } + button { onclick: move |_| chosen.set(None), Icon { name: "close" } "let go of it" } + } + }, + None => rsx! { + div { class: "dim", "Type in the bar to start a new list headed by that text (or a list's name to choose it); choose a list below to add to it. In the memory view, Ctrl+Shift+click a text to head a list and Ctrl+click another, then Enlist." } + }, + } + } + if all.len() > 1 { + Alike { all: all.clone(), dot: dot.clone() } + } + if shown.is_empty() && all.is_empty() { + div { class: "card empty", "No lists yet." } + } + ManyLists { picked, all: all.clone() } + for l in shown { + ListCard { + key: "{l.list}", + is_chosen: cur.as_ref().is_some_and(|c| c.key == l.list), + is_picked: picked().contains(&l.list), + on_pick: move |k: String| { let mut p = picked.write(); if let Some(i) = p.iter().position(|x| *x == k) { p.remove(i); } else { p.push(k); } }, + list: l.clone(), + on_choose: move |h: Hit| chosen.set(Some(h)), + on_open: move |k: String| open.set(Some(k)), + } + } + crate::views::pictures::Pictures { list: None, names: names.clone() } + } + } +} + +/// how alike the lists are: the cosine of each two lists' letter vectors (1 is the same +/// letters in the same proportions), as the Bevy app's grid +#[component] +fn Alike(all: Vec<ListInfo>, dot: Vec<Vec<f64>>) -> Element { + if dot.len() != all.len() { + return rsx! {}; + } + let n = all.len(); + rsx! { + div { class: "card", + h3 { "how alike" } + div { class: "dim small", "the cosine of each two lists' letter vectors: 1 is the same letters in the same proportions" } + div { class: "alike", style: "grid-template-columns: 130px repeat({n}, minmax(38px, 52px));", + span {} + for l in all.iter() { + span { key: "h{l.list}", class: "alike-col", title: "{l.name}", {l.name.chars().take(7).collect::<String>()} } + } + for (i , l) in all.iter().enumerate() { + span { key: "r{l.list}", class: "alike-row", title: "{l.name}", {l.name.chars().take(18).collect::<String>()} } + for (j , v) in dot[i].iter().enumerate() { + span { + key: "{i}-{j}", + class: "alike-cell", + title: "{all[i].name} · {all[j].name}: {v:.3}", + style: "background: hsl({anend_core::spread::seed_hue((v * 360.0) as i64)} 60% 55% / {0.15 + 0.75 * v.clamp(0.0, 1.0):.2});", + {format!("{v:.2}")} + } + } + } + } + } + } +} + +/// a list as the Bevy app showed it: its name and key, choose and unlist, its figures, the +/// list read as one text, its letters as bars, and its members as chips with their sums +#[component] +fn ListCard( + list: ListInfo, + is_chosen: bool, + is_picked: bool, + on_pick: EventHandler<String>, + on_choose: EventHandler<Hit>, + on_open: EventHandler<String>, +) -> Element { + let ui = ui(); + let api = api(); + let mut armed = use_signal(|| false); + let joined: String = list + .members + .iter() + .map(|m| m.text.as_str()) + .collect::<Vec<_>>() + .join(" "); + let m = gem::Measure::of(&joined); + let max = list.vector.iter().cloned().fold(0.0f64, f64::max).max(1e-9); + let (k1, k2, n1) = (list.list.clone(), list.list.clone(), list.name.clone()); + let api_u = api.clone(); + let members_keys: Vec<String> = list.members.iter().map(|h| h.key.clone()).collect(); + rsx! { + div { class: match (is_chosen, is_picked) { (true, true) => "card listcard chosen picked", (true, false) => "card listcard chosen", (false, true) => "card listcard picked", _ => "card listcard" }, + div { class: "row", + button { class: "plain lname", "data-tip": "its page: rename, edit members, pictures · Shift+click picks lists, several at once", + onclick: move |e: MouseEvent| if e.modifiers().shift() { on_pick.call(k1.clone()) } else { on_open.call(k1.clone()) }, h3 { "{list.name}" } } + span { class: "dim small mono", "{list.list}" } + span { class: "grow" } + button { class: if is_chosen { "primary" } else { "" }, "data-tip": "the bar's Enter adds to it", + onclick: move |_| on_choose.call(Hit { key: k2.clone(), text: n1.clone(), note: false }), + if is_chosen { "chosen" } else { "choose" } } + button { + class: if armed() { "armed" } else { "plain" }, + "data-tip": "unlist: the list goes, its members stay (click twice)", + onclick: move |_| { + if !armed() { armed.set(true); return; } + let (api, key, members) = (api_u.clone(), list.list.clone(), members_keys.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.unlist(&key).await { + Ok(n) => { ui.did(Did::Unlisted { list: key, members }); ui.say(format!("unlisted {n} members · Ctrl+Z brings it back")); ui.touched(); } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "delete" } + if armed() { "unlist?" } else { "unlist" } + } + } + div { class: "figures-row", + div { b { "{list.count}" } span { "members" } } + div { b { "{list.ordinal_sum}" } span { "ordinal" } } + div { b { {format!("{:.1}", list.ordinal_mean)} } span { "ordinal mean" } } + div { b { "{list.reversed_sum}" } span { "reversed" } } + div { b { {format!("{:.1}", list.reversed_mean)} } span { "reversed mean" } } + } + div { class: "small", "as one: ordinal {m.ordinal} · reversed {m.reversed} · letters " span { class: "mono", {gem::letters(&m.frequency).chars().take(40).collect::<String>()} } } + div { class: "dim small mono", {gem::gsum_line(&joined)} } + if m.ordinal > 1 { + crate::views::memory::PfLine { n: m.ordinal } + } + if !list.vector.is_empty() { + div { class: "letterbars", title: "its letters as a vector", + for (i , v) in list.vector.iter().enumerate() { + div { key: "{i}", class: "col", + span { class: "bar", style: "height: {(v / max * 34.0).max(1.0):.1}px;" } + span { class: "l", {((b'a' + i as u8) as char).to_string()} } + } + } + } + } + div { class: "memberchips", + for h in list.members.iter().cloned() { + MemberChip { key: "{h.key}", list: list.list.clone(), hit: h } + } + } + } + } +} + +#[component] +fn MemberChip(list: String, hit: Hit) -> Element { + let ui = ui(); + let api = api(); + let (s, r) = gem::sums(&hit.text); + rsx! { + span { class: "mchip", title: "{hit.key}", + span { class: "mt", onclick: { let t = hit.text.clone(); move |_| ui.set_bar(&t) }, "{hit.text}" } + span { class: "ms", "{s}·{r}" } + button { class: "plain mx", "aria-label": "take it out of the list", "data-tip": "take it out (it stays a text)", + onclick: move |_| { + let (api, l, k) = (api.clone(), list.clone(), hit.key.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.delist(&l, &k).await { + Ok(()) => { ui.did(Did::Delisted { list: l, member: k }); ui.touched(); } + Err(e) => ui.fail(e), + } + }); + }, + "×" + } + } + } +} + +#[component] +fn ListPage(list: ListInfo, back: EventHandler<()>) -> Element { + let ui = ui(); + let api = api(); + let mut page = use_signal(|| 0usize); + let mut armed = use_signal(|| false); + let mut name = use_signal(|| list.name.clone()); + let pages = list.members.len().div_ceil(PAGE).max(1); + let p = page().min(pages - 1); + let members: Vec<Hit> = list.members.iter().skip(p * PAGE).take(PAGE).cloned().collect(); + let key = list.list.clone(); + let k2 = key.clone(); + let api2 = api.clone(); + let api3 = api.clone(); + let old_name = list.name.clone(); + rsx! { + div { class: "page list-page", + div { class: "row", + button { class: "plain tip-right", "data-tip": "all the lists · Esc", "aria-label": "back", onclick: move |_| back.call(()), Icon { name: "chevron-left" } } + input { + class: "name", + r#type: "text", + "aria-label": "the list's name", + initial_value: "{name}", + style: "flex: 1; height: auto; background: none;", + oninput: move |e| name.set(e.value()), + onchange: move |_| { + let n = name(); + if n.trim().is_empty() || n == old_name { return; } + let (api, key, old) = (api2.clone(), k2.clone(), old_name.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.put_memory(&key, &n).await { + Ok(()) => { ui.did(Did::Edited { key, old }); ui.say("renamed"); ui.touched(); } + Err(e) => ui.fail(e), + } + }); + }, + } + button { + class: if armed() { "armed" } else { "plain" }, + "data-tip": "delete the list (its members stay); click twice", + "aria-label": "delete the list", + onclick: move |_| { + if !armed() { armed.set(true); return; } + let (api, key) = (api3.clone(), key.clone()); + let members: Vec<String> = list.members.iter().map(|h| h.key.clone()).collect(); + dioxus::dioxus_core::spawn_forever(async move { + match api.unlist(&key).await { + Ok(n) => { ui.did(Did::Unlisted { list: key, members }); ui.say(format!("the list is gone ({n} members); Ctrl+Z brings it back")); ui.touched(); } + Err(e) => ui.fail(e), + } + }); + back.call(()); + }, + Icon { name: "delete" } + if armed() { "delete the list?" } + } + } + div { class: "card members", + if members.is_empty() { span { class: "dim", "no members yet" } } + for (i , m) in members.into_iter().enumerate() { + Member { key: "{m.key}", list: list.list.clone(), hit: m, n: p * PAGE + i + 1 } + } + } + if pages > 1 { + div { class: "pager", + button { disabled: p == 0, onclick: move |_| page.set(p.saturating_sub(1)), Icon { name: "chevron-left" } } + span { "page {p + 1} of {pages}" } + button { disabled: p + 1 >= pages, onclick: move |_| page.set(p + 1), Icon { name: "chevron-right" } } + } + } + crate::views::pictures::Pictures { list: Some(list.name.clone()), names: vec![] } + Figures { list: list.clone() } + } + } +} + +#[component] +fn Member(list: String, hit: Hit, n: usize) -> Element { + let ui = ui(); + let api = api(); + let mut text = use_signal(|| hit.text.clone()); + let (api1, api2) = (api.clone(), api.clone()); + let h1 = hit.clone(); + let h2 = hit.clone(); + rsx! { + div { class: "member", + span { class: "key", title: "its key", "{n}. {hit.key}" } + input { + r#type: "text", + "aria-label": "member {n}", + initial_value: "{text}", + readonly: hit.note, + oninput: move |e| text.set(e.value()), + onchange: move |_| { + let t = text(); + if t == h1.text || t.trim().is_empty() { return; } + let (api, h) = (api1.clone(), h1.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.put_memory(&h.key, &t).await { + Ok(()) => { ui.did(Did::Edited { key: h.key.clone(), old: h.text.clone() }); ui.say(format!("{} now reads “{t}”", h.key)); } + Err(e) => ui.fail(e), + } + }); + }, + } + button { + class: "plain tip-left", + "data-tip": "take it out of the list (it stays a text)", + "aria-label": "take out of the list", + onclick: move |_| { + let (api, h, l) = (api2.clone(), h2.clone(), list.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.delist(&l, &h.key).await { + Ok(()) => { ui.did(Did::Delisted { list: l, member: h.key }); ui.touched(); } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "close" } + } + } + } +} + +#[component] +fn Figures(list: ListInfo) -> Element { + let joined: String = list + .members + .iter() + .map(|m| m.text.as_str()) + .collect::<Vec<_>>() + .join(" "); + let (s, r) = gem::sums(&joined); + let max = list.vector.iter().cloned().fold(0.0f64, f64::max).max(1e-9); + rsx! { + div { class: "card", + h3 { "figures" } + div { class: "figures", + div { b { "{list.count}" } "members" } + div { b { "{list.ordinal_sum}" } "ordinal, all of them" } + div { b { "{list.reversed_sum}" } "reversed, all of them" } + div { b { "{list.ordinal_mean:.2}" } "ordinal mean" } + div { b { "{list.reversed_mean:.2}" } "reversed mean" } + div { b { "{gem::byte_sum(&joined)}" } "bytes (1–256)" } + div { b { "{((s as f64) * (r as f64)).sqrt().floor()}" } "⌊√(s·r)⌋ of them whole" } + } + if !list.vector.is_empty() { + div { class: "letterbars", title: "the members' letters", + for (i , v) in list.vector.iter().enumerate() { + div { key: "{i}", class: "col", + span { class: "bar", style: "height: {(v / max * 34.0).max(1.0):.1}px;" } + span { class: "l", {((b'a' + i as u8) as char).to_string()} } + } + } + } + } + } + } +} + +/// the lists picked with Shift+click on their names: unlist them together, or let go +#[component] +fn ManyLists(picked: Signal<Vec<String>>, all: Vec<ListInfo>) -> Element { + let ui = ui(); + let api = api(); + let mut armed = use_signal(|| false); + let n = picked().len(); + if n == 0 { + return rsx! {}; + } + rsx! { + div { class: "card many", role: "status", + div { class: "row", + b { {format!("{n} list{} picked", if n == 1 { "" } else { "s" })} } + span { class: "dim small", {all.iter().filter(|l| picked().contains(&l.list)).map(|l| l.name.clone()).collect::<Vec<_>>().join(" · ")} } + span { class: "grow" } + button { class: if armed() { "btn small danger" } else { "btn small" }, + onclick: move |_| { + if !armed() { armed.set(true); return; } + let (api, keys) = (api.clone(), picked()); + let members: Vec<(String, Vec<String>)> = all.iter().filter(|l| keys.contains(&l.list)).map(|l| (l.list.clone(), l.members.iter().map(|h| h.key.clone()).collect())).collect(); + spawn(async move { + for (key, m) in members { + match api.unlist(&key).await { + Ok(_) => ui.did(Did::Unlisted { list: key, members: m }), + Err(e) => { ui.fail(e); return; } + } + } + picked.set(vec![]); + armed.set(false); + ui.say(format!("unlisted {} lists (their members stay) · Ctrl+Z brings them back one by one", keys.len())); + ui.touched(); + }); + }, + Icon { name: "delete" } if armed() { "sure? unlist them" } else { "unlist them" } } + button { class: "btn small", onclick: move |_| picked.set(vec![]), Icon { name: "close" } "let go" } + } + } + } +} diff --git a/app/src/views/memory.rs b/app/src/views/memory.rs new file mode 100644 index 00000000..fef3c529 --- /dev/null +++ b/app/src/views/memory.rs @@ -0,0 +1,1563 @@ +//! The memory view: weum's memory page (docs/weum-reference/memory.js) on a black field. +//! The results header (the sum and its pfR line) and the texts sit in a centre field +//! whose width is dragged at its edges and stays centered; the sidecar and the toggles +//! are on the strip over the bar. +//! +//! weum's behaviour, kept: the hover title is the key and `gsum(text, 1)`; click puts a +//! text in the bar (its sums in the sidecar), Ctrl+click makes it the list candidate, +//! Ctrl+Shift+click the list (Shift+click selects, as Alt+click; a box drawn selects), double click puts its key in the bar, Ctrl+right click gsearches +//! ⌊√(ordinal·reversed)⌋; underlines by the opposite sum's group with seedCLR; toasts; `r` +//! toggles reversed; ← → gsearch the sidecar's first and last; Enter, Ctrl+Enter, +//! Shift+Enter and Delete as weum; Enlist, List, Delist, Unlist. Added: Alt+click selects +//! (then a list is picked visually, or a tag typed), the right-click menu, the left-edge +//! strip of sum buckets, the triangle, spacing, and the bar's undo. + +use dioxus::prelude::*; + +use crate::backend::{BucketCount, Hit}; +use crate::gem::{self, Mode}; +use crate::keys::Action; +use crate::shell::set_pref; +use crate::ui::*; +use crate::views::{TChip, use_keys}; + +#[derive(Clone, PartialEq, Default)] +struct Header { + /// the sum (or what was searched) + title: String, + /// the number pfR runs on + n: Option<u64>, +} + +#[derive(Clone, Copy)] +struct Mem { + results: Signal<Vec<Hit>>, + header: Signal<Option<Header>>, + hover: Signal<String>, + /// the text under the pointer, for its words' types under the hover line + hover_text: Signal<String>, + picking: Signal<bool>, +} + +/// weum's `envale(v)`: the header, then everything filed under `n` +fn envale(ui: Ui, api: Api, m: Mem, n: u64, mode: Mode) { + let mode = if mode == Mode::Frequency { Mode::Ordinal } else { mode }; + show_sum(ui, m, n.to_string(), Some(n), None); + dioxus::dioxus_core::spawn_forever(async move { + match api.gsearch(mode, &n.to_string()).await { + Ok(hits) => { + set_topline( + ui, + &n.to_string(), + mode, + hits.first().map(|h| h.text.as_str()), + hits.len(), + ); + let mut r = m.results; + r.set(hits); + } + Err(e) => ui.fail(e), + } + }); +} + +fn show_sum(_ui: Ui, mut m: Mem, title: String, n: Option<u64>, keep: Option<Vec<Hit>>) { + m.header.set(Some(Header { title, n })); + m.results.set(keep.unwrap_or_default()); +} + +/// the search line in the top bar: what was searched, and the triangle of `text` +fn set_topline(mut ui: Ui, title: &str, mode: Mode, text: Option<&str>, count: usize) { + let (s, r) = text.map(gem::sums).unwrap_or((0, 0)); + ui.topline.set(Some(TopLine { + title: title.to_string(), + detail: format!("{} · {count} text{}", mode.name(), if count == 1 { "" } else { "s" }), + s, + r, + ..Default::default() + })); +} + +fn add_hit(mut m: Mem, h: Hit) { + let mut r = m.results.write(); + if !r.iter().any(|x| x.key == h.key) { + r.push(h); + } +} + +/// the list commands typed in the bar +async fn list_command(ui: Ui, api: Api, m: Mem, word: &str) -> bool { + if !["Enlist", "List", "Delist", "Unlist"].contains(&word) { + return false; + } + let p = ui.picks.peek().clone(); + let Some(list) = p.list else { + ui.fail("Ctrl+Shift+click a text to pick the list first"); + return true; + }; + let r = match word { + "Enlist" | "Delist" => { + let Some(c) = p.candidate else { + ui.fail("Ctrl+click a text to pick the candidate first"); + return true; + }; + if word == "Enlist" { + api.enlist(&list.key, &c.key).await.map(|_| { + ui.did(Did::Enlisted { + list: list.key.clone(), + member: c.key.clone(), + }); + format!("“{}” is in the list “{}”", c.text, list.text) + }) + } else { + api.delist(&list.key, &c.key).await.map(|_| { + ui.did(Did::Delisted { + list: list.key.clone(), + member: c.key.clone(), + }); + format!("“{}” left the list “{}”", c.text, list.text) + }) + } + } + "Unlist" => { + let members: Vec<String> = match api.lists().await { + Ok(l) => l + .lists + .into_iter() + .find(|x| x.list == list.key) + .map(|x| x.members.into_iter().map(|h| h.key).collect()) + .unwrap_or_default(), + Err(_) => vec![], + }; + api.unlist(&list.key).await.map(|n| { + ui.did(Did::Unlisted { + list: list.key.clone(), + members, + }); + let mut picks = ui.picks; + picks.write().list = None; + format!("the list “{}” is gone ({n} members)", list.text) + }) + } + _ => Ok(String::new()), + }; + match r { + Ok(msg) => { + if !msg.is_empty() { + ui.say(msg); + } + ui.touched(); + // List (and after a change): the list and its members + if let Ok(l) = api.lists().await { + let members = l + .lists + .into_iter() + .find(|x| x.list == list.key) + .map(|x| x.members) + .unwrap_or_default(); + show_sum( + ui, + m, + list.text.clone(), + None, + Some([vec![list.clone()], members].concat()), + ); + } + } + Err(e) => ui.fail(e), + } + true +} + +/// anagrams: everything with the same letters as `t` +async fn letters_search(ui: Ui, api: Api, m: Mem, t: String) { + let letters = gem::letters(&gem::Measure::of(&t).frequency); + show_sum(ui, m, letters.clone(), None, None); + match api.gsearch(Mode::Frequency, &t).await { + Ok(hits) => { + set_topline(ui, &letters, Mode::Frequency, Some(&t), hits.len()); + let mut r = m.results; + r.set(hits); + } + Err(e) => ui.fail(e), + } +} + +/// Enter in the bar (weum's term onkeydown) +async fn enter(mut ui: Ui, api: Api, m: Mem, raw: String, ctrl: bool, shift: bool) { + let t = raw.trim().to_string(); + if t.is_empty() { + return; + } + let mode = ui.mode(); + let (gsearch_text, saturate) = { + let p = ui.prefs.peek(); + (p.gsearch_text, p.saturate) + }; + // the right-click menu's edit and tag + let pending = ui.pending.peek().clone(); + match pending { + Pending::Edit(h) => { + ui.pending.set(Pending::None); + match api.put_memory(&h.key, &t).await { + Ok(()) => { + ui.did(Did::Edited { + key: h.key.clone(), + old: h.text.clone(), + }); + let mut r = m.results; + for x in r.write().iter_mut().filter(|x| x.key == h.key) { + x.text = t.clone(); + } + ui.say(format!("{} now reads “{t}” · Ctrl+Z takes it back", h.key)); + ui.touched(); + } + Err(e) => ui.fail(e), + } + return; + } + Pending::Tag(hs) => { + ui.pending.set(Pending::None); + let mut done = 0; + for h in &hs { + match api.tag(&h.key, &t).await { + Ok(()) => done += 1, + Err(e) => ui.fail(e), + } + } + ui.say(format!("tagged {done} with “{t}”")); + ui.set_bar(""); + ui.touched(); + return; + } + // a space placement's own text, left pending when the view changed: dropped + Pending::EditOwn { .. } => ui.pending.set(Pending::None), + Pending::None => {} + } + if list_command(ui, api.clone(), m, &t).await { + return; + } + // `Run <program> [arguments]`: an s program of the save + if crate::views::scode::run_from_bar(ui, &api, &t).await { + return; + } + let (tint, cls_search) = { + let p = ui.prefs.peek(); + (p.tint.clone(), p.cls_search) + }; + if cls_search && !tint.is_empty() && !shift { + classifier_search(ui, api, m, &tint, &t).await; + return; + } + let number: Option<u64> = t.parse().ok(); + if shift { + // remember by key + match api.remember(&t).await { + Ok(h) => show_sum(ui, m, t.clone(), None, Some(vec![h])), + Err(e) => ui.fail(e), + } + return; + } + if let Some(n) = number { + envale(ui, api, m, n, mode); + return; + } + if mode == Mode::Frequency && !ctrl { + letters_search(ui, api.clone(), m, t.clone()).await; + if saturate { + saturate_and_show(ui, api, m, &t, false).await; + } + return; + } + let s = gem::sum_in(&t, mode); + if ctrl { + // weum: gsearch the text's sum, saturate it, toast its key + envale(ui, api.clone(), m, s, mode); + saturate_and_show(ui, api, m, &t, true).await; + return; + } + if gsearch_text { + envale(ui, api.clone(), m, s, mode); + set_topline(ui, &s.to_string(), mode, Some(&t), 0); + // and the words: the text itself, when it's there + match api.search(&t, true).await { + Ok(found) => { + if let Some(h) = found.into_iter().find(|h| h.text == t) { + add_hit(m, h); + } else if saturate { + saturate_and_show(ui, api, m, &t, true).await; + } + } + Err(e) => ui.fail(e), + } + } else { + // weum's tryfulSearchVariations: the words, with variations + show_sum(ui, m, t.clone(), None, None); + match api.search(&t, true).await { + Ok(found) => { + let present = found.iter().any(|h| h.text == t); + set_topline(ui, &t, mode, Some(&t), found.len()); + let mut r = m.results; + r.set(found); + if !present && saturate { + saturate_and_show(ui, api, m, &t, true).await; + } + } + Err(e) => ui.fail(e), + } + } +} + +/// the classifier search mode: a class's name (and words after it) finds the texts most +/// likely in that class; any other text, the texts the classifier reads most like it +async fn classifier_search(ui: Ui, api: Api, m: Mem, name: &str, t: &str) { + let classes: Vec<String> = match api.call("classify.get", serde_json::json!({ "name": name })).await { + Ok(v) => v["classes"] + .as_array() + .into_iter() + .flatten() + .filter_map(|c| c.as_str().map(str::to_string)) + .collect(), + Err(e) => return ui.fail(e), + }; + let lower = t.to_lowercase(); + let class = classes.iter().find(|c| { + let c = c.to_lowercase(); + lower == c || lower.starts_with(&format!("{c} ")) + }); + let mode = ui.mode(); + match class { + Some(c) => { + let words = t[c.len()..].trim().to_string(); + let title = if words.is_empty() { + format!("{name}: {c}") + } else { + format!("{name}: {c} · {words}") + }; + show_sum(ui, m, title.clone(), None, None); + match api.model_search(name, c, &words).await { + Ok(found) => { + // the texts it counts in the class; when there are none, the likeliest + let members = found.iter().filter(|s| s.member).count(); + if members == 0 { + ui.say(format!("{name} counts nothing here as {c}; these are the likeliest")); + } + let hits: Vec<Hit> = found + .into_iter() + .filter(|s| s.member || members == 0) + .take(if members == 0 { 24 } else { usize::MAX }) + .filter_map(|s| { + Some(Hit { + key: s.key?, + text: s.text, + note: s.note, + }) + }) + .collect(); + set_topline(ui, &title, mode, hits.first().map(|h| h.text.as_str()), hits.len()); + let mut r = m.results; + r.set(hits); + } + Err(e) => ui.fail(e), + } + } + None => { + let title = format!("like “{t}” · {name}"); + show_sum(ui, m, title.clone(), None, None); + match api + .call( + "classify.similar", + serde_json::json!({ "name": name, "text": t, "limit": 60 }), + ) + .await + { + Ok(v) => { + let hits: Vec<Hit> = v["results"] + .as_array() + .into_iter() + .flatten() + .filter_map(|h| { + Some(Hit { + key: h["key"].as_str()?.to_string(), + text: h["text"].as_str()?.to_string(), + note: h["note"].as_bool().unwrap_or(false), + }) + }) + .collect(); + set_topline(ui, &title, mode, Some(t), hits.len()); + let mut r = m.results; + r.set(hits); + } + Err(e) => ui.fail(e), + } + } + } +} + +async fn saturate_and_show(ui: Ui, api: Api, m: Mem, t: &str, toast: bool) { + match api.saturate(t).await { + Ok((key, new)) => { + if new { + ui.did(Did::Remembered { + key: key.clone(), + text: t.to_string(), + }); + ui.touched(); + } + if toast || new { + ui.toast(key.clone()); + } + add_hit( + m, + Hit { + key, + text: t.to_string(), + note: false, + }, + ); + } + Err(e) => ui.fail(e), + } +} + +async fn forget(ui: Ui, api: Api, m: Mem, key: String) { + match api.forget(&key).await { + Ok(text) => { + ui.did(Did::Forgot { + key: key.clone(), + text: text.clone(), + }); + ui.say(format!("forgot “{text}” ({key}) · Ctrl+Z takes it back")); + let mut r = m.results; + r.write().retain(|h| h.key != key); + ui.set_bar(""); + ui.touched(); + } + Err(e) => ui.fail(e), + } +} + +fn set_mode(ui: Ui, mode: Mode) { + set_pref(ui, |p| p.mode = mode); +} + +#[component] +pub fn Memory() -> Element { + let mut ui = ui(); + let api = api(); + let m = Mem { + results: use_signal(Vec::new), + header: use_signal(|| None), + hover: use_signal(String::new), + hover_text: use_signal(String::new), + picking: use_signal(|| false), + }; + use_context_provider(|| m); + + // the keys (weum's window.onkeydown, and the bar's) + { + let api = api.clone(); + use_keys(View::Memory, move |k: KeyPress| { + if k.bar { + match k.key.as_str() { + "Enter" => { + dioxus::dioxus_core::spawn_forever(enter(ui, api.clone(), m, k.text.clone(), k.ctrl, k.shift)); + true + } + "Delete" => { + dioxus::dioxus_core::spawn_forever(forget(ui, api.clone(), m, k.text.trim().to_string())); + true + } + _ => false, + } + } else { + let measure = ui.measure.peek().clone(); + let mode = ui.mode(); + if k.key == "Escape" { + let mut p = m.picking; + p.set(false); + ui.picks.write().selected.clear(); + return true; + } + match k.action { + Some(Action::BucketReversed) => set_mode( + ui, + if mode == Mode::Reversed { + Mode::Ordinal + } else { + Mode::Reversed + }, + ), + Some(Action::BucketOrdinal) => set_mode(ui, Mode::Ordinal), + Some(Action::BucketFrequency) => set_mode( + ui, + if mode == Mode::Frequency { + Mode::Ordinal + } else { + Mode::Frequency + }, + ), + Some(Action::ToggleGsearch) => set_pref(ui, |p| p.gsearch_text = !p.gsearch_text), + Some(Action::ToggleSaturate) => set_pref(ui, |p| p.saturate = !p.saturate), + Some(Action::Letters) => set_pref(ui, |p| p.letters = !p.letters), + Some(Action::WhiteMode) => set_pref(ui, |p| p.white = !p.white), + Some(Action::WordTypes) => set_pref(ui, |p| p.word_types = !p.word_types), + Some(Action::ClassifierSearch) if !ui.prefs.peek().tint.is_empty() => { + set_pref(ui, |p| p.cls_search = !p.cls_search) + } + Some(Action::SideOrdinal) => match measure { + // the sidecar's first: the ordinal sum, gsearched in ordinal + Some(me) => { + set_mode(ui, Mode::Ordinal); + envale(ui, api.clone(), m, me.ordinal, Mode::Ordinal); + } + None => return false, + }, + Some(Action::SideReversed) => match measure { + // the last: the reversed sum, gsearched in reversed + Some(me) => { + set_mode(ui, Mode::Reversed); + envale(ui, api.clone(), m, me.reversed, Mode::Reversed); + } + None => return false, + }, + Some(Action::SideFrequency) => match measure { + // the letters: gsearched by frequency + Some(me) => { + set_mode(ui, Mode::Frequency); + let _ = me; + let t = ui.bar.peek().trim().to_string(); + dioxus::dioxus_core::spawn_forever(letters_search(ui, api.clone(), m, t)); + } + None => return false, + }, + _ => return false, + } + true + } + }); + } + + let results = (m.results)(); + let header = (m.header)(); + let mode = ui.prefs.read().mode; + let width = ui.prefs.read().field_width; + let picks = (ui.picks)(); + let field_style = if width > 0.0 { + format!("max-width: {width}px;") + } else { + String::new() + }; + let nsel = picks.selected.len(); + let (word_types_on, white) = { + let p = ui.prefs.read(); + (p.word_types, p.white) + }; + rsx! { + div { class: if white { "memory white" } else { "memory" }, style: "position: absolute; inset: 0;", + div { class: "edge" } + Buckets {} + div { class: "mem-main", + if header.is_none() && results.is_empty() { + div { class: "mem-intro", + p { "Type a word below and press Enter: it is remembered, and everything sharing its sum comes up." } + p { "A number gsearches it; Shift+Enter brings back a key (like 0,12). Shift+click (or Alt+click) selects texts, a box drawn round them too; Ctrl+Shift+click heads a list, Ctrl+click picks a candidate." } + } + } else { + div { class: "spacer" } + Field { style: field_style, header, results, mode, picks: picks.clone() } + div { class: "spacer" } + } + } + if nsel > 0 { + SelBar { n: nsel } + } + div { class: "mem-hover", "{m.hover}" } + if !(m.hover_text)().is_empty() && !word_types_on { + div { class: "mem-types", "aria-label": "its words' types", TaggedText { text: (m.hover_text)(), labels: true } } + } + } + } +} + +/// each word type's short label +pub(crate) fn type_label(t: &str) -> &'static str { + match t { + "noun" => "n", + "verb" => "v", + "adjective" => "adj", + "adverb" => "adv", + "pronoun" => "pron", + "determiner" => "det", + "preposition" => "prep", + "conjunction" => "conj", + "interjection" => "intj", + "name" => "name", + "number" => "num", + "date" => "date", + "time" => "time", + "link" => "link", + "email" => "email", + "hashtag" => "tag", + _ => "", + } +} + +/// a text with each word labelled by its type (core's `kinds::tag`), in that type's colour; +/// the spaces and punctuation between words kept as they are +#[component] +pub(crate) fn TaggedText( + text: String, + #[props(default = true)] labels: bool, + /// as ruby: the words stay inline text, so a text's own underline (the gematria + /// colour of its reversed-sum group) runs under them untouched; the type is the label + /// under each word, in its colour, never an underline + #[props(default)] + ruby: bool, +) -> Element { + // English types only on English (other languages get their own tag sets) + let tags = if anend_core::kinds::looks_english(&text) { + anend_core::kinds::tag(&text) + } else { + vec![] + }; + let mut parts: Vec<(String, Option<&'static str>)> = Vec::new(); + let mut at = 0; + for t in &tags { + if t.start > at { + parts.push((text[at..t.start].to_string(), None)); + } + parts.push((text[t.start..t.end].to_string(), Some(t.ty))); + at = t.end; + } + if at < text.len() { + parts.push((text[at..].to_string(), None)); + } + rsx! { + span { class: "tagged", + for (i , (piece , ty)) in parts.into_iter().enumerate() { + match ty { + Some(ty) if ruby => rsx! { + ruby { key: "{i}", class: "rw t-{ty}", title: "{ty}", + "{piece}" + rt { "{type_label(ty)}" } + } + }, + Some(ty) => rsx! { + span { key: "{i}", class: "tw t-{ty}", title: "{ty}", + span { class: "w", "{piece}" } + if labels { span { class: "l", "{type_label(ty)}" } } + } + }, + None => rsx! { span { key: "{i}", "{piece}" } }, + } + } + } + } +} + +/// the word types shown, each in its colour, with how many of each +#[component] +fn TypesLegend(texts: Vec<String>) -> Element { + let mut counts: std::collections::BTreeMap<usize, (&'static str, usize)> = Default::default(); + for t in texts.iter().filter(|t| anend_core::kinds::looks_english(t)) { + for w in anend_core::kinds::tag(t) { + let i = anend_core::kinds::WORD_TYPES + .iter() + .position(|x| *x == w.ty) + .unwrap_or(99); + counts.entry(i).or_insert((w.ty, 0)).1 += 1; + } + } + rsx! { + div { class: "types-legend", "aria-label": "word types", + for (_ , (ty , n)) in counts { + span { key: "{ty}", class: "tw t-{ty}", b { "{type_label(ty)}" } span { "{ty} {n}" } } + } + } + } +} + +/// the lists, and the picked list (Ctrl+Shift+click, or a new one) even while it's empty +fn with_picked(mut lists: Vec<crate::backend::ListInfo>, picked: Option<Hit>) -> Vec<crate::backend::ListInfo> { + if let Some(h) = picked + && !lists.iter().any(|l| l.list == h.key) + { + lists.insert( + 0, + crate::backend::ListInfo { + list: h.key, + name: h.text, + ..Default::default() + }, + ); + } + lists +} + +#[component] +fn SelBar(n: usize) -> Element { + let mut ui = ui(); + let api = api(); + let m = use_context::<Mem>(); + let mut picking = m.picking; + let api_r = api.clone(); + let lists = use_resource(move || { + let api = api_r.clone(); + let open = picking(); + async move { if open { api.lists().await.ok() } else { None } } + }); + rsx! { + div { class: "selbar", role: "toolbar", + "{n} selected" + button { onclick: move |_| picking.set(!picking()), Icon { name: "list" } "put in a list…" } + button { + onclick: move |_| { + let sel = ui.picks.peek().selected.clone(); + ui.pending.set(Pending::Tag(sel)); + ui.set_bar(""); + ui.focus_bar(); + }, + Icon { name: "tag" } + "tag…" + } + button { onclick: move |_| ui.picks.write().selected.clear(), Icon { name: "close" } "clear" } + } + if picking() { + div { class: "listpick", + match &*lists.read() { + Some(Some(l)) if !l.lists.is_empty() || ui.picks.read().list.is_some() => rsx! { + for li in with_picked(l.lists.clone(), ui.picks.read().list.clone()) { + button { + key: "{li.list}", + title: "{li.count} members · {li.list}", + onclick: { + let api = api.clone(); + let li = li.clone(); + move |_| { + let api = api.clone(); + let li = li.clone(); + dioxus::dioxus_core::spawn_forever(async move { + let sel = ui.picks.peek().selected.clone(); + for h in &sel { + match api.enlist(&li.list, &h.key).await { + Ok(()) => ui.did(Did::Enlisted { list: li.list.clone(), member: h.key.clone() }), + Err(e) => ui.fail(e), + } + } + ui.say(format!("{} into the list “{}”", sel.len(), li.name)); + ui.picks.write().selected.clear(); + let mut p = m.picking; + p.set(false); + ui.touched(); + }); + } + }, + "{li.name} ({li.count})" + } + } + }, + Some(Some(_)) => rsx! { span { "no lists yet: Ctrl+Shift+click a text to make one its head" } }, + _ => rsx! { span { "…" } }, + } + } + } + } +} + +/// the memory view's box selection: a drag that starts on the field's empty space draws a +/// box; on release, the keys of the texts it touches go to Rust (`add` with Shift) +const BOX_SELECT: &str = r#" +// the newest field's channel; the listeners go in once +window.__anendBoxSend = (m) => dioxus.send(m); +if (!window.__anendBoxSel) { + window.__anendBoxSel = true; + let b = null; + document.addEventListener('mousedown', (e) => { + const arts = e.target.closest && e.target.closest('.arts'); + if (e.button !== 0 || !arts || e.target.closest('.art')) return; + b = { x0: e.clientX, y0: e.clientY, add: e.shiftKey, el: null }; + }); + document.addEventListener('mousemove', (e) => { + if (!b) return; + if (!b.el && Math.hypot(e.clientX - b.x0, e.clientY - b.y0) < 5) return; + if (!b.el) { b.el = document.createElement('div'); b.el.className = 'selbox'; document.body.append(b.el); } + const x = Math.min(b.x0, e.clientX), y = Math.min(b.y0, e.clientY); + Object.assign(b.el.style, { left: x + 'px', top: y + 'px', width: Math.abs(e.clientX - b.x0) + 'px', height: Math.abs(e.clientY - b.y0) + 'px' }); + e.preventDefault(); + }); + document.addEventListener('mouseup', () => { + if (!b) return; + const was = b; b = null; + if (!was.el) return; + const r = was.el.getBoundingClientRect(); + was.el.remove(); + const keys = [...document.querySelectorAll('.arts .art[data-key]')].filter((el) => { + const q = el.getBoundingClientRect(); + return q.right >= r.left && q.left <= r.right && q.bottom >= r.top && q.top <= r.bottom; + }).map((el) => el.dataset.key); + if (window.__anendBoxSend) window.__anendBoxSend({ keys, add: was.add }); + }); +} +await new Promise(() => {}); +"#; + +#[component] +fn Field(style: String, header: Option<Header>, results: Vec<Hit>, mode: Mode, picks: Picks) -> Element { + let ui = ui(); + let api = api(); + let keys: Vec<String> = results.iter().map(|h| h.key.clone()).collect(); + let keys = use_memo(use_reactive!(|keys| keys)); + let tints = use_resource(move || { + let api = api.clone(); + let name = ui.prefs.read().tint.clone(); + let keys = keys(); + let _ = (ui.changed)(); + async move { + if name.is_empty() || keys.is_empty() { + return None; + } + let keys: Vec<String> = keys.into_iter().take(5000).collect(); + api.call("classify.tints", serde_json::json!({ "name": name, "keys": keys })) + .await + .ok() + } + }); + let tinted = tints.read().clone().flatten(); + let (tint_of, legend) = tint_map(tinted.as_ref()); + // a box drawn on the field's empty space selects the texts it touches (Shift adds) + let shown = use_signal(Vec::<Hit>::new); + { + let mut shown = shown; + if *shown.peek() != results { + shown.set(results.clone()); + } + } + use_hook(move || { + let mut ev = document::eval(BOX_SELECT); + spawn(async move { + while let Ok(v) = ev.recv::<serde_json::Value>().await { + let keys: Vec<String> = crate::views::classifiers::strs(&v["keys"]); + let add = v["add"] == true; + let all = shown.peek().clone(); + let mut picks = ui.picks; + let mut p = picks.write(); + if !add { + p.selected.clear(); + } + for h in all.into_iter().filter(|h| keys.contains(&h.key)) { + if !p.selected.iter().any(|x| x.key == h.key) { + p.selected.push(h); + } + } + } + }); + }); + // the effects of the pipes turned on (stacked in their order) + let api_fx = use_context::<Api>(); + let fx = use_resource(move || { + let api = api_fx.clone(); + let names = ui.prefs.read().pipes.clone(); + let keys = keys(); + let _ = (ui.changed)(); + async move { + if names.is_empty() || keys.is_empty() { + return std::collections::HashMap::new(); + } + let keys: Vec<String> = keys.into_iter().take(5000).collect(); + let v = api + .call("pipes.effects", serde_json::json!({ "names": names, "keys": keys })) + .await + .unwrap_or_default(); + v["effects"] + .as_array() + .into_iter() + .flatten() + .map(|e| (e["key"].as_str().unwrap_or("").to_string(), e.clone())) + .collect::<std::collections::HashMap<String, serde_json::Value>>() + } + }); + let fx_of = fx.read().clone().unwrap_or_default(); + // the search filter (the square at the strip's right): what it keeps of the results + let filter = ui.prefs.read().filter.clone(); + let filter_open = ui.prefs.read().filter_open; + let class_of = class_map(tinted.as_ref()); + let api_f = use_context::<Api>(); + let judged = use_resource(move || { + let api = api_f.clone(); + let name = ui.prefs.read().tint.clone(); + let want = ui.prefs.read().filter.feedback || ui.prefs.read().filter_open; + let _ = (ui.changed)(); + async move { + if name.is_empty() || !want { + return None; + } + let d = api + .call("classify.get", serde_json::json!({ "name": name })) + .await + .ok()?; + let bias = api + .call( + "classify.steer", + serde_json::json!({ "name": name, "steer": {}, "save": false }), + ) + .await + .ok() + .map(|v| v["bias"].clone()); + let keys: std::collections::HashSet<String> = d["feedback"] + .as_array() + .into_iter() + .flatten() + .filter_map(|f| f["key"].as_str().map(str::to_string)) + .collect(); + Some(( + keys, + bias.unwrap_or_default(), + d["feedback_count"].as_u64().unwrap_or(0), + )) + } + }); + let judged = judged.read().clone().flatten(); + let all_results = results.clone(); + let results: Vec<Hit> = results + .into_iter() + .filter(|h| { + keeps( + &filter, + h, + class_of.get(&h.key).map(String::as_str), + judged.as_ref().map(|j| &j.0), + ) + }) + .collect(); + let hidden = all_results.len() - results.len(); + let mut drag: Signal<Option<(f64, f64, f64)>> = use_signal(|| None); + let mut rect: Signal<Option<std::rc::Rc<MountedData>>> = use_signal(|| None); + let start = move |e: MouseEvent, side: f64| { + e.prevent_default(); + let x = e.client_coordinates().x; + dioxus::dioxus_core::spawn_forever(async move { + let w = match rect.peek().clone() { + Some(r) => r.get_client_rect().await.map(|r| r.width()).unwrap_or(800.0), + None => 800.0, + }; + drag.set(Some((x, w, side))); + }); + }; + rsx! { + div { + class: "field", + style: "{style}", + onmounted: move |e| rect.set(Some(e.data())), + div { class: "grip l", title: "drag: the field's width (it stays centered); double click: the whole width", + onmousedown: move |e| start(e, -1.0), + ondoubleclick: move |_| set_pref(ui, |p| p.field_width = 0.0) } + div { class: "grip r", title: "drag: the field's width (it stays centered); double click: the whole width", + onmousedown: move |e| start(e, 1.0), + ondoubleclick: move |_| set_pref(ui, |p| p.field_width = 0.0) } + if let Some(h) = header { + div { class: "results-head", + h3 { "{h.title}" } + if let Some(n) = h.n { + PfLine { n } + } + } + } + if !legend.is_empty() { + div { class: "tint-legend", "aria-label": "colours", + for (c , colour , n) in legend.clone() { + span { key: "{c}", span { class: "dot", style: "background: {colour};" } "{c} {n}" } + } + } + } + if hidden > 0 { + div { class: "filter-note", "the filter hides {hidden} of {all_results.len()} · the square at the right of the strip changes it" } + } + if ui.prefs.read().word_types && !results.is_empty() { + TypesLegend { texts: results.iter().map(|h| h.text.clone()).collect::<Vec<_>>() } + } + div { class: "arts", role: "list", + if results.is_empty() && hidden == 0 { + span { class: "dim", style: "color: #bbb; padding: 6px;", "nothing filed here yet" } + } + for h in results { + Art { + key: "{h.key}", + tint: tint_of.get(&h.key).cloned(), + fx: fx_of.get(&h.key).cloned(), + under: gem::underline(&h.text, mode), + is_list: picks.list.as_ref().is_some_and(|l| l.key == h.key), + is_cand: picks.candidate.as_ref().is_some_and(|l| l.key == h.key), + selected: picks.selected.iter().any(|s| s.key == h.key), + hit: h, + } + } + } + } + if filter_open { + FilterPanel { shown: all_results.clone(), class_of: class_of.clone(), legend: legend.clone(), judged: judged.clone() } + } + if let Some((x0, w0, side)) = drag() { + div { + style: "position: fixed; inset: 0; z-index: 90; cursor: ew-resize;", + onmousemove: move |e| { + let x = e.client_coordinates().x; + let w = (w0 + 2.0 * side * (x - x0)).max(240.0); + set_pref(ui, |p| p.field_width = w as f32); + }, + onmouseup: move |_| drag.set(None), + } + } + } +} + +/// each key's class name under the colouring classifier ("unsure" when in none) +fn class_map(v: Option<&serde_json::Value>) -> std::collections::HashMap<String, String> { + let mut out = std::collections::HashMap::new(); + let Some(v) = v else { return out }; + let names: Vec<String> = crate::views::classifiers::strs(&v["classes"]); + for t in v["tints"].as_array().into_iter().flatten() { + let Some(key) = t["key"].as_str() else { continue }; + let c = t["class"] + .as_u64() + .and_then(|c| names.get(c as usize).cloned()) + .unwrap_or_else(|| "unsure".into()); + out.insert(key.to_string(), c); + } + out +} + +/// whether the search filter keeps a text +fn keeps( + f: &crate::prefs::MemFilter, + h: &Hit, + class: Option<&str>, + judged: Option<&std::collections::HashSet<String>>, +) -> bool { + if (h.note && f.no_notes) || (!h.note && f.no_texts) { + return false; + } + if !f.kinds.is_empty() && !f.kinds.contains(anend_core::kinds::detect(&h.text)) { + return false; + } + if !f.words.is_empty() { + let types = anend_core::kinds::word_types(&h.text); + if !f.words.iter().all(|w| types.iter().any(|(_, k)| k == w)) { + return false; + } + } + if !f.classes.is_empty() && class.is_some_and(|c| !f.classes.contains(c)) { + return false; + } + if f.feedback && judged.is_some_and(|j| !j.contains(&h.key)) { + return false; + } + true +} + +/// counts of a thing among the shown texts, most first +fn tally<'a>(items: impl Iterator<Item = &'a str>) -> Vec<(String, usize)> { + let mut m: std::collections::BTreeMap<&str, usize> = Default::default(); + for i in items { + *m.entry(i).or_default() += 1; + } + let mut v: Vec<(String, usize)> = m.into_iter().map(|(k, n)| (k.to_string(), n)).collect(); + v.sort_by(|a, b| b.1.cmp(&a.1).then(a.0.cmp(&b.0))); + v +} + +/// the search filter panel: what the shown texts are (their kinds, their words' types, +/// their classes under the colouring classifier, which were given a verdict, the +/// classifier's bias), each a chip that keeps only those +#[component] +fn FilterPanel( + shown: Vec<Hit>, + class_of: std::collections::HashMap<String, String>, + legend: Legend, + judged: Option<(std::collections::HashSet<String>, serde_json::Value, u64)>, +) -> Element { + let ui = ui(); + let f = ui.prefs.read().filter.clone(); + let tint = ui.prefs.read().tint.clone(); + let kinds = tally(shown.iter().map(|h| anend_core::kinds::detect(&h.text))); + let words = tally( + shown + .iter() + .flat_map(|h| anend_core::kinds::word_types(&h.text)) + .map(|(_, k)| k) + .collect::<Vec<_>>() + .into_iter(), + ); + let notes = shown.iter().filter(|h| h.note).count(); + let classes: Vec<(String, usize)> = legend.iter().map(|(c, _, n)| (c.clone(), *n)).collect(); + let flip = move |set: fn(&mut crate::prefs::MemFilter) -> &mut std::collections::BTreeSet<String>, v: String| { + set_pref(ui, move |p| { + let s = set(&mut p.filter); + if !s.remove(&v) { + s.insert(v.clone()); + } + }) + }; + let _ = &class_of; + rsx! { + div { class: "filter-panel", role: "dialog", "aria-label": "search filter", + div { class: "row", + b { "filter what's shown" } + span { class: "grow" } + if f.active() { + button { class: "plain", onclick: move |_| set_pref(ui, |p| p.filter = Default::default()), "clear" } + } + button { class: "plain", "aria-label": "close the filter", onclick: move |_| set_pref(ui, |p| p.filter_open = false), Icon { name: "close" } } + } + div { class: "fgroup", + span { class: "dim small", "entries" } + button { class: if !f.no_texts { "chip on" } else { "chip" }, onclick: move |_| set_pref(ui, |p| p.filter.no_texts = !p.filter.no_texts), + "texts " span { class: "dim", "{shown.len() - notes}" } } + button { class: if !f.no_notes { "chip on" } else { "chip" }, onclick: move |_| set_pref(ui, |p| p.filter.no_notes = !p.filter.no_notes), + "notes " span { class: "dim", "{notes}" } } + } + div { class: "fgroup", + span { class: "dim small", "kind" } + for (k , n) in kinds { + button { key: "{k}", class: if f.kinds.contains(&k) { "chip on" } else { "chip" }, + onclick: { let k = k.clone(); move |_| flip(|f| &mut f.kinds, k.clone()) }, + "{k} " span { class: "dim", "{n}" } } + } + } + div { class: "fgroup", + span { class: "dim small", "has words of type" } + for (k , n) in words { + button { key: "{k}", class: if f.words.contains(&k) { "chip on" } else { "chip" }, + title: "{n} words of this type among the texts shown", + onclick: { let k = k.clone(); move |_| flip(|f| &mut f.words, k.clone()) }, + "{k} " span { class: "dim", "{n}" } } + } + } + if tint.is_empty() { + div { class: "fgroup dim small", "pick a classifier in the strip (the palette) to filter by its classes, its verdicts and see its bias" } + } else { + div { class: "fgroup", + span { class: "dim small", "{tint}" } + for (c , n) in classes { + button { key: "{c}", class: if f.classes.contains(&c) { "chip on" } else { "chip" }, + onclick: { let c = c.clone(); move |_| flip(|f| &mut f.classes, c.clone()) }, + "{c} " span { class: "dim", "{n}" } } + } + } + div { class: "fgroup", + span { class: "dim small", "feedback" } + button { class: if f.feedback { "chip on" } else { "chip" }, + title: "only texts this classifier was given a yes or no on (its latest 50)", + onclick: move |_| set_pref(ui, |p| p.filter.feedback = !p.filter.feedback), + "given a verdict " + span { class: "dim", {judged.as_ref().map(|j| format!("{} of {}", shown.iter().filter(|h| j.0.contains(&h.key)).count(), j.2)).unwrap_or_default()} } + } + } + if let Some((_, bias, _)) = &judged && bias.is_object() { + div { class: "fgroup small", + span { class: "dim", "bias" } + span { title: "mean KL of the steered from the trained outputs", {format!("KL {:.3}", bias["mean_kl"].as_f64().unwrap_or(0.0))} } + span { title: "share of texts whose top class the steering flips", {format!("flipped {:.0}%", 100.0 * bias["flipped"].as_f64().unwrap_or(0.0))} } + span { title: "how uneven the classes' shares are", {format!("imbalance {:.2}", bias["imbalance"].as_f64().unwrap_or(0.0))} } + span { title: "how far the predicted shares are from the training lists'", {format!("prior skew {:.2}", bias["prior_skew"].as_f64().unwrap_or(0.0))} } + } + } + } + } + } +} + +/// weum's pfR line; its numbers go into the bar when clicked +#[component] +pub(crate) fn PfLine(n: u64) -> Element { + let ui = ui(); + let segs = gem::pf_line(n); + rsx! { + div { class: "pf", + for (i , s) in segs.into_iter().enumerate() { + match s { + anend_core::weum::Seg::Text(t) => rsx! { span { key: "{i}", "{t}" } }, + anend_core::weum::Seg::Num(v) => rsx! { + i { key: "{i}", title: "into the bar", onclick: move |_| ui.set_bar(&v.to_string()), "{v}" } + }, + } + } + } + } +} + +#[component] +fn Art( + hit: Hit, + under: Option<String>, + is_list: bool, + is_cand: bool, + selected: bool, + tint: Option<String>, + fx: Option<serde_json::Value>, +) -> Element { + let mut ui = ui(); + let api = api(); + let m = use_context::<Mem>(); + let title = format!("{} {}", hit.key, gem::gsum_line(&hit.text)); + // a long text shows piece by piece (lines at word boundaries, a few lines a piece) + let (pw, pl) = { + let p = ui.prefs.read(); + (p.piece_line, p.piece_lines) + }; + let n_pieces = anend_core::pieces::count(&hit.text, pw, pl); + let long = n_pieces > 1; + let mut shown = use_signal(|| 1usize); + let shown_n = shown().min(n_pieces); + let shown_text: String = if long { + anend_core::pieces::pieces(&hit.text, pw, pl)[..shown_n].concat() + } else { + String::new() + }; + let mut class = String::from("art"); + for (on, c) in [ + (is_list, " is-list"), + (is_cand, " is-candidate"), + (selected, " selected"), + (hit.note, " note"), + (long, " long"), + ] { + if on { + class.push_str(c); + } + } + // a pipe's underline stands in for the gematria one + let fx_s = |k: &str| fx.as_ref().and_then(|f| f[k].as_str()).map(String::from); + let under_style = match fx_s("underline").or(under.clone()) { + Some(c) => format!("text-decoration: underline; text-decoration-color: {c};"), + None => String::new(), + }; + let label = fx_s("label"); + // a long text underlines its piece, not the controls under it + let mut style = if long { String::new() } else { under_style.clone() }; + if let Some(t) = fx_s("colour").as_ref().or(tint.as_ref()) { + style.push_str(&format!(" border-left: 5px solid {t};")); + } + if let Some(sz) = fx.as_ref().and_then(|f| f["size"].as_f64()) { + style.push_str(&format!(" font-size: calc(var(--mfs, 20px) * {sz:.2});")); + } + if let Some(g) = fx_s("glow") { + style.push_str(&format!(" text-shadow: 0 0 6px {g}, 0 0 12px {g};")); + } + if long { + style.push_str(&format!(" --piece-ch: {pw}ch;")); + if shown_n > 1 { + class.push_str(" open"); + } + } + let (h1, h2, h3, h4) = (hit.clone(), hit.clone(), hit.clone(), hit.clone()); + // the hover line: the title, the text's kind and its words' types (kinds.rs) + let words = anend_core::kinds::describe_words(&hit.text); + let t2 = if words.is_empty() { + title.clone() + } else { + format!("{title} · {} · {words}", anend_core::kinds::detect(&hit.text)) + }; + let mut hover = m.hover; + let mut hover_text = m.hover_text; + // the words' types strip shows a long text's first piece, not all of it + let ht = if long { + anend_core::pieces::pieces(&hit.text, pw, pl)[0].to_string() + } else { + hit.text.clone() + }; + let tagged = ui.prefs.read().word_types; + // the tooltip has the word types on a line of their own + let tip = if words.is_empty() { + title.clone() + } else { + format!("{title}\n{} · {words}", anend_core::kinds::detect(&hit.text)) + }; + rsx! { + div { + class: "{class}", + style: "{style}", + role: "listitem", + "data-key": "{hit.key}", + tabindex: "0", + title: "{tip}", + onmouseenter: move |_| { + hover.set(t2.clone()); + hover_text.set(ht.clone()); + }, + onclick: move |e: MouseEvent| { + let md = e.modifiers(); + if (md.ctrl() || md.meta()) && md.shift() { + let mut p = ui.picks.write(); + p.candidate = None; + p.list = Some(h1.clone()); + drop(p); + ui.say(format!("list: {}", h1.text)); + } else if md.ctrl() || md.meta() { + ui.picks.write().candidate = Some(h1.clone()); + ui.say(format!("candidate: {}", h1.text)); + } else if md.shift() || md.alt() { + let mut p = ui.picks.write(); + if let Some(i) = p.selected.iter().position(|x| x.key == h1.key) { + p.selected.remove(i); + } else { + p.selected.push(h1.clone()); + } + } else { + ui.set_bar(&h1.text); + ui.focus_bar(); + } + }, + ondoubleclick: move |_| ui.set_bar(&h2.key), + onauxclick: { + let h = hit.clone(); + move |e: PointerEvent| { + // the middle button opens a note in the editor + if e.trigger_button() == Some(dioxus::html::input_data::MouseButton::Auxiliary) && h.note { + let mut o = ui.open_note; + o.set(Some(h.key.clone())); + crate::shell::go(ui, View::Notes); + } + } + }, + onkeydown: move |e: KeyboardEvent| { + if e.key() == Key::Enter { + ui.set_bar(&h4.text); + ui.focus_bar(); + } + }, + oncontextmenu: move |e: MouseEvent| { + e.prevent_default(); + if e.modifiers().ctrl() { + // weum: gsearch ⌊√(s·r)⌋ in the current mode + let me = gem::Measure::of(&h3.text); + envale(ui, api.clone(), m, me.triangle(), ui.mode()); + } else { + let p = e.client_coordinates(); + ui.menu.set(Some(Menu { hit: h3.clone(), x: p.x, y: p.y })); + } + }, + if long { + div { class: "piece", style: "{under_style}", + if tagged { TaggedText { text: shown_text.clone(), labels: true, ruby: true } } else { "{shown_text}" } + } + div { class: "pieces-more", + span { class: "dim", {format!("{} of {} pieces · {} KB", shown_n, n_pieces, hit.text.len().div_ceil(1000))} } + if shown_n < n_pieces { + button { class: "plain", title: "the next pieces", + onclick: move |e| { e.stop_propagation(); shown.set((shown_n + 4).min(n_pieces)); }, "more" } + button { class: "plain", title: "every piece (a long text takes a while to lay out)", + onclick: move |e| { e.stop_propagation(); shown.set(n_pieces); }, "all" } + } + if shown_n > 1 { + button { class: "plain", title: "back to the first piece", + onclick: move |e| { e.stop_propagation(); shown.set(1); }, "less" } + } + } + } else if tagged { TaggedText { text: hit.text.clone(), labels: true, ruby: true } } else { "{hit.text}" } + if let Some(l) = label { + span { class: "fx-label", "{l}" } + } + } + } +} + +/// each class shown, its colour, and how many texts it has here +type Legend = Vec<(String, String, usize)>; + +/// a classifier's tints as each key's colour (its class's, fainter when less sure; grey +/// when it's in none) and the legend: each class, its colour, how many texts it has here +fn tint_map(v: Option<&serde_json::Value>) -> (std::collections::HashMap<String, String>, Legend) { + let mut map = std::collections::HashMap::new(); + let Some(v) = v else { return (map, vec![]) }; + let names: Vec<String> = v["classes"] + .as_array() + .into_iter() + .flatten() + .filter_map(|c| c.as_str().map(str::to_string)) + .collect(); + let palette: Vec<String> = v["palette"] + .as_array() + .into_iter() + .flatten() + .filter_map(|c| c.as_str().map(str::to_string)) + .collect(); + let mut counts = vec![0usize; names.len() + 1]; + for t in v["tints"].as_array().into_iter().flatten() { + let Some(key) = t["key"].as_str() else { continue }; + let strength = t["strength"].as_f64().unwrap_or(0.0).clamp(0.0, 1.0); + let colour = match t["class"].as_u64().map(|c| c as usize) { + Some(c) if c < palette.len() => { + counts[c] += 1; + format!( + "color-mix(in srgb, {} {:.0}%, transparent)", + palette[c], + 35.0 + 65.0 * strength + ) + } + _ => { + counts[names.len()] += 1; + "#6b6461".to_string() + } + }; + map.insert(key.to_string(), colour); + } + let mut legend: Vec<(String, String, usize)> = names + .iter() + .zip(&palette) + .zip(&counts) + .filter(|(_, k)| **k > 0) + .map(|((n, c), k)| (n.clone(), c.clone(), *k)) + .collect(); + if counts[names.len()] > 0 { + legend.push(("unsure".into(), "#6b6461".into(), counts[names.len()])); + } + (map, legend) +} + +/// the classifier colouring the memory view, picked in the strip, and its search mode +#[component] +fn TintPick() -> Element { + let ui = ui(); + let api = api(); + let p = ui.prefs.read().clone(); + let models = use_resource(move || { + let api = api.clone(); + let _ = (ui.changed)(); + async move { api.models().await.unwrap_or_default() } + }); + let trained: Vec<String> = models + .read() + .clone() + .unwrap_or_default() + .into_iter() + .filter(|m| m.trained) + .map(|m| m.name) + .collect(); + if trained.is_empty() && p.tint.is_empty() { + return rsx! {}; + } + rsx! { + span { class: "toggles tintpick", + span { class: "icon-l", title: "colour the texts by a classifier's classes", Icon { name: "palette" } } + select { + "aria-label": "colour by a classifier", + title: "colour the texts by a classifier's classes", + onchange: move |e| { let v = e.value(); set_pref(ui, |p| { p.tint = v; if p.tint.is_empty() { p.cls_search = false; } }) }, + option { value: "", selected: p.tint.is_empty(), "no colours" } + for n in trained { + option { key: "{n}", value: "{n}", selected: p.tint == n, "{n}" } + } + } + if !p.tint.is_empty() { + TChip { label: format!("search with {}: a class's name finds its texts, any other text the texts like it · C", p.tint), icon: "classifier", on: p.cls_search, onclick: move |_| set_pref(ui, |p| p.cls_search = !p.cls_search) } + } + } + } +} + +/// the left edge: a circle per sum bucket, sized by how many texts it holds +#[component] +fn Buckets() -> Element { + let ui = ui(); + let api = api(); + let m = use_context::<Mem>(); + let mode = ui.prefs.read().mode; + let counts = use_resource(move || { + let api = api.clone(); + let _ = (ui.changed)(); + let mode = ui.prefs.read().mode; + async move { + api.bucket_counts(if mode == Mode::Frequency { Mode::Ordinal } else { mode }) + .await + .unwrap_or_default() + } + }); + let all: Vec<BucketCount> = counts.read().clone().unwrap_or_default(); + let max = all.iter().map(|b| b.count).max().unwrap_or(1).max(1) as f64; + let shown_mode = if mode == Mode::Frequency { Mode::Ordinal } else { mode }; + let on = (m.header)().and_then(|h| h.n); + let api2 = use_context::<Api>(); + rsx! { + nav { class: "buckets", "aria-label": "sum buckets", + div { class: "line" } + for b in all.into_iter().take(4000) { + div { + key: "{b.sum}", + class: if on == Some(b.sum as u64) { "b on" } else { "b" }, + style: "--r: {2.0 + 6.0 * (b.count as f64 / max).sqrt():.1}px;", + title: format!("{} {} · {} text{}", shown_mode.name(), b.sum, b.count, if b.count == 1 { "" } else { "s" }), + onclick: { + let api = api2.clone(); + move |_| envale(ui, api.clone(), m, b.sum.max(0) as u64, shown_mode) + }, + span { class: "dot" } + "{b.sum}" + } + } + } + } +} + +/// the strip over the bar: the sidecar (the bar's sums) and the toggles +#[component] +pub fn MemoryStrip() -> Element { + let ui = ui(); + let measure = (ui.measure)(); + let p = ui.prefs.read().clone(); + rsx! { + if let Some(me) = measure { + span { class: "sidecar", "aria-label": "the bar's sums", + "(" + for (i , (v , md)) in [(me.ordinal, Mode::Ordinal), (me.reversed, Mode::Reversed)].into_iter().enumerate() { + if i > 0 { ", " } + span { + class: if p.mode == md { "num on" } else { "num" }, + title: format!("gsearch {} {v} ({})", md.name(), if i == 0 { "←" } else { "→" }), + onclick: move |_| { + // as ← and → do + let key = if md == Mode::Ordinal { "ArrowLeft" } else { "ArrowRight" }; + let h = ui.keys.peek().iter().find(|(w, _)| *w == View::Memory).map(|(_, h)| *h); + if let Some(h) = h { + h.call(KeyPress { key: key.into(), code: String::new(), ctrl: false, shift: false, alt: false, bar: false, typing: false, text: String::new(), action: Some(if md == Mode::Ordinal { Action::SideOrdinal } else { Action::SideReversed }) }); + } + }, + "{v}" + } + } + ")" + span { class: "extra", title: "the byte sum (bytes 1–256)", "· b {me.bytes}" } + if p.letters { + span { class: "letters", title: "the letters (frequency); L hides them", "{gem::letters(&me.frequency)}" } + } + } + } + span { class: "toggles", role: "group", "aria-label": "mode", + for md in Mode::ALL { + TChip { + key: "{md.name()}", + label: format!("{} · {}", md.name(), match md { Mode::Ordinal => "O", Mode::Reversed => "R toggles", Mode::Frequency => "F" }), + letter: md.letter(), + on: p.mode == md, + onclick: move |_| set_mode(ui, md), + } + } + } + span { class: "toggles", + TChip { label: "gsearch text: by its sum, not its words · G", icon: "search", on: p.gsearch_text, onclick: move |_| set_pref(ui, |p| p.gsearch_text = !p.gsearch_text) } + TChip { label: "saturate: remember what's searched · S", icon: "bolt", on: p.saturate, onclick: move |_| set_pref(ui, |p| p.saturate = !p.saturate) } + TChip { label: "letters in the sidecar · L", letter: "abc", on: p.letters, onclick: move |_| set_pref(ui, |p| p.letters = !p.letters) } + TChip { label: format!("word types: label every word (noun, verb, name, number…) · {}", ui.key_of(Action::WordTypes)), letter: "n·v", on: p.word_types, onclick: move |_| set_pref(ui, |p| p.word_types = !p.word_types) } + TChip { label: format!("white: dark texts on white · {}", ui.key_of(Action::WhiteMode)), icon: "sun", on: p.white, onclick: move |_| set_pref(ui, |p| p.white = !p.white) } + } + TintPick {} + span { class: "toggles filter-square", + TChip { + label: if p.filter.active() { "the search filter (on): kinds, word types, classes, verdicts, bias".to_string() } else { "the search filter: kinds, word types, classes, verdicts, bias".to_string() }, + icon: "filter", + on: p.filter_open || p.filter.active(), + onclick: move |_| set_pref(ui, |p| p.filter_open = !p.filter_open), + } + } + } +} diff --git a/app/src/views/mod.rs b/app/src/views/mod.rs new file mode 100644 index 00000000..c196e790 --- /dev/null +++ b/app/src/views/mod.rs @@ -0,0 +1,137 @@ +//! The views. Every view stays mounted (the space keeps its scene, each view its page and +//! scroll) and loads when first shown; only the open one is visible. + +pub mod classifiers; +pub mod clsmore; +pub mod flt; +pub mod forge; +pub mod hubui; +pub mod judge; +pub mod lists; +pub mod memory; +pub mod models; +pub mod notes; +pub mod pictures; +pub mod pipes; +pub mod reader; +pub mod scode; +pub mod settings; +pub mod space; +pub mod specs; +pub mod stats; +pub mod tags; +pub mod tagsets; +pub mod taxonomy; + +use dioxus::prelude::*; + +use crate::ui::*; + +#[component] +pub fn ViewHost(view: View) -> Element { + let ui = ui(); + let open = (ui.view)() == view; + // a view is built the first time it's shown, then kept + let mut seen = use_signal(|| false); + if open && !*seen.peek() { + seen.set(true); + } + if !seen() { + return rsx! {}; + } + rsx! { + section { + class: "view {view.name()}", + hidden: !open, + "aria-label": "{view.name()}", + match view { + View::Memory => rsx! { memory::Memory {} }, + View::Space => rsx! { space::Space {} }, + View::Lists => rsx! { lists::Lists {} }, + View::Reader => rsx! { reader::Reader {} }, + View::Notes => rsx! { notes::Notes {} }, + View::Tags => rsx! { tags::Tags {} }, + View::Stats => rsx! { stats::Stats {} }, + View::Models => rsx! { classifiers::Models {} }, + View::Filters => rsx! { models::Filters {} }, + } + } + } +} + +/// what a view adds at the command bar's right end: the memory view's and the space's sums +/// and toggles, the other views' counts and hints +#[component] +pub fn Side(view: View) -> Element { + let ui = ui(); + match view { + View::Memory => rsx! { memory::MemoryStrip {} }, + View::Space => rsx! { space::SpaceStrip {} }, + _ => { + let note = ui.side.read().get(&view).cloned().unwrap_or_default(); + rsx! { span { class: "sidenote", "{note}" } } + } + } +} + +/// registers a view's key handler with the shell +pub fn use_keys(view: View, f: impl FnMut(KeyPress) -> bool + 'static) { + let mut ui = ui(); + let cb = use_callback(f); + use_hook(move || { + ui.keys.write().push((view, cb)); + }); +} + +/// a toggle as small as an icon or a letter; its name and key in the tip +#[component] +pub fn TChip( + label: String, + #[props(default)] icon: String, + #[props(default)] letter: String, + on: bool, + onclick: EventHandler<()>, +) -> Element { + rsx! { + button { + class: if on { "tchip on tip-up tip-left" } else { "tchip tip-up tip-left" }, + "data-tip": "{label}", + "aria-label": "{label}", + "aria-pressed": "{on}", + onclick: move |_| onclick.call(()), + if !icon.is_empty() { + Icon { name: icon.clone() } + } else { + "{letter}" + } + } + } +} + +/// a section that folds, remembered by name +#[component] +pub fn Fold(name: String, title: String, children: Element) -> Element { + let ui = ui(); + let folded = ui.prefs.read().folded(&name); + let n = name.clone(); + rsx! { + div { class: if folded { "section folded" } else { "section" }, + button { + class: "shead", + "aria-expanded": "{!folded}", + onclick: move |_| { + crate::shell::set_pref(ui, |p| { + if !p.collapsed.remove(&n) { + p.collapsed.insert(n.clone()); + } + }) + }, + Icon { name: "chevron-right", class: "chev" } + "{title}" + } + if !folded { + div { class: "body", {children} } + } + } + } +} diff --git a/app/src/views/models.rs b/app/src/views/models.rs new file mode 100644 index 00000000..fc1759e5 --- /dev/null +++ b/app/src/views/models.rs @@ -0,0 +1,163 @@ +//! Filters (the models view is `classifiers.rs`). +//! +//! **Filters** run the query model (`entries.query`): words, a sum range, a time range, a +//! tag and a kind, intersected. Filters are kept in the save's settings by name. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use crate::backend::{EntryQuery, Hit}; +use crate::ui::*; +use crate::views::use_keys; + +#[component] +pub fn Filters() -> Element { + let ui = ui(); + let api = api(); + let mut q = use_signal(EntryQuery::default); + let mut since = use_signal(String::new); + let mut until = use_signal(String::new); + let mut name = use_signal(String::new); + let mut form = use_signal(|| 0u64); + let mut found: Signal<Option<(u64, Vec<Hit>)>> = use_signal(|| None); + let api_s = api.clone(); + let saved = use_resource(move || { + let api = api_s.clone(); + let _ = (ui.changed)(); + async move { + let raw = api.setting("filters").await.ok().flatten().unwrap_or_default(); + serde_json::from_str::<Vec<(String, Value)>>(&raw).unwrap_or_default() + } + }); + let run = { + let api = api.clone(); + move || { + let api = api.clone(); + let mut query = q.peek().clone(); + let day = |d: &str, end: bool| { + (!d.is_empty()).then(|| format!("{d}T{}", if end { "23:59:59Z" } else { "00:00:00Z" })) + }; + query.since = + day(&since.peek(), false).or_else(|| (!until.peek().is_empty()).then(|| "1970-01-01T00:00:00Z".into())); + query.until = + day(&until.peek(), true).or_else(|| query.since.as_ref().map(|_| "9999-12-31T23:59:59Z".into())); + query.limit = 300; + dioxus::dioxus_core::spawn_forever(async move { + match api.query(&query).await { + Ok(r) => found.set(Some(r)), + Err(e) => ui.fail(e), + } + }); + } + }; + { + let run = run.clone(); + use_keys(View::Filters, move |k: KeyPress| { + if !(k.bar && k.key == "Enter") { + return false; + } + // a sum (79) or a range (70-90), else words + let t = k.text.trim().to_string(); + let range: Option<(i64, i64)> = match t.split_once('-') { + Some((a, b)) => a.trim().parse().ok().zip(b.trim().parse().ok()), + None => t.parse().ok().map(|n| (n, n)), + }; + let mut w = q.write(); + match range { + Some((a, b)) => { + w.from = Some(a.min(b)); + w.to = Some(a.max(b)); + if w.bucket.is_empty() { + w.bucket = "ordinal".into(); + } + } + None => w.words = t, + } + drop(w); + form += 1; + run(); + true + }); + } + let cur = q(); + let saved_list = saved.read().clone().unwrap_or_default(); + let api_save = api.clone(); + let run2 = run.clone(); + rsx! { + div { class: "page", + div { class: "row", h2 { "filters and pipes" } span { class: "dim small", "find texts by words, sums, time, tags and kind; below, by what classifiers say, in groups, and pipes: a filter with effects shown in the views" } } + // remade when a kept filter or the bar fills it (its inputs aren't bound while typing) + for g in [form()] { + div { key: "{g}", class: "card", + div { class: "cond", Icon { name: "search" } "words" + input { r#type: "text", initial_value: "{cur.words}", placeholder: "any", oninput: move |e| q.write().words = e.value() } } + div { class: "cond", Icon { name: "hash" } "sum" + select { value: "{cur.bucket}", onchange: move |e| q.write().bucket = e.value(), + option { value: "", "any" } option { value: "ordinal", "ordinal" } option { value: "reversed", "reversed" } } + "from" input { r#type: "number", initial_value: cur.from.map(|v| v.to_string()).unwrap_or_default(), oninput: move |e| q.write().from = e.value().parse().ok() } + "to" input { r#type: "number", initial_value: cur.to.map(|v| v.to_string()).unwrap_or_default(), oninput: move |e| q.write().to = e.value().parse().ok() } } + div { class: "cond", Icon { name: "sort" } "written between" + input { r#type: "date", initial_value: "{since}", oninput: move |e| since.set(e.value()) } "and" + input { r#type: "date", initial_value: "{until}", oninput: move |e| until.set(e.value()) } } + div { class: "cond", Icon { name: "tag" } "tag" + input { r#type: "text", initial_value: cur.tag.clone().unwrap_or_default(), placeholder: "any", oninput: move |e| { let v = e.value(); q.write().tag = (!v.is_empty()).then_some(v); } } } + div { class: "cond", Icon { name: "filter" } "kind" + for (k , label) in [("", "everything"), ("memories", "texts"), ("notes", "notes")] { + button { key: "{k}", class: if cur.kind == k { "chip on" } else { "chip" }, onclick: move |_| q.write().kind = k.to_string(), "{label}" } + } } + div { class: "row", + button { class: "primary", onclick: { let run2 = run2.clone(); move |_| run2() }, Icon { name: "play" } "run" } + input { r#type: "text", placeholder: "a name to keep it", initial_value: "{name}", oninput: move |e| name.set(e.value()) } + button { disabled: name().trim().is_empty(), onclick: { let api_save = api_save.clone(); move |_| { + let api = api_save.clone(); + let mut all = saved.peek().clone().unwrap_or_default(); + let n = name.peek().trim().to_string(); + all.retain(|(x, _)| *x != n); + all.push((n.clone(), json!({ "q": serde_json::to_value(&*q.peek()).unwrap_or_default(), "since": since.peek().clone(), "until": until.peek().clone() }))); + dioxus::dioxus_core::spawn_forever(async move { + match api.set_setting("filters", &serde_json::to_string(&all).unwrap_or_default()).await { + Ok(()) => { ui.say(format!("kept “{n}”")); ui.touched(); } + Err(e) => ui.fail(e), + } + }); + } }, Icon { name: "save" } "keep" } + } + } + } + if !saved_list.is_empty() { + div { class: "row", + span { class: "dim", "kept:" } + for (n , v) in saved_list { + button { key: "{n}", class: "chip", onclick: { + let run = run.clone(); + move |_| { + if let Ok(query) = serde_json::from_value::<EntryQuery>(v["q"].clone()) { q.set(query); } + form += 1; + since.set(v["since"].as_str().unwrap_or("").to_string()); + until.set(v["until"].as_str().unwrap_or("").to_string()); + name.set(n.clone()); + run(); + } + }, "{n}" } + } + } + } + crate::views::flt::Builder {} + if let Some((total, hits)) = found() { + div { class: "card", + h3 { "{total} found" if total as usize > hits.len() { " (the first {hits.len()})" } } + div { class: "results", + for h in hits { + div { key: "{h.key}", class: "result", + span { class: "p", "{h.key}" } + span { class: "t", title: "{h.text}", if h.note { "✎ " } "{h.text}" } + button { class: "plain", "aria-label": "into the bar", "data-tip": "into the bar", + onclick: { let t = h.text.clone(); move |_| ui.set_bar(&t) }, Icon { name: "text" } } + } + } + } + } + } + } + } +} diff --git a/app/src/views/notes.rs b/app/src/views/notes.rs new file mode 100644 index 00000000..fd893303 --- /dev/null +++ b/app/src/views/notes.rs @@ -0,0 +1,1479 @@ +//! Notes: chronological (newest first) at the left, each with its date; long titles show +//! in full on hover. The editor at the right holds `# title` and markdown, its tags in a +//! box; Ctrl+S (or the save button) keeps it. The layout is a grid, so the editor takes +//! whatever room the window gives it. The bar narrows the list by words. + +use dioxus::prelude::*; + +use crate::backend::{Note, NoteQuery, NoteSummary}; +use crate::keys::Action; +use crate::shell::set_pref; +use crate::ui::*; +use crate::views::use_keys; + +fn when(iso: &str) -> String { + chrono::DateTime::parse_from_rfc3339(iso) + .map(|t| t.with_timezone(&chrono::Local).format("%d %b %Y, %H:%M").to_string()) + .unwrap_or_default() +} + +/// keeps the highlighting layer scrolled with the pad (once per page) +const PAD_JS: &str = r#" +// the colour layer's segments, kept by Rust (`highlight::Layer`): set them all, or +// replace a run of them; a last span keeps an empty last line's height +window.__anendHl = window.__anendHl || { + mk(html) { const s = document.createElement('span'); s.innerHTML = html; return s; }, + tail(h, end) { + let t = h.lastElementChild; + if (!t || !t.classList.contains('hl-end')) { t = document.createElement('span'); t.className = 'hl-end'; h.append(t); } + t.textContent = end ? ' ' : ''; + }, + set(htmls, end) { + const h = document.getElementById('note-hl'); + if (!h) return; + h.replaceChildren(...htmls.map((x) => this.mk(x))); + this.tail(h, end); + }, + patch(from, count, htmls, end) { + const h = document.getElementById('note-hl'); + if (!h) return; + const kids = h.children; + const before = kids[from + count] || null; + for (let i = 0; i < count && kids[from]; i++) kids[from].remove(); + for (const x of htmls) h.insertBefore(this.mk(x), before && before.isConnected ? before : h.lastElementChild); + this.tail(h, end); + }, +}; +if (!window.__anendPad) { + window.__anendPad = true; + document.addEventListener('scroll', (e) => { + const t = e.target; + if (t && t.id === 'note-pad') { + const h = document.getElementById('note-hl'); + if (h) { h.scrollTop = t.scrollTop; h.scrollLeft = t.scrollLeft; } + } + }, true); + // the pad's own undo: the desktop's web view has none for a text box, and a + // replacement put in by a click must come back out with Ctrl+Z too. A pause in typing + // ends a step; Ctrl+Z undoes, Ctrl+Shift+Z or Ctrl+Y redoes. + const stacks = new WeakMap(); + const st = (p) => { let s = stacks.get(p); if (!s) { s = { undo: [], redo: [], last: 0 }; stacks.set(p, s); } return s; }; + window.__anendPadSnap = (p, force) => { + const s = st(p); + const now = Date.now(); + if (force || now - s.last > 800 || !s.undo.length) s.undo.push({ v: p.value, a: p.selectionStart, b: p.selectionEnd }); + if (s.undo.length > 500) s.undo.shift(); + s.last = force ? 0 : now; + s.redo = []; + }; + document.addEventListener('beforeinput', (e) => { + const p = e.target; + if (p && p.id === 'note-pad' && !window.__anendPadReplaying) window.__anendPadSnap(p, false); + }, true); + document.addEventListener('keydown', (e) => { + const p = e.target; + if (!p || p.id !== 'note-pad' || !(e.ctrlKey || e.metaKey) || e.altKey) return; + const k = e.key.toLowerCase(); + const undo = k === 'z' && !e.shiftKey, redo = (k === 'z' && e.shiftKey) || k === 'y'; + if (!undo && !redo) return; + e.preventDefault(); + e.stopImmediatePropagation(); + const s = st(p); + const snap = (undo ? s.undo : s.redo).pop(); + if (!snap) return; + (undo ? s.redo : s.undo).push({ v: p.value, a: p.selectionStart, b: p.selectionEnd }); + p.value = snap.v; + p.setSelectionRange(snap.a, snap.b); + s.last = 0; + window.__anendPadReplaying = true; + p.dispatchEvent(new Event('input', { bubbles: true })); + window.__anendPadReplaying = false; + }, true); +} +"#; + +/// typing in segments (the user's approach for long texts, docs/format.md "Long texts"): +/// each change to the pad goes to Rust as the range it replaced and what went in +/// (UTF-16 units), so a key sends a few characters rather than the whole text. A pad +/// whose last value isn't known (just opened) sends its whole text once. +const PAD_SYNC_JS: &str = r#" +window.__anendPadSend = (m) => dioxus.send(m); +if (!window.__anendPadSync) { + window.__anendPadSync = true; + document.addEventListener('input', (e) => { + const p = e.target; + if (!p || p.id !== 'note-pad' || !window.__anendPadSend) return; + const v = p.value, prev = p.__prev; + p.__prev = v; + if (typeof prev !== 'string') { window.__anendPadSend({ full: v, caret: p.selectionStart }); return; } + const n = Math.min(prev.length, v.length); + let a = 0; + while (a < n && prev.charCodeAt(a) === v.charCodeAt(a)) a++; + let b = 0; + while (b < n - a && prev.charCodeAt(prev.length - 1 - b) === v.charCodeAt(v.length - 1 - b)) b++; + window.__anendPadSend({ at: a, del: prev.length - a - b, ins: v.slice(a, v.length - b), len: v.length, caret: p.selectionStart }); + }, true); + // s code: Ctrl+click goes to a word's definition; Tab takes the first completion + document.addEventListener('click', (e) => { + const p = e.target; + if (p && p.id === 'note-pad' && (e.ctrlKey || e.metaKey) && window.__anendPadSend) window.__anendPadSend({ goto: p.selectionStart }); + }, true); + document.addEventListener('keydown', (e) => { + const p = e.target; + const c = window.__anendCompl; + if (!p || p.id !== 'note-pad' || e.key !== 'Tab' || e.shiftKey || !c) return; + e.preventDefault(); + const a = p.selectionStart; + p.setRangeText(c, a, a, 'end'); + window.__anendCompl = null; + p.dispatchEvent(new Event('input', { bubbles: true })); + }, true); +} +await new Promise(() => {}); +"#; + +/// selects a span of the pad and scrolls it into view (go to definition, the outline) +fn pad_show(a: usize, b: usize) { + // the pad counts UTF-16 units; Rust's offsets are bytes + document::eval(&format!( + "const p = document.getElementById('note-pad'); if (p) {{ const enc = new TextEncoder(); const v = p.value; let a = 0, b = 0, n = 0; for (let i = 0; i < v.length; i++) {{ if (n === {a}) a = i; if (n === {b}) {{ b = i; break; }} n += enc.encode(v[i]).length; b = i + 1; }} p.focus(); p.setSelectionRange(a, b); const lh = parseFloat(getComputedStyle(p).lineHeight) || 20; const line = v.slice(0, a).split('\\n').length - 1; p.scrollTop = Math.max(0, line * lh - p.clientHeight / 3); }}" + )); +} + +/// the output a run wrote, as one line beside the code that wrote it (`> a b` writes +/// "\n a b"): its lines joined, at most 80 characters +fn inline_result(out: &str) -> String { + let s: Vec<&str> = out + .split('\n') + .map(|l| l.strip_prefix(' ').unwrap_or(l)) + .filter(|l| !l.is_empty()) + .collect(); + let s = s.join(" · "); + if s.chars().count() > 80 { + format!("{}…", s.chars().take(79).collect::<String>()) + } else { + s + } +} + +/// a change sent by `PAD_SYNC_JS`, applied to the text; false when it doesn't fit (the +/// pad's whole text is asked for then) +fn apply_delta(t: &mut String, m: &serde_json::Value) -> Delta { + if let Some(full) = m["full"].as_str() { + *t = full.to_string(); + return Delta::Whole; + } + match splice(t, m) { + Some(e) => Delta::Edit(e), + None => Delta::Lost, + } +} + +/// the notes view's colour layer: its segments, and whether it shows spelling flags +#[derive(Default)] +struct PadLayer { + layer: crate::highlight::Layer, + flagged: bool, +} + +/// what a pad change did to the text +enum Delta { + /// the whole text came + Whole, + /// bytes `a..b` were replaced by `ins` + Edit((usize, usize, String)), + /// it didn't fit: the pad's whole text is asked for + Lost, +} + +fn splice(t: &mut String, m: &serde_json::Value) -> Option<(usize, usize, String)> { + let (Some(at), Some(del), Some(ins), Some(len)) = ( + m["at"].as_u64(), + m["del"].as_u64(), + m["ins"].as_str(), + m["len"].as_u64(), + ) else { + return None; + }; + // UTF-16 offsets to byte offsets + let byte_of = |t: &str, u: usize| -> Option<usize> { + let mut units = 0; + for (i, c) in t.char_indices() { + if units == u { + return Some(i); + } + units += c.len_utf16(); + if units > u { + return None; + } + } + (units == u).then_some(t.len()) + }; + let a = byte_of(t, at as usize)?; + let b = byte_of(&t[a..], del as usize).map(|x| a + x)?; + t.replace_range(a..b, ins); + // the length check: a pad changed without an input event would drift + (t.encode_utf16().count() == len as usize).then(|| (a, b, ins.to_string())) +} + +/// puts a replacement in the pad as one undo step of its own (Ctrl+Z takes it back); +/// `from`..`to` in UTF-16 units +fn replace_in_pad(from: usize, to: usize, with: &str) { + let js = format!( + r#"(() => {{ + const p = document.getElementById('note-pad'); + if (!p) return; + p.focus(); + if (window.__anendPadSnap) window.__anendPadSnap(p, true); + p.setRangeText({with}, {from}, {to}, 'end'); + window.__anendPadReplaying = true; + p.dispatchEvent(new Event('input', {{ bubbles: true }})); + window.__anendPadReplaying = false; +}})();"#, + with = serde_json::to_string(with).unwrap_or_default() + ); + document::eval(&js); +} + +/// a flagged word the pointer clicked, and where +#[derive(Clone, PartialEq)] +struct Pick { + flag: serde_json::Value, + x: f64, + y: f64, +} + +/// a note longer than this (bytes) is typed without the spelling check (which reads the +/// whole text), unless the save's `limits.grammar_check_bytes` says otherwise; the +/// colours stay on at any length, as the layer is coloured in segments +const BIG: usize = 200_000; + +fn split_tags(t: &str) -> Vec<String> { + t.split(',') + .map(|x| x.trim().to_string()) + .filter(|x| !x.is_empty()) + .collect() +} + +#[component] +pub fn Notes() -> Element { + let ui = ui(); + let api = api(); + let mut q = use_signal(String::new); + let mut open: Signal<Option<Note>> = use_signal(|| None); + let mut text = use_signal(String::new); + let mut tags: Signal<Vec<String>> = use_signal(Vec::new); + let mut dirty = use_signal(|| false); + let mut armed = use_signal(|| false); + // notes picked with Shift+click, to tag or delete together + let mut picked: Signal<Vec<String>> = use_signal(Vec::new); + let mut seq = use_signal(|| 0u64); + let mut reading = use_signal(|| false); + let mut judging = use_signal(|| false); + // an s program's last run: its output and error + let mut ran: Signal<Option<serde_json::Value>> = use_signal(|| None); + // the code editor (`views::scode`): the save's s programs (title, key), the words that + // complete what's being typed, a go-to asked for (a place in the text), the outline + // shown, and a stepped run (how many steps in, its seed) with what it shows + let mut progs: Signal<Vec<(String, String)>> = use_signal(Vec::new); + let mut compl: Signal<(String, Vec<String>)> = use_signal(|| (String::new(), vec![])); + let mut goto_req: Signal<Option<usize>> = use_signal(|| None); + let mut outline_open = use_signal(|| false); + let mut dbg: Signal<Option<(u64, u64)>> = use_signal(|| None); + let mut snap: Signal<Option<serde_json::Value>> = use_signal(|| None); + let mut tag_gen = use_signal(|| 0u64); + let mut tag_draft = use_signal(String::new); + // the spelling check: the flags for the text they were made for + let mut flags: Signal<(String, Vec<serde_json::Value>)> = use_signal(|| (String::new(), vec![])); + let mut check_gen = use_signal(|| 0u64); + let mut report: Signal<Option<serde_json::Value>> = use_signal(|| None); + let mut pick: Signal<Option<Pick>> = use_signal(|| None); + // how long a note the spelling check reads (the save's limit) + let mut big_at = use_signal(|| BIG); + { + let api = api.clone(); + use_hook(move || { + spawn(async move { + if let Ok(v) = api.call("limits.list", serde_json::json!({})).await { + let n = v + .as_array() + .into_iter() + .flatten() + .find(|l| l["name"] == "limits.grammar_check_bytes") + .and_then(|l| l["value"].as_u64()); + if let Some(n) = n { + big_at.set(n as usize); + } + } + }); + }); + } + // the colour layer, kept in typing segments (`highlight::Layer`); `layer_gen` asks for + // it whole (a note opened, a text put in, the colours or the flags changed) + let layer: std::rc::Rc<std::cell::RefCell<PadLayer>> = use_hook(Default::default); + let mut layer_gen = use_signal(|| 0u64); + use_hook(|| { + document::eval(PAD_JS); + }); + // the pad's changes, as deltas (`PAD_SYNC_JS`) + let layer_d = layer.clone(); + use_hook(move || { + let layer = layer_d.clone(); + spawn(async move { + let mut ev = document::eval(PAD_SYNC_JS); + while let Ok(m) = ev.recv::<serde_json::Value>().await { + // s code: a Ctrl+click asks for the word's definition + if let Some(at) = m["goto"].as_u64() { + goto_req.set(Some(at as usize)); + continue; + } + let d = text.with_mut(|t| apply_delta(t, &m)); + match d { + Delta::Lost => { + // out of step: the whole text once, then deltas again + document::eval( + "const p = document.getElementById('note-pad'); if (p) { p.__prev = undefined; p.dispatchEvent(new Event('input', { bubbles: true })); }", + ); + continue; + } + Delta::Whole => layer_gen += 1, + Delta::Edit((a, b, ins)) => { + // only the segments around the edit are coloured again; a layer + // showing spelling flags (now stale) is made again whole + let colour = ui.prefs.peek().highlight; + let patched = { + let mut l = layer.borrow_mut(); + if l.flagged { + None + } else { + l.layer.edit(a, b, &ins, colour) + } + }; + match patched { + Some((from, went, html)) => { + let end = text.peek().ends_with('\n') || text.peek().is_empty(); + document::eval(&format!( + "window.__anendHl && window.__anendHl.patch({from}, {went}, {}, {end});", + serde_json::to_string(&html).unwrap_or_default() + )); + } + None => layer_gen += 1, + } + } + } + dirty.set(true); + pick.set(None); + // s code: the words that complete what's typed before the caret + if tags.peek().iter().any(|t| t == anend_core::ops::script::TAG) + && let Some(caret) = m["caret"].as_u64() + { + let t = text.peek(); + let prefix = crate::views::scode::prefix_at(&t, caret as usize).to_string(); + let titles: Vec<String> = progs.peek().iter().map(|p| p.0.clone()).collect(); + let mut words: Vec<String> = + anend_core::s::machine::COMMANDS.iter().map(|w| w.to_string()).collect(); + words.extend( + anend_core::s::lib::words() + .into_iter() + .flat_map(|(_, w)| w) + .map(|w| w.to_string()), + ); + words.extend(titles.iter().cloned()); + let body_at = crate::views::scode::body_offset(&t); + words.extend( + crate::views::scode::outline(&t[body_at..], &titles) + .into_iter() + .map(|i| i.name), + ); + let c = crate::views::scode::complete(&prefix, &words, 8); + let rest = c.first().map(|w| w[prefix.len()..].to_string()); + document::eval(&format!( + "window.__anendCompl = {};", + serde_json::to_string(&rest).unwrap_or("null".into()) + )); + compl.set((prefix, c)); + } else if !compl.peek().1.is_empty() { + compl.set((String::new(), vec![])); + document::eval("window.__anendCompl = null;"); + } + } + }); + }); + let api_r = api.clone(); + let list = use_resource(move || { + let api = api_r.clone(); + let _ = (ui.changed)(); + let query = NoteQuery { + q: q(), + ..Default::default() + }; + async move { api.notes(&query).await } + }); + let save = { + let api = api.clone(); + move || { + let api = api.clone(); + let mut note = open.peek().clone().unwrap_or_default(); + note.tags = tags.peek().clone(); + let t = text.peek().clone(); + if anend_core::note::split(&t).0.trim().is_empty() { + ui.fail("a note needs a '# title' line before it can be saved"); + return; + } + dioxus::dioxus_core::spawn_forever(async move { + match api.save_note(¬e, &t).await { + Ok(n) => { + open.set(Some(n)); + dirty.set(false); + ui.say("saved"); + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + } + }; + let mut new_note = move || { + open.set(Some(Note::default())); + text.set("# \n\n".into()); + seq += 1; + tags.set(Vec::new()); + dirty.set(false); + reading.set(false); + document::eval( + "setTimeout(() => { const p = document.getElementById('note-pad'); if (p) { p.focus(); p.setSelectionRange(2, 2); } }, 30);", + ); + }; + let save_k = save.clone(); + use_keys(View::Notes, move |k: KeyPress| { + if k.bar && k.key == "Enter" { + let t = k.text.trim().to_string(); + // Enter again on the same words opens the first note found + if t == *q.peek() + && let Some(first) = list + .peek() + .as_ref() + .and_then(|r| r.as_ref().ok()) + .and_then(|v| v.first().cloned()) + { + let mut o = ui.open_note; + o.set(Some(first.key)); + document::eval("document.activeElement && document.activeElement.blur()"); + return true; + } + q.set(t); + return true; + } + match k.action { + Some(Action::Save) => save_k(), + Some(Action::NewNote) => new_note(), + Some(Action::ToggleRead) => { + reading.set(!reading()); + seq += 1; + } + Some(Action::ToggleList) => set_pref(ui, |p| p.hide_list = !p.hide_list), + Some(Action::NoteClassifiers) => judging.set(!judging()), + _ => return false, + } + true + }); + // leaving the view keeps a titled note's changes, as the Bevy app did + { + let save = save.clone(); + use_effect(move || { + let v = (ui.view)(); + if v != View::Notes + && *dirty.peek() + && open.peek().is_some() + && !anend_core::note::split(&text.peek()).0.trim().is_empty() + { + save(); + } + }); + } + // closing the window keeps a titled note's changes too (desktop) + { + let api = api.clone(); + use_effect(move || { + if (ui.closing)() != 1 { + return; + } + let t = text.peek().clone(); + if !*dirty.peek() || open.peek().is_none() || anend_core::note::split(&t).0.trim().is_empty() { + return; + } + let mut c = ui.closing; + c.set(2); + let mut note = open.peek().clone().unwrap_or_default(); + note.tags = tags.peek().clone(); + let api = api.clone(); + dioxus::dioxus_core::spawn_forever(async move { + let _ = api.save_note(¬e, &t).await; + #[cfg(not(target_arch = "wasm32"))] + std::process::exit(0); + }); + }); + } + // a note another view asked to open (the reader's edit) + { + let api = api.clone(); + use_effect(move || { + let Some(key) = (ui.open_note)() else { return }; + let mut asked = ui.open_note; + asked.set(None); + let api = api.clone(); + spawn(async move { + match api.note(&key).await { + Ok(note) => { + text.set( + note.source + .clone() + .unwrap_or_else(|| anend_core::note::compose(¬e.title, ¬e.markdown)), + ); + tags.set(note.tags.clone()); + open.set(Some(note)); + reading.set(false); + seq += 1; + dirty.set(false); + } + Err(e) => ui.fail(e), + } + }); + }); + } + // the bar's right end: how many notes there are, or match + use_effect(move || { + let n = list + .read() + .as_ref() + .and_then(|r| r.as_ref().ok()) + .map(|v| v.len()) + .unwrap_or(0); + let words = q(); + ui.side_note( + View::Notes, + if words.is_empty() { + format!("{n} note{}", if n == 1 { "" } else { "s" }) + } else { + format!("{n} with “{words}” · Enter again to narrow") + }, + ); + }); + // checked a beat after typing stops + { + let api = api.clone(); + use_effect(move || { + let on = ui.prefs.read().check_spelling; + if !on || text.read().len() > big_at() { + return; + } + let t = text(); + if t.trim().is_empty() { + return; + } + let g = *check_gen.peek() + 1; + check_gen.set(g); + let key = open.peek().as_ref().map(|n| n.key.clone()).unwrap_or_default(); + let api = api.clone(); + spawn(async move { + crate::ui::sleep_ms(700).await; + if *check_gen.peek() != g { + return; + } + match api + .call("grammar.check", serde_json::json!({ "text": t, "exclude": key })) + .await + { + Ok(r) => { + if *check_gen.peek() == g { + let fl = r["flags"].as_array().cloned().unwrap_or_default(); + flags.set((t, fl)); + report.set(Some(r["report"].clone())); + } + } + // a hub from before the check: say nothing, show nothing + Err(_) => flags.set((String::new(), vec![])), + } + }); + }); + } + let notes: Vec<NoteSummary> = match &*list.read() { + Some(Ok(v)) => v.clone(), + _ => vec![], + }; + let cur_key = open().map(|n| n.key).unwrap_or_default(); + // read mode shows the note as saved (its replacements and views put in) until it's + // edited + let read_text = match open() { + Some(n) if !dirty() && !n.key.is_empty() => { + anend_core::note::compose(&n.title, n.rendered.as_deref().unwrap_or(&n.markdown)) + } + // only read mode shows it: no copy of a long text on every key + _ if reading() => text(), + _ => String::new(), + }; + let shown_title = anend_core::note::split(&text.read()).0; + let (hide_list, list_right, colour) = { + let p = ui.prefs.read(); + (p.hide_list, p.list_right, p.highlight) + }; + // with no note open the list is all there is: it shows whatever was chosen (the choice + // to slide it away holds while a note is open) + let hide_list = hide_list && open().is_some(); + // a note tagged `s` is s code (docs/s.md): right-aligned, coloured by s's word + // classes, run with ▶; the spelling check leaves it alone + let code = tags.read().iter().any(|t| t == anend_core::ops::script::TAG); + // the code editor: the programs (for go to definition and completion), when it's code + { + let api = api.clone(); + use_effect(use_reactive!(|code| { + if !code { + return; + } + let api = api.clone(); + spawn(async move { + if let Ok(v) = api.call("s.programs", serde_json::json!({})).await { + progs.set( + v.as_array() + .into_iter() + .flatten() + .map(|p| { + ( + p["title"].as_str().unwrap_or("").to_string(), + p["key"].as_str().unwrap_or("").to_string(), + ) + }) + .collect(), + ); + } + }); + })); + } + // the stepped run: run again to the step asked for; the token it stops before is + // marked in the pad when it's the program's own + { + let api = api.clone(); + let layer = layer.clone(); + use_effect(move || { + let state = dbg(); + let layer = layer.clone(); + let Some((n, seed)) = state else { + snap.set(None); + let had = layer.borrow().layer.at.is_some(); + if had { + layer.borrow_mut().layer.at = None; + layer_gen += 1; + } + return; + }; + let whole = text.peek().clone(); + let body_at = crate::views::scode::body_offset(&whole); + let body = whole[body_at..].to_string(); + let api = api.clone(); + spawn(async move { + match api + .call("s.debug", serde_json::json!({ "code": body, "steps": n, "seed": seed })) + .await + { + Ok(r) => { + let at = (r["main"] == true) + .then(|| { + Some( + body_at + r["at"]["start"].as_u64()? as usize + ..body_at + r["at"]["end"].as_u64()? as usize, + ) + }) + .flatten(); + if *text.peek() == whole { + layer.borrow_mut().layer.at = at; + layer_gen += 1; + } + snap.set(Some(r)); + } + Err(e) => ui.fail(e), + } + }); + }); + } + // a Ctrl+click: the word's definition here, else the program it names + { + let api = api.clone(); + use_effect(move || { + let Some(at) = goto_req() else { return }; + goto_req.set(None); + let t = text.peek().clone(); + let Some((_, _, w)) = crate::views::scode::word_at(&t, at) else { + return; + }; + let name = crate::views::scode::stem(w).to_string(); + let titles: Vec<String> = progs.peek().iter().map(|p| p.0.clone()).collect(); + let body_at = crate::views::scode::body_offset(&t); + let here = crate::views::scode::outline(&t[body_at..], &titles) + .into_iter() + .find(|i| i.name == name && i.kind != "call"); + if let Some(i) = here { + pad_show(body_at + i.at, body_at + i.at + i.name.len()); + return; + } + let Some((_, key)) = progs + .peek() + .iter() + .find(|p| p.0 == name || format!("{}.s", p.0) == name) + .cloned() + else { + ui.say(format!( + "“{name}” isn't defined in this program, nor a program of the save" + )); + return; + }; + let api = api.clone(); + spawn(async move { + match api.note(&key).await { + Ok(note) => { + text.set( + note.source + .clone() + .unwrap_or_else(|| anend_core::note::compose(¬e.title, ¬e.markdown)), + ); + tags.set(note.tags.clone()); + open.set(Some(note)); + seq += 1; + dirty.set(false); + armed.set(false); + } + Err(e) => ui.fail(e), + } + }); + }); + } + let check = ui.prefs.read().check_spelling && !code; + let shown_flags: Vec<crate::highlight::Flag> = { + let (t, fl) = &*flags.read(); + if check && *t == *text.read() { + fl.iter() + .map(|f| { + let sug: Vec<String> = f["suggestions"] + .as_array() + .into_iter() + .flatten() + .map(|s| match s["text"].as_str().unwrap_or("") { + "" => "take it out".to_string(), + x => x.to_string(), + }) + .collect(); + crate::highlight::Flag { + start: f["start"].as_u64().unwrap_or(0) as usize, + end: f["end"].as_u64().unwrap_or(0) as usize, + kind: if f["kind"] == "spelling" { "spell" } else { "grammar" }, + title: format!("{} · click: {}", f["kind"].as_str().unwrap_or(""), sug.join(", ")), + } + }) + .collect() + } else { + vec![] + } + }; + // the colour layer, kept in typing segments by `layer` (made whole here when asked; + // each typed change patches only its segments, in the pad's delta loop). The spelling + // check still pauses on long notes. + let big = text.read().len() > big_at(); + // s code always has its layer (inline results and the stepped token live in it) + let layered = colour || !shown_flags.is_empty() || code; + { + let layer = layer.clone(); + let flags_now = shown_flags.clone(); + use_effect(use_reactive!(|layered, colour, flags_now, code| { + let _ = layer_gen(); + let mut l = layer.borrow_mut(); + l.layer.s = code; + if !layered { + l.layer = Default::default(); + l.flagged = false; + document::eval("window.__anendHl && window.__anendHl.set([], false);"); + return; + } + let t = text.peek(); + let html = l.layer.full(&t, colour, &flags_now); + l.flagged = !flags_now.is_empty(); + let end = t.ends_with('\n') || t.is_empty(); + document::eval(&format!( + "window.__anendHl && window.__anendHl.set({}, {end});", + serde_json::to_string(&html).unwrap_or_default() + )); + })); + } + let api_d = api.clone(); + let api_m = api.clone(); + let mut class = String::from("notes"); + if hide_list { + class.push_str(" no-list"); + } + if list_right { + class.push_str(" list-right"); + } + let unsaved = dirty(); + rsx! { + div { class: "{class}", + // slid away, the list waits off the edge and slides in while the pointer is + // near that edge (or on the list), as the Bevy app's `hide_list` + if hide_list { + div { class: "list-edge", "aria-hidden": "true" } + } + div { class: "card notelist", + button { class: "primary", "data-tip": "start a new note · {ui.key_of(Action::NewNote)}", onclick: move |_| new_note(), + Icon { name: "new" } "a new note" } + ManyNotes { picked, api: api_m.clone() } + ul { role: "listbox", "aria-label": "notes, newest first", "aria-multiselectable": "true", + if open().is_some_and(|n| n.key.is_empty()) { + li { class: "on", role: "option", {if shown_title.trim().is_empty() { "untitled".to_string() } else { shown_title.clone() }} if unsaved { " •" } span { class: "when", "not saved yet" } } + } + if notes.is_empty() { + li { class: "dim", "no notes" if !q().is_empty() { " with “{q}”" } } + } + for n in notes { + li { + key: "{n.key}", + class: match (n.key == cur_key, picked().contains(&n.key)) { (true, true) => "on picked", (true, false) => "on", (false, true) => "picked", _ => "" }, + title: "{n.title}", + role: "option", + "aria-selected": "{picked().contains(&n.key)}", + tabindex: "0", + onclick: { + let api = api.clone(); + let key = n.key.clone(); + move |e: MouseEvent| { + // Shift+click picks notes, several at once + if e.modifiers().shift() { + let mut p = picked.write(); + if let Some(i) = p.iter().position(|k| *k == key) { p.remove(i); } else { p.push(key.clone()); } + return; + } + picked.write().clear(); + let api = api.clone(); + let key = key.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.note(&key).await { + Ok(note) => { + // with replacements, the note as written + text.set(note.source.clone().unwrap_or_else(|| anend_core::note::compose(¬e.title, ¬e.markdown))); + tags.set(note.tags.clone()); + open.set(Some(note)); + seq += 1; + dirty.set(false); + armed.set(false); + } + Err(e) => ui.fail(e), + } + }); + } + }, + if n.key == cur_key { "{shown_title}" if unsaved { " •" } } else { "{n.title}" } + span { class: "when", "{when(&n.created)}" if !n.tags.is_empty() { {format!(" · {}", n.tags.join(", "))} } } + } + } + } + } + div { class: "card editor", + if let Some(note) = open() { + div { class: "head", + button { class: "plain", "data-tip": "slide the note list away / back · {ui.key_of(Action::ToggleList)}", "aria-label": "the note list", + onclick: move |_| set_pref(ui, |p| p.hide_list = !p.hide_list), Icon { name: "sidebar" } } + span { class: "title", title: "{shown_title}", "{shown_title}" if unsaved { span { class: "dim", " •" } } } + div { class: "tagchips", + for t in tags() { + button { key: "{t}", class: "chip", "data-tip": "take the tag off", + onclick: { let t = t.clone(); move |_| { tags.write().retain(|x| *x != t); dirty.set(true); } }, + "#{t}" span { class: "x", "×" } } + } + for g in [tag_gen()] { + input { key: "{g}", class: "taginput", r#type: "text", placeholder: "a tag", "aria-label": "add a tag (Enter or a comma)", + oninput: move |e| { + let v = e.value(); + if v.contains(',') { + for t in split_tags(&v) { if !tags.peek().contains(&t) { tags.write().push(t); } } + dirty.set(true); + tag_draft.set(String::new()); + tag_gen += 1; + } else { + tag_draft.set(v); + } + }, + onkeydown: move |e: KeyboardEvent| { + if e.key() == Key::Enter { + e.prevent_default(); + for t in split_tags(&tag_draft.peek()) { if !tags.peek().contains(&t) { tags.write().push(t); dirty.set(true); } } + tag_draft.set(String::new()); + tag_gen += 1; + document::eval("setTimeout(() => { const i = document.querySelector('.taginput'); if (i) i.focus(); }, 20);"); + } + }, + } + } + } + button { + class: if code { "plain on" } else { "plain" }, + "data-tip": if code { "s code: right-aligned, the acting words in a column; click to make it a plain note" } else { "make it s code (the tag s): right-aligned, coloured by s's words, run with ▶" }, + "aria-label": "s code", + "aria-pressed": "{code}", + onclick: move |_| { + let on = tags.peek().iter().any(|t| t == "s"); + if on { tags.write().retain(|t| t != "s"); } else { tags.write().push("s".to_string()); } + dirty.set(true); + layer_gen += 1; + }, + "s" + } + if code { + button { + class: "plain", + "data-tip": "run it (its files are the save's s programs, by title)", + "aria-label": "run the program", + onclick: { let api = api.clone(); let layer = layer.clone(); move |_| { + let api = api.clone(); + let layer = layer.clone(); + let whole = text.peek().clone(); + let body_at = crate::views::scode::body_offset(&whole); + let body = whole[body_at..].to_string(); + spawn(async move { + match api.call("s.run", serde_json::json!({ "code": body, "trace": true })).await { + Ok(r) => { + // each line's output beside it, while the text stays as it ran + let mut notes: std::collections::BTreeMap<usize, String> = Default::default(); + for w in r["writes"].as_array().into_iter().flatten() { + let at = body_at + w["from"].as_u64().unwrap_or(0) as usize; + let line = crate::views::scode::line_of(&whole, at); + let shown = inline_result(w["out"].as_str().unwrap_or("")); + let n = notes.entry(line).or_default(); + if !n.is_empty() { n.push_str(" · "); } + n.push_str(&shown); + } + if *text.peek() == whole { + layer.borrow_mut().layer.notes = notes; + layer_gen += 1; + } + ran.set(Some(r)); + } + Err(e) => ran.set(Some(serde_json::json!({ "out": "", "err": e }))), + } + }); + } }, + Icon { name: "play" } + } + button { + class: if dbg().is_some() { "plain on" } else { "plain" }, + "data-tip": "step through it: the stack, the values and the token it stops before", + "aria-label": "step through the program", + onclick: move |_| { + if dbg.peek().is_some() { dbg.set(None); } else { + // one seed for the whole session, so each step runs the same run again + let seed = text.peek().bytes().fold(0x5eed_u64, |h, b| h.rotate_left(5) ^ b as u64).wrapping_add(seq() * 7919); + dbg.set(Some((0, seed))); + } + }, + Icon { name: "chevron-right" } + } + button { + class: if outline_open() { "plain on" } else { "plain" }, + "data-tip": "the outline: what it defines and the programs it calls (Ctrl+click a word: its definition)", + "aria-label": "the program's outline", + onclick: move |_| outline_open.set(!outline_open()), + Icon { name: "list" } + } + } + button { + class: if check { "plain on" } else { "plain" }, + "data-tip": if check { "the spelling check is on: click an underlined word for what it may be" } else { "check spelling and word choice" }, + "aria-label": "check spelling", + "aria-pressed": "{check}", + onclick: move |_| set_pref(ui, |p| p.check_spelling = !p.check_spelling), + Icon { name: "check" } + } + button { + class: if judging() { "plain on" } else { "plain" }, + "data-tip": "the classifiers this note is measured on · {ui.key_of(Action::NoteClassifiers)}", + "aria-label": "the note's classifiers", + onclick: move |_| judging.set(!judging()), + Icon { name: "classifier" } + } + button { + class: "plain", + "data-tip": if reading() { format!("edit it · {}", ui.key_of(Action::ToggleRead)) } else { format!("read it · {}", ui.key_of(Action::ToggleRead)) }, + "aria-label": if reading() { "edit" } else { "read" }, + onclick: move |_| { reading.set(!reading()); seq += 1; }, + Icon { name: if reading() { "edit" } else { "view" } } + } + button { class: if dirty() { "primary" } else { "" }, "data-tip": "save · {ui.key_of(Action::Save)}", "aria-label": "save", + onclick: { let s = save.clone(); move |_| s() }, Icon { name: "save" } } + if !note.key.is_empty() { + button { + class: if armed() { "armed" } else { "plain" }, + "data-tip": "delete (click twice)", + "aria-label": "delete", + onclick: move |_| { + if !armed() { armed.set(true); return; } + let api = api_d.clone(); + let key = note.key.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.delete_note(&key).await { + Ok(()) => { open.set(None); ui.say("deleted"); ui.touched(); } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "delete" } + if armed() { "delete?" } + } + } + } + if !note.created.is_empty() { + span { class: "dim small", "written {when(¬e.created)}" if !note.edits.is_empty() { " · {note.edits.len()} edits" } } + } + if judging() { + if cur_key.is_empty() { + div { class: "judge dim small", "save the note first: then pick classifiers to measure it on" } + } else { + crate::views::judge::Judge { entry: cur_key.clone() } + } + } + if reading() { + div { class: "md rendered", dangerous_inner_html: crate::md::to_html(&read_text) } + } + if !reading() { + Replace { text, dirty, seq } + } + for pad in [format!("{}-{}", cur_key, seq())].into_iter().filter(|_| !reading()) { + div { key: "{pad}", class: format!("pad{}{}", if layered { " hl-on" } else { "" }, if code { " code" } else { "" }), + // the colours, painted under the textarea's transparent glyphs + // its segments are put in by `layer` (not by the render) + pre { id: "note-hl", class: "hl", "aria-hidden": "true", + onmounted: move |_| layer_gen += 1, + } + // not bound to the signal while typing (a round trip per key would + // drop letters typed fast); its text is put in when a note opens + textarea { + id: "note-pad", + "aria-label": "the note: # title, then markdown", + spellcheck: "false", + onmounted: move |_| { + let js = format!( + "const p = document.getElementById('note-pad'); if (p) {{ p.value = {}; p.__prev = p.value; }}", + serde_json::to_string(&*text.peek()).unwrap_or_default() + ); + document::eval(&js); + }, + onclick: move |e: MouseEvent| { + if !ui.prefs.peek().check_spelling || flags.peek().1.is_empty() { + return; + } + let c = e.client_coordinates(); + spawn(async move { + let mut ev = document::eval("const p = document.getElementById('note-pad'); dioxus.send(p ? p.selectionStart : -1);"); + let Ok(at) = ev.recv::<i64>().await else { return }; + let (t, fl) = flags.peek().clone(); + if t != *text.peek() || at < 0 { + return; + } + let at = at as u64; + let hit = fl.into_iter().find(|f| { + f["from"].as_u64().unwrap_or(0) <= at && at <= f["to"].as_u64().unwrap_or(0) + }); + pick.set(hit.map(|flag| Pick { flag, x: c.x, y: c.y })); + }); + }, + } + } + if code && let Some(r) = ran() { + div { class: "s-run", + div { class: "row", + span { class: "dim small", {format!("ran in {} steps{}", r["steps"].as_u64().unwrap_or(0), match r["code"].as_i64() { Some(c) if c != 0 => format!(" · exit {c}"), _ => String::new() })} } + span { class: "grow" } + button { class: "plain small", onclick: move |_| ran.set(None), Icon { name: "close" } } + } + pre { class: "s-out", {r["out"].as_str().unwrap_or("").trim_start_matches('\n').to_string()} } + if let Some(e) = r["err"].as_str() { + pre { class: "s-err", role: "alert", "s: {e}" } + } + } + } + if code && !compl().1.is_empty() { + div { class: "s-compl row wrap", + span { class: "dim small", "Tab:" } + for (i, w) in compl().1.into_iter().enumerate() { + { + let rest = w[compl().0.len().min(w.len())..].to_string(); + rsx! { + button { key: "{w}", class: if i == 0 { "chip small on" } else { "chip small" }, + onclick: move |_| { + document::eval(&format!( + "const p = document.getElementById('note-pad'); if (p) {{ const a = p.selectionStart; p.setRangeText({}, a, a, 'end'); p.focus(); window.__anendCompl = null; p.dispatchEvent(new Event('input', {{ bubbles: true }})); }}", + serde_json::to_string(&rest).unwrap_or_default() + )); + }, + "{w}" + } + } + } + } + } + } + if code && outline_open() { + { + let t = text.read().clone(); + let body_at = crate::views::scode::body_offset(&t); + let titles: Vec<String> = progs.read().iter().map(|p| p.0.clone()).collect(); + let items = crate::views::scode::outline(&t[body_at..], &titles); + rsx! { + div { class: "s-outline", + div { class: "row", + span { class: "dim small", if items.is_empty() { "it defines nothing and calls no other program" } else { "the outline · Ctrl+click a word in the code: its definition" } } + span { class: "grow" } + button { class: "plain small", "aria-label": "close the outline", onclick: move |_| outline_open.set(false), Icon { name: "close" } } + } + for (i, it) in items.into_iter().enumerate() { + { + let (a, b) = (body_at + it.at, body_at + it.at + it.name.len()); + let line = crate::views::scode::line_of(&t, a) + 1; + let what = match it.kind { "script" => "script", "word" => "word", _ => "calls" }; + rsx! { + button { key: "{i}", class: "plain s-item", onclick: move |_| pad_show(a, b), + span { class: "chip small", "{what}" } + b { " {it.name}" } + span { class: "dim small", " line {line}" } + } + } + } + } + } + } + } + } + if code && let (Some((n, seed)), Some(s)) = (dbg(), snap()) { + div { class: "s-run s-dbg", + div { class: "row wrap", + span { class: "dim small", {format!("step {}{}", s["steps"].as_u64().unwrap_or(n), if s["done"] == true { " · it ended" } else { "" })} } + span { class: "grow" } + button { class: "btn small", title: "back to the start", onclick: move |_| dbg.set(Some((0, seed))), "⏮" } + button { class: "btn small primary", disabled: s["done"] == true, title: "one step", onclick: move |_| dbg.set(Some((n + 1, seed))), "step" } + button { class: "btn small", disabled: s["done"] == true, onclick: move |_| dbg.set(Some((n + 10, seed))), "+10" } + button { class: "btn small", disabled: s["done"] == true, onclick: move |_| dbg.set(Some((n + 100, seed))), "+100" } + button { class: "btn small", disabled: s["done"] == true, title: "run to the end", onclick: move |_| dbg.set(Some((n + 1_000_000, seed))), "⏭" } + button { class: "plain small", "aria-label": "stop stepping", onclick: move |_| dbg.set(None), Icon { name: "close" } } + } + if s["done"] != true && s["main"] != true { + div { class: "small", "in a call, depth {s[\"depth\"]}: " code { class: "s-unit", {s["unit"].as_str().unwrap_or("").chars().take(80).collect::<String>()} } } + } + div { class: "row wrap s-stack", + span { class: "dim small", if s["ow"] == true { "stack (ow on)" } else { "stack" } } + for (i, v) in s["stack"].as_array().cloned().unwrap_or_default().into_iter().enumerate() { + span { key: "{i}", class: "chip small", {v.as_str().unwrap_or("").to_string()} } + } + } + { + let mut rows: Vec<(String, String)> = Vec::new(); + for k in ["locals", "mem", "numbers"] { + for (name, v) in s[k].as_object().into_iter().flatten() { + if k != "numbers" || !s["mem"].as_object().is_some_and(|m| m.contains_key(name)) { + rows.push((name.clone(), v.as_str().unwrap_or("").to_string())); + } + } + } + for (name, v) in s["lists"].as_object().into_iter().flatten() { + let items: Vec<String> = v.as_array().into_iter().flatten().filter_map(|x| x.as_str().map(str::to_string)).collect(); + rows.push((format!("{name} []"), items.join(" · "))); + } + rsx! { + if !rows.is_empty() { + div { class: "s-vals", + for (i, (k, v)) in rows.into_iter().enumerate() { + div { key: "{i}", class: "small", b { "{k}" } " {v}" } + } + } + } + } + } + if !s["out"].as_str().unwrap_or("").is_empty() { + pre { class: "s-out", {s["out"].as_str().unwrap_or("").trim_start_matches('\n').to_string()} } + } + if let Some(e) = s["err"].as_str() { + pre { class: "s-err", role: "alert", "s: {e}" } + } + } + } + if let Some(pk) = pick() { + SpellPick { + pick: pk, + on_close: move |_| pick.set(None), + } + } + if big { + div { class: "spell-note dim small", {format!("a long note ({} KB): the spelling check pauses above {} KB, so typing stays quick", text.read().len() / 1000, big_at() / 1000)} } + } + if check && !big { + if let Some(r) = report() { + div { class: "spell-note dim small", + title: "measured on a fifth of its corpus held out, with errors put in the same way it was trained: real typing errors are harder", + {format!( + "spelling check: finds {:.0}% of the errors put into held-out text, {:.0}% of what it flags is one, the first suggestion is right {:.0}% of the time; {:.1} false alarms per 1000 clean words", + r["recall"].as_f64().unwrap_or(0.0) * 100.0, + r["precision"].as_f64().unwrap_or(0.0) * 100.0, + r["top1"].as_f64().unwrap_or(0.0) * 100.0, + r["false_alarms_per_1000"].as_f64().unwrap_or(0.0), + )} + } + } + } + } + } else { + div { class: "empty", + p { "Pick a note in the list, or make a new one ({ui.key_of(Action::NewNote)}). A note is a text whose first line is its # title." } + } + } + } + } + } +} + +/// what a flagged word may be: each suggestion (a click puts it in; Ctrl+Z takes it back) +#[component] +fn SpellPick(pick: Pick, on_close: EventHandler<()>) -> Element { + let f = pick.flag.clone(); + let from = f["from"].as_u64().unwrap_or(0) as usize; + let to = f["to"].as_u64().unwrap_or(0) as usize; + let kind = f["kind"].as_str().unwrap_or("").to_string(); + let p = f["p"].as_f64().unwrap_or(0.0) * 100.0; + let sugs: Vec<(String, f64)> = f["suggestions"] + .as_array() + .into_iter() + .flatten() + .map(|s| { + ( + s["text"].as_str().unwrap_or("").to_string(), + s["p"].as_f64().unwrap_or(0.0), + ) + }) + .collect(); + let what = match kind.as_str() { + "repeated" => "a word twice", + "confused" => "another word may fit", + _ => "not a word it knows", + }; + rsx! { + div { class: "spell-pick", style: "left: {pick.x:.0}px; top: {pick.y + 14.0:.0}px;", role: "menu", + div { class: "dim small", "{what} · {p:.0}% sure" } + if sugs.is_empty() { + div { class: "dim small", "no suggestion" } + } + for (s , sp) in sugs { + button { + key: "{s}", + class: "plain", + role: "menuitem", + onclick: { + let s = s.clone(); + move |_| { + replace_in_pad(from, to, &s); + on_close.call(()); + } + }, + if s.is_empty() { i { "take it out" } } else { b { "{s}" } } + span { class: "dim small", " {sp * 100.0:.0}%" } + } + } + button { class: "plain dim small", onclick: move |_| on_close.call(()), "leave it" } + } + } +} + +/// the text before the selection, the word, the text after, and the word's alternatives +type Around = (String, String, String, Vec<serde_json::Value>); + +/// the editor's replacements: `{{key}}` puts an entry's text in (live: it shows that +/// entry as it is now), `{{filter:name}}` a saved filter's results; a word's synonyms and +/// registers come from the lists it is in, those keeping the text's sum first +#[component] +fn Replace(text: Signal<String>, dirty: Signal<bool>, seq: Signal<u64>) -> Element { + let ui = ui(); + let api = api(); + // (the text before the selection, the word, the text after) and its alternatives + let mut alts: Signal<Option<Around>> = use_signal(|| None); + let mut find = use_signal(String::new); + let mut find_gen = use_signal(|| 0u64); + // puts a new text into the pad and the signal + let mut put = move |t: String| { + text.set(t.clone()); + dirty.set(true); + let js = format!( + "const p = document.getElementById('note-pad'); if (p) {{ p.value = {}; p.__prev = undefined; p.dispatchEvent(new Event('input', {{ bubbles: true }})); p.focus(); }}", + serde_json::to_string(&t).unwrap_or_default() + ); + document::eval(&js); + }; + // the pad's text around its selection (the word under the caret when nothing is selected) + const AROUND: &str = r#" + const p = document.getElementById('note-pad'); + if (!p) { dioxus.send(null); } else { + let a = p.selectionStart, b = p.selectionEnd, v = p.value; + if (a === b && WORD) { + while (a > 0 && /[\p{L}\p{N}'-]/u.test(v[a - 1])) a--; + while (b < v.length && /[\p{L}\p{N}'-]/u.test(v[b])) b++; + } + dioxus.send([v.slice(0, a), v.slice(a, b), v.slice(b)]); + }"#; + let api_a = api.clone(); + let synonyms = move |_| { + let api = api_a.clone(); + spawn(async move { + let mut ev = document::eval(&AROUND.replace("WORD", "true")); + let Ok(Some((before, word, after))) = ev.recv::<Option<(String, String, String)>>().await else { + return; + }; + if word.trim().is_empty() { + ui.say("select a word (or put the caret in one) first"); + return; + } + match api.alternatives(word.trim()).await { + Ok(v) => { + let list: Vec<serde_json::Value> = v["alternatives"].as_array().cloned().unwrap_or_default(); + if list.is_empty() { + ui.say(format!( + "“{}” is in no list: make one of words that may stand for each other", + word.trim() + )); + alts.set(None); + } else { + alts.set(Some((before, word, after, list))); + } + } + Err(e) => ui.fail(e), + } + }); + }; + let api_f = api.clone(); + let insert = move || { + let api = api_f.clone(); + let want = find.peek().trim().to_string(); + if want.is_empty() { + return; + } + spawn(async move { + // a key as it is, a filter by its name, else the first text with those words + let piece = if want.starts_with("filter:") || anend_core::graph::record::parse_label(&want).is_some() { + format!("{{{{{want}}}}}") + } else { + match api.search(&want, false).await { + Ok(hits) if !hits.is_empty() => format!("{{{{{}}}}}", hits[0].key.trim_start_matches("note:")), + Ok(_) => { + ui.fail(format!("no text with “{want}”")); + return; + } + Err(e) => { + ui.fail(e); + return; + } + } + }; + let mut ev = document::eval(&AROUND.replace("WORD", "false")); + let Ok(Some((before, sel, after))) = ev.recv::<Option<(String, String, String)>>().await else { + return; + }; + let _ = sel; + put(format!("{before}{piece}{after}")); + find.set(String::new()); + find_gen += 1; + ui.say(format!( + "{piece} goes in where the caret was: it shows that entry's text when read" + )); + }); + }; + let insert2 = insert.clone(); + let _ = seq; + rsx! { + div { class: "replace row", + button { class: "plain", "data-tip": "a word's synonyms and registers: the other words of the lists it is in", onclick: synonyms, + Icon { name: "swap" } "alternatives" } + if let Some((before, word, after, list)) = alts() { + select { + "aria-label": "replace “{word}” with", + onchange: move |e| { + let v = e.value(); + if !v.is_empty() { + put(format!("{before}{v}{after}")); + ui.say(format!("“{}” → “{v}”", word.trim())); + } + alts.set(None); + }, + option { value: "", {format!("“{}” (o {} r {}) →", word.trim(), crate::gem::sums(word.trim()).0, crate::gem::sums(word.trim()).1)} } + for a in list.iter() { + option { key: "{a[\"key\"]}", value: "{a[\"text\"].as_str().unwrap_or(\"\")}", + {format!("{}{} · {} · o {} r {}", + if a["same_ordinal"].as_bool() == Some(true) { "= " } else { "" }, + a["text"].as_str().unwrap_or(""), + a["list"].as_str().unwrap_or(""), + a["ordinal"], a["reversed"])} + } + } + } + } + span { class: "grow" } + for g in [find_gen()] { + input { key: "{g}", r#type: "text", placeholder: "put in {{{{key}}}}: a key, words, or filter:name", + "aria-label": "an entry to put in where the caret is", + oninput: move |e| find.set(e.value()), + onkeydown: { let insert = insert.clone(); move |e: KeyboardEvent| if e.key() == Key::Enter { insert() } }, + } + } + button { onclick: move |_| insert2(), "put in" } + } + } +} + +/// the notes picked with Shift+click: tag them, delete them (two clicks), or let them go +#[component] +fn ManyNotes(picked: Signal<Vec<String>>, api: Api) -> Element { + let ui = ui(); + let mut tag = use_signal(String::new); + let mut armed = use_signal(|| false); + let n = picked().len(); + if n == 0 { + return rsx! {}; + } + let (a1, a2) = (api.clone(), api.clone()); + rsx! { + div { class: "many", role: "status", + b { {format!("{n} note{} picked", if n == 1 { "" } else { "s" })} } + div { class: "row", + input { r#type: "text", placeholder: "a tag", "aria-label": "a tag for them", value: "{tag}", oninput: move |e| tag.set(e.value()) } + button { class: "btn small", disabled: tag().trim().is_empty(), + onclick: move |_| { + let (api, keys, t) = (a1.clone(), picked(), tag().trim().trim_start_matches('#').to_string()); + spawn(async move { + for k in &keys { + if let Err(e) = api.call("tags.add", serde_json::json!({ "key": k, "tag": t })).await { ui.fail(e); return; } + } + ui.say(format!("tagged #{t}: {} notes", keys.len())); + ui.touched(); + }); + }, + Icon { name: "tag" } "tag them" } + } + div { class: "row", + button { class: if armed() { "btn small danger" } else { "btn small" }, + onclick: move |_| { + if !armed() { armed.set(true); return; } + let (api, keys) = (a2.clone(), picked()); + spawn(async move { + for k in &keys { + if let Err(e) = api.delete_note(k).await { ui.fail(e); return; } + } + picked.set(vec![]); + armed.set(false); + ui.say(format!("{} notes deleted", keys.len())); + ui.touched(); + }); + }, + Icon { name: "delete" } if armed() { "sure? delete them" } else { "delete them" } } + button { class: "btn small", onclick: move |_| picked.set(vec![]), Icon { name: "close" } "let go" } + } + } + } +} diff --git a/app/src/views/pictures.rs b/app/src/views/pictures.rs new file mode 100644 index 00000000..84a382b0 --- /dev/null +++ b/app/src/views/pictures.rs @@ -0,0 +1,303 @@ +//! The pictures panel (docs/app-api.md, `pictures.*`): the save's pictures as +//! thumbnails, added by dropping files on the panel or picking them, put into lists +//! (by name, beside the texts of the list with that head) and taken out, deleted with +//! two clicks. In the lists view, for all the save's pictures (with a picker of the +//! picture lists) and on a list's page for that list's (what is added there goes into +//! it). Spec models train on them (`{"from": "pictures", "list": ..}`). + +use dioxus::html::HasFileData; +use dioxus::prelude::*; +use serde_json::Value; + +use crate::ui::*; + +/// thumbnails' side in pixels +const THUMB: u32 = 128; + +fn str_of<'a>(v: &'a Value, k: &str) -> &'a str { + v.get(k).and_then(Value::as_str).unwrap_or("") +} + +#[component] +pub fn Pictures( + /// the list whose pictures these are (None: all the save's) + list: Option<String>, + /// list names to offer when putting a picture into a list + names: Vec<String>, +) -> Element { + let ui = ui(); + let api = api(); + let mut rev = use_signal(|| 0u64); + // the picture list shown when this is the save's panel ("" for all) + let mut showing = use_signal(String::new); + let mut over = use_signal(|| false); + let mut busy = use_signal(|| 0usize); + let fixed = list.clone(); + let api_r = api.clone(); + let pics = use_resource(move || { + let api = api_r.clone(); + let l = fixed.clone().or_else(|| Some(showing()).filter(|s| !s.is_empty())); + let _ = ((ui.changed)(), rev()); + async move { api.pictures(l.as_deref(), THUMB).await } + }); + let api_l = api.clone(); + let plists = use_resource(move || { + let api = api_l.clone(); + let _ = ((ui.changed)(), rev()); + async move { api.picture_lists().await } + }); + // files in: each read and sent; the panel's list gets them too + let into = list.clone().or_else(|| Some(showing()).filter(|s| !s.is_empty())); + let take = { + let api = api.clone(); + let into = into.clone(); + move |files: Vec<dioxus::html::FileData>| { + let api = api.clone(); + let into = into.clone(); + async move { + let n = files.len(); + if n == 0 { + return; + } + busy += n; + let (mut added, mut had) = (0, 0); + for f in files { + let name = f.name(); + match f.read_bytes().await { + Ok(b) => match api.add_picture(&b, &name, into.as_deref()).await { + Ok(v) if v.get("new").and_then(Value::as_bool) == Some(true) => added += 1, + Ok(_) => had += 1, + Err(e) => ui.fail(format!("{name}: {e}")), + }, + Err(e) => ui.fail(format!("couldn't read {name}: {e}")), + } + busy -= 1; + } + match (added, had) { + (0, 0) => {} + (a, 0) => ui.say(format!("{a} picture{} added", if a == 1 { "" } else { "s" })), + (a, h) => ui.say(format!("{a} added, {h} the save had already")), + } + rev += 1; + } + } + }; + let take_drop = take.clone(); + // on the desktop a file's path works too (where the system's file dialog doesn't) + let on_disk = api.on_disk(); + let mut path = use_signal(String::new); + // bumped to empty the path field (it isn't bound to the signal, so fast typing keeps + // every letter) + let mut path_gen = use_signal(|| 0u64); + let add_path = { + let api = api.clone(); + let into = into.clone(); + move || { + let p = path.peek().trim().to_string(); + if p.is_empty() { + return; + } + let (api, into) = (api.clone(), into.clone()); + spawn(async move { + match api.add_picture_path(&p, into.as_deref()).await { + Ok(v) => { + ui.say(if v.get("new").and_then(Value::as_bool) == Some(true) { + "the picture is in" + } else { + "the save had that picture already" + }); + path.set(String::new()); + path_gen += 1; + rev += 1; + } + Err(e) => ui.fail(e), + } + }); + } + }; + let add_path2 = add_path.clone(); + let (shown, note): (Vec<Value>, Option<String>) = match &*pics.read() { + Some(Ok(v)) => (v.clone(), None), + Some(Err(e)) => (vec![], Some(e.clone())), + None => (vec![], None), + }; + let lists: Vec<(String, u64)> = match &*plists.read() { + Some(Ok(v)) => v + .iter() + .map(|l| { + ( + str_of(l, "list").to_string(), + l.get("count").and_then(Value::as_u64).unwrap_or(0), + ) + }) + .collect(), + _ => vec![], + }; + let mut offer: Vec<String> = names.clone(); + for (l, _) in &lists { + if !offer.contains(l) { + offer.push(l.clone()); + } + } + offer.sort_by_key(|n| n.to_lowercase()); + let dl = format!("pic-lists-{}", list.as_deref().unwrap_or("all").replace(' ', "-")); + rsx! { + div { + class: if over() { "card pictures over" } else { "card pictures" }, + ondragover: move |e: DragEvent| { e.prevent_default(); over.set(true); }, + ondragleave: move |_| over.set(false), + ondrop: move |e: DragEvent| { + e.prevent_default(); + over.set(false); + let files = e.files(); + let take = take_drop.clone(); + spawn(async move { take(files).await }); + }, + div { class: "row", + h3 { Icon { name: "image" } "pictures" } + span { class: "dim small", + match &list { + Some(l) => format!("{} in “{l}” · drop PNG or JPEG files here, or pick them", shown.len()), + None => format!("{} shown · drop PNG or JPEG files here, or pick them; spec models learn from them", shown.len()), + } + } + span { class: "grow" } + if busy() > 0 { span { class: "dim small", "adding {busy()}…" } } + label { class: "button", "data-tip": "PNG or JPEG files", + Icon { name: "upload" } "add pictures" + input { r#type: "file", accept: "image/png,image/jpeg", multiple: true, style: "display: none;", + "aria-label": "pictures to add", + onchange: move |e: FormEvent| { + let take = take.clone(); + async move { take(e.files()).await } + }, + } + } + } + if on_disk { + div { class: "row", + for g in [path_gen()] { + input { key: "{g}", r#type: "text", style: "flex: 1;", placeholder: "or a picture's path: /home/you/Pictures/cat.png", + "aria-label": "a picture's path", + oninput: move |e| path.set(e.value()), + onkeydown: { let add_path = add_path.clone(); move |e: KeyboardEvent| if e.key() == Key::Enter { add_path() } }, + } + } + button { onclick: move |_| add_path2(), "add" } + } + } + if list.is_none() && !lists.is_empty() { + div { class: "row chips", role: "tablist", "aria-label": "picture lists", + button { class: if showing().is_empty() { "chip on" } else { "chip" }, onclick: move |_| showing.set(String::new()), "all" } + for (l , n) in lists.iter().cloned() { + button { key: "{l}", class: if showing() == l { "chip on" } else { "chip" }, + onclick: { let l = l.clone(); move |_| showing.set(l.clone()) }, + "{l} " span { class: "dim", "{n}" } } + } + } + } + if let Some(n) = note { div { class: "bad small", "{n}" } } + datalist { id: "{dl}", + for n in offer.iter() { option { key: "{n}", value: "{n}" } } + } + if shown.is_empty() { + div { class: "pic-drop dim", "no pictures yet: drop some here" } + } + div { class: "pic-grid", + for p in shown.into_iter() { + Thumb { key: "{str_of(&p, \"id\")}", pic: p.clone(), datalist: dl.clone(), on_change: move |_| rev += 1 } + } + } + } + } +} + +#[component] +fn Thumb(pic: Value, datalist: String, on_change: EventHandler<()>) -> Element { + let ui = ui(); + let api = api(); + let mut armed = use_signal(|| false); + let mut into = use_signal(String::new); + let mut into_gen = use_signal(|| 0u64); + let id = str_of(&pic, "id").to_string(); + let name = str_of(&pic, "name").to_string(); + let thumb = str_of(&pic, "thumb").to_string(); + let (w, h) = ( + pic.get("width").and_then(Value::as_u64).unwrap_or(0), + pic.get("height").and_then(Value::as_u64).unwrap_or(0), + ); + let kb = pic.get("size").and_then(Value::as_u64).unwrap_or(0).div_ceil(1024); + let lists: Vec<String> = crate::views::classifiers::strs(pic.get("lists").unwrap_or(&Value::Null)); + let shown_name = if name.is_empty() { + id[..8.min(id.len())].to_string() + } else { + name.clone() + }; + let tag = { + let (api, id) = (api.clone(), id.clone()); + move |list: String, remove: bool| { + let (api, id) = (api.clone(), id.clone()); + spawn(async move { + match api.tag_picture(&id, &list, remove).await { + Ok(_) => { + ui.say(if remove { + format!("out of “{list}”") + } else { + format!("in “{list}” now") + }); + on_change.call(()); + } + Err(e) => ui.fail(e), + } + }); + } + }; + let tag2 = tag.clone(); + let api_d = api.clone(); + let id_d = id.clone(); + rsx! { + div { class: "pic", title: "{shown_name} · {w}×{h} · {kb} KB", + img { src: "data:image/png;base64,{thumb}", alt: "{shown_name}" } + div { class: "pic-name small", "{shown_name}" } + div { class: "pic-lists", + for l in lists.iter().cloned() { + span { key: "{l}", class: "chip small", + "{l}" + button { class: "plain", "aria-label": "take it out of {l}", "data-tip": "take it out of the list", + onclick: { let tag = tag.clone(); let l = l.clone(); move |_| tag(l.clone(), true) }, + Icon { name: "close" } } + } + } + } + div { class: "row pic-tools", + for g in [into_gen()] { + input { key: "{g}", r#type: "text", list: "{datalist}", placeholder: "into a list…", "aria-label": "put it into a list", + oninput: move |e| into.set(e.value()), + onkeydown: { let tag2 = tag2.clone(); move |e: KeyboardEvent| { + if e.key() == Key::Enter { + let l = into().trim().to_string(); + if !l.is_empty() { tag2(l, false); into.set(String::new()); into_gen += 1; } + } + } }, + } + } + button { + class: if armed() { "armed" } else { "plain" }, + "aria-label": "delete the picture", + "data-tip": "delete the picture; click twice", + onclick: move |_| { + if !armed() { armed.set(true); return; } + let (api, id) = (api_d.clone(), id_d.clone()); + spawn(async move { + match api.delete_picture(&id).await { + Ok(()) => { ui.say("the picture is gone"); on_change.call(()); } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "delete" } + } + } + } + } +} diff --git a/app/src/views/pipes.rs b/app/src/views/pipes.rs new file mode 100644 index 00000000..d9c163ca --- /dev/null +++ b/app/src/views/pipes.rs @@ -0,0 +1,274 @@ +//! Pipes in the filters view (docs/architecture.md 2, 3; `pipes.*` in docs/app-api.md): +//! the builder's filter, with the effects it has on the texts it lets through and the +//! actions it can do to them, kept by name. Kept pipes are turned on and off for the +//! memory view and the space (stacked in the order they were turned on), edited in the +//! builder, made to act, and deleted. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use crate::shell::set_pref; +use crate::ui::*; + +/// the effects the editor offers +const EFFECTS: [(&str, &str); 7] = [ + ("colour", "a colour"), + ("colour_by", "a classifier's colours"), + ("underline", "an underline"), + ("label", "a label"), + ("size", "a size"), + ("glow", "a glow"), + ("gather", "gather in the space"), +]; + +const ACTIONS: [(&str, &str); 3] = [ + ("enlist", "put them in a list"), + ("tag", "tag them"), + ("run", "run a program on each"), +]; + +fn blank(kind: &str) -> Value { + match kind { + "colour" => json!({ "kind": "colour", "colour": "#e07a3f" }), + "colour_by" => json!({ "kind": "colour_by", "classifier": "" }), + "underline" => json!({ "kind": "underline", "colour": "#3f7ae0" }), + "label" => json!({ "kind": "label", "text": "" }), + "size" => json!({ "kind": "size", "scale": 1.5 }), + "glow" => json!({ "kind": "glow", "colour": "#ffd166" }), + "gather" => json!({ "kind": "gather" }), + "enlist" => json!({ "kind": "enlist", "list": "" }), + "tag" => json!({ "kind": "tag", "tag": "" }), + _ => json!({ "kind": "run", "program": "" }), + } +} + +/// a pipe's effects or actions in one line each, for the kept list +pub fn describe(v: &Value) -> String { + let mut out = Vec::new(); + for e in v["effects"].as_array().into_iter().flatten() { + out.push(match e["kind"].as_str().unwrap_or("") { + "colour" => format!("colour {}", e["colour"].as_str().unwrap_or("")), + "colour_by" => format!("{}'s colours", e["classifier"].as_str().unwrap_or("")), + "underline" => format!("underline {}", e["colour"].as_str().unwrap_or("")), + "label" => format!("label “{}”", e["text"].as_str().unwrap_or("")), + "size" => format!("size ×{}", e["scale"]), + "glow" => format!("glow {}", e["colour"].as_str().unwrap_or("")), + "gather" => "gathers".to_string(), + k => k.to_string(), + }); + } + for a in v["actions"].as_array().into_iter().flatten() { + out.push(match a["kind"].as_str().unwrap_or("") { + "enlist" => format!("→ list “{}”", a["list"].as_str().unwrap_or("")), + "tag" => format!("→ tag {}", a["tag"].as_str().unwrap_or("")), + "run" => format!("→ runs {}", a["program"].as_str().unwrap_or("")), + k => k.to_string(), + }); + } + if out.is_empty() { + "no effects yet".into() + } else { + out.join(" · ") + } +} + +/// the effects and actions being edited, under the builder's filter +#[component] +pub fn Parts(effects: Signal<Vec<Value>>, actions: Signal<Vec<Value>>, classifiers: Vec<String>) -> Element { + let api = api(); + let programs = use_resource(move || { + let api = api.clone(); + async move { + api.call("s.programs", json!({})) + .await + .ok() + .and_then(|v| v.as_array().cloned()) + .unwrap_or_default() + .iter() + .filter_map(|p| p["title"].as_str().map(String::from)) + .collect::<Vec<_>>() + } + }); + let programs = programs.read().clone().unwrap_or_default(); + let mut effects = effects; + let mut actions = actions; + rsx! { + div { class: "pipe-parts", + div { class: "row", + b { "effects" } + span { class: "dim small", "what the texts it lets through look like, where the pipe is on" } + span { class: "grow" } + select { key: "{effects().len()}", "aria-label": "add an effect", value: "", + onchange: move |e| { let k = e.value(); if !k.is_empty() { effects.write().push(blank(&k)); } }, + option { value: "", selected: true, "add an effect…" } + for (k , l) in EFFECTS { option { key: "{k}", value: "{k}", "{l}" } } + } + } + for (i , e) in effects().into_iter().enumerate() { + div { key: "{i}-{e[\"kind\"]}", class: "cond row", + match e["kind"].as_str().unwrap_or("") { + k @ ("colour" | "underline" | "glow") => rsx! { + span { {match k { "colour" => "colour", "underline" => "underline", _ => "glow" }} } + input { r#type: "color", "aria-label": "its colour", value: "{e[\"colour\"].as_str().unwrap_or(\"#000000\")}", + oninput: move |ev| { if let Some(x) = effects.write().get_mut(i) { x["colour"] = json!(ev.value()); } } } + }, + "colour_by" => rsx! { + span { "each in its class's colour, by" } + select { "aria-label": "the classifier", + onchange: move |ev| { if let Some(x) = effects.write().get_mut(i) { x["classifier"] = json!(ev.value()); } }, + option { value: "", "a classifier…" } + for c in classifiers.iter() { option { key: "{c}", value: "{c}", selected: e["classifier"] == c.as_str(), "{c}" } } + } + }, + "label" => rsx! { + span { "label" } + input { r#type: "text", maxlength: "40", placeholder: "a word or two", initial_value: "{e[\"text\"].as_str().unwrap_or(\"\")}", + oninput: move |ev| { if let Some(x) = effects.write().get_mut(i) { x["text"] = json!(ev.value()); } } } + }, + "size" => rsx! { + span { "size ×" } + input { r#type: "number", min: "0.25", max: "4", step: "0.25", style: "width: 70px;", initial_value: "{e[\"scale\"]}", + oninput: move |ev| { if let (Some(x), Ok(v)) = (effects.write().get_mut(i), ev.value().parse::<f64>()) { x["scale"] = json!(v); } } } + }, + "gather" => rsx! { span { "in the space, they pull together" } }, + k => rsx! { span { class: "dim", "{k}" } }, + } + span { class: "grow" } + button { class: "plain ibtn", "aria-label": "remove it", onclick: move |_| { let mut w = effects.write(); if i < w.len() { w.remove(i); } }, Icon { name: "close" } } + } + } + div { class: "row", + b { "actions" } + span { class: "dim small", "done once, when you ask, to every text it lets through" } + span { class: "grow" } + select { key: "{actions().len()}", "aria-label": "add an action", value: "", + onchange: move |e| { let k = e.value(); if !k.is_empty() { actions.write().push(blank(&k)); } }, + option { value: "", selected: true, "add an action…" } + for (k , l) in ACTIONS { option { key: "{k}", value: "{k}", "{l}" } } + } + } + for (i , a) in actions().into_iter().enumerate() { + div { key: "{i}-{a[\"kind\"]}", class: "cond row", + match a["kind"].as_str().unwrap_or("") { + "enlist" => rsx! { + Icon { name: "list" } span { "into the list" } + input { r#type: "text", placeholder: "its name", initial_value: "{a[\"list\"].as_str().unwrap_or(\"\")}", + oninput: move |ev| { if let Some(x) = actions.write().get_mut(i) { x["list"] = json!(ev.value()); } } } + }, + "tag" => rsx! { + Icon { name: "tag" } span { "tagged" } + input { r#type: "text", placeholder: "a tag", initial_value: "{a[\"tag\"].as_str().unwrap_or(\"\")}", + oninput: move |ev| { if let Some(x) = actions.write().get_mut(i) { x["tag"] = json!(ev.value()); } } } + }, + _ => rsx! { + Icon { name: "play" } span { "run the program" } + select { "aria-label": "the program", + onchange: move |ev| { if let Some(x) = actions.write().get_mut(i) { x["program"] = json!(ev.value()); } }, + option { value: "", "a program…" } + for p in programs.iter() { option { key: "{p}", value: "{p}", selected: a["program"] == p.as_str(), "{p}" } } + } + span { class: "dim small", "on each, the text as its first argument" } + }, + } + span { class: "grow" } + button { class: "plain ibtn", "aria-label": "remove it", onclick: move |_| { let mut w = actions.write(); if i < w.len() { w.remove(i); } }, Icon { name: "close" } } + } + } + } + } +} + +/// the kept pipes: on in the views or not, into the builder, acting, deleting +#[component] +pub fn KeptPipes(rev: Signal<u64>, on_open: EventHandler<Value>) -> Element { + let ui = ui(); + let api = api(); + let api_l = api.clone(); + let list = use_resource(move || { + let api = api_l.clone(); + let _ = ((ui.changed)(), rev()); + async move { api.call("pipes.list", json!({})).await } + }); + let pipes: Vec<Value> = match &*list.read() { + Some(Ok(v)) => v.as_array().cloned().unwrap_or_default(), + _ => vec![], + }; + if pipes.is_empty() { + return rsx! {}; + } + let on = ui.prefs.read().pipes.clone(); + rsx! { + div { class: "card", + h3 { Icon { name: "filter" } "pipes" span { class: "dim small", " on: their effects show in the memory view and the space, stacked in the order turned on" } } + for p in pipes { + { + let pipe = p["pipe"].clone(); + let name = pipe["name"].as_str().unwrap_or("").to_string(); + let lit = on.iter().position(|n| *n == name); + rsx! { + PipeRow { key: "{name}", name: name.clone(), pipe: pipe.clone(), lit, on_open } + } + } + } + } + } +} + +#[component] +fn PipeRow(name: String, pipe: Value, lit: Option<usize>, on_open: EventHandler<Value>) -> Element { + let ui = ui(); + let api = api(); + let mut armed = use_signal(|| false); + let has_actions = pipe["actions"].as_array().is_some_and(|a| !a.is_empty()); + let (n1, n2, n3) = (name.clone(), name.clone(), name.clone()); + let (api1, api2) = (api.clone(), api.clone()); + rsx! { + div { class: "row kept", + label { class: "row small", "data-tip": "show its effects in the memory view and the space", + input { r#type: "checkbox", checked: lit.is_some(), "aria-label": "{name} on in the views", + onchange: move |e| { + let (n, on) = (n1.clone(), e.checked()); + set_pref(ui, |p| { p.pipes.retain(|x| *x != n); if on { p.pipes.push(n); } }); + } } + if let Some(i) = lit { span { class: "pipe-n", "{i + 1}" } } + } + b { "{name}" } + span { class: "dim small grow", {describe(&pipe)} } + button { class: "plain", "data-tip": "into the builder", onclick: move |_| on_open.call(pipe.clone()), Icon { name: "edit" } } + if has_actions { + button { class: "plain", "data-tip": "do its actions now, on every text it lets through", + onclick: move |_| { + let (api, n) = (api1.clone(), n2.clone()); + spawn(async move { + match api.call("pipes.apply", json!({ "name": n })).await { + Ok(v) => { + let parts: Vec<String> = v["done"].as_array().into_iter().flatten().map(|d| match d["kind"].as_str() { + Some("enlist") => format!("{} into “{}”", d["texts"], d["list"].as_str().unwrap_or("")), + Some("tag") => format!("{} tagged {}", d["texts"], d["tag"].as_str().unwrap_or("")), + _ => format!("{} ran {}{}", d["program"].as_str().unwrap_or(""), d["texts"], + if d["failed"].as_u64().unwrap_or(0) > 0 { format!(" ({} failed)", d["failed"]) } else { String::new() }), + }).collect(); + ui.say(format!("{}: {}", n, parts.join(", "))); + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "play" } "act" } + } + button { class: if armed() { "armed" } else { "plain" }, "data-tip": "delete it (click twice)", + onclick: move |_| { + if !armed() { armed.set(true); return; } + let (api, n) = (api2.clone(), n3.clone()); + spawn(async move { + match api.call("pipes.delete", json!({ "name": n.clone() })).await { + Ok(_) => { set_pref(ui, |p| p.pipes.retain(|x| *x != n)); ui.touched(); } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "delete" } } + } + } +} diff --git a/app/src/views/reader.rs b/app/src/views/reader.rs new file mode 100644 index 00000000..7f49e25b --- /dev/null +++ b/app/src/views/reader.rs @@ -0,0 +1,382 @@ +//! The reader: notes and texts as cards, a page at a time; short texts flow in a tight +//! grid. Clicking one (or Enter on it) expands it to read big, one at a time, ← and → +//! stepping through; Esc goes back. The bar narrows by words. +//! +//! What it shows is a view (`views.run`, docs/architecture.md part 4): its own three +//! (everything, notes, texts) are built-in presets, and any s program that loads +//! `std/view.s.` is a view of its own beside them: where its texts come from, their order, +//! headings, a layout (cards, a tight grid or a list) and the pipes whose effects it shows. + +use dioxus::prelude::*; + +use serde_json::Value; + +use crate::backend::Hit; +use crate::keys::Action; + +use crate::ui::*; +use crate::views::use_keys; + +#[component] +pub fn Reader() -> Element { + let ui = ui(); + let api = api(); + let mut view = use_signal(|| "everything".to_string()); + let mut page = use_signal(|| 0usize); + let mut words = use_signal(String::new); + let mut expanded: Signal<Option<usize>> = use_signal(|| None); + let mut tag: Signal<Option<String>> = use_signal(|| None); + let api_r = api.clone(); + let found = use_resource(move || { + let api = api_r.clone(); + let _ = (ui.changed)(); + let mut a = serde_json::json!({ "name": view(), "words": words() }); + if let Some(t) = tag() { + a["tag"] = serde_json::json!(t); + } + async move { api.call("views.run", a).await } + }); + let api_v = api.clone(); + let views = use_resource(move || { + let api = api_v.clone(); + let _ = (ui.changed)(); + async move { + api.call("views.list", serde_json::json!({})) + .await + .ok() + .and_then(|v| v.as_array().cloned()) + .unwrap_or_default() + } + }); + let views = views.read().clone().unwrap_or_default(); + // each note's dates, for its card (as the Bevy reader showed them) + let api_n = api.clone(); + let dates = use_resource(move || { + let api = api_n.clone(); + let _ = (ui.changed)(); + async move { + api.notes(&crate::backend::NoteQuery::default()) + .await + .unwrap_or_default() + .into_iter() + .map(|n| (n.key.clone(), (n.created.clone(), n.modified.clone(), n.edits))) + .collect::<std::collections::HashMap<_, _>>() + } + }); + let dates = dates.read().clone().unwrap_or_default(); + let got: Value = match &*found.read() { + Some(Ok(v)) => v.clone(), + _ => Value::Null, + }; + let fail = match &*found.read() { + Some(Err(e)) => Some(e.clone()), + _ => None, + }; + let raw: Vec<Value> = got["hits"].as_array().cloned().unwrap_or_default(); + let all: Vec<Hit> = raw + .iter() + .filter_map(|h| serde_json::from_value(h.clone()).ok()) + .collect(); + let fx: Vec<Value> = raw.iter().map(|h| h["fx"].clone()).collect(); + // a group's heading goes before its first text + let heads: std::collections::HashMap<usize, (String, u64)> = got["groups"] + .as_array() + .into_iter() + .flatten() + .filter(|g| !g["name"].as_str().unwrap_or("").is_empty()) + .map(|g| { + ( + g["from"].as_u64().unwrap_or(0) as usize, + ( + g["name"].as_str().unwrap_or("").to_string(), + g["count"].as_u64().unwrap_or(0), + ), + ) + }) + .collect(); + let layout = got["layout"].as_str().unwrap_or("auto").to_string(); + let title = got["title"].as_str().unwrap_or("").to_string(); + let builtin = views + .iter() + .any(|v| v["name"] == view().as_str() && v["builtin"] == true); + let tiny = match layout.as_str() { + "grid" => true, + "cards" | "list" => false, + _ => all.iter().filter(|h| h.text.chars().count() <= 40 && !h.note).count() * 2 > all.len(), + }; + let listed = layout == "list"; + let per = if tiny || listed { 240 } else { 48 }; + let pages = all.len().div_ceil(per).max(1); + let p = page().min(pages - 1); + let n = all.len(); + let total = got["total"].as_u64().map(|t| t as usize).unwrap_or(n); + use_keys(View::Reader, move |k: KeyPress| { + if k.bar && k.key == "Enter" { + words.set(k.text.trim().to_string()); + page.set(0); + expanded.set(None); + return true; + } + if k.bar { + return false; + } + let step = match k.action { + Some(Action::ReadNext) => 1, + Some(Action::ReadPrev) => -1, + _ => 0, + }; + match (k.key.as_str(), step, expanded()) { + ("Escape", _, Some(_)) => expanded.set(None), + (_, 1, Some(i)) => expanded.set(Some((i + 1).min(n.saturating_sub(1)))), + (_, -1, Some(i)) => expanded.set(Some(i.saturating_sub(1))), + (_, 1, None) => page.set((p + 1).min(pages - 1)), + (_, -1, None) => page.set(p.saturating_sub(1)), + _ => return false, + } + true + }); + if let Some(i) = expanded() + && let Some(h) = all.get(i).cloned() + { + return rsx! { + Expanded { + hit: h, + i, + n, + on_close: move |_| expanded.set(None), + on_step: move |d: i64| expanded.set(Some((i as i64 + d).clamp(0, n as i64 - 1) as usize)), + on_tag: move |t: String| { + tag.set(Some(t)); + page.set(0); + expanded.set(None); + }, + } + }; + } + let shown: Vec<(usize, Hit)> = all.into_iter().enumerate().skip(p * per).take(per).collect(); + rsx! { + div { class: "page", style: "max-width: 1200px;", + div { class: "row", + h2 { "reader" } + for v in views.iter() { + { + let name = v["name"].as_str().unwrap_or("").to_string(); + let own = v["builtin"] != true; + let tip = if own { format!("your view: the s program “{name}”") } else { v["about"].as_str().unwrap_or("").to_string() }; + rsx! { + button { key: "{name}", class: if view() == name { if own { "chip on own" } else { "chip on" } } else if own { "chip own" } else { "chip" }, + "data-tip": "{tip}", + onclick: { let n = name.clone(); move |_| { view.set(n.clone()); page.set(0); expanded.set(None); } }, + if own { Icon { name: "editor" } } "{name}" } + } + } + } + span { class: "dim small", "{total} found" if total > n { " (the first {n} here)" } if !words().is_empty() { " for “{words}”" } " · click one to read it big" } + if !builtin && !title.is_empty() { + span { class: "small view-title", "{title}" } + } + if let Some(t) = tag() { + button { class: "chip on", "data-tip": "show them all again", onclick: move |_| { tag.set(None); page.set(0); }, "#{t}" span { class: "x", " ×" } } + } + } + if let Some(e) = fail { + div { class: "card bad", "{e}" } + } + div { class: if listed { "reader-list" } else if tiny { "reader-grid tiny" } else { "reader-grid" }, + for (i , h) in shown { + div { key: "{h.key}", style: "display: contents;", + if let Some((g, c)) = heads.get(&i) { + h3 { class: "reader-head", "{g}" span { class: "dim small", " {c}" } } + } + div { + class: if listed { "rrow" } else if tiny { "card rcard tiny" } else { "card rcard" }, + style: fx_style(&fx[i]), + tabindex: "0", + role: "button", + title: "{h.text}", + onclick: move |_| expanded.set(Some(i)), + onkeydown: move |e: KeyboardEvent| if e.key() == Key::Enter { expanded.set(Some(i)) }, + if h.note { + h3 { "{h.text}" } + { + let d = dates.get(h.key.trim_start_matches("note:")).cloned(); + rsx! { + span { class: "dim small rdate", + match d { + Some((c, m, e)) => rsx! { + "{short_date(&c)}" + if e > 0 && !m.is_empty() && m != c { " · edited {relative(&m)}" } + }, + None => rsx! { "a note" }, + } + } + } + } + } else { + div { class: "body", "{h.text}" } + } + if let Some(l) = fx[i]["label"].as_str() { + span { class: "fx-label", "{l}" } + } + } + } + } + } + if pages > 1 { + div { class: "pager", + button { "aria-label": "the page before", disabled: p == 0, onclick: move |_| page.set(p.saturating_sub(1)), Icon { name: "chevron-left" } } + span { "page {p + 1} of {pages}" } + button { "aria-label": "the next page", disabled: p + 1 >= pages, onclick: move |_| page.set(p + 1), Icon { name: "chevron-right" } } + } + } + } + } +} + +/// a pipe's effects on a card: its colour as the left edge, its glow, its size +fn fx_style(fx: &Value) -> String { + let mut s = String::new(); + if let Some(c) = fx["colour"].as_str() { + s.push_str(&format!("border-left: 5px solid {c};")); + } + if let Some(c) = fx["underline"].as_str() { + s.push_str(&format!("text-decoration: underline; text-decoration-color: {c};")); + } + if let Some(c) = fx["glow"].as_str() { + s.push_str(&format!("box-shadow: 0 0 10px {c};")); + } + if let Some(z) = fx["size"].as_f64() { + s.push_str(&format!("font-size: {z:.2}em;")); + } + s +} + +/// a card's date: `19 October 2026` +fn short_date(iso: &str) -> String { + chrono::DateTime::parse_from_rfc3339(iso) + .map(|t| t.with_timezone(&chrono::Local).format("%-d %B %Y").to_string()) + .unwrap_or_default() +} + +/// how long ago, in words +fn relative(iso: &str) -> String { + let full = long_date(iso); + full.rsplit_once('(') + .map(|(_, r)| r.trim_end_matches(')').to_string()) + .unwrap_or(full) +} + +/// a date for people: `19 Oct 2026, 08:46`, and how long ago +fn long_date(iso: &str) -> String { + let Ok(t) = chrono::DateTime::parse_from_rfc3339(iso) else { + return String::new(); + }; + let local = t.with_timezone(&chrono::Local); + let ago = chrono::Local::now().signed_duration_since(local); + let rel = if ago.num_days() >= 365 { + format!("{} years ago", ago.num_days() / 365) + } else if ago.num_days() >= 30 { + format!("{} months ago", ago.num_days() / 30) + } else if ago.num_days() >= 1 { + format!("{} days ago", ago.num_days()) + } else if ago.num_hours() >= 1 { + format!("{} hours ago", ago.num_hours()) + } else if ago.num_minutes() >= 1 { + format!("{} minutes ago", ago.num_minutes()) + } else { + "just now".into() + }; + format!("{} ({rel})", local.format("%A %-d %B %Y, %H:%M")) +} + +#[component] +fn Expanded( + hit: Hit, + i: usize, + n: usize, + on_close: EventHandler<()>, + on_step: EventHandler<i64>, + on_tag: EventHandler<String>, +) -> Element { + let mut ui = ui(); + let api = api(); + let key = hit.key.clone(); + let note = hit.note; + let api_b = api.clone(); + let body = use_resource(move || { + let api = api_b.clone(); + let key = key.clone(); + async move { if note { api.note(&key).await.ok() } else { None } } + }); + // when it was written and last changed (any entry) + let k2 = hit.key.clone(); + let info = use_resource(move || { + let api = api.clone(); + let k = k2.clone(); + async move { api.call("entries.info", serde_json::json!({ "key": k })).await.ok() } + }); + let mut judging = use_signal(|| true); + let n_body = body.read().clone().flatten(); + let info = info.read().clone().flatten(); + let created = info + .as_ref() + .and_then(|v| v["created"].as_str()) + .unwrap_or("") + .to_string(); + let edited = info + .as_ref() + .and_then(|v| v["edited"].as_str()) + .unwrap_or("") + .to_string(); + let kind = info.as_ref().and_then(|v| v["kind"].as_str()).unwrap_or("").to_string(); + let edits = n_body.as_ref().map(|n| n.edits.len()).unwrap_or(0); + let tags = n_body.as_ref().map(|n| n.tags.clone()).unwrap_or_default(); + let md = n_body.as_ref().map(|n| n.markdown.clone()).unwrap_or_default(); + let open_key = hit.key.clone(); + rsx! { + div { class: "card expand", + div { class: "row", + button { class: "plain", "aria-label": "back", onclick: move |_| on_close.call(()), Icon { name: "chevron-left" } "back" } + span { class: "grow" } + if note { + button { class: "plain", "data-tip": "edit it in the notes view", "aria-label": "edit", + onclick: move |_| { + ui.open_note.set(Some(open_key.clone())); + crate::shell::go(ui, View::Notes); + }, + Icon { name: "edit" } "edit" } + } + button { class: if judging() { "plain on" } else { "plain" }, "data-tip": "how it measures on your classifiers", "aria-label": "classifiers", + onclick: move |_| judging.set(!judging()), Icon { name: "classifier" } } + button { class: "plain", "aria-label": "the one before", "data-tip": "the one before · {ui.key_of(Action::ReadPrev)}", disabled: i == 0, onclick: move |_| on_step.call(-1), Icon { name: "chevron-left" } } + span { class: "dim", "{i + 1} of {n}" } + button { class: "plain", "aria-label": "the next one", "data-tip": "the next one · {ui.key_of(Action::ReadNext)}", disabled: i + 1 >= n, onclick: move |_| on_step.call(1), Icon { name: "chevron-right" } } + } + if hit.note { + h2 { "{hit.text}" } + } + div { class: "dates dim small", + if !created.is_empty() { span { "written " b { "{long_date(&created)}" } } } + if !edited.is_empty() && edited != created { span { " · last changed " b { "{long_date(&edited)}" } } } + if edits > 0 { span { " · {edits} edit" if edits != 1 { "s" } } } + if !kind.is_empty() { span { " · a {kind}" } } + } + if !tags.is_empty() { + div { class: "row", + for t in tags { + button { key: "{t}", class: "chip", "data-tip": "the notes tagged #{t}", onclick: { let t = t.clone(); move |_| on_tag.call(t.clone()) }, "#{t}" } + } + } + } + if hit.note { + div { class: "md", dangerous_inner_html: crate::md::to_html(&md) } + } else { + div { class: "text", style: "font-size: 1.6em;", "{hit.text}" } + } + div { class: "dim small", "{hit.key} · {crate::gem::gsum_line(&hit.text)}" } + if judging() { + crate::views::judge::Judge { key: "{hit.key}", entry: hit.key.clone(), title: "how it measures on:" } + } + } + } +} diff --git a/app/src/views/scode.rs b/app/src/views/scode.rs new file mode 100644 index 00000000..9c7a935d --- /dev/null +++ b/app/src/views/scode.rs @@ -0,0 +1,201 @@ +//! The notes view as s's code editor (docs/s.md; queued requests #11, #12): what it knows of +//! a program's text. An outline of what the program defines (scripts, `name$`; words, +//! `value word ><`) and the other programs it calls (`name.`), the word at a place (for +//! go to definition), and the words to complete a prefix with. + +use anend_core::s::lex::{Tok, lex_spans}; + +/// one thing in the outline: its name, what it is, and where (a byte offset in the code) +#[derive(Clone, Debug, PartialEq)] +pub struct Item { + pub name: String, + /// `script` (`name$`), `word` (`value word ><`) or `call` (`name.` of another program) + pub kind: &'static str, + pub at: usize, +} + +/// a word without the suffix that makes it a form: `loop.` and `loop..` are `loop` +pub fn stem(w: &str) -> &str { + let w = w.strip_suffix("..").unwrap_or(w); + if w.chars().count() >= 2 + && let Some(last) = w.chars().last() + && anend_core::s::machine::SUFFIXES.contains(&last) + { + return &w[..w.len() - last.len_utf8()]; + } + w +} + +/// what the program defines, in order, and the programs it calls (by `titles`) +pub fn outline(code: &str, titles: &[String]) -> Vec<Item> { + let Ok(toks) = lex_spans(code) else { return vec![] }; + let mut out: Vec<Item> = Vec::new(); + for (i, (t, r)) in toks.iter().enumerate() { + let Tok::Word(w) = t else { continue }; + if w == "><" { + // the word defined is the token before + let name = match i.checked_sub(1).map(|j| &toks[j].0) { + Some(Tok::Word(x)) | Some(Tok::Quote(x)) => x.clone(), + _ => continue, + }; + out.push(Item { + name, + kind: "word", + at: toks[i - 1].1.start, + }); + } else if w.len() >= 2 && w.ends_with('$') && !w.ends_with("$$") { + out.push(Item { + name: w[..w.len() - 1].to_string(), + kind: "script", + at: r.start, + }); + } else if (w.ends_with('.') || w.ends_with("..")) && w.len() >= 2 { + let s = stem(w); + if titles.iter().any(|t| t == s || format!("{t}.s") == s) + && !out.iter().any(|x| x.kind == "call" && x.name == s) + { + out.push(Item { + name: s.to_string(), + kind: "call", + at: r.start, + }); + } + } + } + out +} + +/// the word around a place (a byte offset): its start, its end and its text; words run +/// between whitespace and braces or quotes +pub fn word_at(text: &str, at: usize) -> Option<(usize, usize, &str)> { + let at = at.min(text.len()); + if !text.is_char_boundary(at) { + return None; + } + let edge = |c: char| c.is_whitespace() || matches!(c, '{' | '}' | '\''); + let a = text[..at] + .char_indices() + .rev() + .find(|(_, c)| edge(*c)) + .map_or(0, |(i, c)| i + c.len_utf8()); + let b = text[at..] + .char_indices() + .find(|(_, c)| edge(*c)) + .map_or(text.len(), |(i, _)| at + i); + (a < b).then(|| (a, b, &text[a..b])) +} + +/// the word being typed before a place: its text (a prefix, empty when none) +pub fn prefix_at(text: &str, at: usize) -> &str { + match word_at(text, at) { + Some((a, _, _)) if a < at && text.is_char_boundary(at) => &text[a..at], + _ => "", + } +} + +/// the words a prefix may be (shortest first, then alphabetical), not itself, at most `n` +pub fn complete(prefix: &str, words: &[String], n: usize) -> Vec<String> { + if prefix.is_empty() || prefix.chars().all(|c| c.is_ascii_digit() || c == '.' || c == '-') { + return vec![]; + } + let mut c: Vec<String> = words + .iter() + .filter(|w| w.starts_with(prefix) && w.as_str() != prefix) + .cloned() + .collect(); + c.sort_by(|a, b| a.len().cmp(&b.len()).then(a.cmp(b))); + c.dedup(); + c.truncate(n); + c +} + +/// a byte offset's line, counted from 0 +pub fn line_of(text: &str, at: usize) -> usize { + text.as_bytes()[..at.min(text.len())] + .iter() + .filter(|b| **b == b'\n') + .count() +} + +/// where a note's body starts in its whole text: after its `# title` line and the blank +/// space after it (as `note::split` takes the body, without trimming its end) +pub fn body_offset(text: &str) -> usize { + let mut at = 0; + for line in text.split_inclusive('\n') { + if line.trim_start().starts_with('#') { + let after = at + line.len(); + let rest = &text[after..]; + return after + (rest.len() - rest.trim_start().len()); + } + at += line.len(); + } + // no title: the body is the text, from its first non-blank character + text.len() - text.trim_start().len() +} + +/// the bar's `Run <program> [arguments]`: the save's s program of that title, run; what it +/// wrote shown, or its error. True when the bar's text was a `Run` +pub async fn run_from_bar(ui: crate::ui::Ui, api: &crate::ui::Api, text: &str) -> bool { + let Some(rest) = text.trim().strip_prefix("Run ") else { + return false; + }; + let mut words = rest.split_whitespace(); + let Some(title) = words.next().map(|t| t.strip_suffix(".s").unwrap_or(t).to_string()) else { + return false; + }; + let args: Vec<String> = words.map(str::to_string).collect(); + let progs = api.call("s.programs", serde_json::json!({})).await.unwrap_or_default(); + let Some(key) = progs + .as_array() + .into_iter() + .flatten() + .find(|p| p["title"] == title.as_str()) + .and_then(|p| p["key"].as_str().map(str::to_string)) + else { + ui.fail(format!("the save has no s program titled “{title}” (a note tagged s)")); + return true; + }; + match api.call("s.run", serde_json::json!({ "key": key, "args": args })).await { + Ok(r) => { + let out = r["out"].as_str().unwrap_or("").trim_start_matches('\n').to_string(); + match r["err"].as_str() { + Some(e) => ui.fail(format!("{title}: {e}")), + None => ui.toast(if out.trim().is_empty() { + format!("{title} ran ({} steps)", r["steps"]) + } else { + out + }), + } + } + Err(e) => ui.fail(e), + } + true +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn outline_words_and_completion() { + let code = "{n~ 0 >> step.?} loop$\n{1 +} 'inc' ><\nworld who@ greet.\nloop.."; + let o = outline(code, &["greet".to_string()]); + let names: Vec<(&str, &str)> = o.iter().map(|i| (i.name.as_str(), i.kind)).collect(); + assert_eq!(names, [("loop", "script"), ("inc", "word"), ("greet", "call")]); + assert_eq!(&code[o[0].at..o[0].at + 5], "loop$"); + assert_eq!(stem("loop.."), "loop"); + assert_eq!(stem("a~"), "a"); + assert_eq!(stem(">"), ">"); + let at = code.find("greet").unwrap() + 2; + assert_eq!(word_at(code, at).unwrap().2, "greet."); + assert_eq!(prefix_at(code, at), "gr"); + assert_eq!(word_at("{abc}", 2).unwrap().2, "abc"); + let words: Vec<String> = ["loop", "load", "lo", "l"].iter().map(|s| s.to_string()).collect(); + assert_eq!(complete("lo", &words, 5), ["load", "loop"]); + assert!(complete("12", &words, 5).is_empty()); + assert_eq!(line_of(code, code.find("world").unwrap()), 2); + assert_eq!(body_offset("# t\n\nbody"), 5); + assert_eq!(body_offset("# t\n\n{a} >\n\n"), 5); + assert_eq!(body_offset(" x"), 2); + } +} diff --git a/app/src/views/settings.rs b/app/src/views/settings.rs new file mode 100644 index 00000000..d0d6180e --- /dev/null +++ b/app/src/views/settings.rs @@ -0,0 +1,1064 @@ +//! Settings: a dialog that closes on a click outside it (or Esc), its sections folding +//! (remembered), separated by rules. Looks, the memory view, the space, the saves (open, +//! new, copy, rename, delete, a backup, and importing weum's all-of-it.json step by step), +//! the keys, and the hub (folded; absent without the `hub` feature). + +use dioxus::prelude::*; + +use crate::backend::{Imported, SaveInfo}; +use crate::keys::{Action, Binding, Scope}; +use crate::shell::set_pref; +use crate::theme::{PALETTES, ROLES, colour}; +use crate::ui::*; +use crate::views::Fold; + +#[component] +pub fn Settings() -> Element { + let mut ui = ui(); + let mut forge = use_signal(|| false); + if forge() { + return rsx! { crate::views::forge::Forge { on_close: move |_| forge.set(false) } }; + } + rsx! { + div { + class: "overlay", + onclick: move |_| ui.settings.set(false), + div { + class: "dialog", + role: "dialog", + "aria-modal": "true", + "aria-label": "settings", + onclick: move |e| e.stop_propagation(), + div { class: "head", + h2 { "settings" } + span { class: "grow" } + button { class: "plain", "data-tip": "the forge: a save from other saves", onclick: move |_| forge.set(true), Icon { name: "forge" } "forge" } + a { class: "btn plain", href: "https://github.com/SaulDoesCode/anend/blob/main/docs/guide.md", target: "_blank", rel: "noopener", "data-tip": "the guide (opens in a browser)", Icon { name: "help" } "guide" } + button { class: "plain ibtn close tip-left", "data-tip": "close · Esc", "aria-label": "close", + onclick: move |_| ui.settings.set(false), Icon { name: "close" } } + } + Looks {} + hr {} + MemorySettings {} + hr {} + Saves {} + hr {} + GpuSettings {} + hr {} + LimitSettings {} + hr {} + Keys {} + if cfg!(feature = "hub") { + hr {} + crate::views::hubui::Hub {} + } + } + } + } +} + +#[component] +fn Looks() -> Element { + let ui = ui(); + let p = ui.prefs.read().clone(); + // the desktop lists the installed families; the web offers common ones + let font_names: Vec<String> = match crate::fonts::system() { + Some(all) if !all.is_empty() => std::iter::once("Fira Sans".to_string()) + .chain(all.iter().cloned()) + .collect(), + _ => crate::fonts::COMMON.iter().map(|s| s.to_string()).collect(), + }; + // the role whose colour the hue / saturation / lightness editor holds + let mut editing: Signal<Option<&'static str>> = use_signal(|| None); + rsx! { + Fold { name: "looks", title: "looks", + label { "palette" } + div { class: "row", + for name in PALETTES { + button { + key: "{name}", + class: if p.palette == name { "on" } else { "" }, + onclick: move |_| set_pref(ui, |p| { p.palette = name.to_string(); p.colours.clear(); }), + "{name}" + } + } + } + label { "your colours" } + div { class: "swatches", + for (role , _) in ROLES { + label { key: "{role}", + input { + r#type: "color", + value: "{colour(&p.palette, &p.colours, role)}", + "aria-label": "{role}", + oninput: move |e| set_pref(ui, |p| { p.colours.insert(role.to_string(), e.value()); }), + } + "{role}" + } + } + if !p.colours.is_empty() { + button { class: "plain", onclick: move |_| set_pref(ui, |p| p.colours.clear()), "the palette's own" } + } + } + label { r#for: "hsl-role", "edit a colour" } + div { class: "hsl-edit", + select { id: "hsl-role", value: editing().unwrap_or(""), + onchange: move |e| { let v = e.value(); editing.set(ROLES.iter().map(|r| r.0).find(|r| *r == v)); }, + option { value: "", "pick a role…" } + for (role, _) in ROLES { + option { key: "{role}", value: "{role}", selected: editing() == Some(role), "{role}" } + } + } + if let Some(role) = editing() { + HslEditor { key: "{role}", role, hex: colour(&p.palette, &p.colours, role) } + } + } + label { r#for: "fs", "text size" } + div { class: "row", + input { id: "fs", r#type: "range", min: "11", max: "22", step: "0.5", value: "{p.font_size}", + oninput: move |e| set_pref(ui, |p| p.font_size = e.value().parse().unwrap_or(14.0)) } + span { "{p.font_size}px" } + } + label { "zen" } + div { class: "row", + label { class: "row", input { r#type: "checkbox", checked: p.zen, onchange: move |e| set_pref(ui, |p| p.zen = e.checked()) } "fade the bars while you rest" } + input { r#type: "range", min: "0.5", max: "10", step: "0.5", value: "{p.zen_delay}", "aria-label": "seconds before zen fades", + oninput: move |e| set_pref(ui, |p| p.zen_delay = e.value().parse().unwrap_or(2.5)) } + span { "after {p.zen_delay}s" } + } + label { "the top bar" } + label { class: "row", input { r#type: "checkbox", checked: p.hide_bar, onchange: move |e| set_pref(ui, |p| p.hide_bar = e.checked()) } "slide it away until the pointer comes near the top" } + label { "the bars" } + label { class: "row", input { r#type: "checkbox", checked: p.bars_swapped, onchange: move |e| set_pref(ui, |p| p.bars_swapped = e.checked()) } "the top bar at the bottom, and the command bar at the top" } + label { r#for: "tbh", "sizes" } + div { class: "row", + "top bar" input { id: "tbh", r#type: "range", min: "24", max: "64", step: "1", value: "{p.top_bar}", oninput: move |e| set_pref(ui, |p| p.top_bar = e.value().parse().unwrap_or(32.0)) } span { "{p.top_bar}px" } + "command bar" input { r#type: "range", min: "24", max: "64", step: "1", value: "{p.bottom_bar}", "aria-label": "the command bar's height", oninput: move |e| set_pref(ui, |p| p.bottom_bar = e.value().parse().unwrap_or(32.0)) } span { "{p.bottom_bar}px" } + button { class: "plain", onclick: move |_| set_pref(ui, |p| { p.top_bar = 32.0; p.bottom_bar = 32.0; p.font_size = 14.0; p.zoom = 1.0; }), "default sizes" } + } + label { r#for: "font", "fonts" } + div { class: "row", + input { id: "font", r#type: "text", list: "fontlist", placeholder: "Fira Sans (built in)", initial_value: "{p.font}", "aria-label": "the interface's font", oninput: move |e| set_pref(ui, |p| p.font = e.value()) } + input { r#type: "text", list: "fontlist", placeholder: "the memory view: system serif", initial_value: "{p.memory_family}", "aria-label": "the memory view's font", oninput: move |e| set_pref(ui, |p| p.memory_family = e.value()) } + datalist { id: "fontlist", + for f in font_names.iter() { option { key: "{f}", value: "{f}" } } + } + span { class: "dim small", + if let Some(n) = crate::fonts::system().map(<[String]>::len) { + "one of this machine's {n} families (type to narrow them); empty for the built-in" + } else { + "a font's name as the system knows it; empty for the built-in" + } + } + } + label { "the editor" } + div { class: "row", + label { class: "row", input { r#type: "checkbox", checked: p.highlight, onchange: move |e| set_pref(ui, |p| p.highlight = e.checked()) } "colour the markdown (headings, emphasis, code, links, tags…)" } + label { class: "row", input { r#type: "checkbox", checked: p.list_right, onchange: move |e| set_pref(ui, |p| p.list_right = e.checked()) } "the note list on the right" } + } + label { r#for: "zoom", "zoom" } + div { class: "row", + input { id: "zoom", r#type: "range", min: "0.5", max: "3", step: "0.05", value: "{p.zoom}", + oninput: move |e| set_pref(ui, |p| p.zoom = e.value().parse().unwrap_or(1.0)) } + span { "{(p.zoom * 100.0).round()}%" } + span { class: "dim small", "Ctrl+= / Ctrl+− or Ctrl+PageUp / PageDown; Ctrl+0 resets" } + } + } + } +} + +#[component] +fn MemorySettings() -> Element { + let ui = ui(); + let p = ui.prefs.read().clone(); + rsx! { + Fold { name: "memory", title: "the memory view and the space", + label { r#for: "mfs", "texts' size" } + div { class: "row", + input { id: "mfs", r#type: "range", min: "12", max: "40", step: "1", value: "{p.memory_font}", + oninput: move |e| set_pref(ui, |p| p.memory_font = e.value().parse().unwrap_or(20.0)) } + span { "{p.memory_font}px" } + } + label { r#for: "pline", "long texts, shown piece by piece" } + div { class: "row", + input { id: "pline", r#type: "number", min: "10", max: "400", step: "1", value: "{p.piece_line}", style: "width: 5em;", + onchange: move |e| set_pref(ui, |p| p.piece_line = e.value().parse::<usize>().unwrap_or(80).clamp(10, 400)) } + span { "characters a line," } + input { r#type: "number", "aria-label": "lines a piece", min: "1", max: "200", step: "1", value: "{p.piece_lines}", style: "width: 4em;", + onchange: move |e| set_pref(ui, |p| p.piece_lines = e.value().parse::<usize>().unwrap_or(6).clamp(1, 200)) } + span { "lines a piece" } + span { class: "dim small", "a longer text shows its first piece, and opens into the rest" } + } + label { r#for: "msp", "space between texts" } + div { class: "row", + input { id: "msp", r#type: "range", min: "0", max: "24", step: "1", value: "{p.spacing}", + oninput: move |e| set_pref(ui, |p| p.spacing = e.value().parse().unwrap_or(4.0)) } + span { "{p.spacing}px" } + } + label { "the centre field" } + div { class: "row", + span { if p.field_width > 0.0 { "{p.field_width.round()}px wide" } else { "the whole width" } } + button { class: "plain", onclick: move |_| set_pref(ui, |p| p.field_width = 0.0), "whole width" } + span { class: "dim small", "or drag its edges" } + } + label { r#for: "sbg", "the space's background" } + div { class: "row", + input { id: "sbg", r#type: "color", value: "{p.space_bg}", + oninput: move |e| set_pref(ui, |p| p.space_bg = e.value()) } + for (name , c) in [("sand", "#e4d4be"), ("night", "#14120f"), ("deep", "#0b1622"), ("paper", "#f4f1ea")] { + button { key: "{name}", class: "plain", onclick: move |_| set_pref(ui, |p| p.space_bg = c.to_string()), "{name}" } + } + } + } + } +} + +#[derive(Clone, PartialEq)] +enum Step { + Closed, + /// the file read: its rows and a sample + Read { + target: String, + data: String, + rows: usize, + sample: Vec<String>, + }, + Importing, + Done(Imported), +} + +/// the open save's checkpoints (redb savepoints): made by hand with a name, gone back to +/// (dropping what changed since, and the checkpoints after it), deleted +#[component] +fn Checkpoints(on_back: EventHandler<()>) -> Element { + let ui = ui(); + let api = api(); + let mut rev = use_signal(|| 0u64); + let mut made = use_signal(|| 0u64); + let mut armed: Signal<Option<u64>> = use_signal(|| None); + let api_r = api.clone(); + let list = use_resource(move || { + let api = api_r.clone(); + let _ = (rev(), (ui.changed)()); + async move { api.call("saves.checkpoints", serde_json::json!({})).await } + }); + let cps: Vec<serde_json::Value> = match &*list.read() { + Some(Ok(v)) => v.as_array().cloned().unwrap_or_default(), + _ => vec![], + }; + let call = move |op: &'static str, args: serde_json::Value, said: String, back: bool| { + let api = api.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.call(op, args).await { + Ok(_) => { + ui.say(said); + rev += 1; + if back { + on_back.call(()); + } + } + Err(e) => ui.fail(e), + } + }); + }; + let when = |ms: u64| { + chrono::DateTime::from_timestamp_millis(ms as i64) + .map(|t| t.with_timezone(&chrono::Local).format("%d %b %Y, %H:%M").to_string()) + .unwrap_or_default() + }; + let call2 = call.clone(); + rsx! { + div { class: "checkpoints", + span { class: "dim small", "checkpoints of this save" } + if cps.is_empty() { + span { class: "dim small", " · none yet" } + } + for c in cps { + div { key: "{c[\"id\"]}", class: "row checkpoint", + Icon { name: "save" } + b { {c["name"].as_str().unwrap_or("").to_string()} } + span { class: "dim small", {when(c["at"].as_u64().unwrap_or(0))} } + span { class: "grow" } + button { + class: if armed() == c["id"].as_u64() { "armed" } else { "plain" }, + "data-tip": "go back to it: what changed since goes, and the checkpoints made after it (click twice)", + onclick: { let call = call.clone(); let id = c["id"].as_u64().unwrap_or(0); let n = c["name"].as_str().unwrap_or("").to_string(); move |_| { + if armed() != Some(id) { armed.set(Some(id)); return; } + armed.set(None); + call("saves.restore_checkpoint", serde_json::json!({ "id": id }), format!("back to the checkpoint {n}"), true); + } }, + Icon { name: "undo" } + if armed() == c["id"].as_u64() { "go back?" } else { "go back" } + } + button { class: "plain", "data-tip": "delete the checkpoint (the save stays as it is)", "aria-label": "delete the checkpoint", + onclick: { let call = call.clone(); let id = c["id"].as_u64().unwrap_or(0); move |_| call("saves.delete_checkpoint", serde_json::json!({ "id": id }), "checkpoint deleted".into(), false) }, + Icon { name: "delete" } } + } + } + div { class: "row", + // not bound while typing (a round trip per key drops fast letters); a new + // one after each checkpoint + // read when the button is pressed: re-rendering on every key dropped letters + // in the desktop's web view + for g in [made()] { + input { key: "{g}", id: "cp-name", r#type: "text", placeholder: "a name (or the time)", "aria-label": "the checkpoint's name" } + } + button { onclick: move |_| { + let call2 = call2.clone(); + spawn(async move { + let mut ev = document::eval("const i = document.getElementById('cp-name'); dioxus.send(i ? i.value : '');"); + let n: String = ev.recv().await.unwrap_or_default(); + call2("saves.checkpoint", serde_json::json!({ "name": n }), "checkpoint made".into(), false); + made += 1; + }); + }, + Icon { name: "save" } "a checkpoint now" } + } + } + } +} + +#[component] +fn Saves() -> Element { + let ui = ui(); + let api = api(); + let mut reload = use_signal(|| 0); + let api_r = api.clone(); + let saves = use_resource(move || { + let api = api_r.clone(); + let _ = reload(); + let _ = (ui.changed)(); + async move { api.saves().await } + }); + let mut name = use_signal(String::new); + let mut made = use_signal(|| 0u64); + let mut step = use_signal(|| Step::Closed); + let mut armed = use_signal(|| None::<String>); + let mut renaming: Signal<Option<(String, String)>> = use_signal(|| None); + let list: Vec<SaveInfo> = match &*saves.read() { + Some(Ok(v)) => v.clone(), + _ => vec![], + }; + let on_disk = api.on_disk(); + let api_k = use_signal(|| api.clone()); + // the desktop opens the save it had open last (`prefs.save`), so its folder too + let keep = move || { + if on_disk { + let path = api_k.peek().describe(); + set_pref(ui, |p| p.save = Some(path)); + } + }; + let act = move |f: crate::backend::Fut<()>, msg: String| { + dioxus::dioxus_core::spawn_forever(async move { + match f.await { + Ok(()) => { + ui.say(msg); + keep(); + reload += 1; + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + }; + let api_f = api.clone(); + let folder = use_resource(move || { + let api = api_f.clone(); + let _ = reload(); + async move { api.call("saves.folder", serde_json::json!({})).await } + }); + let folder_now = match &*folder.read() { + Some(Ok(v)) if v["can"].as_bool() == Some(true) => v["folder"].as_str().map(str::to_string), + _ => None, + }; + let mut folder_text = use_signal(String::new); + let mut folder_gen = use_signal(|| 0u64); + let use_folder = { + let api = api.clone(); + move || { + let api = api.clone(); + let path = folder_text(); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("saves.folder", serde_json::json!({ "path": path })).await { + Ok(v) => { + ui.say(format!( + "saves from {}: opened {}", + v["folder"].as_str().unwrap_or(""), + v["save"].as_str().unwrap_or("") + )); + keep(); + folder_text.set(String::new()); + folder_gen += 1; + reload += 1; + ui.touched(); + ui.refresh(api); + } + Err(e) => ui.fail(e), + } + }); + } + }; + rsx! { + Fold { name: "saves", title: "saves", + if let Some(f) = folder_now { + label { r#for: "savesfolder", "saves folder" } + div { class: "row", + for g in [folder_gen()] { + input { key: "{g}", id: "savesfolder", r#type: "text", style: "flex: 1; min-width: 12em;", + placeholder: "another folder, or a .redb file", + oninput: move |e| folder_text.set(e.value()), + onkeydown: { let u = use_folder.clone(); move |e: KeyboardEvent| if e.key() == Key::Enter { u() } } } + } + button { disabled: folder_text().trim().is_empty(), onclick: { let u = use_folder.clone(); move |_| u() }, + Icon { name: "folder" } "use it" } + span { class: "dim small", "now {f}. A folder lists its saves and opens the first (or makes a main); a .redb file opens that save, and its folder becomes the saves folder." } + } + } + div { class: "wide", + table { class: "saves", + thead { tr { th { "save" } th { "entries" } th { "size" } th { "" } } } + tbody { + for s in list { + tr { key: "{s.name}", class: if s.open { "open" } else { "" }, + td { "{s.name}" if s.open { span { class: "dim", " · open" } } } + td { {s.memories.map(|m| m.to_string()).unwrap_or_default()} } + td { "{s.size / 1024} kB" } + td { class: "row", + if !s.open { + button { class: "plain", "data-tip": "open it", "aria-label": "open", + onclick: { let api = api.clone(); let n = s.name.clone(); move |_| act(api.open_save(&n), format!("opened {n}")) }, + Icon { name: "open" } } + } + button { class: "plain", "data-tip": "a backup: its texts in one JSON, the rest in another", "aria-label": "backup", + onclick: { let api = api.clone(); let n = s.name.clone(); move |_| { + let api = api.clone(); let n = n.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.backup(&n).await { + Ok(b) if !b.paths.is_empty() => ui.say(format!("backed up: {}", b.paths.join(" and "))), + Ok(b) => { + let text = |v: &serde_json::Value| v.as_str().map(str::to_string).unwrap_or_else(|| v.to_string()); + download(&format!("{n} texts.json"), &text(&b.texts)); + download(&format!("{n} other.json"), &text(&b.other)); + ui.say("backed up: two downloads"); + } + Err(e) => ui.fail(e), + } + }); + } }, + Icon { name: "download" } } + button { class: "plain", "data-tip": "import weum's all-of-it.json into this save", "aria-label": "import", + onclick: { let n = s.name.clone(); move |_| step.set(Step::Read { target: n.clone(), data: String::new(), rows: 0, sample: vec![] }) }, + Icon { name: "upload" } } + button { class: "plain", "data-tip": "rename it", "aria-label": "rename", + onclick: { let n = s.name.clone(); move |_| renaming.set(Some((n.clone(), n.clone()))) }, + Icon { name: "rename" } } + button { class: "plain", "data-tip": "export a bundle (.anend.json): keys, lists, notes, classifiers and all", "aria-label": "export a bundle", + onclick: { let api = api.clone(); let n = s.name.clone(); move |_| { + let (api, n) = (api.clone(), n.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("saves.export", serde_json::json!({ "name": n })).await { + Ok(b) => { download(&format!("{n}.anend.json"), &b.to_string()); ui.say(format!("{n}.anend.json: a download")); } + Err(e) => ui.fail(e), + } + }); + } }, + Icon { name: "export" } } + button { class: "plain", "data-tip": "copy", "aria-label": "copy", + onclick: { let api = api.clone(); let n = s.name.clone(); move |_| act(api.copy_save(&n, ""), format!("copied {n}")) }, + Icon { name: "copy" } } + if !s.open { + button { + class: if armed() == Some(s.name.clone()) { "armed" } else { "plain" }, + "data-tip": "delete (click twice)", + "aria-label": "delete", + onclick: { let api = api.clone(); let n = s.name.clone(); move |_| { + if armed() == Some(n.clone()) { + armed.set(None); + act(api.delete_save(&n), format!("deleted {n}")); + } else { + armed.set(Some(n.clone())); + } + } }, + Icon { name: "delete" } + if armed() == Some(s.name.clone()) { "delete?" } + } + } + } + } + if s.open { + tr { key: "{s.name} checkpoints", class: "checkpoints-row", + td { colspan: "4", Checkpoints { on_back: move |_| { reload += 1; ui.touched(); } } } + } + } + } + } + } + } + label { r#for: "newsave", "a new save" } + div { class: "row", + for g in [made()] { + input { key: "{g}", id: "newsave", r#type: "text", placeholder: "its name", initial_value: "{name}", oninput: move |e| name.set(e.value()) } + } + button { onclick: { let api = api.clone(); move |_| { let n = name(); act(api.new_save(&n), format!("made and opened {n}")); name.set(String::new()); made += 1; } }, + Icon { name: "new" } "make it" } + button { class: "plain", onclick: move |_| step.set(Step::Read { target: String::new(), data: String::new(), rows: 0, sample: vec![] }), + Icon { name: "upload" } "a new save from all-of-it.json" } + } + if let Some((from, to)) = renaming() { + label { "rename “{from}”" } + div { class: "row", + input { r#type: "text", initial_value: "{to}", "aria-label": "its new name", oninput: move |e| { let f = from.clone(); renaming.set(Some((f, e.value()))) } } + button { class: "primary", onclick: { let api = api.clone(); move |_| { + if let Some((f, t)) = renaming() { act(api.rename_save(&f, &t), format!("renamed {f} to {t}")); } + renaming.set(None); + } }, "rename" } + button { class: "plain", onclick: move |_| renaming.set(None), "cancel" } + } + } + label { "a bundle" } + div { class: "row", + label { class: "button btn", Icon { name: "upload" } "import a bundle (.anend.json) as a new save" + input { r#type: "file", accept: ".json,.anend.json", style: "display: none;", + onchange: { let api = api.clone(); move |e: FormEvent| { + let api = api.clone(); + let files = e.files(); + spawn(async move { + let Some(f) = files.into_iter().next() else { return }; + let text = match f.read_string().await { Ok(t) => t, Err(e) => return ui.fail(e.to_string()) }; + let Ok(b) = serde_json::from_str::<serde_json::Value>(&text) else { return ui.fail("that isn't a bundle (JSON)") }; + match api.import_bundle(b, "", false).await { + Ok(im) => { ui.say(format!("imported {} texts{}", im.memories, im.save.map(|s| format!(" into “{s}”")).unwrap_or_default())); reload += 1; ui.touched(); } + Err(e) => ui.fail(e), + } + }); + } }, + } + } + } + if step() != Step::Closed { + div { class: "wide import", + ImportSteps { step } + } + } + } + } +} + +/// importing weum's all-of-it.json: choose the file, see what's in it, import, done +#[component] +fn ImportSteps(step: Signal<Step>) -> Element { + let ui = ui(); + let api = api(); + let mut new_name = use_signal(|| "weum".to_string()); + let cur = step(); + let on_disk = api.on_disk(); + let mut path = use_signal(String::new); + let target_p = match &cur { + Step::Read { target, .. } => target.clone(), + _ => String::new(), + }; + let n = match &cur { + Step::Read { rows: 0, .. } => 1, + Step::Read { .. } => 2, + Step::Importing => 3, + _ => 4, + }; + rsx! { + div { class: "steps", + for (i , label) in ["1 the file", "2 what's in it", "3 importing", "4 done"].into_iter().enumerate() { + span { key: "{i}", class: if i + 1 == n { "on" } else { "" }, "{label}" } + } + span { class: "grow" } + button { class: "plain ibtn", "aria-label": "close the import", onclick: move |_| step.set(Step::Closed), Icon { name: "close" } } + } + match cur { + Step::Read { target, rows: 0, .. } => { + let t2 = target.clone(); + rsx! { + div { class: "row", + "weum's all-of-it.json (or a backup's texts.json):" + input { + r#type: "file", + accept: ".json,application/json", + onchange: move |e: FormEvent| { + let target = target.clone(); + async move { + let Some(f) = e.files().into_iter().next() else { return }; + match f.read_string().await { + Ok(data) => read_rows(ui, step, target, data), + Err(e) => ui.fail(format!("couldn't read it: {e}")), + } + } + }, + } + } + if on_disk { + div { class: "row", + "or its path:" + input { r#type: "text", placeholder: "/home/you/all-of-it.json", style: "flex: 1;", + oninput: move |e| path.set(e.value()), + onkeydown: move |e: KeyboardEvent| if e.key() == Key::Enter { read_path(ui, step, t2.clone(), path()) } } + button { onclick: move |_| read_path(ui, step, target_p.clone(), path()), "read it" } + } + } + } + } + Step::Read { target, data, rows, sample } => rsx! { + div { "{rows} rows. The first: " span { class: "dim", {sample.join(" · ")} } } + div { class: "row", + if target.is_empty() { + "into a new save named" + input { r#type: "text", initial_value: "{new_name}", oninput: move |e| new_name.set(e.value()) } + } else { + "into “{target}”: keys already there are replaced (the old text kept as a version)" + } + button { class: "primary", + onclick: move |_| { + let api = api.clone(); + let data = data.clone(); + let into_new = if target.is_empty() { new_name() } else { String::new() }; + let target = target.clone(); + step.set(Step::Importing); + dioxus::dioxus_core::spawn_forever(async move { + // into a save that isn't open: open it first + if !target.is_empty() + && target != ui.hello.peek().save + && let Err(e) = api.open_save(&target).await + { + ui.fail(e); + step.set(Step::Closed); + return; + } + match api.import_texts(&data, &into_new).await { + Ok(im) => { + step.set(Step::Done(im)); + ui.touched(); + } + Err(e) => { + ui.fail(e); + step.set(Step::Closed); + } + } + }); + }, + Icon { name: "upload" } + "import" + } + } + }, + Step::Importing => rsx! { div { "importing…" } }, + Step::Done(im) => rsx! { + div { "imported {im.memories} texts" if let Some(s) = im.save { " into “{s}”" } "." } + }, + Step::Closed => rsx! {}, + } + } +} + +/// a weum file's rows read: on to the step that shows what's in it +fn read_rows(ui: Ui, mut step: Signal<Step>, target: String, data: String) { + match serde_json::from_str::<serde_json::Value>(&data) { + Ok(serde_json::Value::Array(rows)) => { + let sample = rows + .iter() + .take(8) + .filter_map(|r| r.get(0).and_then(|t| t.as_str()).map(str::to_string)) + .collect(); + step.set(Step::Read { + target, + data, + rows: rows.len(), + sample, + }); + } + _ => ui.fail("that isn't a list of [text, [key bytes]] rows"), + } +} + +/// the desktop reads the file at a path typed in (when a file dialog isn't at hand) +fn read_path(ui: Ui, step: Signal<Step>, target: String, path: String) { + #[cfg(not(target_arch = "wasm32"))] + match std::fs::read_to_string(path.trim()) { + Ok(data) => read_rows(ui, step, target, data), + Err(e) => ui.fail(format!("couldn't read {}: {e}", path.trim())), + } + #[cfg(target_arch = "wasm32")] + { + let _ = (step, target, path); + ui.fail("pick the file instead"); + } +} + +/// what a `reading` answer says, in words +fn reading_words(r: &serde_json::Value) -> String { + let dev = match r["device"].as_str() { + Some("gpu") => "the GPU", + Some("gpu_fast") => "the GPU (fast)", + Some("cpu") => "the CPU", + _ => return String::new(), + }; + let mut s = format!("now on {dev}"); + if let Some(g) = r["gpu"].as_str() { + s += &format!(", {g}"); + } + if r["device"] != "cpu" { + s += if r["exact"] == true { + ", the CPU's results bit for bit" + } else { + ", within a small difference of the CPU's results" + }; + } + if let Some(n) = r["note"].as_str() { + s += &format!(": {n}"); + } + s +} + +/// the limits the open save sets for itself (`limits.*`), each a number with its default; +/// none caps how long a text can be +/// a colour as hue, saturation and lightness sliders and a hex box (the Bevy app's), each +/// change kept as the role's own colour +#[component] +fn HslEditor(role: &'static str, hex: String) -> Element { + let ui = ui(); + let (h, s, l) = crate::theme::hsl_of(&hex); + let set = move |h: f64, s: f64, l: f64| { + let c = crate::theme::hex_of_hsl(h, s.clamp(0.0, 1.0), l.clamp(0.0, 1.0)); + set_pref(ui, move |p| { + p.colours.insert(role.to_string(), c.clone()); + }); + }; + let mut draft = use_signal(|| hex.clone()); + rsx! { + div { class: "hsl-sliders", + span { class: "hsl-swatch", style: "background: {hex};" } + label { span { "hue" } + input { r#type: "range", min: "0", max: "359", step: "1", value: "{h.round()}", class: "hue", + oninput: move |e| set(e.value().parse().unwrap_or(h), s, l) } + span { class: "num", "{h.round()}°" } } + label { span { "saturation" } + input { r#type: "range", min: "0", max: "100", step: "1", value: "{(s * 100.0).round()}", + oninput: move |e| set(h, e.value().parse::<f64>().unwrap_or(s * 100.0) / 100.0, l) } + span { class: "num", "{(s * 100.0).round()}%" } } + label { span { "lightness" } + input { r#type: "range", min: "0", max: "100", step: "1", value: "{(l * 100.0).round()}", + oninput: move |e| set(h, s, e.value().parse::<f64>().unwrap_or(l * 100.0) / 100.0) } + span { class: "num", "{(l * 100.0).round()}%" } } + label { span { "hex" } + input { r#type: "text", value: "{hex}", "aria-label": "{role} as hex", style: "width: 7em;", + oninput: move |e| draft.set(e.value()), + onchange: move |_| { + let v = draft().trim().to_string(); + let v = if v.starts_with('#') { v } else { format!("#{v}") }; + if v.len() == 7 && v[1..].chars().all(|c| c.is_ascii_hexdigit()) { + set_pref(ui, move |p| { p.colours.insert(role.to_string(), v.to_lowercase()); }); + } else { + ui.fail("a colour in hex is like #a07850"); + } + } } } + } + } +} + +#[component] +fn LimitSettings() -> Element { + let ui = ui(); + let api = api(); + let mut rows = use_signal(Vec::<serde_json::Value>::new); + { + let api = api.clone(); + use_hook(move || { + spawn(async move { + if let Ok(v) = api.call("limits.list", serde_json::json!({})).await { + rows.set(v.as_array().cloned().unwrap_or_default()); + } + }); + }); + } + rsx! { + Fold { name: "limits", title: "limits of this save", + div { class: "wide dim small", "Limits the save sets for itself, with their defaults. Empty puts a default back. None of them limits how long a text can be." } + for r in rows() { + { + let name = r["name"].as_str().unwrap_or("").to_string(); + let label = name.trim_start_matches("limits.").trim_start_matches("graph.").replace('_', " "); + let id = format!("lim-{}", name.replace('.', "-")); + let api = api.clone(); + let n2 = name.clone(); + let value = r["value"].to_string(); + rsx! { + label { key: "{name}", r#for: "{id}", "{label}" } + div { class: "row", + input { id: "{id}", r#type: "number", min: "0", step: "1", style: "width: 9em;", + value: "{value}", + onchange: move |e| { + let (api, n) = (api.clone(), n2.clone()); + let v = e.value(); + spawn(async move { + match api.call("limits.set", serde_json::json!({ "name": n, "value": v })).await { + Ok(_) => { + if let Ok(v) = api.call("limits.list", serde_json::json!({})).await { + rows.set(v.as_array().cloned().unwrap_or_default()); + } + ui.say(format!("{n} set")); + } + Err(e) => ui.fail(e), + } + }); + } + } + span { class: "dim small", {format!("{} (default {})", r["about"].as_str().unwrap_or(""), r["default"])} } + } + } + } + } + } + } +} + +/// the GPU: where classifiers read texts (predict, search, indexing, buckets, tints), +/// and a report on this machine's GPU for the user to send back +#[component] +fn GpuSettings() -> Element { + let ui = ui(); + let api = api(); + let mut state = use_signal(|| serde_json::Value::Null); + let mut busy = use_signal(|| false); + let mut written = use_signal(String::new); + { + let api = api.clone(); + use_hook(move || { + spawn(async move { + if let Ok(v) = api.call("classify.device", serde_json::json!({})).await { + state.set(v); + } + }); + }); + } + let choice = ui.prefs.read().read_device.clone(); + let mut now = reading_words(&state.read()["reading"]); + if choice == "auto" && state.read()["reading"]["device"] == "gpu" { + // auto's answer depends on the model's size, measured on its first reading + now = format!( + "the GPU here, {}, gives the CPU's results bit for bit; auto reads on it with the model sizes it is faster for, measured on each size's first reading", + state.read()["reading"]["gpu"].as_str().unwrap_or("") + ); + } + let speeds: Vec<String> = state.read()["speeds"] + .as_array() + .map(|a| { + a.iter() + .filter_map(|s| s["words"].as_str().map(str::to_string)) + .collect() + }) + .unwrap_or_default(); + let again = { + let api = api.clone(); + move |_| { + let api = api.clone(); + spawn(async move { + match api + .call("classify.device", serde_json::json!({ "measure_again": true })) + .await + { + Ok(r) => { + state.set(r); + ui.say("each model size is measured again the next time it reads"); + } + Err(e) => ui.fail(e), + } + }); + } + }; + let set = { + let api = api.clone(); + move |e: Event<FormData>| { + let v = e.value(); + set_pref(ui, |p| p.read_device = v.clone()); + let api = api.clone(); + spawn(async move { + match api.call("classify.device", serde_json::json!({ "device": v })).await { + Ok(r) => state.set(r), + Err(e) => ui.fail(e), + } + }); + } + }; + let report = move |_| { + let api = api.clone(); + busy.set(true); + ui.say("measuring the GPU and the CPU; this takes some minutes (about twenty on a software renderer)"); + spawn(async move { + let r = api.call("gpu.report", serde_json::json!({})).await; + busy.set(false); + let r = match r { + Ok(r) => r, + Err(e) => return ui.fail(e), + }; + let text = serde_json::to_string_pretty(&r).unwrap_or_default(); + let secs = (now_ms() / 1000.0) as u64; + let file = format!("gpu-report-{secs}.json"); + #[cfg(not(target_arch = "wasm32"))] + { + let dir = crate::prefs::data_dir().join("exports"); + let path = dir.join(&file); + match std::fs::create_dir_all(&dir).and_then(|_| std::fs::write(&path, &text)) { + Ok(()) => { + written.set(format!("written to {}", path.display())); + ui.say(format!("the GPU report is in {}", path.display())); + } + Err(e) => ui.fail(format!("couldn't write {}: {e}", path.display())), + } + } + #[cfg(target_arch = "wasm32")] + { + download(&file, &text); + written.set(format!("downloaded as {file}")); + ui.say(format!("the GPU report downloaded as {file}")); + } + }); + }; + rsx! { + Fold { name: "gpu", title: "the GPU", + label { r#for: "readdev", "classifiers read texts on" } + div { class: "row", + select { id: "readdev", onchange: set, + option { value: "auto", selected: choice == "auto", "auto: the GPU when it gives the CPU's results and is faster" } + option { value: "cpu", selected: choice == "cpu", "the CPU" } + option { value: "gpu", selected: choice == "gpu", "the GPU" } + option { value: "gpu_fast", selected: choice == "gpu_fast", "the GPU, fast" } + } + span { class: "dim small", "{now}" } + } + if !speeds.is_empty() { + label { "measured on this machine" } + div { class: "wide small", + for w in speeds.iter() { + div { "{w}" } + } + } + div { class: "row", + button { onclick: again, Icon { name: "refresh" } "measure again" } + span { class: "dim small", "forgets these rates; each model size is measured again on its next reading" } + } + } + div { class: "wide dim small", + "Predicting, classifier search, indexing, buckets, colouring by a classifier and filters by one. Training picks its device on the classifier's page." + } + label { "a report on this machine's GPU" } + div { class: "row", + button { disabled: busy(), onclick: report, Icon { name: "stats" } if busy() { "measuring…" } else { "write a GPU report" } } + span { class: "dim small", "the adapter and driver, its limits, whether every kernel gives the CPU's bits, and timings of a fixed training run and of reading up to 10 000 texts on the CPU and the GPU (two minutes at most on each); it takes some minutes, about twenty on a software renderer" } + } + if !written().is_empty() { + div { class: "wide small", "{written} — paste the file back to report how the GPU does" } + } + } + } +} + +/// a file handed to the viewer (the web build's backups) +pub fn download(name: &str, text: &str) { + let js = format!( + "const a = document.createElement('a'); a.href = URL.createObjectURL(new Blob([{}], {{type: 'application/json'}})); a.download = {}; a.click(); setTimeout(() => URL.revokeObjectURL(a.href), 4000);", + serde_json::to_string(text).unwrap_or_default(), + serde_json::to_string(name).unwrap_or_default() + ); + document::eval(&js); +} + +/// the keys menu's answer: the key pressed while it waited for one +pub fn rebind(mut ui: Ui, a: Action, k: &KeyPress) { + ui.listening.set(None); + if k.key == "Escape" { + ui.say("the key stays as it was"); + return; + } + let Some(b) = Binding::of(&k.code, k.ctrl, k.shift, k.alt) else { + ui.fail(format!( + "{} can't be bound", + if k.code.is_empty() { &k.key } else { &k.code } + )); + return; + }; + let mut map = ui.keymap(); + let other = map.rebind(a, b); + set_pref(ui, |p| p.keymap = map.changes()); + match other { + Some(o) => ui.say(format!( + "{} is {b} now; {} takes {} instead", + a.label(), + o.label(), + map.get(o) + )), + None => ui.say(format!("{} is {b} now", a.label())), + } +} + +/// every action and its key: click a key, then press the new one (Esc leaves it); a key +/// another action holds where both work is swapped with it; kept in the settings file +#[component] +fn Keys() -> Element { + let mut ui = ui(); + let map = crate::keys::Keymap::from_changes(&ui.prefs.read().keymap); + let listening = (ui.listening)(); + let changed = !ui.prefs.read().keymap.is_empty(); + let mut groups: Vec<(Scope, Vec<Action>)> = Vec::new(); + for a in Action::ALL { + match groups.iter_mut().find(|(s, _)| *s == a.scope()) { + Some((_, v)) => v.push(a), + None => groups.push((a.scope(), vec![a])), + } + } + let rows = [ + ("Ctrl+Z / Ctrl+Shift+Z in the bar", "undo and redo the bar's typing"), + ( + "Enter in the bar", + "the view's search; Ctrl+Enter saturates, Shift+Enter brings back a key", + ), + ("Delete in the bar", "forget the key typed"), + ("↑ ↓ in the space's bar", "its history"), + ( + "click / Ctrl / Shift / Alt + click", + "into the bar / candidate / list / select", + ), + ("double click", "the key into the bar"), + ("right click / Ctrl+right click", "the menu / gsearch ⌊√(s·r)⌋"), + ("Esc", "close, cancel an edit or tag, leave the bar"), + ]; + rsx! { + Fold { name: "keys", title: "keys", + div { class: "wide dim small", + "Click a key, then press the new one (with Ctrl, Alt or Shift if you like); Esc leaves it. A key another action holds is swapped with it. Keys without Ctrl or Alt only act while you're not typing in a text box." + } + div { class: "wide keymap", + for (scope , acts) in groups { + div { key: "{scope.name()}", class: "keygroup", + h4 { "{scope.name()}" } + for a in acts { + div { key: "{a.id()}", class: "keyrow", + span { class: "what", "{a.label()}" } + button { + class: if listening == Some(a) { "keycap on" } else if map.get(a) != a.default_binding() { "keycap changed" } else { "keycap" }, + "aria-label": "the key for {a.label()}", + onclick: move |_| ui.listening.set(Some(a)), + if listening == Some(a) { "press a key…" } else { "{map.get(a)}" } + } + } + } + } + } + } + div { class: "wide row", + button { disabled: !changed, onclick: move |_| { set_pref(ui, |p| p.keymap.clear()); ui.say("every key is back to its default"); }, Icon { name: "undo" } "reset to defaults" } + } + div { class: "wide", + table { class: "keys", + for (k , what) in rows { + tr { key: "{k}", td { kbd { "{k}" } } td { "{what}" } } + } + } + } + } + } +} diff --git a/app/src/views/space.rs b/app/src/views/space.rs new file mode 100644 index 00000000..fbce3f35 --- /dev/null +++ b/app/src/views/space.rs @@ -0,0 +1,3880 @@ +//! The space. Rust searches and gathers what each text is (`space.features`: its sums, +//! length, kind, word types, lists, time; the colouring classifier's class); the room runs +//! the free spread and draws. On the desktop the room is `anend_render::room::Room`, in +//! Rust, drawn on wgpu (native_room; no JavaScript, and neither space.js nor three.js is in +//! the desktop build): under the see-through webview on Linux, in the page on macOS and +//! Windows. On the web it is the three.js room (app/src/space.js, over the vendored +//! three.js in app/vendor) hosted through Dioxus's JS interop. Both take the same commands +//! and send the same events. +//! +//! As the Bevy app's space had it: the terminal (the command bar: Enter, Ctrl+Enter, +//! Shift+Enter, Delete, ↑ ↓ history, `#123` `#r123` `#name`, the words Enlist List Delist +//! Unlist Count Backup Clear ClearAll Settle Maps `Save name` Help); texts dragged (then +//! pinned), pushed and pulled with the wheel, pinned (U), new (N, a double click on empty +//! room), edited (Enter), removed (Delete), copied (Ctrl+C), undone (Ctrl+Z); maps saved +//! (Shift+X) and exported (X); the physics panel (O) with pause (P) and settle (K); the +//! position card (I), help (H), and the details of the text under the pointer in a window +//! that moves (M), its close button showing on hover. + +use std::collections::{BTreeMap, HashMap}; + +use dioxus::prelude::*; +#[cfg(not(feature = "desktop"))] +use futures_util::{StreamExt, future::Either}; +use serde_json::{Value, json}; + +use crate::backend::Hit; +use crate::gem::{self, Mode}; +use crate::keys::Action; +use crate::shell::set_pref; +use crate::ui::*; +use crate::views::{TChip, use_keys}; + +mod animwin; +mod flightwin; +mod lightwin; +mod native_room; +use native_room::NativeHost; +mod prefabwin; +mod soundwin; +mod texwin; +mod wirewin; + +#[cfg(not(feature = "desktop"))] +const THREE: &str = include_str!("../../vendor/three.module.min.js"); +#[cfg(any(test, not(feature = "desktop")))] +const ENGINE: &str = include_str!("../space.js"); + +/// a physics slider: its key (space.js `PHYSICS`), label, range, step, default and group +pub struct Slider { + pub key: &'static str, + pub label: &'static str, + pub min: f64, + pub max: f64, + pub step: f64, + pub def: f64, + pub group: &'static str, +} + +const fn sl( + key: &'static str, + label: &'static str, + min: f64, + max: f64, + step: f64, + def: f64, + group: &'static str, +) -> Slider { + Slider { + key, + label, + min, + max, + step, + def, + group, + } +} + +/// the physics panel; a weight runs from −1 (texts alike that way push apart) to +1 (they +/// pull together) +pub const SLIDERS: [Slider; 26] = [ + sl( + "w_ordinal", + "ordinal sums", + -1.0, + 1.0, + 0.05, + 0.6, + "what pulls texts together", + ), + sl( + "w_reversed", + "reversed sums", + -1.0, + 1.0, + 0.05, + 0.3, + "what pulls texts together", + ), + sl( + "w_bucket", + "the same bucket", + -1.0, + 1.0, + 0.05, + 0.8, + "what pulls texts together", + ), + sl("w_length", "length", -1.0, 1.0, 0.05, 0.2, "what pulls texts together"), + sl( + "w_types", + "kind and word types", + -1.0, + 1.0, + 0.05, + 0.3, + "what pulls texts together", + ), + sl( + "w_lists", + "shared lists", + -1.0, + 1.0, + 0.05, + 0.7, + "what pulls texts together", + ), + sl( + "w_class", + "the colouring classifier's class", + -1.0, + 1.0, + 0.05, + 0.5, + "what pulls texts together", + ), + sl( + "w_time", + "written near in time", + -1.0, + 1.0, + 0.05, + 0.2, + "what pulls texts together", + ), + sl( + "w_letters", + "the same letters", + -1.0, + 1.0, + 0.05, + 0.4, + "what pulls texts together", + ), + sl( + "qscale", + "how near sums count as alike", + 1.0, + 100.0, + 1.0, + 12.0, + "what pulls texts together", + ), + sl("attract", "attraction", 0.0, 4.0, 0.05, 0.9, "motion"), + sl("repel", "repulsion", 0.0, 60.0, 0.5, 9.0, "motion"), + sl("link", "distance between alike texts", 0.5, 20.0, 0.1, 4.0, "motion"), + sl("gravity", "gravity to the centre", 0.0, 1.0, 0.005, 0.06, "motion"), + sl("pad", "gap between texts", 0.0, 2.0, 0.05, 0.3, "motion"), + sl("damping", "damping", 0.0, 10.0, 0.1, 2.2, "motion"), + sl("cool", "cooling", 0.001, 0.08, 0.001, 0.012, "motion"), + sl("substeps", "speed (steps per frame)", 0.0, 8.0, 1.0, 2.0, "motion"), + sl("depth", "depth by the measure", 0.0, 20.0, 0.25, 0.0, "depth"), + sl("flat", "flatness", 0.0, 5.0, 0.05, 1.5, "depth"), + sl("distance", "spread distance", 5.0, 200.0, 1.0, 26.0, "depth"), + sl("look", "look sensitivity", 0.2, 3.0, 0.05, 1.0, "camera"), + sl( + "smooth", + "look smoothness (higher: snappier)", + 2.0, + 40.0, + 1.0, + 14.0, + "camera", + ), + sl("size", "text size", 0.1, 3.0, 0.05, 0.5, "texts"), + sl("wrap", "text wrap (characters)", 16.0, 160.0, 1.0, 60.0, "texts"), + sl("minPx", "hide texts under px", 0.0, 8.0, 0.1, 1.2, "texts"), +]; + +pub const DEPTH_BY: [&str; 4] = ["none", "ordinal", "length", "time"]; + +#[derive(Debug, Clone, PartialEq, serde::Deserialize)] +pub(crate) struct SpaceEvent { + kind: String, + #[serde(default)] + key: String, + #[serde(default)] + text: String, + #[serde(default)] + note: bool, + #[serde(default)] + free: bool, + #[serde(default)] + x: f64, + #[serde(default)] + y: f64, + #[serde(default)] + ctrl: bool, + #[serde(default)] + shift: bool, + #[serde(default)] + alt: bool, + #[serde(default)] + q: f64, + #[serde(default)] + hue: f64, + #[serde(default)] + pinned: bool, + #[serde(default)] + data: Value, + /// the placement in the room (a copy's own key); `key` is the entry's + #[serde(default)] + node: String, + /// how many placements the entry has in the room, and whether this is the first + #[serde(default)] + copies: u32, + #[serde(default)] + primary: bool, + /// a detached placement: the entry's version it keeps (its edited time, ms) + #[serde(default)] + det: u64, + /// an inheriting placement's own text, shadowing its entry's + #[serde(default)] + own: Option<String>, + /// the entry's text (what an inheriting placement shows without its own) + #[serde(default)] + entry_text: String, + /// the chain it heads or is in (the chain entry's key), its place among the members + /// (-1: the head), how many members a head has, and the node of its head + #[serde(default)] + chain: String, + #[serde(default = "minus_one")] + idx: i64, + #[serde(default)] + members: u32, + #[serde(default)] + head_node: String, + /// a note's body shown as the second of a chain of two (no entry of its own) + #[serde(default)] + virt: bool, + /// its font size in steps of 1/50 unit (0: the default), and the default's step + #[serde(default)] + font: u32, + #[serde(default)] + font_default: u32, +} + +/// a placement's size, − and + a step, and back to the default (the details window and +/// the menu) +#[component] +fn SizeRow(ev: SpaceEvent, on_send: EventHandler<Value>) -> Element { + let shown = if ev.font == 0 { + format!("default ({:.2})", ev.font_default as f64 / 50.0) + } else { + format!("{:.2}", ev.font as f64 / 50.0) + }; + let node = ev.node.clone(); + let step = move |by: i32| { + let n = node.clone(); + move |_| on_send.call(json!({ "cmd": "size", "node": n, "by": by })) + }; + let n0 = ev.node.clone(); + rsx! { + div { class: "row size-row", + span { class: "dim small", "size " } + button { class: "btn small", title: "smaller by 0.1 (sizes go in steps of 0.02)", onclick: step(-5), "−" } + span { class: "num", title: "units per em; the default is the physics window's text size", "{shown}" } + button { class: "btn small", title: "larger by 0.1", onclick: step(5), "+" } + if ev.font != 0 { + button { class: "btn small", title: "back to the default size", onclick: move |_| on_send.call(json!({ "cmd": "size", "node": n0, "to": 0 })), "default" } + } + } + } +} + +fn minus_one() -> i64 { + -1 +} + +impl SpaceEvent { + /// how this placement relates to its entry, in words + fn relation(&self) -> String { + if self.free { + return String::new(); + } + if self.virt { + return "a note's body, shown under its title as a chain of two".into(); + } + if self.idx >= 0 { + return format!( + "text {} of a chain under its title (drag any of it to move it)", + self.idx + 1 + ); + } + if !self.chain.is_empty() { + return format!("heads a chain of {} texts", self.members); + } + if self.det > 0 { + let when = chrono_date(self.det); + return format!("detached on {when}: keeps the text as it read then"); + } + if self.own.is_some() { + return "its own text over the entry's".into(); + } + "inherits: shows the entry's text as it is now".into() + } +} + +/// what a chain op does to the room once it's done +#[derive(Clone, PartialEq)] +enum ChainThen { + /// the text becomes the new chain's head, and the chain is the one to add to + Start(String), + /// the chain changed (cut: a new one starts beside it); the node, when given, leaves + /// the room (it went into the chain) + Changed(Option<String>), + /// the chain broke: its head shows its title again + Broke, +} + +/// a change to a chain's members' keys +type MembersEdit = std::rc::Rc<dyn Fn(&mut Vec<Value>)>; + +/// the right-click menu's chain items: start one, add to the chain being built, move a +/// member, cut, take out, break (docs/format.md answer 4, queued #8) +#[component] +fn ChainItems(ev: SpaceEvent, sp_menu: Signal<Option<SpaceEvent>>, on_send: EventHandler<Value>) -> Element { + let ui = ui(); + let api = api(); + if ev.free || ev.virt { + return rsx! {}; + } + let building = ui.picks.read().chain.clone(); + // runs a chain op, tells the room, then closes the menu (its handler goes with it) + let run = { + let api = api.clone(); + move |op: &'static str, args: Value, then: ChainThen| { + let api = api.clone(); + let mut sm = sp_menu; + spawn(async move { + match api.call(op, args).await { + Ok(r) => match then { + ChainThen::Start(node) => { + on_send.call(json!({ "cmd": "chainify", "node": node, "chain": r })); + let mut p = ui.picks; + p.write().chain = Some(Hit { + key: r["key"].as_str().unwrap_or("").to_string(), + text: r["title"]["text"].as_str().unwrap_or("").to_string(), + note: false, + }); + ui.say("a chain: right-click other texts to add them to it"); + } + ChainThen::Changed(gone) => { + let (chain, new) = if r.get("chain").is_some() { + (r["chain"].clone(), r["new"].clone()) + } else { + (r.clone(), Value::Null) + }; + on_send.call(json!({ "cmd": "chain", "key": chain["key"], "chain": chain })); + if !new.is_null() { + on_send.call(json!({ "cmd": "addchain", "near": chain["key"], "chain": new })); + } + if let Some(n) = gone { + on_send.call(json!({ "cmd": "removenode", "node": n, "quiet": true })); + ui.say(format!( + "added to the chain “{}”", + chain["title"]["text"].as_str().unwrap_or("") + )); + } + } + ChainThen::Broke => { + on_send.call(json!({ "cmd": "chain", "key": r["key"], "chain": Value::Null })); + let mut p = ui.picks; + if p.peek() + .chain + .as_ref() + .is_some_and(|c| Some(c.key.as_str()) == r["key"].as_str()) + { + p.write().chain = None; + } + ui.say("the chain broke: its texts stay"); + } + }, + Err(e) => ui.fail(e), + } + sm.set(None); + }); + } + }; + // the chain's members' keys with one change made + let reorder = { + let api = api.clone(); + let run = run.clone(); + move |chain: String, f: MembersEdit| { + let (api, run) = (api.clone(), run.clone()); + spawn(async move { + match api.call("chains.get", json!({ "key": chain })).await { + Ok(c) => { + let mut keys: Vec<Value> = c["members"] + .as_array() + .into_iter() + .flatten() + .map(|m| m["key"].clone()) + .collect(); + f(&mut keys); + run( + "chains.set", + json!({ "key": chain, "members": keys }), + ChainThen::Changed(None), + ); + } + Err(e) => ui.fail(e), + } + }); + } + }; + let idx = ev.idx; + let member = ev.idx >= 0; + let head = ev.idx < 0 && !ev.chain.is_empty(); + let chain = ev.chain.clone(); + rsx! { + if !member && !head && !ev.note { + button { role: "menuitem", onclick: { let run = run.clone(); let (k, n) = (ev.key.clone(), ev.node.clone()); move |_| run("chains.make", json!({ "title": k, "members": [] }), ChainThen::Start(n.clone())) }, + Icon { name: "list" } "start a chain with this as its title" } + } + if let Some(b) = building.clone().filter(|b| !member && b.key != ev.key && b.key != chain) { + button { role: "menuitem", onclick: { let api = api.clone(); let run = run.clone(); let (k, n) = (ev.key.clone(), ev.node.clone()); let b = b.clone(); move |_| { + let (api, run, k, n, b) = (api.clone(), run.clone(), k.clone(), n.clone(), b.clone()); + spawn(async move { + match api.call("chains.get", json!({ "key": b.key })).await { + Ok(c) => { + let mut keys: Vec<Value> = c["members"].as_array().into_iter().flatten().map(|m| m["key"].clone()).collect(); + keys.push(json!(k)); + run("chains.set", json!({ "key": b.key, "members": keys }), ChainThen::Changed(Some(n))); + } + Err(e) => ui.fail(e), + } + }); + } }, + Icon { name: "list" } "add it to the chain “{b.text}”" } + } + if head { + button { role: "menuitem", onclick: { let (k, t) = (chain.clone(), ev.text.clone()); move |_| { + let mut p = ui.picks; p.write().chain = Some(Hit { key: k.clone(), text: t.clone(), note: false }); + ui.say("right-click other texts to add them to this chain"); + let mut sm = sp_menu; sm.set(None); + } }, + Icon { name: "list" } "add texts to this chain" span { class: "dim small", " ({ev.members} now)" } } + button { role: "menuitem", onclick: { let run = run.clone(); let k = chain.clone(); move |_| run("chains.break", json!({ "key": k }), ChainThen::Broke) }, + Icon { name: "close" } "break the chain" span { class: "dim small", " (its texts stay)" } } + } + if member { + if idx > 0 { + button { role: "menuitem", onclick: { let r = reorder.clone(); let k = chain.clone(); move |_| r(k.clone(), std::rc::Rc::new(move |v: &mut Vec<Value>| v.swap(idx as usize - 1, idx as usize))) }, + Icon { name: "chevron-right", class: "rot-up" } "earlier in the chain" } + } + button { role: "menuitem", onclick: { let r = reorder.clone(); let k = chain.clone(); move |_| r(k.clone(), std::rc::Rc::new(move |v: &mut Vec<Value>| if (idx as usize) + 1 < v.len() { v.swap(idx as usize, idx as usize + 1) })) }, + Icon { name: "chevron-right", class: "rot-down" } "later in the chain" } + button { role: "menuitem", onclick: { let run = run.clone(); let k = chain.clone(); move |_| run("chains.cut", json!({ "key": k, "at": idx }), ChainThen::Changed(None)) }, + Icon { name: "close" } "cut the chain before this" span { class: "dim small", " (this heads a new one)" } } + button { role: "menuitem", onclick: { let r = reorder.clone(); let k = chain.clone(); move |_| r(k.clone(), std::rc::Rc::new(move |v: &mut Vec<Value>| { if (idx as usize) < v.len() { v.remove(idx as usize); } })) }, + Icon { name: "close" } "take it out of the chain" } + } + } +} + +/// a date from ms since 1970, as "2026-10-25 14:03 UTC" +fn chrono_date(ms: u64) -> String { + let secs = (ms / 1000) as i64; + let days = secs.div_euclid(86_400); + let rem = secs.rem_euclid(86_400); + // days since 1970-01-01 to a civil date (Howard Hinnant's algorithm) + let z = days + 719_468; + let era = z.div_euclid(146_097); + let doe = z - era * 146_097; + let yoe = (doe - doe / 1460 + doe / 36_524 - doe / 146_096) / 365; + let doy = doe - (365 * yoe + yoe / 4 - yoe / 100); + let mp = (5 * doy + 2) / 153; + let d = doy - (153 * mp + 2) / 5 + 1; + let m = if mp < 10 { mp + 3 } else { mp - 9 }; + let y = yoe + era * 400 + i64::from(m <= 2); + format!("{y}-{m:02}-{d:02} {:02}:{:02} UTC", rem / 3600, rem % 3600 / 60) +} + +#[cfg(not(feature = "desktop"))] +fn boot_js() -> String { + format!( + r#" +const THREE_SRC = {three}; +const ENGINE_SRC = {engine}; +window.__anendNoLock = {no_lock}; +const url = (src) => URL.createObjectURL(new Blob([src], {{ type: 'text/javascript' }})); +const tu = url(THREE_SRC); +const eu = url(ENGINE_SRC.split("'__THREE__'").join(JSON.stringify(tu))); +let host = null; +for (let i = 0; i < 100 && !host; i++) {{ host = document.getElementById('space-host'); if (!host) await new Promise((r) => setTimeout(r, 20)); }} +try {{ + const mod = await import(eu); + const sp = new mod.Space(host, (m) => dioxus.send(m)); + window.__anendSpace = sp; + dioxus.send({{ kind: 'ready' }}); + while (true) {{ + const c = await dioxus.recv(); + if (c.cmd === 'place') sp.place(c.texts, c.again); + else if (c.cmd === 'effects') sp.effects(c.fx); + else if (c.cmd === 'copies') sp.setCopies(c.list || []); + else if (c.cmd === 'batch') sp.setBatch(!!c.on); + else if (c.cmd === 'wiremode') sp.setWiring(c.toggle ? null : !!c.on); + else if (c.cmd === 'wired') sp.record({{ kind: 'wired', items: c.items || [] }}); + else if (c.cmd === 'groups') {{ + sp.setGroups(c.list || []); + if (c.made) {{ sp.record({{ kind: 'grouped', id: c.made }}); sp.pickGroup(c.made); }} + if (c.broke) {{ sp.record({{ kind: 'ungrouped', members: c.broke.members, name: c.broke.name }}); sp.afterMulti(); }} + if (c.select) sp.pickGroup(c.select); + }} + else if (c.cmd === 'group') dioxus.send({{ kind: 'groupmake', data: {{ members: sp.groupMembers() }} }}); + else if (c.cmd === 'ungroup') dioxus.send({{ kind: 'groupbreak', data: {{ id: sp.selGroup }} }}); + else if (c.cmd === 'removemulti') dioxus.send({{ kind: 'removedmulti', data: sp.removeMulti() }}); + else if (c.cmd === 'clearmulti') sp.clearMulti(); + else if (c.cmd === 'copygone') sp.copyGone(c.ids || [], c.restore); + else if (c.cmd === 'opencopy') sp.openCopyNamed(c.id); + else if (c.cmd === 'closecopy') sp.closeCopy(); + else if (c.cmd === 'pickcopy') sp.pickCopy(c.id); + else if (c.cmd === 'clear') sp.clear(!!c.all); + else if (c.cmd === 'room') sp.setRoom(c.bg, c.ink); + else if (c.cmd === 'start') sp.start(); + else if (c.cmd === 'stop') sp.stop(); + else if (c.cmd === 'mark') sp.mark(c.list, c.candidate); + else if (c.cmd === 'focus') host.focus(); + else if (c.cmd === 'keys') sp.setKeys(c.map); + else if (c.cmd === 'physics') sp.setPhysics(c.p); + else if (c.cmd === 'pause') sp.paused = !!c.on; + else if (c.cmd === 'settle') dioxus.send({{ kind: 'settled', data: sp.settle() }}); + else if (c.cmd === 'undo') dioxus.send({{ kind: 'undone', data: sp.undoLast() }}); + else if (c.cmd === 'pin') dioxus.send({{ kind: 'toast', text: sp.pinSelected() || 'select a text first' }}); + else if (c.cmd === 'remove') {{ const k = sp.removeSelected(); dioxus.send({{ kind: 'toast', text: k ? 'text removed · Ctrl+Z puts it back' : 'select a text first' }}); }} + else if (c.cmd === 'free') dioxus.send({{ kind: 'made', key: sp.addFree(c.text), text: c.text || 'text', free: true }}); + else if (c.cmd === 'retext') sp.editFree(c.key, c.text); + else if (c.cmd === 'rows') dioxus.send({{ kind: 'rows', data: {{ why: c.why, name: c.name || '', rows: sp.rows() }} }}); + else if (c.cmd === 'load') sp.loadRows(c.rows, c.feats || {{}}); + else if (c.cmd === 'colours') sp.colours(c.map || {{}}); + else if (c.cmd === 'blocks') {{ + sp.setBlocks(c.blocks, c.textures || {{}}, !!c.replace); + if (c.added) sp.record({{ kind: 'blockadd', ids: c.added }}); + if (c.select != null) sp.pickBlock(c.select); + }} + else if (c.cmd === 'unblock') sp.unblock(c.ids || []); + else if (c.cmd === 'sky') sp.setSky(c.about || null); + else if (c.cmd === 'anims') sp.setAnims(c.anims || [], c.textures || {{}}); + else if (c.cmd === 'playanims') sp.playAnims(!!c.on); + else if (c.cmd === 'wires') sp.setWires(c.wires || [], !!c.live); + else if (c.cmd === 'thumbs') dioxus.send({{ kind: 'thumbs', data: sp.thumbs(c.prefabs || [], c.textures || {{}}) }}); + else if (c.cmd === 'prefabspot') dioxus.send({{ kind: 'prefabspot', data: {{ ...sp.blockSpot(), want: c.want }} }}); + else if (c.cmd === 'rays') sp.showRays(c.rays || []); + else if (c.cmd === 'sounddata') sp.soundData(c.id, c.data || ''); + else if (c.cmd === 'sounds') sp.sounds(c.sounds || []); + else if (c.cmd === 'soundpreview') sp.previewSound(c.id); + else if (c.cmd === 'clearcollected') sp.clearCollected(); + else if (c.cmd === 'ghost') sp.startGhost(c.prefab, c.parts || [], c.textures || {{}}, c.name); + else if (c.cmd === 'noghost') sp.stopGhost(); + else if (c.cmd === 'animpreview') sp.previewAnim(c.id, c.anim || null, c.p); + else if (c.cmd === 'lights') sp.setLights(c.lights || [], c.changed || null); + else if (c.cmd === 'showlights') sp.showLights(!!c.on, c.picked); + else if (c.cmd === 'lightspot') dioxus.send({{ kind: 'lightspot', data: {{ ...sp.lightSpot(), want: c.want }} }}); + else if (c.cmd === 'preview') sp.preview(c.id, c.about || {{}}, c.tiles || 1, !!c.variants); + else if (c.cmd === 'blockspot') dioxus.send({{ kind: 'spot', data: {{ ...sp.blockSpot(), want: c.want }} }}); + else if (c.cmd === 'blockfields') sp.setBlockFields(c.id, c.t); + else if (c.cmd === 'pickblock') sp.pickBlock(c.id); + else if (c.cmd === 'dup') {{ const k = sp.duplicate(c.node, c.det || 0); dioxus.send({{ kind: 'toast', text: !k ? 'select a text first' : c.det ? 'a detached copy: it keeps the text as it reads now · Ctrl+Z takes it away' : 'a copy that inherits: it shows the entry as it changes · Ctrl+Z takes it away' }}); }} + else if (c.cmd === 'size') sp.setSize(c.node, c.by || 0, c.to); + else if (c.cmd === 'chain') sp.setChain(c.key, c.chain); + else if (c.cmd === 'chainify') sp.chainify(c.node, c.chain); + else if (c.cmd === 'addchain') sp.addChain(c.near, c.chain); + else if (c.cmd === 'own') {{ const k = sp.setOwn(c.node, c.text); dioxus.send({{ kind: 'toast', text: !k ? 'that placement can\'t have its own text' : c.text ? 'this placement has its own text now; the entry is unchanged · Ctrl+Z undoes it' : 'it follows the entry again · Ctrl+Z undoes it' }}); }} + else if (c.cmd === 'removenode') {{ const k = sp.removeNode(c.node); if (!c.quiet) dioxus.send({{ kind: 'toast', text: k ? 'taken out of the room (the entry stays) · Ctrl+Z puts it back' : 'gone already' }}); }} + else if (c.cmd === 'pinnode') dioxus.send({{ kind: 'toast', text: sp.pinNode(c.node) || 'gone already' }}); + }} +}} catch (e) {{ + dioxus.send({{ kind: 'error', text: String(e && e.message || e) }}); +}} +"#, + three = serde_json::to_string(THREE).unwrap_or_default(), + engine = serde_json::to_string(ENGINE).unwrap_or_default(), + no_lock = cfg!(feature = "desktop"), + ) +} + +#[derive(Clone, Copy, PartialEq)] +struct Sp { + tx: Signal<Option<futures_channel::mpsc::UnboundedSender<Value>>>, + /// the texts in the room (memory texts and notes), by key + texts: Signal<Vec<Hit>>, + /// what the details window shows: the text under the pointer, else the selected one + card: Signal<Option<SpaceEvent>>, + selected: Signal<Option<SpaceEvent>>, + pos: Signal<String>, + /// ↑ ↓ in the bar: where in the history + hist_at: Signal<Option<usize>>, + paused: Signal<bool>, + /// each text's bucket axis Q, for the shared-bucket underlines + q_bucket: Signal<HashMap<String, u64>>, + /// the selected block: `{id, kind, texture, x, y, z, w, h, d, about}` + block: Signal<Option<Value>>, + /// how many blocks and textures the save has + block_use: Signal<(u64, u64)>, + /// the room's lights (`lights.list`), as the room bakes them + lights: Signal<Vec<Value>>, + /// wiring by dragging is on + wiremode: Signal<bool>, + /// a light picked in the room (its marker clicked), for the lights window + lightpick: Signal<Option<u64>>, + /// the selection of many in the room: `{count, blocks, copies, texts, lights}` + multi: Signal<Option<Value>>, + /// the right-click menu on a text + menu: Signal<Option<SpaceEvent>>, + /// bumped when a scene is saved, so the scenes window reads them again + scenes_rev: Signal<u64>, + /// the right-click menu on a block: where + bmenu: Signal<Option<(f64, f64)>>, + /// the blocks window shows the selected block's bend editor open + bend_open: Signal<bool>, + /// the room is live: clicks fire wired blocks, timers run (the wiring window's play) + live: Signal<bool>, + /// what the last cause set off (`wiring.fire`'s events) + fired: Signal<Vec<Value>>, + /// the save's prefabs (`prefabs.list`), their copies, and each one's picture + prefabs: Signal<Vec<Value>>, + copies: Signal<Vec<Value>>, + thumbs: Signal<HashMap<u64, String>>, + /// how the camera moves: `fly` (the default), `walk` or `super` (superflight) + mode: Signal<String>, + /// the texts superflight flew through, in order: `{key, text}` + collected: Signal<Vec<Value>>, + /// the native room's texture previews (`Previews`) + previews: Signal<HashMap<String, String>>, +} + +/// the native room's texture previews (the textures window's), by canvas id: PNG data +/// URLs the room draws in Rust, shown as pictures where space.js drew into canvases +#[derive(Clone, Copy)] +pub(super) struct Previews(pub Signal<HashMap<String, String>>); + +/// whether the room is the native one (Rust, drawn by anend-render, no JavaScript): always +/// on the desktop; on the web with `?room=wgpu` where the browser has WebGPU (else space.js) +pub(super) fn native_space() -> bool { + #[cfg(feature = "desktop")] + return true; + #[cfg(not(feature = "desktop"))] + { + thread_local! { + static GPU: bool = web_sys::window() + .and_then(|w| js_sys::Reflect::get(&w.navigator(), &"gpu".into()).ok()) + .is_some_and(|g| !g.is_undefined() && !g.is_null()) + // opted into until it's been seen in a real browser (questions 121): `?room=wgpu` + && web_sys::window().and_then(|w| w.location().search().ok()).is_some_and(|q| q.contains("room=wgpu")); + } + GPU.with(|g| *g) + } +} + +impl Sp { + fn send(&self, v: Value) { + if let Some(tx) = self.tx.peek().as_ref() { + let _ = tx.unbounded_send(v); + } + } +} + +/// the physics' settings for space.js: the sliders (defaults and the person's changes) +fn physics(ui: Ui) -> Value { + let p = ui.prefs.peek(); + let mut o = serde_json::Map::new(); + for s in &SLIDERS { + o.insert( + s.key.into(), + json!(p.space.physics.get(s.key).copied().unwrap_or(s.def)), + ); + } + o.insert("depth_by".into(), json!(p.space.depth_by)); + o.insert("reversed".into(), json!(p.space_reversed as u8)); + Value::Object(o) +} + +/// the letters of a text as counts a–z, for the "same letters" weight +fn letter_counts(t: &str) -> Vec<u32> { + let mut v = vec![0u32; 26]; + for c in t.bytes() { + let c = c | 32; + if c.is_ascii_lowercase() { + v[(c - b'a') as usize] += 1; + } + } + v +} + +/// lays hits out: in place of what's there (pinned and free texts stay), or (keep) added +/// to it; each with what it is, from `space.features` and the colouring classifier +fn show(ui: Ui, api: Api, sp: Sp, hits: Vec<Hit>) { + let (keep, reversed, tint) = { + let p = ui.prefs.peek(); + (p.space_keep, p.space_reversed, p.tint.clone()) + }; + let mut all = if keep { sp.texts.peek().clone() } else { vec![] }; + let again = keep && !all.is_empty(); + let mut fresh = Vec::new(); + for h in hits { + if !all.iter().any(|x| x.key == h.key) { + all.push(h.clone()); + fresh.push(h); + } + } + let mut texts = sp.texts; + if all.is_empty() { + texts.set(vec![]); + sp.send(json!({ "cmd": "clear", "all": false })); + return; + } + dioxus::dioxus_core::spawn_forever(async move { + let keys: Vec<String> = fresh.iter().map(|h| h.key.clone()).collect(); + let feats = api + .call("space.features", json!({ "keys": keys })) + .await + .unwrap_or(Value::Null); + let mut by: HashMap<String, Value> = HashMap::new(); + for f in feats["features"].as_array().into_iter().flatten() { + by.insert(f["key"].as_str().unwrap_or("").to_string(), f.clone()); + } + let mut tints: HashMap<String, (Value, Value, String)> = HashMap::new(); + if !tint.is_empty() + && let Ok(t) = api.call("classify.tints", json!({ "name": tint, "keys": keys })).await + { + let palette = crate::views::classifiers::strs(&t["palette"]); + for x in t["tints"].as_array().into_iter().flatten() { + let c = x["class"].as_u64().map(|c| c as usize); + let colour = c.and_then(|c| palette.get(c).cloned()).unwrap_or_default(); + tints.insert( + x["key"].as_str().unwrap_or("").to_string(), + (x["class"].clone(), x["strength"].clone(), colour), + ); + } + } + // the bucket axis Q (r, or s when reversed) and how many of the room share it + let mut qs = sp.q_bucket.peek().clone(); + if !again { + qs.clear(); + } + for h in &fresh { + let (s, r) = gem::sums(&h.text); + qs.insert(h.key.clone(), if reversed { s } else { r }); + } + let mut count: HashMap<u64, usize> = HashMap::new(); + for q in qs.values() { + *count.entry(*q).or_default() += 1; + } + let payload: Vec<Value> = fresh + .iter() + .map(|h| { + let f = by.get(&h.key).cloned().unwrap_or(Value::Null); + let (s, r) = gem::sums(&h.text); + let q = if reversed { s } else { r }; + let mut v = json!({ + "key": h.key, "text": h.text, "note": h.note, "shown": first_piece(ui, &h.text), + "s": s, "r": r, "q": q, "hue": anend_core::spread::seed_hue(q as i64), + "shared": count.get(&q).copied().unwrap_or(0) >= 2, + // the gematria grouping underline, the memory view's colour for it + "under": gem::underline(&h.text, if reversed { Mode::Reversed } else { Mode::Ordinal }), + "chars": f["chars"], "words": f["words"], "kind": f["kind"], "types": f["types"], + "created": f["created"], "lists": f["lists"], "freq": letter_counts(&h.text), + "chain": f["chain"], "isChain": f["isChain"], "titleKey": f["titleKey"], + }); + if let Some((c, st, colour)) = tints.get(&h.key) { + v["cls"] = c.clone(); + v["strength"] = st.clone(); + if !colour.is_empty() { + v["colour"] = json!(colour); + } + } + v + }) + .collect(); + // the room's counts in the search line + let mut tl = ui.topline; + if let Some(l) = tl.write().as_mut() { + l.counts = Some((qs.len(), count.len())); + } + let mut q_bucket = sp.q_bucket; + q_bucket.set(qs); + sp.send(json!({ "cmd": "place", "texts": payload, "again": again })); + texts.set(all); + }); +} + +/// the space's search line: what was searched and its mode; the room's counts follow +/// when the texts are placed (`place`), with icons +fn topline(ui: Ui, title: String, mode: Mode, text: Option<&str>, n: usize) { + topline_pf(ui, title, mode, text, n, None); +} + +fn topline_pf(mut ui: Ui, title: String, mode: Mode, text: Option<&str>, n: usize, pf: Option<u64>) { + let (s, r) = text.map(gem::sums).unwrap_or((0, 0)); + ui.topline.set(Some(TopLine { + title, + detail: mode.name().to_string(), + s, + r, + counts: (n == 0).then_some((0, 0)), + pf, + })); +} + +fn space_mode(ui: Ui) -> Mode { + if ui.prefs.peek().space_reversed { + Mode::Reversed + } else { + Mode::Ordinal + } +} + +async fn gsearch(ui: Ui, api: Api, sp: Sp, n: u64, mode: Mode, text: Option<String>) { + set_pref(ui, |p| { + p.space.address = format!("{}{n}", if mode == Mode::Reversed { "r" } else { "" }) + }); + match api.gsearch(mode, &n.to_string()).await { + Ok(hits) => { + let t = text.or_else(|| hits.first().map(|h| h.text.clone())); + topline_pf(ui, n.to_string(), mode, t.as_deref(), hits.len(), (n > 1).then_some(n)); + if hits.is_empty() { + ui.say(format!("nothing in {} {n} yet", mode.name())); + } + show(ui, api, sp, hits); + } + Err(e) => ui.fail(e), + } +} + +/// a value into the bar, and gsearch it (remem's `envale`) +fn envale(ui: Ui, api: Api, sp: Sp, n: u64, mode: Mode) { + ui.set_bar(&n.to_string()); + dioxus::dioxus_core::spawn_forever(gsearch(ui, api, sp, n, mode, None)); +} + +/// the scenes saved in the save: name → rows (`scenes.maps`) +async fn maps(api: &Api) -> BTreeMap<String, Value> { + match api.call("scenes.maps", json!({})).await { + Ok(v) => serde_json::from_value(v).unwrap_or_default(), + Err(_) => BTreeMap::new(), + } +} + +/// `#123` an ordinal bucket, `#r123` a reversed one, `#name` a map +async fn route(ui: Ui, api: Api, sp: Sp, addr: &str) { + let addr = addr.trim(); + let (rev, digits) = match addr.strip_prefix('r') { + Some(d) => (true, d), + None => (false, addr), + }; + if !digits.is_empty() + && digits.bytes().all(|b| b.is_ascii_digit()) + && let Ok(n) = digits.parse::<u64>() + { + if ui.prefs.peek().space_reversed != rev { + set_pref(ui, |p| p.space_reversed = rev); + } + gsearch(ui, api, sp, n, if rev { Mode::Reversed } else { Mode::Ordinal }, None).await; + return; + } + let all = maps(&api).await; + let Some(rows) = all.get(addr).cloned() else { + ui.fail(format!("there's no map named {addr}")); + return; + }; + // the memory texts of the map, with what they are + let keys: Vec<String> = rows + .as_array() + .into_iter() + .flatten() + .filter_map(|r| r[4]["key"].as_str().map(str::to_string)) + .collect(); + let feats = api + .call("space.features", json!({ "keys": keys })) + .await + .unwrap_or(Value::Null); + let reversed = ui.prefs.peek().space_reversed; + let mut fm = serde_json::Map::new(); + for f in feats["features"].as_array().into_iter().flatten() { + let k = f["key"].as_str().unwrap_or("").to_string(); + let mut f = f.clone(); + let (s, r) = (f["s"].as_u64().unwrap_or(0), f["r"].as_u64().unwrap_or(0)); + let q = if reversed { s } else { r }; + f["q"] = json!(q); + f["hue"] = json!(anend_core::spread::seed_hue(q as i64)); + let text = rows + .as_array() + .into_iter() + .flatten() + .find(|r| r[4]["key"].as_str() == Some(k.as_str())) + .and_then(|r| r[0].as_str()) + .unwrap_or("") + .to_string(); + f["under"] = json!(gem::underline( + &text, + if reversed { Mode::Reversed } else { Mode::Ordinal } + )); + f["shown"] = json!(first_piece(ui, &text)); + fm.insert(k, f); + } + let hits: Vec<Hit> = rows + .as_array() + .into_iter() + .flatten() + .filter_map(|r| { + Some(Hit { + key: r[4]["key"].as_str()?.to_string(), + text: r[0].as_str().unwrap_or("").to_string(), + note: r[4]["key"].as_str()?.starts_with("note:"), + }) + }) + .collect(); + let mut texts = sp.texts; + texts.set(hits); + sp.send(json!({ "cmd": "load", "rows": rows, "feats": fm })); + set_pref(ui, |p| p.space.address = addr.to_string()); + let mut tl = ui.topline; + tl.set(Some(TopLine { + title: format!("map {addr}"), + detail: format!("{} texts", rows.as_array().map(|a| a.len()).unwrap_or(0)), + s: 0, + r: 0, + ..Default::default() + })); +} + +fn push_history(ui: Ui, sp: Sp, v: &str) { + set_pref(ui, |p| { + let h = &mut p.space.history; + if h.last().map(String::as_str) != Some(v) { + h.push(v.to_string()); + } + let n = h.len(); + if n > 300 { + h.drain(0..n - 300); + } + }); + let mut at = sp.hist_at; + at.set(None); +} + +fn need(ui: Ui, h: Option<Hit>, what: &str) -> Option<Hit> { + if h.is_none() { + ui.fail(format!( + "no {what}: {} a text to set it", + if what == "list" { + "Ctrl+Shift+click" + } else { + "Ctrl+click" + } + )); + } + h +} + +/// the space's words (the Bevy terminal's commands) +async fn command(ui: Ui, api: Api, sp: Sp, word: &str, rest: &str) { + let picks = ui.picks.peek().clone(); + match word { + "Enlist" => { + if let (Some(l), Some(c)) = (need(ui, picks.list, "list"), need(ui, picks.candidate, "candidate")) { + match api.enlist(&l.key, &c.key).await { + Ok(()) => { + ui.did(Did::Enlisted { + list: l.key.clone(), + member: c.key.clone(), + }); + ui.say(format!("enlisted “{}” in “{}”", c.text, l.text)); + ui.touched(); + } + Err(e) => ui.fail(e), + } + } + } + "Delist" => { + if let (Some(l), Some(c)) = (need(ui, picks.list, "list"), need(ui, picks.candidate, "candidate")) { + match api.delist(&l.key, &c.key).await { + Ok(()) => { + ui.did(Did::Delisted { + list: l.key.clone(), + member: c.key.clone(), + }); + ui.say(format!("delisted “{}” from “{}”", c.text, l.text)); + ui.touched(); + } + Err(e) => ui.fail(e), + } + } + } + "List" => { + if let Some(l) = need(ui, picks.list, "list") { + match api.lists().await { + Ok(all) => { + let members = all + .lists + .into_iter() + .find(|x| x.list == l.key) + .map(|x| x.members) + .unwrap_or_default(); + let mut tl = ui.topline; + tl.set(Some(TopLine { + title: format!("list {}", l.text), + detail: String::new(), + s: 0, + r: 0, + ..Default::default() + })); + show(ui, api, sp, members); + } + Err(e) => ui.fail(e), + } + } + } + "Unlist" => { + if let Some(l) = need(ui, picks.list, "list") { + let members: Vec<String> = api + .lists() + .await + .ok() + .and_then(|a| a.lists.into_iter().find(|x| x.list == l.key)) + .map(|x| x.members.into_iter().map(|m| m.key).collect()) + .unwrap_or_default(); + match api.unlist(&l.key).await { + Ok(n) => { + ui.did(Did::Unlisted { + list: l.key.clone(), + members, + }); + ui.say(format!("unlisted “{}” ({n} members) · Ctrl+Z brings it back", l.text)); + ui.touched(); + } + Err(e) => ui.fail(e), + } + } + } + "Count" => { + let h = ui.hello.peek().clone(); + ui.toast(format!("{} texts · {} notes", h.counts.memories, h.counts.notes)); + } + "Backup" => { + let name = ui.hello.peek().save.clone(); + match api.backup(&name).await { + Ok(b) if !b.paths.is_empty() => ui.say(format!("backed up: {}", b.paths.join(" and "))), + Ok(_) => ui.say("backed up"), + Err(e) => ui.fail(e), + } + } + "Clear" | "ClearAll" => { + let mut texts = sp.texts; + texts.set(vec![]); + sp.send(json!({ "cmd": "clear", "all": word == "ClearAll" })); + } + "Settle" => sp.send(json!({ "cmd": "settle" })), + "Help" => set_pref(ui, |p| p.space.show_help = !p.space.show_help), + "Maps" => { + let all = maps(&api).await; + if all.is_empty() { + ui.say("no maps yet: Save name (or Shift+X) keeps the room as one"); + } else { + ui.toast(format!( + "maps: {} (#name opens one)", + all.keys().map(|k| format!("#{k}")).collect::<Vec<_>>().join(" ") + )); + } + } + "Save" => { + let name = rest.trim(); + let name = if name.is_empty() { + default_map_name(ui) + } else { + name.to_string() + }; + sp.send(json!({ "cmd": "rows", "why": "save", "name": name })); + } + _ => {} + } +} + +/// what a text's label in the space shows: a long text's first piece (lines at word +/// boundaries, `anend_core::pieces`) and how many more there are; None for a short text +fn first_piece(ui: Ui, text: &str) -> Option<String> { + let (w, l) = { + let p = ui.prefs.peek(); + (p.piece_line, p.piece_lines) + }; + let n = anend_core::pieces::count(text, w, l); + (n > 1).then(|| { + let first = anend_core::pieces::pieces(text, w, l)[0].trim_end(); + format!("{first} … ({} more pieces, {} KB)", n - 1, text.len().div_ceil(1000)) + }) +} + +fn default_map_name(ui: Ui) -> String { + let a = ui.prefs.peek().space.address.clone(); + let rev = a.starts_with('r'); + let digits = a.trim_start_matches('r'); + if !digits.is_empty() && digits.bytes().all(|b| b.is_ascii_digit()) { + format!("spread-{}{digits}", if rev { "r" } else { "" }) + } else if a.is_empty() { + "untitled".into() + } else { + a + } +} + +const COMMANDS: [&str; 14] = [ + "Enlist", "List", "Delist", "Unlist", "Count", "Backup", "Clear", "ClearAll", "Settle", "Maps", "Save", "Help", + "Note", "Notes", +]; + +async fn enter(mut ui: Ui, api: Api, sp: Sp, raw: String, ctrl: bool, shift: bool) { + let t = raw.trim().to_string(); + // an edit started from the right-click menu or Enter on a text + let pending = ui.pending.peek().clone(); + if let Pending::EditOwn { node, .. } = &pending { + ui.pending.set(Pending::None); + if !t.is_empty() { + sp.send(json!({ "cmd": "own", "node": node, "text": t })); + } + ui.set_bar(""); + return; + } + if let Pending::Edit(h) = pending { + ui.pending.set(Pending::None); + if t.is_empty() { + return; + } + if h.key.starts_with("t:") { + sp.send(json!({ "cmd": "retext", "key": h.key, "text": t })); + } else { + match api.put_memory(&h.key, &t).await { + Ok(()) => { + ui.did(Did::Edited { + key: h.key.clone(), + old: h.text.clone(), + }); + sp.send(json!({ "cmd": "retext", "key": h.key, "text": t })); + ui.say(format!("{} now reads “{t}”", h.key)); + ui.touched(); + } + Err(e) => ui.fail(e), + } + } + ui.set_bar(""); + return; + } + if t.is_empty() { + return; + } + push_history(ui, sp, &t); + let mut words = t.split_whitespace(); + let word = words.next().unwrap_or_default().to_string(); + let rest: Vec<&str> = words.collect(); + // `Run <program> [arguments]`: an s program of the save + if word == "Run" && crate::views::scode::run_from_bar(ui, &api, &t).await { + return; + } + if COMMANDS.contains(&word.as_str()) && (rest.is_empty() || word == "Save") { + if matches!(word.as_str(), "Note" | "Notes") { + ui.say("weum's notes on memories aren't part of anend; lists are"); + } else { + command(ui, api, sp, &word, &rest.join(" ")).await; + } + return; + } + if let Some(addr) = t.strip_prefix('#') { + route(ui, api, sp, addr).await; + return; + } + let (gs, sat) = { + let p = ui.prefs.peek(); + (p.gsearch_text, p.saturate) + }; + let mode = space_mode(ui); + if shift { + // recall by key + match api.remember(&t).await { + Ok(h) => { + let mut tl = ui.topline; + tl.set(Some(TopLine { + title: format!("key {}", h.key), + detail: String::new(), + s: 0, + r: 0, + ..Default::default() + })); + show(ui, api, sp, vec![h]); + } + Err(e) => ui.fail(e), + } + return; + } + // the search modes: by the colouring classifier (a class's name, then words), or + // weum's random hashmap search (texts sharing a word, in no order) + let how = if ctrl { + "normal".to_string() + } else { + ui.prefs.peek().space_search.clone() + }; + if how == "classifier" { + classifier_search(ui, api, sp, &t).await; + return; + } + if how == "random" { + match api + .call( + "mem.random", + json!({ "q": if t == "*" { "" } else { t.as_str() }, "limit": 60 }), + ) + .await + { + Ok(v) => { + let hits: Vec<Hit> = serde_json::from_value(v).unwrap_or_default(); + topline(ui, format!("random “{t}”"), mode, None, hits.len()); + if hits.is_empty() { + ui.say(format!("no text shares a word with {t} (* takes any)")); + } + show(ui, api, sp, hits); + } + Err(e) => ui.fail(e), + } + return; + } + if let Ok(n) = t.parse::<u64>() { + gsearch(ui, api, sp, n, mode, None).await; + return; + } + if !gs && !ctrl { + match api.search(&t, true).await { + Ok(hits) => { + topline(ui, format!("search “{t}”"), mode, Some(&t), hits.len()); + if hits.is_empty() { + ui.say(format!("didn't find anything for {t}")); + } + show(ui, api, sp, hits); + } + Err(e) => ui.fail(e), + } + return; + } + if sat || ctrl { + match api.saturate(&t).await { + Ok((key, new)) => { + if new { + ui.did(Did::Remembered { + key: key.clone(), + text: t.clone(), + }); + ui.say(format!("remembered “{t}” under {key}")); + ui.touched(); + } + } + Err(e) => ui.fail(e), + } + } + gsearch(ui, api, sp, gem::sum_in(&t, mode), mode, Some(t)).await; +} + +/// the bar's text as a class of the colouring classifier (and words after it): the texts +/// it counts in that class, or the likeliest when it counts none +async fn classifier_search(ui: Ui, api: Api, sp: Sp, t: &str) { + let name = ui.prefs.peek().tint.clone(); + if name.is_empty() { + ui.fail("pick a colouring classifier first (the palette in the memory view's strip)"); + return; + } + let classes: Vec<String> = match api.call("classify.get", json!({ "name": name })).await { + Ok(v) => v["classes"] + .as_array() + .into_iter() + .flatten() + .filter_map(|c| c.as_str().map(str::to_string)) + .collect(), + Err(e) => return ui.fail(e), + }; + let lower = t.to_lowercase(); + let Some(c) = classes.iter().find(|c| { + let c = c.to_lowercase(); + lower == c || lower.starts_with(&format!("{c} ")) + }) else { + ui.fail(format!( + "{name}'s classes: {} (type one, then words if you like)", + classes.join(", ") + )); + return; + }; + let words = t[c.len()..].trim().to_string(); + match api.model_search(&name, c, &words).await { + Ok(found) => { + let members = found.iter().filter(|s| s.member).count(); + if members == 0 { + ui.say(format!("{name} counts nothing here as {c}; these are the likeliest")); + } + let hits: Vec<Hit> = found + .into_iter() + .filter(|s| s.member || members == 0) + .take(if members == 0 { 24 } else { 400 }) + .filter_map(|s| { + Some(Hit { + key: s.key?, + text: s.text, + note: s.note, + }) + }) + .collect(); + topline(ui, format!("{name}: {c}"), space_mode(ui), None, hits.len()); + show(ui, api, sp, hits); + } + Err(e) => ui.fail(e), + } +} + +/// the bar's Delete: forget the memory under the key typed +async fn forget_typed(ui: Ui, api: Api, sp: Sp, raw: String) { + let key = raw.trim().to_string(); + match api.forget(&key).await { + Ok(text) => { + ui.did(Did::Forgot { + key: key.clone(), + text: text.clone(), + }); + ui.say(format!("forgot {key}: “{text}” · Ctrl+Z puts it back")); + let mut texts = sp.texts; + texts.write().retain(|h| h.key != key); + ui.touched(); + } + Err(e) => ui.fail(e), + } +} + +fn copy_text(ui: Ui, text: &str) { + let js = format!( + "(async () => {{ const t = {}; try {{ await navigator.clipboard.writeText(t); }} catch {{ const a = document.createElement('textarea'); a.value = t; document.body.append(a); a.select(); document.execCommand('copy'); a.remove(); }} }})();", + serde_json::to_string(text).unwrap_or_default() + ); + document::eval(&js); + ui.say("copied"); +} + +/// the room's texts to a file: a download on the web, a file in the data folder on the +/// desktop +fn export(ui: Ui, name: &str, rows: &Value) { + let text = serde_json::to_string_pretty(rows).unwrap_or_default(); + let file = format!("{name}.json"); + let n = rows.as_array().map(|a| a.len()).unwrap_or(0); + #[cfg(not(target_arch = "wasm32"))] + { + let dir = crate::prefs::data_dir().join("exports"); + let path = dir.join(&file); + match std::fs::create_dir_all(&dir).and_then(|_| std::fs::write(&path, &text)) { + Ok(()) => ui.say(format!("{n} texts to {}", path.display())), + Err(e) => ui.fail(format!("couldn't write {}: {e}", path.display())), + } + } + #[cfg(target_arch = "wasm32")] + { + crate::views::settings::download(&file, &text); + ui.say(format!("{n} texts to {file}")); + } +} + +#[component] +pub fn Space() -> Element { + let ui = ui(); + let api = api(); + let sp = Sp { + tx: use_signal(|| None), + texts: use_signal(Vec::new), + card: use_signal(|| None), + selected: use_signal(|| None), + pos: use_signal(String::new), + hist_at: use_signal(|| None), + paused: use_signal(|| false), + q_bucket: use_signal(HashMap::new), + block: use_signal(|| None), + block_use: use_signal(|| (0, 0)), + lights: use_signal(Vec::new), + lightpick: use_signal(|| None), + wiremode: use_signal(|| false), + multi: use_signal(|| None), + menu: use_signal(|| None), + scenes_rev: use_signal(|| 0), + bmenu: use_signal(|| None), + bend_open: use_signal(|| false), + live: use_signal(|| false), + fired: use_signal(Vec::new), + prefabs: use_signal(Vec::new), + copies: use_signal(Vec::new), + thumbs: use_signal(HashMap::new), + mode: use_signal(|| "fly".to_string()), + collected: use_signal(Vec::new), + previews: use_signal(HashMap::new), + }; + use_context_provider(|| Previews(sp.previews)); + // the pipes turned on: their effects on the room's texts, sent whenever they or the texts change + { + let api = api.clone(); + let texts = sp.texts; + let _fx = use_resource(move || { + let api = api.clone(); + let names = ui.prefs.read().pipes.clone(); + let keys: Vec<String> = texts.read().iter().map(|h| h.key.clone()).take(5000).collect(); + let _ = (ui.changed)(); + async move { + let fx = if names.is_empty() || keys.is_empty() { + json!({}) + } else { + let v = api + .call("pipes.effects", json!({ "names": names, "keys": keys })) + .await + .unwrap_or_default(); + let mut m = serde_json::Map::new(); + for e in v["effects"].as_array().into_iter().flatten() { + m.insert(e["key"].as_str().unwrap_or("").to_string(), e.clone()); + } + Value::Object(m) + }; + sp.send(json!({ "cmd": "effects", "fx": fx })); + } + }); + } + // the engine and its channel + { + let api = api.clone(); + use_hook(move || { + let (tx, rx) = futures_channel::mpsc::unbounded::<Value>(); + let mut stx = sp.tx; + stx.set(Some(tx)); + // the room in Rust, drawn natively (no JavaScript): its loop takes the commands + if native_space() { + let api = api.clone(); + native_room::run(rx, move |e| on_event(ui, api.clone(), sp, e)); + #[cfg(not(feature = "desktop"))] + return; + } + #[cfg(not(feature = "desktop"))] + spawn(async move { + let mut rx = rx; + let mut ev = document::eval(&boot_js()); + loop { + let got = { + let recv = ev.recv::<SpaceEvent>(); + let next = rx.next(); + futures_util::pin_mut!(recv, next); + match futures_util::future::select(recv, next).await { + Either::Left((r, _)) => Either::Left(r), + Either::Right((c, _)) => Either::Right(c), + } + }; + match got { + Either::Left(Ok(e)) => on_event(ui, api.clone(), sp, e), + Either::Left(Err(_)) => break, + Either::Right(Some(c)) => { + let _ = ev.send(c); + } + Either::Right(None) => break, + } + } + }); + }); + } + // the save's blocks, whenever another save opens + { + let api = api.clone(); + use_effect(move || { + let save = (ui.hello)().save; + let api = api.clone(); + dioxus::dioxus_core::spawn_forever(async move { + let _ = save; + load_blocks(ui, api, sp).await; + }); + }); + } + // running only while shown; the room's colour and ink from the settings + use_effect(move || { + let shown = (ui.view)() == View::Space; + sp.send(json!({ "cmd": if shown { "start" } else { "stop" } })); + }); + // the flying keys as the keymap binds them + use_effect(move || { + let map = crate::keys::Keymap::from_changes(&ui.prefs.read().keymap).flying(); + sp.send(json!({ "cmd": "keys", "map": map })); + }); + // the physics, whenever a slider moves + use_effect(move || { + let p = ui.prefs.read(); + let _ = (&p.space.physics, &p.space.depth_by, p.space_reversed); + drop(p); + sp.send(json!({ "cmd": "physics", "p": physics(ui) })); + }); + use_effect(move || { + let bg = ui.prefs.read().space_bg.clone(); + sp.send(json!({ "cmd": "room", "bg": bg, "ink": crate::theme::ink_on(&bg) })); + }); + use_effect(move || { + let p = (ui.picks)(); + sp.send(json!({ "cmd": "mark", "list": p.list.map(|h| h.key), "candidate": p.candidate.map(|h| h.key) })); + }); + { + let api = api.clone(); + use_keys(View::Space, move |k: KeyPress| { + if k.bar { + match k.key.as_str() { + "Enter" => { + dioxus::dioxus_core::spawn_forever(enter(ui, api.clone(), sp, k.text.clone(), k.ctrl, k.shift)); + // the bar lets go, so the flying keys move again; a click on the bar + // (or the focus key) types again + document::eval( + "const b = document.getElementById('bar'); if (b) b.blur(); const h = document.getElementById('space-host'); if (h) h.focus({ preventScroll: true });", + ); + return true; + } + "Delete" => { + dioxus::dioxus_core::spawn_forever(forget_typed(ui, api.clone(), sp, k.text.clone())); + return true; + } + "ArrowUp" | "ArrowDown" => { + let h = ui.prefs.peek().space.history.clone(); + if h.is_empty() || k.text.contains('\n') { + return true; + } + let n = h.len(); + let cur = sp.hist_at.peek().unwrap_or(n); + let i = if k.key == "ArrowUp" { + cur.saturating_sub(1) + } else { + (cur + 1).min(n) + }; + let mut at = sp.hist_at; + at.set(Some(i)); + ui.set_bar(h.get(i).map(String::as_str).unwrap_or("")); + return true; + } + _ => return false, + } + } + if k.key == "Escape" { + let mut s = sp.selected; + s.set(None); + return true; + } + let sel = sp.selected.peek().clone(); + match k.action { + Some(Action::Help) => set_pref(ui, |p| p.space.show_help = !p.space.show_help), + Some(Action::Hud) => set_pref(ui, |p| p.space.show_hud = !p.space.show_hud), + Some(Action::Details) => set_pref(ui, |p| p.space.show_details = !p.space.show_details), + Some(Action::Physics) => set_pref(ui, |p| p.space.show_physics = !p.space.show_physics), + Some(Action::Reversed) => set_pref(ui, |p| p.space_reversed = !p.space_reversed), + Some(Action::Pause) => { + let on = !*sp.paused.peek(); + let mut p = sp.paused; + p.set(on); + sp.send(json!({ "cmd": "pause", "on": on })); + ui.say(if on { "physics paused" } else { "physics running" }); + } + Some(Action::Settle) => sp.send(json!({ "cmd": "settle" })), + Some(Action::Pin) => sp.send(json!({ "cmd": "pin" })), + Some(Action::DeleteText) if sp.multi.peek().is_some() => sp.send(json!({ "cmd": "removemulti" })), + Some(Action::Group) => sp.send(json!({ "cmd": "group" })), + Some(Action::WireMode) => sp.send(json!({ "cmd": "wiremode", "toggle": true })), + Some(Action::Ungroup) => sp.send(json!({ "cmd": "ungroup" })), + Some(Action::DeleteText) => match sp + .block + .peek() + .as_ref() + .and_then(|b| b["id"].as_str().map(str::to_string)) + { + Some(id) => delete_block(ui, api.clone(), sp, id), + None => sp.send(json!({ "cmd": "remove" })), + }, + Some(Action::NewText) => { + let t = ui.bar.peek().trim().to_string(); + sp.send(json!({ "cmd": "free", "text": if t.is_empty() { "text".to_string() } else { t } })); + } + Some(Action::EditText) => match sel { + Some(s) => start_edit(ui, &s), + None => ui.focus_bar(), + }, + Some(Action::CopyText) => match sel { + Some(s) => copy_text(ui, &s.text), + None => ui.say("select a text first"), + }, + Some(Action::Undo) => sp.send(json!({ "cmd": "undo" })), + Some(Action::Export) => { + sp.send(json!({ "cmd": "rows", "why": "export", "name": default_map_name(ui) })) + } + Some(Action::SaveMap) => sp.send(json!({ "cmd": "rows", "why": "save", "name": default_map_name(ui) })), + Some(Action::SideSum) | Some(Action::SideReversedSum) => { + let t = ui.bar.peek().clone(); + let (s, r) = gem::sums(&t); + if k.action == Some(Action::SideSum) { + envale(ui, api.clone(), sp, s, Mode::Ordinal); + } else { + envale(ui, api.clone(), sp, r, Mode::Reversed); + } + } + // the engine flies and hops on the rest itself + _ => { + return matches!( + k.key.as_str(), + "ArrowLeft" | "ArrowRight" | "ArrowUp" | "ArrowDown" | " " + ); + } + } + true + }); + } + // the last address, opened the first time the space is shown + { + let api = api.clone(); + use_hook(move || { + let a = ui.prefs.peek().space.address.clone(); + if !a.is_empty() { + dioxus::dioxus_core::spawn_forever(async move { + // the engine boots first + sleep_ms(500).await; + route(ui, api, sp, &a).await; + }); + } + }); + } + let card = (sp.card)(); + let n = sp.texts.read().len(); + let p = ui.prefs.read().clone(); + let bg = p.space_bg.clone(); + let ink = crate::theme::ink_on(&bg); + let api_g = api.clone(); + let api_b = api.clone(); + rsx! { + div { class: "space", style: "position: absolute; inset: 0; --room-bg: {bg}; --room-ink: {ink};", + if native_space() { + NativeHost {} + } else { + div { id: "space-host", class: "space-host", tabindex: "0", "aria-label": "the space: right drag looks, W A S D fly, arrows hop between texts" } + } + if p.space.show_hud { + PosCard { pos: sp.pos } + } + // the hint while the room has nothing in it: no texts, no blocks and no prefab copies + if n == 0 && (sp.block_use)().0 == 0 && sp.copies.read().is_empty() { + div { class: "space-empty", + p { "The room is empty." } + p { class: "small", "Type a word, a number or a key in the bar and press Enter: its bucket spreads out here, pulled together by how alike the texts are. Hold the right mouse button to look around, W A S D to fly, the arrow keys hop from text to text; H for help." } + } + } + if p.space.show_help { + Help {} + } + if p.space.show_physics { + PhysicsPanel { + paused: (sp.paused)(), + on_settle: move |_| sp.send(json!({ "cmd": "settle" })), + on_pause: move |on: bool| { + let mut ps = sp.paused; + ps.set(on); + sp.send(json!({ "cmd": "pause", "on": on })); + }, + } + } + if let Some(m) = (sp.multi)() { + div { class: "multibar", role: "status", + b { {format!("{} selected", m["count"])} } + span { class: "dim small", + {[("blocks", "block"), ("copies", "copy"), ("texts", "text"), ("lights", "light")].iter().filter_map(|(k, one)| { + let n = m[*k].as_u64().unwrap_or(0); + (n > 0).then(|| format!("{n} {}", if n == 1 { one.to_string() } else { k.to_string() })) + }).collect::<Vec<_>>().join(" · ")} + } + if let Some(g) = m["group"].as_str().map(String::from) { + span { class: "small", b { {if m["name"].as_str().unwrap_or("").is_empty() { "a group".to_string() } else { format!("the group “{}”", m["name"].as_str().unwrap_or("")) }} } } + button { class: "btn small", onclick: move |_| sp.send(json!({ "cmd": "ungroup" })), Icon { name: "close" } "ungroup" kbd { "{ui.key_of(Action::Ungroup)}" } } + button { class: "btn small", onclick: { let (g, api) = (g.clone(), api_b.clone()); move |_| group_copy(ui, api.clone(), sp, g.clone()) }, Icon { name: "copy" } "a copy beside it" } + button { class: "btn small", onclick: { let (g, api, n) = (g.clone(), api_b.clone(), m["name"].as_str().unwrap_or("").to_string()); move |_| group_prefab(ui, api.clone(), sp, g.clone(), n.clone()) }, Icon { name: "prefab" } "make a prefab of it" } + } else { + button { class: "btn small", onclick: move |_| sp.send(json!({ "cmd": "group" })), Icon { name: "prefab" } "group them" kbd { "{ui.key_of(Action::Group)}" } } + } + span { class: "dim small", "drag the gizmo to move or turn them all · Shift+click adds or takes out" } + button { class: "btn small", onclick: move |_| sp.send(json!({ "cmd": "removemulti" })), Icon { name: "delete" } "delete them" kbd { "{ui.key_of(Action::DeleteText)}" } } + button { class: "btn small", onclick: move |_| sp.send(json!({ "cmd": "clearmulti" })), Icon { name: "close" } "let go" kbd { "Esc" } } + } + } + if let (Some((x, y)), Some(b)) = ((sp.bmenu)(), (sp.block)().filter(|b| b["copy"] == true)) { + prefabwin::CopyMenu { c: b, x, y, sp } + } else if let (Some((x, y)), Some(b)) = ((sp.bmenu)(), (sp.block)()) { + BlockMenu { b, x, y, sp_bmenu: sp.bmenu, bend_open: sp.bend_open, + on_send: move |v: Value| sp.send(v), + on_duplicate: { let api = api_b.clone(); move |b: Value| duplicate_block(ui, api.clone(), sp, b) }, + on_delete: { let api = api_b.clone(); move |id: String| delete_block(ui, api.clone(), sp, id) }, + } + } + if let Some(m) = (sp.menu)() { + SpaceMenu { ev: m, sp_menu: sp.menu, on_send: move |v: Value| sp.send(v), on_gsearch: { let api = api_b.clone(); move |(n, md): (u64, Mode)| envale(ui, api.clone(), sp, n, md) } } + } + if p.space.show_scenes { + Scenes { + rev: sp.scenes_rev, + on_open: { let api = api_b.clone(); move |name: String| { let api = api.clone(); dioxus::dioxus_core::spawn_forever(async move { route(ui, api, sp, &name).await; }); } }, + on_save: move |name: String| sp.send(json!({ "cmd": "rows", "why": "save", "name": name })), + } + } + if p.space.show_blocks { + Blocks { + selected: (sp.selected)(), + block: (sp.block)().filter(|b| b["copy"] != true), + counts: (sp.block_use)(), + on_send: move |v: Value| sp.send(v), + on_duplicate: { let api = api_b.clone(); move |b: Value| duplicate_block(ui, api.clone(), sp, b) }, + on_delete: { let api = api_b.clone(); move |id: String| delete_block(ui, api.clone(), sp, id) }, + bend_open: sp.bend_open, + } + } + if p.space.show_anims { + animwin::Anims { sp, block: (sp.block)().filter(|b| b["copy"] != true), on_changed: { let api = api_b.clone(); move |_| { let api = api.clone(); dioxus::dioxus_core::spawn_forever(count_blocks(api, sp)); } } } + } + if !(sp.collected)().is_empty() { + flightwin::Collected { sp } + } + if p.space.show_sounds { + soundwin::Sounds { sp } + } + if p.space.show_prefabs { + prefabwin::Prefabs { sp } + } + if p.space.show_wiring { + wirewin::Wires { sp } + } + if p.space.show_lights { + lightwin::Lights { sp } + } + if p.space.show_textures { + texwin::Textures { + selected: (sp.selected)(), + block: (sp.block)().filter(|b| b["copy"] != true), + on_send: move |v: Value| sp.send(v), + on_changed: { let api = api_b.clone(); move |_| { let api = api.clone(); dioxus::dioxus_core::spawn_forever(count_blocks(api, sp)); } }, + } + } + if p.space.show_details { + if let Some(c) = card { + Details { ev: c, on_gsearch: move |(n, m): (u64, Mode)| envale(ui, api_g.clone(), sp, n, m), on_send: move |v: Value| sp.send(v) } + } + } + } + } +} + +/// puts a text in the bar to edit: Enter puts it back (a memory under its key, a free text +/// in its place) +fn start_edit(mut ui: Ui, s: &SpaceEvent) { + ui.set_bar(&s.text); + ui.pending.set(Pending::Edit(Hit { + key: s.key.clone(), + text: s.text.clone(), + note: s.note, + })); + ui.focus_bar(); + ui.say("edit it in the bar; Enter puts it back, Esc leaves it"); +} + +fn on_event(mut ui: Ui, api: Api, sp: Sp, e: SpaceEvent) { + let hit = Hit { + key: e.key.clone(), + text: e.text.clone(), + note: e.note, + }; + let mut card = sp.card; + let mut pos = sp.pos; + let mut selected = sp.selected; + match e.kind.as_str() { + "info" => pos.set(e.text), + "error" => ui.fail(format!("the space couldn't start: {}", e.text)), + "fault" => ui.fail(e.text.clone()), + "toast" => ui.say(e.text), + "hover" | "focus" => card.set(Some(e.clone())), + "select" => { + // an open menu on the same placement shows its new values (its size) + let mut m = sp.menu; + let open = m + .peek() + .as_ref() + .filter(|o| o.node == e.node && !e.node.is_empty()) + .cloned(); + if let Some(o) = open { + m.set(Some(SpaceEvent { + x: o.x, + y: o.y, + ..e.clone() + })); + } + // and so does the details window + if card + .peek() + .as_ref() + .is_some_and(|c| c.node == e.node && !e.node.is_empty()) + { + card.set(Some(e.clone())); + } + selected.set((!e.key.is_empty()).then(|| e.clone())) + } + "settled" => ui.say(format!("settled in {} steps", e.data)), + "block" => { + let mut b = sp.block; + b.set((!e.data.is_null()).then(|| e.data.clone())); + } + "blockset" => { + let mut b = sp.block; + if b.peek().as_ref().map(|x| &x["id"]) == Some(&e.data["id"]) { + let mut v = e.data.clone(); + if let Some(old) = b.peek().as_ref() { + v["about"] = old["about"].clone(); + } + b.set(Some(v)); + } + let args = e.data.clone(); + dioxus::dioxus_core::spawn_forever(async move { + if let Err(err) = api.call("blocks.set", args).await { + ui.fail(err); + } + }); + } + "spot" => { + let want = e.data["want"].clone(); + let mut args = want.clone(); + for k in ["x", "y", "z"] { + args[k] = e.data[k].clone(); + } + dioxus::dioxus_core::spawn_forever(async move { + match api.call("blocks.add", args).await { + Ok(r) => { + let id = r["ids"][0].clone(); + let textures = dress(ui, &api, r["textures"].clone()).await; + sp.send(json!({ "cmd": "blocks", "blocks": r["blocks"], "textures": textures, "added": r["ids"], "select": id })); + count_blocks(api, sp).await; + ui.say("a block · drag its arrows to move it, the knobs on its faces to resize it · Ctrl+Z takes it back"); + } + Err(err) => ui.fail(err), + } + }); + } + // an undo took back blocks just added, or put back blocks just deleted + "lightspot" => lightwin::light_spot(ui, api, sp, e.data.clone()), + "prefabspot" => prefabwin::place_at(ui, api, sp, e.data.clone()), + // placing a prefab by hand: a copy where the ghost was + "ghostplace" => prefabwin::place_exactly(ui, api, sp, e.data.clone()), + // a prefab's copy, as one group + "copyset" => prefabwin::copy_set(ui, api, sp, e.data.clone()), + "copyrestore" => prefabwin::copy_restore(ui, api, sp, e.data.clone()), + // the selection of many + "multi" => { + let mut m = sp.multi; + m.set((e.data["count"].as_u64().unwrap_or(0) > 0).then(|| e.data.clone())); + } + // Delete on many: the room took texts and blocks; copies and lights go here, in the + // same undo step (the room closes it when told) + "removedmulti" => { + let copies: Vec<String> = e.data["copies"].as_array().into_iter().flatten().filter_map(|x| x.as_str().map(String::from)).collect(); + let lights: Vec<Value> = e.data["lights"].as_array().cloned().unwrap_or_default(); + let n = e.data["count"].as_u64().unwrap_or(0); + dioxus::dioxus_core::spawn_forever(async move { + for id in &copies { + match api.call("prefabs.remove", json!({ "id": id })).await { + Ok(r) => sp.send(json!({ "cmd": "copygone", "ids": r["removed"], "restore": r["restore"] })), + Err(err) => ui.fail(err), + } + } + for id in &lights { + if let Err(err) = api.call("lights.delete", json!({ "id": id })).await { + ui.fail(err); + } + } + if !copies.is_empty() { + sp.send(json!({ "cmd": "batch", "on": false })); + prefabwin::load_prefabs(ui, &api, sp).await; + } + if !lights.is_empty() { + lightwin::load_lights(&api, sp).await; + } + count_blocks(api, sp).await; + ui.say(format!("{n} taken away · Ctrl+Z puts them back")); + }); + } + // groups (Ctrl+G, Ctrl+Shift+G, the bar's buttons, an undo) + "groupmake" => groups_call(ui, api, sp, "groups.make", json!({ "members": e.data["members"] }), "made"), + "groupbreak" => { + if e.data["id"].is_null() { + ui.say("select a group first (a click on any of it)"); + return; + } + let why = if e.data["quiet"] == true { "quiet" } else { "broke" }; + groups_call(ui, api, sp, "groups.ungroup", json!({ "id": e.data["id"] }), why) + } + "grouprestore" => groups_call(ui, api, sp, "groups.restore", e.data.clone(), "select"), + // wires made by dragging (and taken back by an undo) + "wiremode" => { + let on = e.data == true; + let mut w = sp.wiremode; + w.set(on); + ui.say(if on { "wiring: drag from one block to another to wire it (again to take the wire away) · J stops" } else { "wiring stopped" }); + } + "wirelink" => { + let args = e.data.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("wiring.link", args).await { + Ok(r) => { + let textures = dress(ui, &api, r["textures"].clone()).await; + sp.send(json!({ "cmd": "blocks", "blocks": r["blocks"], "textures": textures })); + sp.send(json!({ "cmd": "wired", "items": r["changed"] })); + wirewin::load_wires(&api, sp).await; + ui.say(if r["made"] == true { "wired: a click on the first casts its ray to the second · Ctrl+Z takes it back" } else { "the wire is gone · Ctrl+Z puts it back" }); + } + Err(err) => ui.fail(err), + } + }); + } + "wireset" => { + let args = e.data.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("wiring.set", args).await { + Ok(_) => wirewin::load_wires(&api, sp).await, + Err(err) => ui.fail(err), + } + }); + } + "groupopen" => ui.say("the group is open: its things are picked one by one · Esc closes it"), + "lightpick" => { + let mut l = sp.lightpick; + l.set(e.data.as_u64()); + } + // a light moved in the room (with many), or put back by an undo + "lightset" => { + let args = e.data.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("lights.set", args).await { + Ok(_) => lightwin::load_lights(&api, sp).await, + Err(err) => ui.fail(err), + } + }); + } + "lightrestore" => { + let mut args = e.data.clone(); + if let Some(o) = args.as_object_mut() { + o.remove("id"); + } + dioxus::dioxus_core::spawn_forever(async move { + match api.call("lights.add", json!({ "light": args })).await { + Ok(_) => lightwin::load_lights(&api, sp).await, + Err(err) => ui.fail(err), + } + }); + } + "copyopen" => ui.say("the copy is open: its parts are picked one by one, their changes kept as the copy's own · Esc or a click outside closes it"), + "ghostdone" => ui.say("placing stopped"), + "mode" => { + let m = e.data.as_str().unwrap_or("fly").to_string(); + ui.say(match m.as_str() { + "walk" => format!("walking · {} jumps, {} crouches, {} {} lean, {} hooks the grapple · {} flies again", ui.key_of(Action::FlyUp), ui.key_of(Action::FlyDown), ui.key_of(Action::RollLeft), ui.key_of(Action::RollRight), ui.key_of(Action::Grapple), ui.key_of(Action::Walk)), + "super" => format!("superflight · {} thrusts where you look, Shift boosts; texts you fly through are collected · {} flies again", ui.key_of(Action::FlyForward), ui.key_of(Action::SuperFlight)), + _ => "flying".to_string(), + }); + let mut s = sp.mode; + s.set(m); + } + "collected" => { + let mut c = sp.collected; + c.set(e.data.as_array().cloned().unwrap_or_default()); + } + // the room needs a sound's bytes to play it + "soundwant" => { + let id = e.data.as_str().unwrap_or("").to_string(); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("sounds.get", json!({ "id": id })).await { + Ok(r) => sp.send(json!({ "cmd": "sounddata", "id": id, "data": r["data"] })), + Err(e) => ui.fail(e), + } + }); + } + "preview" => { + if let (Some(id), Some(src)) = (e.data["id"].as_str(), e.data["src"].as_str()) { + let mut p = sp.previews; + p.write().insert(id.to_string(), src.to_string()); + } + } + "thumbs" => { + let mut t = sp.thumbs; + let mut m = t.peek().clone(); + for (k, v) in e.data.as_object().into_iter().flatten() { + if let (Ok(k), Some(v)) = (k.parse::<u64>(), v.as_str()) { + m.insert(k, v.to_string()); + } + } + t.set(m); + } + // a wired block fired in the room (a click while playing, a timer, a zone) + "blockfire" => { + let ev = match e.data["event"].as_str().unwrap_or("") { + "click" => "click", + "timer" => "timer", + "enter" => "enter", + "leave" => "leave", + _ => return, + }; + let id = e.data["id"].as_str().unwrap_or("").to_string(); + let from = e.data["from"].as_str().unwrap_or("").to_string(); + wirewin::fire(ui, api.clone(), sp, id, ev, from); + } + "blockmenu" => { + let mut m = sp.bmenu; + m.set(Some((e.x, e.y))); + } + "blockgone" => { + let ids = e.data.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("blocks.delete", json!({ "ids": ids })).await { + Ok(_) => count_blocks(api, sp).await, + Err(err) => ui.fail(err), + } + }); + } + "blockrestore" => { + let blocks = e.data.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("blocks.restore", json!({ "blocks": blocks })).await { + Ok(_) => count_blocks(api, sp).await, + Err(err) => ui.fail(err), + } + }); + } + "undone" => { + if e.data == "nothing" { + undo_last(ui, api); + } else { + ui.say("undone"); + } + } + "made" => { + selected.set(Some(e.clone())); + start_edit(ui, &e); + } + // a double click on the empty room makes a new free text: an empty one to type in, + // or with Shift the bar's text (deliberately: it used to copy the bar's text, which + // after a click is the text clicked) + "newtext" => { + let t = ui.bar.peek().trim().to_string(); + let t = if e.shift && !t.is_empty() { + t + } else { + "text".to_string() + }; + sp.send(json!({ "cmd": "free", "text": t })); + } + "dblclick" => { + if e.free { + start_edit(ui, &e); + } else { + ui.set_bar(&e.key); + } + } + "rows" => { + let rows = e.data["rows"].clone(); + let name = e.data["name"].as_str().unwrap_or("untitled").to_string(); + if e.data["why"] == "export" { + export(ui, &name, &rows); + } else { + let ok = (1..=96).contains(&name.len()) + && name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-'); + if !ok { + ui.fail("a map's name: 1 to 96 of letters, digits, _ and -"); + return; + } + dioxus::dioxus_core::spawn_forever(async move { + let n = rows.as_array().map(|a| a.len()).unwrap_or(0); + match api.call("scenes.save", json!({ "name": name, "rows": rows })).await { + Ok(_) => { + let mut r = sp.scenes_rev; + r += 1; + set_pref(ui, |p| p.space.address = name.clone()); + ui.say(format!("saved the map {name} · {n} texts · #{name} opens it")); + } + Err(e) => ui.fail(e), + } + }); + } + } + "click" => { + if e.free { + ui.set_bar(&e.text); + return; + } + if e.ctrl && !e.shift { + ui.picks.write().candidate = Some(hit.clone()); + ui.say(format!("candidate: {}", hit.text)); + } else if e.shift { + let mut p = ui.picks.write(); + p.candidate = None; + p.list = Some(hit.clone()); + drop(p); + ui.say(format!("list: {}", hit.text)); + } else { + ui.set_bar(&hit.text); + let mode = space_mode(ui); + // its triangle in the top bar + let (s, r) = gem::sums(&hit.text); + ui.topline.set(Some(TopLine { + title: hit.text.clone(), + detail: format!("{} {}", mode.name(), gem::sum_in(&hit.text, mode)), + s, + r, + ..Default::default() + })); + card.set(Some(e.clone())); + } + } + "menu" => { + if e.ctrl && !e.free { + let m = gem::Measure::of(&hit.text); + dioxus::dioxus_core::spawn_forever(gsearch(ui, api, sp, m.triangle(), space_mode(ui), Some(hit.text))); + } else { + let mut m = sp.menu; + m.set(Some(e.clone())); + } + } + _ => {} + } +} + +// ------------------------------------------------------------------ blocks + +/// what the engine needs to draw the textures: a text's grouping colour (its labels' +/// underline), a picture's thumbnail as a data URL +async fn dress(ui: Ui, api: &Api, textures: Value) -> Value { + let mode = space_mode(ui); + let mut out = textures; + if let Some(o) = out.as_object_mut() { + for (k, about) in o.iter_mut() { + if let Some(t) = k.strip_prefix("text:").and(about["text"].as_str().map(str::to_string)) { + about["colour"] = json!(gem::underline(&t, mode)); + } else if let Some(id) = k.strip_prefix("picture:") + && about.get("gone").is_none() + && let Ok(p) = api.call("pictures.get", json!({ "id": id, "thumb": 256 })).await + && let Some(t) = p["thumb"].as_str() + { + about["src"] = json!(format!("data:image/png;base64,{t}")); + } else if k.starts_with("texture:") { + // a recipe: its text's colour, its picture's thumbnail + if let Some(t) = about["text"].as_str().map(str::to_string) { + about["colour"] = json!(gem::underline(&t, mode)); + } + if let Some(id) = about["recipe"]["source"]["picture"].as_str().map(str::to_string) + && about.get("picture_gone").is_none() + && let Ok(p) = api.call("pictures.get", json!({ "id": id, "thumb": 512 })).await + && let Some(t) = p["thumb"].as_str() + { + about["src"] = json!(format!("data:image/png;base64,{t}")); + } + } + } + } + out +} + +async fn count_blocks(api: Api, sp: Sp) { + if let Ok(u) = api.call("blocks.stats", json!({})).await { + let mut c = sp.block_use; + c.set((u["blocks"].as_u64().unwrap_or(0), u["textures"].as_u64().unwrap_or(0))); + } +} + +/// the open save's blocks into the room, in place of what was there +async fn load_blocks(ui: Ui, api: Api, sp: Sp) { + match api.call("blocks.list", json!({})).await { + Ok(r) => { + let textures = dress(ui, &api, r["textures"].clone()).await; + sp.send(json!({ "cmd": "blocks", "blocks": r["blocks"], "textures": textures, "replace": true })); + let mut b = sp.block; + b.set(None); + texwin::load_sky(ui, &api, EventHandler::new(move |v: Value| sp.send(v))).await; + lightwin::load_lights(&api, sp).await; + animwin::load_anims(ui, &api, sp).await; + wirewin::load_wires(&api, sp).await; + // the prefabs' copies: each one a group in the room; and the groups made by hand + prefabwin::load_prefabs(ui, &api, sp).await; + load_groups(&api, sp).await; + count_blocks(api, sp).await; + } + // a hub from before blocks: the room has none + Err(_) => sp.send(json!({ "cmd": "blocks", "blocks": [], "replace": true })), + } +} + +async fn load_groups(api: &Api, sp: Sp) { + if let Ok(l) = api.call("groups.list", json!({})).await { + sp.send(json!({ "cmd": "groups", "list": l })); + } +} + +/// a groups op; `how` says what the room does after: `made` (select it, one undo step), +/// `broke` (one undo step), `select` (select it), `quiet` (nothing: an undo's own work) +fn groups_call(ui: Ui, api: Api, sp: Sp, op: &'static str, args: Value, how: &'static str) { + dioxus::dioxus_core::spawn_forever(async move { + match api.call(op, args).await { + Ok(r) => { + let mut c = json!({ "cmd": "groups", "list": r["groups"] }); + match how { + "made" => { + c["made"] = r["id"].clone(); + ui.say("grouped: a click on any of it picks it all · double-click opens it · Ctrl+Shift+G ungroups"); + } + "broke" => { + c["broke"] = json!({ "members": r["members"] }); + ui.say("ungrouped · Ctrl+Z groups it again"); + } + "select" => c["select"] = r["id"].clone(), + _ => {} + } + sp.send(c); + } + Err(e) => ui.fail(e), + } + }); +} + +/// the selected group: a copy beside it (groups inside it copied as groups), or a prefab +/// of its blocks +fn group_copy(ui: Ui, api: Api, sp: Sp, gid: String) { + dioxus::dioxus_core::spawn_forever(async move { + let list = match api.call("groups.list", json!({})).await { + Ok(l) => l.as_array().cloned().unwrap_or_default(), + Err(e) => return ui.fail(e), + }; + let by = json!([2.0, 0.0, 0.0]); + // copies of every block and prefab copy in it, old id → new + let mut new: HashMap<String, String> = HashMap::new(); + fn leaves(list: &[Value], gid: &str, out: &mut Vec<(String, String)>) { + if let Some(g) = list.iter().find(|g| g["id"] == gid) { + for m in g["members"].as_array().into_iter().flatten() { + let (k, id) = (m["kind"].as_str().unwrap_or(""), m["id"].as_str().unwrap_or("")); + if k == "g" { + leaves(list, id, out) + } else { + out.push((k.to_string(), id.to_string())) + } + } + } + } + let mut ls = Vec::new(); + leaves(&list, &gid, &mut ls); + sp.send(json!({ "cmd": "batch", "on": true })); + for (k, id) in &ls { + let r = if k == "b" { + api.call("blocks.duplicate", json!({ "ids": [id], "by": by })) + .await + .map(|r| (r["ids"][0].as_str().unwrap_or("").to_string(), r)) + } else { + api.call("prefabs.duplicate", json!({ "id": id, "by": by })) + .await + .map(|r| (r["copy"]["id"].as_str().unwrap_or("").to_string(), r)) + }; + match r { + Ok((nid, r)) => { + let textures = dress(ui, &api, r["textures"].clone()).await; + sp.send(json!({ "cmd": "blocks", "blocks": r["blocks"], "textures": textures, "added": if k == "b" { json!([nid]) } else { json!([]) } })); + new.insert(format!("{k}:{id}"), nid); + } + Err(e) => { + sp.send(json!({ "cmd": "batch", "on": false })); + return ui.fail(e); + } + } + } + // the groups again, innermost first + fn remake<'a>( + api: &'a Api, + list: &'a [Value], + gid: &'a str, + new: &'a HashMap<String, String>, + ) -> std::pin::Pin<Box<dyn std::future::Future<Output = Option<String>> + 'a>> { + Box::pin(async move { + let g = list.iter().find(|g| g["id"] == gid)?; + let mut members = Vec::new(); + for m in g["members"].as_array().into_iter().flatten() { + let (k, id) = (m["kind"].as_str().unwrap_or(""), m["id"].as_str().unwrap_or("")); + let nid = if k == "g" { + remake(api, list, id, new).await? + } else { + new.get(&format!("{k}:{id}"))?.clone() + }; + members.push(json!({ "kind": k, "id": nid })); + } + api.call("groups.make", json!({ "members": members, "name": g["name"] })) + .await + .ok() + .and_then(|r| r["id"].as_str().map(String::from)) + }) + } + let made = remake(&api, &list, &gid, &new).await; + sp.send(json!({ "cmd": "batch", "on": false })); + prefabwin::load_prefabs(ui, &api, sp).await; + if let Ok(l) = api.call("groups.list", json!({})).await { + sp.send(json!({ "cmd": "groups", "list": l, "select": made })); + } + count_blocks(api, sp).await; + ui.say("a copy of the group beside it"); + }); +} + +fn group_prefab(ui: Ui, api: Api, sp: Sp, gid: String, name: String) { + dioxus::dioxus_core::spawn_forever(async move { + let list = api + .call("groups.list", json!({})) + .await + .ok() + .and_then(|l| l.as_array().cloned()) + .unwrap_or_default(); + let mut blocks = Vec::new(); + let mut copies = 0; + fn walk(list: &[Value], gid: &str, blocks: &mut Vec<String>, copies: &mut usize) { + if let Some(g) = list.iter().find(|g| g["id"] == gid) { + for m in g["members"].as_array().into_iter().flatten() { + match m["kind"].as_str().unwrap_or("") { + "g" => walk(list, m["id"].as_str().unwrap_or(""), blocks, copies), + "b" => blocks.push(m["id"].as_str().unwrap_or("").to_string()), + _ => *copies += 1, + } + } + } + } + walk(&list, &gid, &mut blocks, &mut copies); + if copies > 0 { + return ui.fail("a prefab is made of blocks: detach the copies in the group first (their menu)"); + } + let name = if name.trim().is_empty() { + "a group".to_string() + } else { + name + }; + match api.call("prefabs.make", json!({ "name": name, "ids": blocks })).await { + Ok(_) => { + load_blocks(ui, api.clone(), sp).await; + ui.say(format!("a prefab, “{name}”: its copy stands where the group was")); + } + Err(e) => ui.fail(e), + } + }); +} + +fn delete_block(ui: Ui, api: Api, sp: Sp, id: String) { + // a copy goes as a whole + if prefabwin::is_copy(&id) { + prefabwin::copy_remove(ui, api, sp, id); + return; + } + // a part of an open copy: the whole copy goes, or the part after detaching it + if id.starts_with("prefab:") { + ui.say("a part of a prefab's copy: remove the whole copy, or detach it, in the prefabs window"); + return; + } + dioxus::dioxus_core::spawn_forever(async move { + match api.call("blocks.delete", json!({ "ids": [id] })).await { + Ok(_) => { + sp.send(json!({ "cmd": "unblock", "ids": [id] })); + let mut b = sp.block; + b.set(None); + count_blocks(api, sp).await; + ui.say("block deleted · Ctrl+Z puts it back"); + } + Err(e) => ui.fail(e), + } + }); +} + +fn duplicate_block(ui: Ui, api: Api, sp: Sp, b: Value) { + let id = b["id"].as_str().unwrap_or("").to_string(); + if prefabwin::is_copy(&id) { + prefabwin::copy_duplicate(ui, api, sp, id); + return; + } + // side by side, along its width + let by = b["w"].as_f64().unwrap_or(1.0) + 0.1; + dioxus::dioxus_core::spawn_forever(async move { + match api + .call("blocks.duplicate", json!({ "ids": [id], "by": [by, 0, 0] })) + .await + { + Ok(r) => { + let textures = dress(ui, &api, r["textures"].clone()).await; + sp.send(json!({ "cmd": "blocks", "blocks": r["blocks"], "textures": textures, "added": r["ids"], "select": r["ids"][0] })); + count_blocks(api, sp).await; + ui.say("a copy: the same texture, stored once"); + } + Err(e) => ui.fail(e), + } + }); +} + +/// the blocks window: make blocks from the selected text, a picture or a colour; the +/// selected block's place and size; copy, delete +#[component] +fn Blocks( + selected: Option<SpaceEvent>, + block: Option<Value>, + counts: (u64, u64), + on_send: EventHandler<Value>, + on_duplicate: EventHandler<Value>, + on_delete: EventHandler<String>, + bend_open: Signal<bool>, +) -> Element { + let ui = ui(); + let api = api(); + let mut pictures: Signal<Vec<(String, String)>> = use_signal(Vec::new); + let mut picture = use_signal(String::new); + let mut colour = use_signal(|| "#b49a6c".to_string()); + use_hook(move || { + let api = api.clone(); + spawn(async move { + if let Ok(v) = api.call("pictures.list", json!({})).await { + let all: Vec<(String, String)> = v + .as_array() + .into_iter() + .flatten() + .map(|p| { + let id = p["id"].as_str().unwrap_or("").to_string(); + let name = p["name"] + .as_str() + .filter(|n| !n.is_empty()) + .unwrap_or(&id[..id.len().min(8)]) + .to_string(); + (id, name) + }) + .collect(); + if let Some((id, _)) = all.first() { + picture.set(id.clone()); + } + pictures.set(all); + } + }); + }); + let text = selected.clone().filter(|s| !s.free && !s.key.is_empty()); + let w = window_width(); + let field = move |b: Value, k: &'static str| { + let v = b[k].as_f64().unwrap_or(0.0); + let id = b["id"].as_str().unwrap_or("").to_string(); + rsx! { + label { class: "bfield", title: if "whd".contains(k) { "a side, in units (the texture tiles once per unit)" } else { "its centre, in units" }, + span { "{k}" } + input { + r#type: "number", + step: "0.25", + value: "{v:.2}", + onchange: move |e| { + if let Ok(x) = e.value().parse::<f64>() { + on_send.call(json!({ "cmd": "blockfields", "id": id, "t": { k: x } })); + } + }, + } + } + } + }; + rsx! { + Win { + id: "blocks", + at: ((w - 330.0).max(8.0), 420.0), + on_close: move |_| set_pref(ui, |p| p.space.show_blocks = false), + title: rsx! { + span { class: "win-title", + Icon { name: "cube" } + "blocks" + span { class: "dim small", style: "font-weight: 400;", "{counts.0} in this save · {counts.1} textures" } + } + }, + div { class: "blocks-add", + button { + class: "btn small", + disabled: text.is_none(), + title: "a block showing the selected text, where it is", + onclick: move |_| { + if let Some(t) = &text { + add_block_from(on_send, "text", &t.key) + } + }, + Icon { name: "text" } + "the selected text" + } + if pictures.read().is_empty() { + span { class: "dim small", title: "add pictures in the models view (spec models, pictures)", "no pictures yet" } + } else { + span { class: "row", + select { + "aria-label": "a picture", + value: "{picture}", + onchange: move |e| picture.set(e.value()), + for (id , name) in pictures.read().iter() { + option { key: "{id}", value: "{id}", selected: *id == picture(), "{name}" } + } + } + button { class: "btn small", onclick: move |_| add_block_from(on_send, "picture", &picture()), Icon { name: "image" } "picture" } + } + } + span { class: "row", + input { r#type: "color", "aria-label": "a colour", value: "{colour}", oninput: move |e| colour.set(e.value()) } + button { class: "btn small", onclick: move |_| add_block_from(on_send, "plain", &colour()), Icon { name: "palette" } "colour" } + } + } + if let Some(b) = block { + div { class: "blocks-sel", + div { class: "small", + b { + { + match b["kind"].as_str().unwrap_or("") { + "text" => format!("“{}”", b["about"]["text"].as_str().unwrap_or("a text")), + "picture" => format!("picture {}", b["about"]["name"].as_str().unwrap_or("")), + "texture" => match b["about"]["name"].as_str().filter(|n| !n.is_empty()) { + Some(n) => format!("the recipe {n}"), + None => "a texture recipe".to_string(), + }, + _ => format!("colour {}", b["texture"].as_str().unwrap_or("")), + } + } + } + span { class: "dim", title: "{b[\"id\"].as_str().unwrap_or(\"\")}", {format!(" · block {} of this texture", b["id"].as_str().and_then(|i| i.rsplit_once('#')).map_or("", |x| x.1))} } + } + div { class: "bfields", + {field(b.clone(), "x")} + {field(b.clone(), "y")} + {field(b.clone(), "z")} + {field(b.clone(), "w")} + {field(b.clone(), "h")} + {field(b.clone(), "d")} + } + TurnRow { b: b.clone(), on_send } + ShapeRow { b: b.clone(), on_send } + ZoneRow { b: b.clone(), on_send } + details { class: "bend", open: bend_open(), hidden: b["shape"].as_str() == Some("sphere"), + summary { onclick: move |e| { e.prevent_default(); let o = bend_open(); let mut bo = bend_open; bo.set(!o); }, "bend" span { class: "dim small", {bend_words(&b["bend"])} } } + if bend_open() { + BendEditor { b: b.clone(), on_send } + } + } + div { class: "row", + button { class: "btn small", title: "a copy beside it (the texture is stored once)", onclick: { let b = b.clone(); move |_| on_duplicate.call(b.clone()) }, Icon { name: "copy" } "copy" } + button { class: "btn small", title: "the textures window: a recipe for this block or one of its faces", onclick: move |_| set_pref(ui, |p| p.space.show_textures = true), Icon { name: "image" } "texture…" } + button { class: "btn small", title: "{ui.key_of(Action::DeleteText)}", onclick: { let id = b["id"].as_str().unwrap_or("").to_string(); move |_| on_delete.call(id.clone()) }, Icon { name: "delete" } "delete" } + } + } + } else { + p { class: "dim small", "Click a block to select it: its arrows move it, the knobs on its faces resize it (the texture tiles, it doesn't stretch), the rings turn it, the ball moves it across the view. Shift snaps to quarter units and 15° turns. Right-click a block for its menu (bend, straighten, turn)." } + } + } + } +} + +/// a block's turn in words: the angle and the axis +fn turn_words(rot: &Value) -> String { + let q: Vec<f64> = rot + .as_array() + .map(|a| a.iter().filter_map(Value::as_f64).collect()) + .unwrap_or_default(); + if q.len() != 4 || (q[3] - 1.0).abs() < 1e-6 { + return "not turned".into(); + } + let angle = 2.0 * q[3].clamp(-1.0, 1.0).acos(); + let s = (1.0 - q[3] * q[3]).sqrt().max(1e-9); + format!( + "turned {:.0}° about ({:.2}, {:.2}, {:.2})", + angle.to_degrees(), + q[0] / s, + q[1] / s, + q[2] / s + ) +} + +/// the quaternion product a·b, as [x, y, z, w] +fn qmul(a: [f64; 4], b: [f64; 4]) -> [f64; 4] { + [ + a[3] * b[0] + a[0] * b[3] + a[1] * b[2] - a[2] * b[1], + a[3] * b[1] - a[0] * b[2] + a[1] * b[3] + a[2] * b[0], + a[3] * b[2] + a[0] * b[1] - a[1] * b[0] + a[2] * b[3], + a[3] * b[3] - a[0] * b[0] - a[1] * b[1] - a[2] * b[2], + ] +} + +fn rot_of(b: &Value) -> [f64; 4] { + let q: Vec<f64> = b["rot"] + .as_array() + .map(|a| a.iter().filter_map(Value::as_f64).collect()) + .unwrap_or_default(); + if q.len() == 4 { + [q[0], q[1], q[2], q[3]] + } else { + [0.0, 0.0, 0.0, 1.0] + } +} + +/// whether a block is a staging zone (texts inside it spread among themselves, bounded +/// by it), and its own physics: each slider starts at the room's value, and "as the room" +/// lets a setting follow the room's again +#[component] +fn ZoneRow(b: Value, on_send: EventHandler<Value>) -> Element { + let ui = ui(); + let id = b["id"].as_str().unwrap_or("").to_string(); + let zone = b["zone"].clone(); + let on = zone.is_object(); + let room = ui.prefs.read().space.physics.clone(); + let send = move |id: &str, z: Value| on_send.call(json!({ "cmd": "blockfields", "id": id, "t": { "zone": z } })); + rsx! { + div { class: "zone-row", + label { class: "row small", title: "texts inside it spread among themselves, kept inside it, under physics of its own (zones can nest)", + input { r#type: "checkbox", checked: on, + oninput: { let id = id.clone(); move |e: FormEvent| send(&id, if e.checked() { json!({}) } else { Value::Null }) } } + "a staging zone" + } + if on { + for (key , short) in [("repel", "push apart"), ("attract", "pull together"), ("link", "spacing"), ("gravity", "to the centre"), ("damping", "damping")] { + { + let s = SLIDERS.iter().find(|s| s.key == key).expect("a physics slider"); + let own = zone[key].as_f64(); + let v = own.unwrap_or_else(|| room.get(key).copied().unwrap_or(s.def)); + let id = id.clone(); + let id2 = id.clone(); + let zone2 = zone.clone(); + let zone3 = zone.clone(); + rsx! { + label { key: "{key}", class: "lt-slider", title: "{s.label}", + span { "{short}" } + input { r#type: "range", min: "{s.min}", max: "{s.max}", step: "{s.step}", value: "{v}", + onchange: move |e| { + let mut z = zone2.clone(); + z[key] = json!(e.value().parse::<f64>().unwrap_or(v)); + send(&id, z); + } } + if own.is_some() { + button { class: "plain small", title: "follow the room's setting again", + onclick: move |_| { + let mut z = zone3.clone(); + if let Some(o) = z.as_object_mut() { o.remove(key); } + send(&id2, z); + }, + "as the room" } + } else { + span { class: "dim small", "the room's" } + } + } + } + } + } + } + } + } +} + +/// a block's shape: a box or a sphere (its sides become the sphere's diameters) +#[component] +fn ShapeRow(b: Value, on_send: EventHandler<Value>) -> Element { + let id = b["id"].as_str().unwrap_or("").to_string(); + let now = b["shape"].as_str().unwrap_or("box").to_string(); + rsx! { + div { class: "row turn-row", + span { class: "dim small", "shape" } + for (shape , label , tip) in [("box", "box", "six faces, which can bend"), ("sphere", "sphere", "round, its sides its diameters; it doesn't bend and has no faces of its own")] { + button { key: "{shape}", class: if now == shape { "btn small on" } else { "plain small" }, title: "{tip}", + onclick: { let id = id.clone(); move |_| on_send.call(json!({ "cmd": "blockfields", "id": id, "t": { "shape": shape } })) }, + "{label}" } + } + } + } +} + +/// a block's turn and buttons to turn it a quarter about each axis or not at all (the +/// rings on the gizmo turn it freely) +#[component] +fn TurnRow(b: Value, on_send: EventHandler<Value>) -> Element { + let id = b["id"].as_str().unwrap_or("").to_string(); + let q = rot_of(&b); + let quarter = move |axis: usize| { + let h = std::f64::consts::FRAC_PI_4; + let mut r = [0.0, 0.0, 0.0, h.cos()]; + r[axis] = h.sin(); + qmul(r, q) + }; + let turn = |r: [f64; 4]| json!({ "rot": r }); + rsx! { + div { class: "row turn-row", + span { class: "dim small", "{turn_words(&b[\"rot\"])}" } + for (i, name) in ["x", "y", "z"].into_iter().enumerate() { + button { key: "{name}", class: "btn small", title: "a quarter turn about {name} (the rings turn it freely)", + onclick: { let id = id.clone(); move |_| on_send.call(json!({ "cmd": "blockfields", "id": id, "t": turn(quarter(i)) })) }, + "↻ {name}" } + } + button { class: "btn small", title: "back to not turned", + onclick: { let id = id.clone(); move |_| on_send.call(json!({ "cmd": "blockfields", "id": id, "t": { "rot": [0, 0, 0, 1] } })) }, + "no turn" } + } + } +} + +/// a bend in words +fn bend_words(b: &Value) -> String { + let r = b["ripple"]["amount"].as_f64().unwrap_or(0.0); + let f = b["fold"]["amount"].as_f64().unwrap_or(0.0); + match (r != 0.0, f != 0.0) { + (false, false) => " · straight".into(), + (true, false) => format!(" · a ripple of {r:.2}"), + (false, true) => format!(" · a fold of {f:.2}"), + (true, true) => format!(" · a ripple of {r:.2} and a fold of {f:.2}"), + } +} + +/// a bend with its defaults filled in (the block's, or straight) +fn bend_of(b: &Value) -> Value { + let d = json!({ + "ripple": { "amount": 0.0, "freq": 2.0, "phase": 0.0, "c1": 1.0, "c2": -1.0 }, + "fold": { "amount": 0.0, "at": 0.0, "c1": 0.0, "c2": 1.0 }, + }); + let mut out = d.clone(); + for part in ["ripple", "fold"] { + if let Some(o) = b["bend"][part].as_object() { + for (k, v) in o { + out[part][k] = v.clone(); + } + } + } + out +} + +/// the bend editor: each shape's curve drawn with its two control points to drag up and +/// down (the cubic bezier's c1 and c2), and sliders for how much, how often and where; +/// every change shows on the block as it's made +#[component] +fn BendEditor(b: Value, on_send: EventHandler<Value>) -> Element { + let id = b["id"].as_str().unwrap_or("").to_string(); + let bend = bend_of(&b); + // which control point is being dragged: (shape, 1 or 2) + let mut dragging: Signal<Option<(&'static str, u8)>> = use_signal(|| None); + let send = { + let id = id.clone(); + move |nb: Value| on_send.call(json!({ "cmd": "blockfields", "id": id, "t": { "bend": nb } })) + }; + let set = { + let bend = bend.clone(); + let send = send.clone(); + move |part: &'static str, key: &'static str, v: f64| { + let mut nb = bend.clone(); + nb[part][key] = json!(v); + send(nb); + } + }; + let slider = { + let bend = bend.clone(); + let set = set.clone(); + move |part: &'static str, key: &'static str, label: &'static str, lo: f64, hi: f64, step: f64| { + let v = bend[part][key].as_f64().unwrap_or(0.0); + let set = set.clone(); + rsx! { + label { class: "bend-slider", + span { "{label}" } + input { r#type: "range", min: "{lo}", max: "{hi}", step: "{step}", value: "{v}", + oninput: move |e| { if let Ok(x) = e.value().parse::<f64>() { set(part, key, x) } } } + span { class: "num", "{v:.2}" } + } + } + } + }; + // the curves: (x, y) points of a cubic bezier with ends p0, p3 and controls c1, c2 + let (w, h) = (220.0f64, 90.0f64); + let ry = |v: f64| h / 2.0 - v * 28.0; + let fy = |v: f64| h - 12.0 - v * 56.0; + let path = |p0: f64, c1: f64, c2: f64, p3: f64, y: &dyn Fn(f64) -> f64| { + let mut d = String::new(); + for i in 0..=40 { + let t = i as f64 / 40.0; + let v = (1.0 - t).powi(3) * p0 + + 3.0 * (1.0 - t).powi(2) * t * c1 + + 3.0 * (1.0 - t) * t * t * c2 + + t.powi(3) * p3; + d += &format!( + "{}{:.1},{:.1} ", + if i == 0 { "M" } else { "L" }, + 10.0 + t * (w - 20.0), + y(v) + ); + } + d + }; + let r = &bend["ripple"]; + let f = &bend["fold"]; + let (rc1, rc2) = (r["c1"].as_f64().unwrap_or(1.0), r["c2"].as_f64().unwrap_or(-1.0)); + let (fc1, fc2) = (f["c1"].as_f64().unwrap_or(0.0), f["c2"].as_f64().unwrap_or(1.0)); + let ripple_path = path(0.0, rc1, rc2, 0.0, &ry); + let fold_path = path(0.0, fc1, fc2, 1.0, &fy); + let x1 = 10.0 + (w - 20.0) / 3.0; + let x2 = 10.0 + 2.0 * (w - 20.0) / 3.0; + // a drag moves the dragged control point to the pointer's height + let drag_to = { + let set = set.clone(); + move |y: f64| { + if let Some((part, n)) = dragging() { + let v = if part == "ripple" { + (h / 2.0 - y) / 28.0 + } else { + (h - 12.0 - y) / 56.0 + }; + let v = (v.clamp(-3.0, 3.0) * 100.0).round() / 100.0; + set(part, if n == 1 { "c1" } else { "c2" }, v); + } + } + }; + let curve = |part: &'static str, d: String, c1: f64, c2: f64, y: &dyn Fn(f64) -> f64, base: f64| { + let drag_to = drag_to.clone(); + let (y1, y2, yb) = (y(c1), y(c2), base); + let y_end = y(if part == "fold" { 1.0 } else { 0.0 }); + rsx! { + svg { class: "bend-curve", width: "{w}", height: "{h}", view_box: "0 0 {w} {h}", + line { x1: "10", y1: "{yb}", x2: "{w - 10.0}", y2: "{yb}", class: "axis" } + line { x1: "10", y1: "{yb}", x2: "{x1}", y2: "{y1}", class: "handle" } + line { x1: "{w - 10.0}", y1: "{y_end}", x2: "{x2}", y2: "{y2}", class: "handle" } + path { d: "{d}", class: "curve" } + circle { cx: "{x1}", cy: "{y1}", r: "7", class: "ctl", onmousedown: move |e| { e.prevent_default(); dragging.set(Some((part, 1))) } } + circle { cx: "{x2}", cy: "{y2}", r: "7", class: "ctl", onmousedown: move |e| { e.prevent_default(); dragging.set(Some((part, 2))) } } + if dragging().is_some_and(|(p, _)| p == part) { + rect { x: "0", y: "0", width: "{w}", height: "{h}", class: "catch", + onmousemove: move |e| drag_to(e.element_coordinates().y), + onmouseup: move |_| dragging.set(None), + onmouseleave: move |_| dragging.set(None), + } + } + } + } + }; + rsx! { + div { class: "bend-editor", + div { class: "bend-part", + b { "curtain ripple" } span { class: "dim small", " a wave across its width; drag the dots to shape one period" } + {curve("ripple", ripple_path, rc1, rc2, &ry, h / 2.0)} + {slider("ripple", "amount", "how much", -2.0, 2.0, 0.01)} + {slider("ripple", "freq", "how many waves", 0.5, 16.0, 0.5)} + {slider("ripple", "phase", "shifted by", 0.0, 1.0, 0.01)} + } + div { class: "bend-part", + b { "fold" } span { class: "dim small", " a curve across the middle, from the fold line to the edges" } + {curve("fold", fold_path, fc1, fc2, &fy, h - 12.0)} + {slider("fold", "amount", "how much", -3.0, 3.0, 0.01)} + {slider("fold", "at", "fold line", -1.0, 1.0, 0.01)} + } + button { class: "btn small", onclick: { let id = id.clone(); move |_| on_send.call(json!({ "cmd": "blockfields", "id": id, "t": { "bend": Value::Null } })) }, "straighten" } + } + } +} + +/// the right-click menu on a block: bend it (the blocks window's bend editor), straighten +/// it, turn it, copy, delete +#[component] +fn BlockMenu( + b: Value, + x: f64, + y: f64, + sp_bmenu: Signal<Option<(f64, f64)>>, + bend_open: Signal<bool>, + on_send: EventHandler<Value>, + on_duplicate: EventHandler<Value>, + on_delete: EventHandler<String>, +) -> Element { + let ui = ui(); + let mut close = move || sp_bmenu.set(None); + let id = b["id"].as_str().unwrap_or("").to_string(); + let title = match b["kind"].as_str().unwrap_or("") { + "text" => format!("a block of “{}”", b["about"]["text"].as_str().unwrap_or("a text")), + "picture" => "a picture block".to_string(), + "texture" => match b["about"]["name"].as_str().filter(|n| !n.is_empty()) { + Some(n) => format!("a block of the recipe {n}"), + None => "a block of a texture recipe".to_string(), + }, + _ => format!("a block of colour {}", b["texture"].as_str().unwrap_or("")), + }; + // a sphere doesn't bend + let round = b["shape"].as_str() == Some("sphere"); + let q = rot_of(&b); + let quarter_y = { + let h = std::f64::consts::FRAC_PI_4; + qmul([0.0, h.sin(), 0.0, h.cos()], q) + }; + rsx! { + div { class: "backdrop", onclick: move |_| close(), oncontextmenu: move |e| { e.prevent_default(); close() } } + div { class: "menu smenu", role: "menu", + style: "left: min({x}px, calc(100vw - 330px)); top: max(8px, min({y}px, calc(100vh - 300px)));", + div { class: "title", "{title}" } + div { class: "title dim small", {if round { format!("{} · a sphere", turn_words(&b["rot"])) } else { format!("{}{}", turn_words(&b["rot"]), bend_words(&b["bend"])) }} } + button { role: "menuitem", hidden: round, onclick: move |_| { set_pref(ui, |p| p.space.show_blocks = true); let mut bo = bend_open; bo.set(true); close(); }, + Icon { name: "edit" } "bend it…" span { class: "dim small", " (the curves in the blocks window)" } } + button { role: "menuitem", onclick: { let id = id.clone(); let to = if b["shape"].as_str() == Some("sphere") { "box" } else { "sphere" }; move |_| { on_send.call(json!({ "cmd": "blockfields", "id": id, "t": { "shape": to } })); close(); } }, + Icon { name: "cube" } {if b["shape"].as_str() == Some("sphere") { "make it a box" } else { "make it a sphere" }} } + button { role: "menuitem", onclick: move |_| { set_pref(ui, |p| p.space.show_textures = true); close(); }, + Icon { name: "image" } "texture it…" span { class: "dim small", " (a recipe for it or one face)" } } + button { role: "menuitem", hidden: round, onclick: { let id = id.clone(); move |_| { on_send.call(json!({ "cmd": "blockfields", "id": id, "t": { "bend": Value::Null } })); close(); } }, + Icon { name: "close" } "straighten" } + button { role: "menuitem", onclick: { let id = id.clone(); move |_| { on_send.call(json!({ "cmd": "blockfields", "id": id, "t": { "rot": quarter_y } })); close(); } }, + Icon { name: "refresh" } "a quarter turn about the upright" } + button { role: "menuitem", onclick: { let id = id.clone(); move |_| { on_send.call(json!({ "cmd": "blockfields", "id": id, "t": { "rot": [0, 0, 0, 1] } })); close(); } }, + Icon { name: "undo" } "no turn" } + button { role: "menuitem", onclick: { let b = b.clone(); move |_| { on_duplicate.call(b.clone()); close(); } }, + Icon { name: "copy" } "a copy beside it" } + button { role: "menuitem", onclick: { let id = id.clone(); move |_| { on_delete.call(id.clone()); close(); } }, + Icon { name: "delete" } "delete it" kbd { "{ui.key_of(Action::DeleteText)}" } } + } + } +} + +fn add_block_from(on_send: EventHandler<Value>, kind: &str, texture: &str) { + if texture.is_empty() { + return; + } + on_send.call(json!({ "cmd": "blockspot", "want": { "kind": kind, "texture": texture } })); +} + +/// the right-click menu on a text in the room: what the details window offers and more; +/// a copy is another placement of the same entry, so taking one out of the room never +/// touches the entry, and forgetting the entry itself is its own, confirmed, item +#[component] +fn SpaceMenu( + ev: SpaceEvent, + sp_menu: Signal<Option<SpaceEvent>>, + on_send: EventHandler<Value>, + on_gsearch: EventHandler<(u64, Mode)>, +) -> Element { + let ui = ui(); + let api = api(); + let mut armed = use_signal(|| false); + let mut close = move || sp_menu.set(None); + let hit = Hit { + key: ev.key.clone(), + text: ev.text.clone(), + note: ev.note, + }; + let node = ev.node.clone(); + let m = gem::Measure::of(&ev.text); + let list = ui.picks.read().list.clone(); + let (x, y) = (ev.x, ev.y); + // a note's body under its title: it isn't an entry of its own, so the menu only opens + // the note (editing it here would put the body in place of the whole note) + if ev.virt { + let k = ev.key.clone(); + return rsx! { + div { class: "backdrop", onclick: move |_| close(), oncontextmenu: move |e| { e.prevent_default(); close() } } + div { class: "menu smenu", role: "menu", + style: "left: min({x}px, calc(100vw - 330px)); top: max(8px, min({y}px, calc(100vh - 160px)));", + div { class: "title", "{ev.text}" } + div { class: "title dim small", "{ev.relation()}" } + button { role: "menuitem", onclick: move |_| { let mut o = ui.open_note; o.set(Some(k.clone())); crate::shell::go(ui, View::Notes); close(); }, + Icon { name: "editor" } "open the note" } + } + }; + } + let copies = ev.copies.max(1); + let which = if ev.free { + "a free text (in this room only)".to_string() + } else if copies > 1 { + format!( + "{} · {} placements in the room · {}", + if ev.primary { "the first placement" } else { "a copy" }, + copies, + ev.relation() + ) + } else { + format!("its only placement in the room · {}", ev.relation()) + }; + rsx! { + div { class: "backdrop", onclick: move |_| close(), oncontextmenu: move |e| { e.prevent_default(); close() } } + div { + class: "menu smenu", + role: "menu", + style: "left: min({x}px, calc(100vw - 330px)); top: max(8px, min({y}px, calc(100vh - 560px)));", + div { class: "title", "{ev.text}" } + div { class: "title dim small", "{which}" } + SizeRow { ev: ev.clone(), on_send: move |v: Value| on_send.call(v) } + button { role: "menuitem", onclick: { let ev = ev.clone(); let h = hit.clone(); move |_| { + if ev.free { start_edit(ui, &ev); } else { + ui.set_bar(&h.text); + let mut p = ui.pending; p.set(Pending::Edit(h.clone())); + ui.focus_bar(); + ui.say("edit it in the bar; Enter puts it back under the same key, Esc leaves it"); + } + close(); + } }, Icon { name: "edit" } "edit" + if !ev.free && ev.det > 0 { span { class: "dim small", " the entry (this copy keeps its text)" } } + else if !ev.free && copies > 1 { span { class: "dim small", " the entry (inheriting copies follow)" } } + kbd { "{ui.key_of(Action::EditText)}" } } + button { role: "menuitem", onclick: { let n = node.clone(); move |_| { on_send.call(json!({ "cmd": "pinnode", "node": n })); close(); } }, + Icon { name: "pin" } if ev.pinned { "unpin" } else { "pin" } kbd { "{ui.key_of(Action::Pin)}" } } + button { role: "menuitem", onclick: { let n = node.clone(); move |_| { on_send.call(json!({ "cmd": "dup", "node": n })); close(); } }, + Icon { name: "copy" } "a copy that inherits" span { class: "dim small", " (follows the entry)" } } + if !ev.free { + button { role: "menuitem", onclick: { let n = node.clone(); let k = ev.key.clone(); let api = api.clone(); move |_| { + let (n, k, api) = (n.clone(), k.clone(), api.clone()); + // the menu stays until the answer is in: its handler goes with it + let mut sm = sp_menu; + spawn(async move { + match api.call("entries.info", json!({ "key": k })).await { + Ok(i) => on_send.call(json!({ "cmd": "dup", "node": n, "det": i["edited_ms"] })), + Err(e) => ui.fail(e), + } + sm.set(None); + }); + } }, + Icon { name: "copy" } "a detached copy" span { class: "dim small", " (keeps the text as it reads now)" } } + if ev.det == 0 { + button { role: "menuitem", onclick: { let n = node.clone(); let t = ev.text.clone(); move |_| { + ui.set_bar(&t); + let mut p = ui.pending; p.set(Pending::EditOwn { node: n.clone(), text: t.clone() }); + ui.focus_bar(); + ui.say("this placement's own text: Enter sets it, Esc leaves it; the entry and its other placements stay"); + close(); + } }, + Icon { name: "edit" } "edit this placement only" } + } + if ev.own.is_some() { + button { role: "menuitem", onclick: { let n = node.clone(); move |_| { on_send.call(json!({ "cmd": "own", "node": n, "text": Value::Null })); close(); } }, + Icon { name: "undo" } "follow the entry again" span { class: "dim small", " (drops its own text)" } } + } + } + ChainItems { ev: ev.clone(), sp_menu, on_send: move |v: Value| on_send.call(v) } + button { role: "menuitem", onclick: { let t = ev.text.clone(); move |_| { copy_text(ui, &t); close(); } }, + Icon { name: "copy" } "copy the text" kbd { "{ui.key_of(Action::CopyText)}" } } + if !ev.free { + if ev.note { + button { role: "menuitem", onclick: { let k = ev.key.clone(); move |_| { let mut o = ui.open_note; o.set(Some(k.clone())); crate::shell::go(ui, View::Notes); close(); } }, + Icon { name: "editor" } "open in notes" } + } else { + button { role: "menuitem", onclick: { let t = ev.text.clone(); move |_| { crate::shell::go(ui, View::Memory); ui.set_bar(&t); close(); } }, + Icon { name: "memory" } "into the memory view's bar" } + } + if let Some(l) = list.clone().filter(|l| l.key != ev.key) { + button { role: "menuitem", onclick: { let api = api.clone(); let k = ev.key.clone(); let l = l.clone(); move |_| { + let api = api.clone(); let k = k.clone(); let l = l.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.enlist(&l.key, &k).await { + Ok(()) => { ui.say(format!("put into the list {}", l.text)); ui.touched(); } + Err(e) => ui.fail(e), + } + }); + close(); + } }, + Icon { name: "list" } "put it in the list “{l.text}”" } + } + button { role: "menuitem", onclick: { let h = hit.clone(); move |_| { let mut p = ui.picks; p.write().list = Some(h.clone()); ui.say(format!("list: {}", h.text)); close(); } }, + Icon { name: "list" } "make it the list" kbd { "Ctrl+Shift+click" } } + button { role: "menuitem", onclick: { let h = hit.clone(); move |_| { let mut p = ui.picks; p.write().candidate = Some(h.clone()); ui.say(format!("candidate: {}", h.text)); close(); } }, + Icon { name: "pick" } "make it the candidate" kbd { "Ctrl+click" } } + button { role: "menuitem", onclick: { let h = hit.clone(); move |_| { + let mut p = ui.pending; p.set(Pending::Tag(vec![h.clone()])); + ui.set_bar(""); ui.focus_bar(); ui.say("type a tag and press Enter"); close(); + } }, Icon { name: "tag" } "tag…" } + button { role: "menuitem", onclick: move |_| { on_gsearch.call((m.ordinal, Mode::Ordinal)); close(); }, Icon { name: "search" } "gsearch its sum {m.ordinal}" } + button { role: "menuitem", onclick: move |_| { on_gsearch.call((m.reversed, Mode::Reversed)); close(); }, Icon { name: "search" } "gsearch its reversed sum {m.reversed}" } + button { role: "menuitem", onclick: move |_| { on_gsearch.call((m.triangle(), space_mode(ui))); close(); }, Icon { name: "search" } "gsearch ⌊√(s·r)⌋ {m.triangle()}" kbd { "Ctrl+right click" } } + button { role: "menuitem", onclick: { let k = ev.key.clone(); move |_| { ui.set_bar(&k); close(); } }, Icon { name: "keys" } "its key into the bar" } + } + button { role: "menuitem", onclick: move |_| { set_pref(ui, |p| p.space.show_details = true); close(); }, Icon { name: "view" } "the details window" kbd { "{ui.key_of(Action::Details)}" } } + button { role: "menuitem", onclick: { let n = node.clone(); move |_| { on_send.call(json!({ "cmd": "removenode", "node": n })); close(); } }, + Icon { name: "close" } if ev.free { "take it out of the room" } else { "take this placement out of the room" } kbd { "{ui.key_of(Action::DeleteText)}" } } + if !ev.free { + button { + role: "menuitem", + class: if armed() { "armed" } else { "" }, + title: "deletes the entry from the save: every placement of it goes; Ctrl+Z brings it back", + onclick: { let api = api.clone(); let h = hit.clone(); move |_| { + if !armed() { armed.set(true); return; } + let api = api.clone(); let h = h.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.forget(&h.key).await { + Ok(text) => { + ui.did(Did::Forgot { key: h.key.clone(), text: text.clone() }); + ui.say(format!("forgot the entry “{text}” ({}) · Ctrl+Z takes it back", h.key)); + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + close(); + } }, + Icon { name: "delete" } + if armed() { "forget the entry? click again" } else if copies > 1 { "forget the entry ({copies} placements)…" } else { "forget the entry…" } + } + } + } + } +} + +/// the saved scenes (maps): open, rename, delete (two clicks, with an undo), and the room +/// saved under a name +#[component] +fn Scenes(rev: Signal<u64>, on_open: EventHandler<String>, on_save: EventHandler<String>) -> Element { + let ui = ui(); + let api = api(); + let mut local = use_signal(|| 0u64); + let mut renaming: Signal<Option<String>> = use_signal(|| None); + let mut armed: Signal<Option<String>> = use_signal(|| None); + let mut gone: Signal<Option<(String, Value)>> = use_signal(|| None); + // the scene being combined into another, and which + let mut combining: Signal<Option<String>> = use_signal(|| None); + let mut into = use_signal(String::new); + let mut name = use_signal(|| default_map_name(ui)); + let api_r = api.clone(); + let all = use_resource(move || { + let api = api_r.clone(); + let _ = (rev(), local()); + async move { maps(&api).await } + }); + let all: BTreeMap<String, Value> = all.read().clone().unwrap_or_default(); + let here = ui.prefs.read().space.address.clone(); + // one `scenes.*` call, then the list read again; `then` sees its answer + let store = { + let api = api.clone(); + move |op: &'static str, args: Value, said: String, then: Option<Callback<Value>>| { + let api = api.clone(); + dioxus::dioxus_core::spawn_forever(async move { + match api.call(op, args).await { + Ok(v) => { + if let Some(f) = then { + f.call(v); + } + ui.say(said); + local += 1; + } + Err(e) => ui.fail(e), + } + }); + } + }; + let ok_name = + |n: &str| (1..=96).contains(&n.len()) && n.chars().all(|c| c.is_ascii_alphanumeric() || c == '_' || c == '-'); + rsx! { + Win { + id: "scenes", + at: (8.0, 120.0), + on_close: move |_| set_pref(ui, |p| p.space.show_scenes = false), + title: rsx! { span { class: "win-title", Icon { name: "folder" } "scenes" span { class: "dim small", style: "font-weight: 400;", "{all.len()} saved" } } }, + div { class: "scenes", + if all.is_empty() { + p { class: "dim small", "No scenes yet: save the room as one below (or Save name in the bar)." } + } + for (n , rows) in all.clone() { + div { key: "{n}", class: if n == here { "scene on" } else { "scene" }, + if renaming().as_deref() == Some(n.as_str()) { + input { + class: "scene-name", + initial_value: "{n}", + "aria-label": "a new name: letters, digits, _ and -", + onmounted: move |e| async move { let _ = e.set_focus(true).await; }, + onkeydown: move |e: KeyboardEvent| { + if e.key() == Key::Escape { renaming.set(None); } + }, + onchange: { + let n = n.clone(); + let all = all.clone(); + let store = store.clone(); + move |e: FormEvent| { + let to = e.value().trim().to_string(); + renaming.set(None); + if to == n { return; } + if !ok_name(&to) { ui.fail("a scene's name: 1 to 96 of letters, digits, _ and -"); return; } + if all.contains_key(&to) { ui.fail(format!("there's a scene {to} already")); return; } + if ui.prefs.peek().space.address == n { let t = to.clone(); set_pref(ui, move |p| p.space.address = t); } + store("scenes.rename", json!({ "from": n, "to": to }), format!("renamed {n} to {to}"), None); + } + }, + } + } else { + button { class: "plain scene-open", title: "open it (#{n})", onclick: { let n = n.clone(); move |_| on_open.call(n.clone()) }, + b { "{n}" } span { class: "dim small", " {rows.as_array().map(|a| a.len()).unwrap_or(0)} texts" } } + } + button { class: "plain ibtn", "data-tip": "rename it", "aria-label": "rename", onclick: { let n = n.clone(); move |_| renaming.set(Some(n.clone())) }, Icon { name: "rename" } } + if all.len() > 1 { + button { class: "plain ibtn", "data-tip": "combine it into another scene (overlaps settle)", "aria-label": "combine", + onclick: { let n = n.clone(); let first = all.keys().find(|k| **k != n).cloned().unwrap_or_default(); move |_| { + if combining().as_deref() == Some(n.as_str()) { combining.set(None); } else { combining.set(Some(n.clone())); into.set(first.clone()); } + } }, + Icon { name: "merge" } } + } + button { + class: if armed().as_deref() == Some(n.as_str()) { "armed" } else { "plain ibtn" }, + "data-tip": "delete it (click twice; it can be undone)", + "aria-label": "delete", + onclick: { + let n = n.clone(); + let store = store.clone(); + move |_| { + if armed().as_deref() != Some(n.as_str()) { armed.set(Some(n.clone())); return; } + armed.set(None); + let keep = Callback::new(move |v: Value| gone.set(Some((v["name"].as_str().unwrap_or("").to_string(), v["rows"].clone())))); + store("scenes.delete", json!({ "name": n }), format!("deleted the scene {n}"), Some(keep)); + } + }, + Icon { name: "delete" } + if armed().as_deref() == Some(n.as_str()) { "delete?" } + } + } + } + if let Some(from) = combining() { + div { class: "row scene-combine", + span { class: "dim small", "combine {from} into" } + select { "aria-label": "the scene to combine it into", value: "{into}", onchange: move |e| into.set(e.value()), + for k in all.keys().filter(|k| **k != from) { + option { key: "{k}", value: "{k}", selected: *k == into(), "{k}" } + } + } + button { class: "btn small", + onclick: { let store = store.clone(); let from = from.clone(); move |_| { + let to = into(); + let open = Callback::new({ let to = to.clone(); move |_: Value| on_open.call(to.clone()) }); + store("scenes.combine", json!({ "from": from, "into": to }), format!("combined {from} into {to}: what overlapped was moved out of the way"), Some(open)); + combining.set(None); + } }, + "combine" } + span { class: "dim small", "(it stays as it is; its copies settle out of what's there)" } + } + } + if let Some((n, v)) = gone() { + div { class: "scene dim small", + "deleted {n} " + button { class: "plain", onclick: { + let store = store.clone(); + move |_| { + gone.set(None); + store("scenes.save", json!({ "name": n, "rows": v }), format!("{n} is back"), None); + } + }, + Icon { name: "undo" } "undo" } + } + } + div { class: "row scene-save", + input { "aria-label": "the scene's name", initial_value: "{name}", oninput: move |e| name.set(e.value()) } + button { class: "btn small", title: "keeps every text in the room where it is", onclick: move |_| { + let n = name().trim().to_string(); + if !ok_name(&n) { ui.fail("a scene's name: 1 to 96 of letters, digits, _ and -"); return; } + on_save.call(n); + }, Icon { name: "save" } "save the room" } + } + } + } + } +} + +/// the position card: its own component, so its many updates (every 120 ms while the +/// spread moves) re-render only it, not the whole room and its windows +#[component] +fn PosCard(pos: Signal<String>) -> Element { + rsx! { div { class: "poscard", "{pos}" } } +} + +/// a window over the room that moves by its title bar and remembers where it was left; +/// its close button shows when the pointer is over it +#[component] +fn Win(id: String, title: Element, at: (f64, f64), on_close: EventHandler<()>, children: Element) -> Element { + let ui = ui(); + let saved = ui.prefs.read().space.wins.get(&id).copied(); + let mut place = use_signal(move || saved.unwrap_or(at)); + let mut grab: Signal<Option<(f64, f64)>> = use_signal(|| None); + let (x, y) = place(); + let id2 = id.clone(); + rsx! { + // kept inside the room however the window is resized: the place is clamped by the + // layout itself, so a window left far right comes back when the room narrows + div { + class: "win", + // never past the bottom: its height is what's left below where it starts (it + // scrolls inside); a tall one moves up when there isn't room for 320 px + style: "left: clamp(0px, {x:.0}px, max(0px, calc(100% - var(--win-w)))); top: clamp(0px, min({y:.0}px, calc(100% - var(--over-bottom, 40px) - 320px)), max(0px, calc(100% - var(--over-bottom, 40px) - 44px))); max-height: calc(100% - var(--over-bottom, 40px) - 8px - clamp(0px, min({y:.0}px, calc(100% - var(--over-bottom, 40px) - 320px)), max(0px, calc(100% - var(--over-bottom, 40px) - 44px))));", + role: "dialog", + div { + class: "win-head", + title: "drag to move it", + onpointerdown: move |e| { + // from where it shows (clamped), not where it was left; no text selection + e.prevent_default(); + let c = e.client_coordinates(); + let o = e.element_coordinates(); + place.set((c.x - o.x, c.y - o.y)); + grab.set(Some((o.x, o.y))); + }, + {title} + button { + class: "plain ibtn close", + "aria-label": "close", + onclick: move |_| on_close.call(()), + onpointerdown: move |e| e.stop_propagation(), + Icon { name: "close" } + } + } + div { class: "win-body", {children} } + } + if grab().is_some() { + // while dragging, a sheet over everything follows the pointer + div { + class: "win-drag", + onpointermove: move |e| { + if let Some((ox, oy)) = grab() { + let c = e.client_coordinates(); + place.set(((c.x - ox).max(0.0), (c.y - oy).max(0.0))); + } + }, + onpointerup: move |_| { + grab.set(None); + let id = id2.clone(); + spawn(async move { + // kept clamped to the window as it is now + let mut ev = document::eval("dioxus.send([innerWidth, innerHeight]);"); + let (w, h) = ev.recv::<(f64, f64)>().await.unwrap_or((1e6, 1e6)); + let (x, y) = place(); + let at = (x.clamp(0.0, (w - 120.0).max(0.0)), y.clamp(0.0, (h - 80.0).max(0.0))); + place.set(at); + set_pref(ui, move |p| { + p.space.wins.insert(id, at); + }); + }); + }, + } + } + } +} + +/// the numbers of a hovered or clicked text (the Bevy app's metrics card), each gsearching +/// itself; its key, bucket and whether it's pinned +#[component] +fn Details(ev: SpaceEvent, on_gsearch: EventHandler<(u64, Mode)>, on_send: EventHandler<Value>) -> Element { + let ui = ui(); + let m = anend_core::spread::metrics(&ev.text); + let rev = ui.prefs.read().space_reversed; + let mode = if rev { Mode::Reversed } else { Mode::Ordinal }; + let n = move |v: i64, md: Option<Mode>| { + let md = md.unwrap_or(mode); + rsx! { + span { + class: "num", + title: "gsearch {v} ({md.name()})", + onclick: move |_| { + if v >= 0 { + on_gsearch.call((v as u64, md)) + } + }, + "{v}" + } + } + }; + let rows: [[(&str, Element); 2]; 7] = [ + [("s", n(m.s, Some(Mode::Ordinal))), ("r", n(m.r, Some(Mode::Reversed)))], + [("s+r", n(m.sr, None)), ("s·r", n(m.product, None))], + [("√(s·r)", rsx! { "{m.root:.3}" }), ("⌊√(s·r)⌋", n(m.jump, None))], + [("s−r", rsx! { "{m.diff}" }), ("s+r+|s−r|", n(m.wide, None))], + [("s+r+(s−r)", n(m.lean, None)), ("|s−r|−(s−r)", n(m.gap, None))], + [("v", n(m.v, None)), ("c", n(m.c, None))], + [("w", rsx! { "{m.w}" }), ("letters", rsx! { "{m.letters}" })], + ]; + let w = window_width(); + let key = ev.key.clone(); + let q = ev.q as u64; + rsx! { + Win { + id: "details", + at: ((w - 330.0).max(8.0), 52.0), + on_close: move |_| set_pref(ui, |p| p.space.show_details = false), + title: rsx! { span { class: "win-title", "{ev.text}" } }, + table { class: "metrics-table", + for (i , row) in rows.into_iter().enumerate() { + tr { key: "{i}", + for (label , cell) in row { + th { key: "{label}", "{label}" } + td { {cell} } + } + } + } + } + Triangle { s: m.s.max(0) as u64, r: m.r.max(0) as u64, height: 40.0 } + div { class: "gsum", {gem::gsum_line(&ev.text)} } + if !ev.free { + div { class: "dim small row", + "key " + span { class: "num", title: "into the bar", onclick: move |_| ui.set_bar(&key), "{ev.key}" } + " · bucket " + span { class: "swatch", style: "display: inline-block; width: 10px; height: 10px; border-radius: 2px; background: hsl({ev.hue} 70% 45%);" } + span { + class: "num", + title: "gsearch it", + onclick: move |_| on_gsearch.call((q, if rev { Mode::Ordinal } else { Mode::Reversed })), + " {q}" + } + if ev.pinned { " · pinned" } + if ev.copies > 1 { {format!(" · {} of {} placements", if ev.primary { "the first" } else { "a copy" }, ev.copies)} } + } + div { class: "dim small", "{ev.relation()}" } + SizeRow { ev: ev.clone(), on_send: move |v: Value| on_send.call(v) } + } else { + div { class: "dim small", + "a free text: double click or Enter edits it" + if ev.pinned { " · pinned" } + } + } + if m.s > 1 { + crate::views::memory::PfLine { n: m.s as u64 } + } + } + } +} + +/// the window's width, for placing a window at the right the first time +fn window_width() -> f64 { + #[cfg(target_arch = "wasm32")] + { + web_sys::window() + .and_then(|w| w.inner_width().ok()) + .and_then(|v| v.as_f64()) + .unwrap_or(1200.0) + } + #[cfg(not(target_arch = "wasm32"))] + { + 1200.0 + } +} + +/// the physics panel: every slider (double click its name: back to its default), what the +/// depth follows, reset all, settle, pause +#[component] +fn PhysicsPanel(paused: bool, on_settle: EventHandler<()>, on_pause: EventHandler<bool>) -> Element { + let ui = ui(); + let p = ui.prefs.read().space.clone(); + let mut groups: Vec<(&str, Vec<&Slider>)> = Vec::new(); + for s in &SLIDERS { + match groups.iter_mut().find(|(g, _)| *g == s.group) { + Some((_, v)) => v.push(s), + None => groups.push((s.group, vec![s])), + } + } + rsx! { + Win { + id: "physics", + at: (8.0, 80.0), + on_close: move |_| set_pref(ui, |p| p.space.show_physics = false), + title: rsx! { + span { class: "win-title", Icon { name: "sliders" } " physics" } + }, + div { class: "physics", + for (g , sliders) in groups { + div { key: "{g}", class: "pgroup", + h4 { "{g}" } + for s in sliders { + PSlider { key: "{s.key}", which: s.key, value: p.physics.get(s.key).copied().unwrap_or(s.def) } + } + if g == "depth" { + label { class: "pslider", + span { class: "pname", "depth follows" } + select { + value: "{p.depth_by}", + onchange: move |e| set_pref(ui, |p| p.space.depth_by = e.value()), + for d in DEPTH_BY { + option { key: "{d}", value: "{d}", selected: p.depth_by == d, "{d}" } + } + } + } + } + } + } + div { class: "row", + button { + onclick: move |_| set_pref(ui, |p| { + p.space.physics.clear(); + p.space.depth_by = "none".into(); + }), + Icon { name: "undo" } + "reset all" + } + button { "data-tip": "settle now · {ui.key_of(Action::Settle)}", onclick: move |_| on_settle.call(()), + Icon { name: "check" } + "settle" + } + button { + class: if paused { "on" } else { "" }, + "data-tip": "pause the physics · {ui.key_of(Action::Pause)}", + onclick: move |_| on_pause.call(!paused), + Icon { name: if paused { "play" } else { "pause" } } + if paused { "run" } else { "pause" } + } + } + } + } + } +} + +#[component] +fn PSlider(which: &'static str, value: f64) -> Element { + let ui = ui(); + let Some(s) = SLIDERS.iter().find(|s| s.key == which) else { + return rsx! {}; + }; + let def = s.def; + let decimals = (-s.step.log10()).ceil().max(0.0) as usize; + rsx! { + label { class: "pslider", + span { + class: "pname", + title: "double click: back to {def}", + ondoubleclick: move |_| set_pref(ui, move |p| { + p.space.physics.remove(which); + }), + "{s.label}" + } + input { + r#type: "range", + min: "{s.min}", + max: "{s.max}", + step: "{s.step}", + value: "{value}", + oninput: move |e| { + if let Ok(x) = e.value().parse::<f64>() { + set_pref(ui, move |p| { + if (x - def).abs() < 1e-9 { + p.space.physics.remove(which); + } else { + p.space.physics.insert(which.to_string(), x); + } + }); + } + }, + } + span { class: "pval", {format!("{value:.decimals$}")} } + } + } +} + +/// the keys as they're bound, and what the mouse does +#[component] +fn Help() -> Element { + let ui = ui(); + let k = |a: Action| ui.key_of(a); + let sections: Vec<(&str, Vec<(String, &str)>)> = vec![ + ( + "flying", + vec![ + ("Right mouse".into(), "hold to look"), + ( + format!( + "{} {} {} {}", + k(Action::FlyForward), + k(Action::FlyLeft), + k(Action::FlyBack), + k(Action::FlyRight) + ), + "move", + ), + (format!("{} / {}", k(Action::FlyUp), k(Action::FlyDown)), "up / down"), + (format!("{} / {}", k(Action::RollLeft), k(Action::RollRight)), "roll"), + ("Shift".into(), "fast"), + ( + format!("{} {} or the wheel", k(Action::Slower), k(Action::Faster)), + "flight speed", + ), + (k(Action::Level), "level the horizon"), + (k(Action::BackToStart), "back to start"), + ("arrows".into(), "hop to the nearest text that way"), + ], + ), + ( + "walking, the grapple, superflight", + vec![ + (k(Action::Walk), "walk / fly: gravity, blocks to stand on and bump into"), + ( + format!( + "{} {} {} {}, Shift, {}", + k(Action::FlyForward), + k(Action::FlyLeft), + k(Action::FlyBack), + k(Action::FlyRight), + k(Action::Sneak) + ), + "walk, run, sneak", + ), + ( + format!("{} / {}", k(Action::FlyUp), k(Action::FlyDown)), + "jump (at a ledge: climb onto it) / crouch", + ), + (format!("{} / {}", k(Action::RollLeft), k(Action::RollRight)), "lean"), + ( + k(Action::Grapple), + "hook the block or text ahead / let go; the wheel reels in and out", + ), + ( + k(Action::SuperFlight), + "superflight / fly: Shift boosts; texts flown through are collected", + ), + ("Esc".into(), "let the pointer go (right-drag still looks)"), + ], + ), + ( + "texts", + vec![ + ("drag a text".into(), "move it; it stays pinned"), + ("wheel on a text".into(), "push away / pull near"), + ("click".into(), "its text into the bar, its numbers in the details"), + ("double click".into(), "its key into the bar (a free text: edit it)"), + ( + format!("double click the room, {}", k(Action::NewText)), + "a new free text", + ), + (k(Action::EditText), "edit the selected text"), + (k(Action::DeleteText), "remove it from the room"), + (k(Action::CopyText), "copy it"), + (k(Action::Pin), "pin / unpin it"), + (k(Action::Undo), "undo (a move, a pin, a removal; else the last action)"), + ( + format!("{} / {}", k(Action::Export), k(Action::SaveMap)), + "export the texts / save the map", + ), + ], + ), + ( + "blocks", + vec![ + ( + "the cube chip".into(), + "the blocks window: a block of the selected text, a picture or a colour", + ), + ("click a block".into(), "select it; drag it across the view"), + ("drag an arrow".into(), "move it along that axis"), + ( + "drag a face's knob".into(), + "resize it: the texture tiles, the far face stays", + ), + ("Shift while dragging".into(), "snap to quarter units"), + (k(Action::DeleteText), "delete the selected block"), + (k(Action::Undo), "undo a move, a resize, an add or a delete"), + ], + ), + ( + "the bar", + vec![ + ("Enter".into(), "a number: its bucket; a text: its sum (or its words)"), + ("Ctrl+Enter".into(), "remember the text, gsearch its sum"), + ("Shift+Enter".into(), "bring back a key, like 0,12"), + ("Delete".into(), "forget the key typed"), + ("↑ ↓".into(), "history"), + ("#123 #r123 #name".into(), "a bucket, a reversed one, a saved map"), + ( + "words".into(), + "Enlist List Delist Unlist Count Backup Clear ClearAll Settle Maps Save name", + ), + ( + "Ctrl+click / Ctrl+Shift+click".into(), + "the list's candidate / the list", + ), + ( + "Shift+click, or a box drawn on empty room".into(), + "select many: blocks, copies, texts, lights", + ), + ("Ctrl+right click".into(), "gsearch ⌊√(s·r)⌋"), + ( + format!("{} {}", k(Action::SideSum), k(Action::SideReversedSum)), + "gsearch the bar's sums", + ), + ], + ), + ( + "panels", + vec![ + (k(Action::Physics), "the physics"), + ( + format!("{} / {}", k(Action::Pause), k(Action::Settle)), + "pause / settle now", + ), + (k(Action::Details), "the details window"), + (k(Action::Hud), "the position card"), + (k(Action::Reversed), "reversed sums"), + (k(Action::Help), "this help"), + ], + ), + ]; + rsx! { + div { class: "space-help", + button { + class: "plain ibtn close", + "aria-label": "close", + onclick: move |_| set_pref(ui, |p| p.space.show_help = false), + Icon { name: "close" } + } + div { class: "help-cols", + for (title , rows) in sections { + div { key: "{title}", + h4 { "{title}" } + table { + for (key , what) in rows { + tr { key: "{key}", + td { kbd { "{key}" } } + td { "{what}" } + } + } + } + } + } + } + } + } +} + +/// what the space adds to the command bar: the bar's sums, the list state, the chips +#[component] +pub fn SpaceStrip() -> Element { + let ui = ui(); + let p = ui.prefs.read().clone(); + let measure = (ui.measure)(); + let picks = (ui.picks)(); + let list = match (&picks.list, &picks.candidate) { + (Some(l), Some(c)) => format!("list {} · candidate {}", l.text, c.text), + (Some(l), None) => format!("list {}", l.text), + (None, Some(c)) => format!("candidate {}", c.text), + _ => String::new(), + }; + rsx! { + if let Some(me) = measure { + span { class: "sidecar", "aria-label": "the bar's sums", + "(" + span { + class: if !p.space_reversed { "num on" } else { "num" }, + title: "ordinal · {ui.key_of(Action::SideSum)} gsearches it", + onclick: move |_| set_pref(ui, |p| p.space_reversed = false), + "{me.ordinal}" + } + ", " + span { + class: if p.space_reversed { "num on" } else { "num" }, + title: "reversed · {ui.key_of(Action::SideReversedSum)} gsearches it", + onclick: move |_| set_pref(ui, |p| p.space_reversed = true), + "{me.reversed}" + } + ")" + } + } + if !list.is_empty() { + span { class: "sidenote", "{list}" } + } + select { + class: "search-mode", + "aria-label": "how Enter searches", + title: "how Enter searches: normal (sums and words), by the colouring classifier (a class's name), or random (texts sharing a word, in no order; * takes any)", + value: "{p.space_search}", + onchange: move |e| { let v = e.value(); set_pref(ui, move |p| p.space_search = v) }, + option { value: "normal", selected: p.space_search == "normal", "normal" } + option { value: "classifier", selected: p.space_search == "classifier", "classifier" } + option { value: "random", selected: p.space_search == "random", "random" } + } + span { class: "toggles", + TChip { + label: "gsearch: a text by its sum, not its words", + icon: "search", + on: p.gsearch_text, + onclick: move |_| set_pref(ui, |p| p.gsearch_text = !p.gsearch_text), + } + TChip { + label: format!("reversed: bucket by the reversed sum · {}", ui.key_of(Action::Reversed)), + letter: "R", + on: p.space_reversed, + onclick: move |_| set_pref(ui, |p| p.space_reversed = !p.space_reversed), + } + TChip { + label: "saturate: remember what's searched", + icon: "bolt", + on: p.saturate, + onclick: move |_| set_pref(ui, |p| p.saturate = !p.saturate), + } + TChip { + label: "keep: add new results to the spread", + icon: "pin", + on: p.space_keep, + onclick: move |_| set_pref(ui, |p| p.space_keep = !p.space_keep), + } + } + span { class: "toggles", + TChip { + label: format!("the physics · {}", ui.key_of(Action::Physics)), + icon: "sliders", + on: p.space.show_physics, + onclick: move |_| set_pref(ui, |p| p.space.show_physics = !p.space.show_physics), + } + TChip { + label: format!("the details window · {}", ui.key_of(Action::Details)), + icon: "view", + on: p.space.show_details, + onclick: move |_| set_pref(ui, |p| p.space.show_details = !p.space.show_details), + } + TChip { + label: "scenes: the saved rooms, to open, combine, rename and delete", + icon: "folder", + on: p.space.show_scenes, + onclick: move |_| set_pref(ui, |p| p.space.show_scenes = !p.space.show_scenes), + } + TChip { + label: "blocks: spatial saves, boxes showing texts and pictures", + icon: "cube", + on: p.space.show_blocks, + onclick: move |_| set_pref(ui, |p| p.space.show_blocks = !p.space.show_blocks), + } + TChip { + label: "animations: keyframes for blocks, eased along timing curves", + icon: "play", + on: p.space.show_anims, + onclick: move |_| set_pref(ui, |p| p.space.show_anims = !p.space.show_anims), + } + TChip { + label: "prefabs: blocks grouped into subassemblies, placed as copies", + icon: "prefab", + on: p.space.show_prefabs, + onclick: move |_| set_pref(ui, |p| p.space.show_prefabs = !p.space.show_prefabs), + } + TChip { + label: "sounds: the save's sounds, and blocks that play them", + icon: "sound", + on: p.space.show_sounds, + onclick: move |_| set_pref(ui, |p| p.space.show_sounds = !p.space.show_sounds), + } + TChip { + label: "wiring: blocks that cast rays and run programs", + icon: "bolt", + on: p.space.show_wiring, + onclick: move |_| set_pref(ui, |p| p.space.show_wiring = !p.space.show_wiring), + } + TChip { + label: "lights: ambient, sun, point and cone lights, baked onto the blocks", + icon: "sun", + on: p.space.show_lights, + onclick: move |_| set_pref(ui, |p| p.space.show_lights = !p.space.show_lights), + } + TChip { + label: "textures: recipes from pictures, texts and colours, for blocks, faces and the sky", + icon: "image", + on: p.space.show_textures, + onclick: move |_| set_pref(ui, |p| p.space.show_textures = !p.space.show_textures), + } + TChip { + label: format!("help · {}", ui.key_of(Action::Help)), + icon: "help", + on: p.space.show_help, + onclick: move |_| set_pref(ui, |p| p.space.show_help = !p.space.show_help), + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sliders_match_the_engine() { + // every slider is one of space.js's PHYSICS keys, with the same default + for s in &SLIDERS { + let pat = format!("{}: {}", s.key, s.def); + let alt = format!("{}: {}", s.key, s.def as i64); + assert!( + ENGINE.contains(&pat) || ENGINE.contains(&alt), + "{} = {} isn't space.js's", + s.key, + s.def + ); + assert!(s.min <= s.def && s.def <= s.max, "{}", s.key); + } + // a free spread: no spiral and no anchors left in the engine + assert!(!ENGINE.contains("spiral(") && !ENGINE.contains("p.anchor")); + assert_eq!(letter_counts("Ab b")[1], 2); + } +} diff --git a/app/src/views/space/animwin.rs b/app/src/views/space/animwin.rs new file mode 100644 index 00000000..057168dd --- /dev/null +++ b/app/src/views/space/animwin.rs @@ -0,0 +1,468 @@ +//! The animations window: keyframe animations for blocks (core's `graph::anims`), made and +//! previewed on the selected block. An animation is an entry of the save, so one is shared +//! by every block that plays it. +//! +//! The window lists the save's animations; one is opened to edit: its name, length and how +//! it repeats, its timing (a cubic-bezier curve whose two control points are dragged, with +//! CSS's named curves one click away), and a timeline of keys. The scrubber shows any +//! moment on the selected block; "a key here" adds a key there with the pose it has; a +//! picked key's move, turn and scale are sliders, its texture a pick, and it can have a +//! timing of its own to the next key. "play" previews it on the block; "keep" saves it; +//! the selected block can then play it, with a delay and a speed of its own. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use super::{Sp, Win, dress}; +use crate::shell::set_pref; +use crate::ui::*; + +/// the save's animations, and the textures their keys show, into the room +pub(super) async fn load_anims(ui: Ui, api: &Api, sp: Sp) -> Vec<Value> { + let list: Vec<Value> = match api.call("anims.list", json!({})).await { + Ok(v) => v.as_array().cloned().unwrap_or_default(), + // a hub from before animations + Err(_) => Vec::new(), + }; + let textures = textures_of(api, &list).await; + let textures = dress(ui, api, textures).await; + sp.send(json!({ "cmd": "anims", "anims": list, "textures": textures })); + list +} + +/// what the keys' textures are, for the room to draw them +async fn textures_of(api: &Api, list: &[Value]) -> Value { + let mut out = serde_json::Map::new(); + let recipes = api.call("textures.list", json!({})).await.ok(); + for a in list { + for k in a["anim"]["keys"].as_array().into_iter().flatten() { + let Some(t) = k["texture"].as_str() else { continue }; + if out.contains_key(t) { + continue; + } + let about = if let Some(c) = t.strip_prefix("plain:") { + json!({ "colour": c }) + } else if let Some(id) = t.strip_prefix("texture:") { + recipes + .as_ref() + .and_then(|r| r.as_array()) + .and_then(|r| r.iter().find(|x| x["id"].as_str() == Some(id)).cloned()) + .unwrap_or(json!({ "gone": true })) + } else { + json!({}) + }; + out.insert(t.to_string(), about); + } + } + Value::Object(out) +} + +fn blank() -> Value { + json!({ "name": "", "duration": 2.0, "repeat": "loop", "timing": [0.25, 0.1, 0.25, 1.0], + "keys": [{ "at": 0.0, "move": [0.0, 0.0, 0.0] }, { "at": 1.0, "move": [0.0, 1.0, 0.0] }] }) +} + +/// CSS's named timings +const NAMED: [(&str, [f64; 4]); 5] = [ + ("linear", [0.0, 0.0, 1.0, 1.0]), + ("ease", [0.25, 0.1, 0.25, 1.0]), + ("ease-in", [0.42, 0.0, 1.0, 1.0]), + ("ease-out", [0.0, 0.0, 0.58, 1.0]), + ("ease-in-out", [0.42, 0.0, 0.58, 1.0]), +]; + +fn four(v: &Value) -> [f64; 4] { + let a: Vec<f64> = v + .as_array() + .map(|a| a.iter().filter_map(Value::as_f64).collect()) + .unwrap_or_default(); + if a.len() == 4 { + [a[0], a[1], a[2], a[3]] + } else { + [0.25, 0.1, 0.25, 1.0] + } +} + +/// two timings the same, as far as f32 storage keeps them +fn same(a: [f64; 4], b: [f64; 4]) -> bool { + a.iter().zip(b).all(|(x, y)| (x - y).abs() < 1e-4) +} + +fn three(v: &Value, d: f64) -> [f64; 3] { + let a: Vec<f64> = v + .as_array() + .map(|a| a.iter().filter_map(Value::as_f64).collect()) + .unwrap_or_default(); + if a.len() == 3 { [a[0], a[1], a[2]] } else { [d; 3] } +} + +/// a cubic-bezier timing drawn in a square: drag either control point +#[component] +fn Curve(t: [f64; 4], on_change: EventHandler<[f64; 4]>) -> Element { + let mut dragging: Signal<Option<u8>> = use_signal(|| None); + let (w, h) = (150.0f64, 150.0f64); + let px = |x: f64| 15.0 + x * (w - 30.0); + // y from -0.5 to 1.5 (overshoot shows) + let py = |y: f64| h - 15.0 - (y + 0.5) / 2.0 * (h - 30.0) - 0.0; + let mut d = String::new(); + for i in 0..=40 { + let s = i as f64 / 40.0; + let b = |a: f64, c: f64| 3.0 * (1.0 - s) * (1.0 - s) * s * a + 3.0 * (1.0 - s) * s * s * c + s * s * s; + d += &format!( + "{}{:.1},{:.1} ", + if i == 0 { "M" } else { "L" }, + px(b(t[0], t[2])), + py(b(t[1], t[3])) + ); + } + let to = move |x: f64, y: f64| -> (f64, f64) { + let fx = ((x - 15.0) / (w - 30.0)).clamp(0.0, 1.0); + let fy = ((h - 15.0 - y) / (h - 30.0) * 2.0 - 0.5).clamp(-0.5, 1.5); + ((fx * 100.0).round() / 100.0, (fy * 100.0).round() / 100.0) + }; + rsx! { + svg { class: "bend-curve anim-curve", width: "{w}", height: "{h}", view_box: "0 0 {w} {h}", + rect { x: "{px(0.0)}", y: "{py(1.0)}", width: "{px(1.0) - px(0.0)}", height: "{py(0.0) - py(1.0)}", class: "anim-box" } + line { x1: "{px(0.0)}", y1: "{py(0.0)}", x2: "{px(t[0])}", y2: "{py(t[1])}", class: "handle" } + line { x1: "{px(1.0)}", y1: "{py(1.0)}", x2: "{px(t[2])}", y2: "{py(t[3])}", class: "handle" } + path { d: "{d}", class: "curve" } + circle { cx: "{px(t[0])}", cy: "{py(t[1])}", r: "7", class: "ctl", onmousedown: move |e| { e.prevent_default(); dragging.set(Some(1)) } } + circle { cx: "{px(t[2])}", cy: "{py(t[3])}", r: "7", class: "ctl", onmousedown: move |e| { e.prevent_default(); dragging.set(Some(2)) } } + if dragging().is_some() { + rect { x: "0", y: "0", width: "{w}", height: "{h}", class: "catch", + onmousemove: move |e| { + let c = e.element_coordinates(); + let (x, y) = to(c.x, c.y); + let mut n = t; + if dragging() == Some(1) { n[0] = x; n[1] = y; } else { n[2] = x; n[3] = y; } + on_change.call(n); + }, + onmouseup: move |_| dragging.set(None), + onmouseleave: move |_| dragging.set(None), + } + } + } + } +} + +/// three sliders for a key's vector, and whether the key sets it at all +fn vec_row( + label: &str, + v: &Value, + (lo, hi, step, rest): (f64, f64, f64, f64), + on: EventHandler<Option<[f64; 3]>>, +) -> Element { + let set = !v.is_null(); + let cur = three(v, rest); + rsx! { + div { class: "anim-vec", + label { class: "sb-tick", title: "whether this key sets it (else it's carried between the keys that do)", + input { r#type: "checkbox", checked: set, oninput: move |e| on.call(if e.checked() { Some(cur) } else { None }) } + "{label}" + } + if set { + for (i , axis) in ["x", "y", "z"].into_iter().enumerate() { + label { key: "{axis}", class: "lt-slider", + span { "{axis}" } + input { r#type: "range", min: "{lo}", max: "{hi}", step: "{step}", value: "{cur[i]}", + oninput: move |e| { let mut n = cur; n[i] = e.value().parse().unwrap_or(rest); on.call(Some(n)) } } + span { class: "dim small", {format!("{:.2}", cur[i])} } + } + } + } + } + } +} + +#[component] +pub(super) fn Anims(sp: Sp, block: Option<Value>, on_changed: EventHandler<()>) -> Element { + let ui = ui(); + let api = api(); + let mut list: Signal<Vec<Value>> = use_signal(Vec::new); + // the animation being edited: its key (None: new) and itself + let mut open: Signal<Option<(Option<String>, Value)>> = use_signal(|| None); + let mut picked: Signal<Option<usize>> = use_signal(|| None); + let mut scrub = use_signal(|| 0.0f64); + let mut playing = use_signal(|| false); + let mut recipes: Signal<Vec<(String, String)>> = use_signal(Vec::new); + let api_l = api.clone(); + use_hook(move || { + let api = api_l.clone(); + spawn(async move { + list.set(load_anims(ui, &api, sp).await); + if let Ok(r) = api.call("textures.list", json!({})).await { + recipes.set( + r.as_array() + .into_iter() + .flatten() + .map(|t| { + let id = t["id"].as_str().unwrap_or("").to_string(); + let name = t["name"] + .as_str() + .filter(|n| !n.is_empty()) + .map(str::to_string) + .unwrap_or_else(|| id.chars().take(8).collect()); + (format!("texture:{id}"), name) + }) + .collect(), + ); + } + }); + }); + let bid = block.as_ref().and_then(|b| b["id"].as_str()).map(str::to_string); + // the open animation shown on the selected block: at the scrubber, or playing + let bid_e = bid.clone(); + use_effect(move || { + let (o, p, play) = (open(), scrub(), playing()); + if let Some(id) = bid_e.clone() { + match o { + Some((_, a)) => sp.send(json!({ "cmd": "animpreview", "id": id, "anim": a, "p": if play { Value::Null } else { json!(p) } })), + None => sp.send(json!({ "cmd": "animpreview", "id": id, "anim": null })), + } + } + }); + let bid_d = bid.clone(); + use_drop(move || { + if let Some(id) = bid_d.clone() { + sp.send(json!({ "cmd": "animpreview", "id": id, "anim": null })); + } + }); + let edit = move |f: &dyn Fn(&mut Value)| { + let mut o = open; + if let Some((_, a)) = o.write().as_mut() { + f(a); + } + }; + let api_k = api.clone(); + let keep = move || { + let api = api_k.clone(); + let Some((key, a)) = open.peek().clone() else { return }; + spawn(async move { + match api.call("anims.save", json!({ "key": key, "anim": a })).await { + Ok(v) => { + let k = v["key"].as_str().unwrap_or("").to_string(); + open.set(Some((Some(k), v["anim"].clone()))); + list.set(load_anims(ui, &api, sp).await); + ui.say("animation kept"); + } + Err(e) => ui.fail(e), + } + }); + }; + + let o = open(); + let keys: Vec<Value> = o + .as_ref() + .map(|(_, a)| a["keys"].as_array().cloned().unwrap_or_default()) + .unwrap_or_default(); + let pk = picked().filter(|&i| i < keys.len()); + let plays = block + .as_ref() + .and_then(|b| b["anim"]["key"].as_str()) + .map(str::to_string); + rsx! { + Win { + id: "anims", + at: (8.0, 80.0), + on_close: move |_| set_pref(ui, |p| p.space.show_anims = false), + title: rsx! { + span { class: "win-title", + Icon { name: "play" } + "animations" + span { class: "dim small", style: "font-weight: 400;", {match list.read().len() { 0 => "none yet".to_string(), 1 => "1 in this save".to_string(), n => format!("{n} in this save") }} } + } + }, + div { class: "row wrap anim-list", + for a in list() { + { + let key = a["key"].as_str().unwrap_or("").to_string(); + let name = a["anim"]["name"].as_str().filter(|n| !n.is_empty()).map(str::to_string).unwrap_or_else(|| format!("animation {key}")); + let on = o.as_ref().and_then(|x| x.0.clone()) == Some(key.clone()); + rsx! { + button { key: "{key}", class: if on { "btn small on" } else { "plain small" }, + title: if plays.as_deref() == Some(key.as_str()) { "the selected block plays this" } else { "open it" }, + onclick: move |_| { open.set(Some((Some(key.clone()), a["anim"].clone()))); picked.set(None); scrub.set(0.0); }, + if plays.as_deref() == Some(a["key"].as_str().unwrap_or("")) { "▶ " } "{name}" } + } + } + } + button { class: "btn small", onclick: move |_| { open.set(Some((None, blank()))); picked.set(Some(1)); scrub.set(1.0); }, Icon { name: "new" } "new" } + } + if let Some((key, a)) = o.clone() { + div { class: "anim-edit", + div { class: "row", + input { r#type: "text", class: "sb-text", placeholder: "its name", value: a["name"].as_str().unwrap_or("").to_string(), + oninput: move |e| edit(&|a| a["name"] = json!(e.value())) } + select { class: "sb-pick", "aria-label": "how it repeats", + onchange: move |e| edit(&|a| a["repeat"] = json!(e.value())), + for (r , w) in [("once", "once"), ("loop", "in a loop"), ("alternate", "back and forth")] { + option { key: "{r}", value: "{r}", selected: a["repeat"].as_str().unwrap_or("once") == r, "{w}" } + } + } + } + label { class: "lt-slider", span { "length" } + input { r#type: "range", min: "0.1", max: "20", step: "0.1", value: "{a[\"duration\"].as_f64().unwrap_or(2.0)}", + oninput: move |e| edit(&|a| a["duration"] = json!(e.value().parse::<f64>().unwrap_or(2.0))) } + span { class: "dim small", {format!("{:.1} s", a["duration"].as_f64().unwrap_or(2.0))} } + } + div { class: "anim-timing", + Curve { t: four(&a["timing"]), on_change: move |t: [f64; 4]| edit(&|a| a["timing"] = json!(t)) } + div { class: "anim-named", + span { class: "dim small", "timing between keys" } + for (n , t) in NAMED { + button { key: "{n}", class: if same(four(&a["timing"]), t) { "btn small on" } else { "plain small" }, onclick: move |_| edit(&|a| a["timing"] = json!(t)), "{n}" } + } + } + } + // the timeline: the keys as dots; the scrubber shows a moment on the block + div { class: "anim-track", + for (i , at) in keys.iter().map(|k| k["at"].as_f64().unwrap_or(0.0)).enumerate() { + button { key: "{i}", class: if pk == Some(i) { "anim-key on" } else { "anim-key" }, + style: "left: {at * 100.0}%;", + title: "the key at {at:.2}", + onclick: move |_| { picked.set(Some(i)); scrub.set(at); playing.set(false); }, + "◆" } + } + input { r#type: "range", class: "anim-scrub", min: "0", max: "1", step: "0.005", value: "{scrub()}", "aria-label": "a moment", + oninput: move |e| { scrub.set(e.value().parse().unwrap_or(0.0)); playing.set(false); } } + } + div { class: "row wrap", + span { class: "dim small", {format!("{:.0}%", scrub() * 100.0)} } + button { class: "btn small", title: "a key at this moment, with the pose it has here", + onclick: move |_| { + let p = (scrub() * 1000.0).round() / 1000.0; + edit(&|a| { + let mut ks = a["keys"].as_array().cloned().unwrap_or_default(); + ks.retain(|k| k["at"].as_f64() != Some(p)); + ks.push(json!({ "at": p })); + ks.sort_by(|x, y| x["at"].as_f64().unwrap_or(0.0).total_cmp(&y["at"].as_f64().unwrap_or(0.0))); + a["keys"] = json!(ks); + }); + let i = open.peek().as_ref().and_then(|(_, a)| a["keys"].as_array().and_then(|k| k.iter().position(|k| k["at"].as_f64() == Some(p)))); + picked.set(i); + }, + Icon { name: "new" } "a key here" } + button { class: "btn small", disabled: bid.is_none(), title: if bid.is_none() { "select a block to see it on" } else { "play it on the selected block" }, + onclick: move |_| playing.set(!playing()), if playing() { "pause" } else { "▶ play" } } + span { class: "grow" } + button { class: "btn small primary", onclick: { let k = keep.clone(); move |_| k() }, Icon { name: "save" } "keep" } + } + if let Some(i) = pk { + { + let k = keys[i].clone(); + let path_set = move |field: &'static str, v: Option<[f64; 3]>| edit(&|a| { + match v { + Some(x) => a["keys"][i][field] = json!(x), + None => { if let Some(o) = a["keys"][i].as_object_mut() { o.remove(field); } } + } + }); + let tex = k["texture"].as_str().unwrap_or("").to_string(); + rsx! { + div { class: "anim-keyed", + div { class: "row", + b { "key {i + 1}" } + label { class: "lt-slider", span { "at" } + input { r#type: "range", min: "0", max: "1", step: "0.005", value: "{k[\"at\"].as_f64().unwrap_or(0.0)}", + oninput: move |e| { let p: f64 = e.value().parse().unwrap_or(0.0); scrub.set(p); edit(&|a| a["keys"][i]["at"] = json!(p)) } } + } + button { class: "plain small", title: "take this key out", + onclick: move |_| { edit(&|a| { if let Some(ks) = a["keys"].as_array_mut() && i < ks.len() { ks.remove(i); } }); picked.set(None); }, + Icon { name: "delete" } } + } + {vec_row("move (units)", &k["move"], (-10.0, 10.0, 0.05, 0.0), EventHandler::new(move |v| path_set("move", v)))} + {vec_row("turn (degrees)", &k["turn"], (-360.0, 360.0, 1.0, 0.0), EventHandler::new(move |v| path_set("turn", v)))} + {vec_row("scale (times)", &k["scale"], (0.1, 4.0, 0.05, 1.0), EventHandler::new(move |v| path_set("scale", v)))} + div { class: "row wrap", + span { class: "small", "texture from here" } + select { class: "sb-pick", "aria-label": "the key's texture", + onchange: move |e| { let t = e.value(); edit(&|a| { if t.is_empty() { if let Some(o) = a["keys"][i].as_object_mut() { o.remove("texture"); } } else { a["keys"][i]["texture"] = json!(t) } }) }, + option { value: "", selected: tex.is_empty(), "the block's own" } + if tex.starts_with("plain:") { option { value: "{tex}", selected: true, "{tex}" } } + for (id , n) in recipes() { option { key: "{id}", value: "{id}", selected: tex == id, "the recipe {n}" } } + } + input { r#type: "color", "aria-label": "a colour from this key", value: tex.strip_prefix("plain:").unwrap_or("#c0a070").to_string(), + onchange: move |e| edit(&|a| a["keys"][i]["texture"] = json!(format!("plain:{}", e.value()))) } + } + div { class: "row wrap", + label { class: "sb-tick", title: "a timing of its own from this key to the next", + input { r#type: "checkbox", checked: !k["timing"].is_null(), + oninput: move |e| { let on = e.checked(); edit(&|a| { if on { let t = a["timing"].clone(); a["keys"][i]["timing"] = t; } else if let Some(o) = a["keys"][i].as_object_mut() { o.remove("timing"); } }) } } + "its own timing to the next key" + } + } + if !k["timing"].is_null() { + Curve { t: four(&k["timing"]), on_change: move |t: [f64; 4]| edit(&|a| a["keys"][i]["timing"] = json!(t)) } + } + } + } + } + } + if let (Some(b), Some(k)) = (block.clone(), key.clone()) { + { + let id = b["id"].as_str().unwrap_or("").to_string(); + let delay = b["anim"]["delay"].as_f64().unwrap_or(0.0); + let speed = b["anim"]["speed"].as_f64().unwrap_or(1.0); + let mine = plays.as_deref() == Some(k.as_str()); + let api = api.clone(); + let set_anim = move |v: Value| { + let (api, id) = (api.clone(), id.clone()); + spawn(async move { + match api.call("blocks.set", json!({ "id": id, "anim": v })).await { + Ok(r) => { + let textures = dress(ui, &api, r["textures"].clone()).await; + sp.send(json!({ "cmd": "blocks", "blocks": r["blocks"], "textures": textures, "select": id })); + on_changed.call(()); + } + Err(e) => ui.fail(e), + } + }); + }; + let (s1, s2, s3, s4) = (set_anim.clone(), set_anim.clone(), set_anim.clone(), set_anim.clone()); + let (k1, k2, k3) = (k.clone(), k.clone(), k.clone()); + rsx! { + div { class: "anim-use", + if mine { + span { class: "small", "the selected block plays it" } + label { class: "lt-slider", span { "after" } + input { r#type: "range", min: "0", max: "10", step: "0.1", value: "{delay}", + onchange: move |e| s1(json!({ "key": k1, "delay": e.value().parse::<f64>().unwrap_or(0.0), "speed": speed })) } + span { class: "dim small", {format!("{delay:.1} s")} } + } + label { class: "lt-slider", span { "speed" } + input { r#type: "range", min: "0.1", max: "4", step: "0.05", value: "{speed}", + onchange: move |e| s2(json!({ "key": k2, "delay": delay, "speed": e.value().parse::<f64>().unwrap_or(1.0) })) } + span { class: "dim small", {format!("{speed:.2}×")} } + } + button { class: "plain small", onclick: move |_| s3(Value::Null), "stop it" } + } else { + button { class: "btn small", title: "the selected block plays this animation (kept in the save)", + onclick: move |_| s4(json!({ "key": k3, "delay": 0.0, "speed": 1.0 })), Icon { name: "play" } "the selected block plays it" } + } + } + } + } + } else if key.is_none() { + p { class: "dim small", "Keep it first; then a block can play it." } + } else { + p { class: "dim small", "Select a block to see it there and have it play it." } + } + if let Some(k) = key.clone() { + button { class: "plain small", title: "delete the animation (blocks playing it stop)", + onclick: { let api = api.clone(); move |_| { + let (api, k) = (api.clone(), k.clone()); + spawn(async move { + match api.call("anims.delete", json!({ "key": k })).await { + Ok(_) => { open.set(None); list.set(load_anims(ui, &api, sp).await); ui.say("animation deleted"); } + Err(e) => ui.fail(e), + } + }); + } }, + Icon { name: "delete" } "delete it" } + } + } + } else { + p { class: "dim small", "Keyframes for blocks, as CSS has them: a move, a turn, a scale and a texture at moments, eased along a timing curve. Open one, or make a new one; select a block to see it there." } + } + } + } +} diff --git a/app/src/views/space/flightwin.rs b/app/src/views/space/flightwin.rs new file mode 100644 index 00000000..f17e3b4d --- /dev/null +++ b/app/src/views/space/flightwin.rs @@ -0,0 +1,99 @@ +//! What superflight collected (queued request #9): the texts flown through, in the order +//! met, shown while there are any. They can become one new entry (their words joined), a +//! chain (the first its title, the rest its members), a list (the first its head), or the +//! bar's text; or be cleared. Free texts (not entries of the save) join the new entry +//! and the bar, but a chain or a list takes entries only. + +use dioxus::prelude::*; +use serde_json::json; + +use super::{Sp, Win}; +use crate::ui::*; + +#[component] +pub(super) fn Collected(sp: Sp) -> Element { + let ui = ui(); + let api = api(); + let got = (sp.collected)(); + let texts: Vec<String> = got + .iter() + .map(|c| c["text"].as_str().unwrap_or("").to_string()) + .collect(); + let joined = texts.join(" "); + // entries only (a free text's key isn't an entry's) + let keys: Vec<String> = got + .iter() + .filter_map(|c| c["key"].as_str()) + .filter(|k| anend_core::graph::record::parse_label(k).is_some()) + .map(str::to_string) + .collect(); + let clear = move || sp.send(json!({ "cmd": "clearcollected" })); + let make = { + let api = api.clone(); + move |what: &'static str| { + let api = api.clone(); + let (joined, keys) = (joined.clone(), keys.clone()); + spawn(async move { + let r: Result<String, String> = match what { + "entry" => api + .call("mem.saturate", json!({ "text": joined })) + .await + .map(|v| format!("an entry: {}", v["key"].as_str().unwrap_or(""))), + "chain" if keys.len() >= 2 => api + .call("chains.make", json!({ "title": keys[0], "members": keys[1..] })) + .await + .map(|v| format!("a chain under “{}”", v["title"]["text"].as_str().unwrap_or(""))), + "list" if keys.len() >= 2 => { + let mut out = Ok(String::new()); + for m in &keys[1..] { + if let Err(e) = api.call("lists.enlist", json!({ "list": keys[0], "member": m })).await { + out = Err(e); + break; + } + } + out.map(|_| format!("a list of {} under its first", keys.len() - 1)) + } + _ => Err("a chain or a list needs two texts of the save at least".into()), + }; + match r { + Ok(said) => { + ui.say(said); + sp.send(json!({ "cmd": "clearcollected" })); + } + Err(e) => ui.fail(e), + } + }); + } + }; + let (m1, m2, m3) = (make.clone(), make.clone(), make.clone()); + let shown = 24; + rsx! { + Win { + id: "collected", + at: (8.0, 200.0), + on_close: move |_| clear(), + title: rsx! { + span { class: "win-title", + Icon { name: "bolt" } + "flown through" + span { class: "dim small", style: "font-weight: 400;", {format!("{} text{}, in order", got.len(), if got.len() == 1 { "" } else { "s" })} } + } + }, + div { class: "wire-targets", + for (i, t) in texts.iter().take(shown).enumerate() { + span { key: "{i}", class: "chip small", "{t}" } + } + if texts.len() > shown { + span { class: "dim small", {format!("…and {} more", texts.len() - shown)} } + } + } + div { class: "row wrap", + button { class: "btn small primary", title: "one new entry: their words joined", onclick: move |_| m1("entry"), "an entry" } + button { class: "btn small", title: "the first its title, the rest its members", onclick: move |_| m2("chain"), "a chain" } + button { class: "btn small", title: "the first its head, the rest its members", onclick: move |_| m3("list"), "a list" } + button { class: "btn small", onclick: { let j = texts.join(" "); move |_| ui.set_bar(&j) }, "into the bar" } + button { class: "btn small", onclick: move |_| clear(), "clear" } + } + } + } +} diff --git a/app/src/views/space/lightwin.rs b/app/src/views/space/lightwin.rs new file mode 100644 index 00000000..9d943f18 --- /dev/null +++ b/app/src/views/space/lightwin.rs @@ -0,0 +1,328 @@ +//! The lights window: the room's lights (core's `graph::lights`), baked onto the blocks by +//! the room (`space.js` `bake`). Add an ambient light, a sun (directional), a point or a +//! cone ahead of you; pick one to set its colour, strength, reach, direction and cone with +//! sliders. Every change shows at once; it's kept when the slider is let go. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use super::{Sp, Win}; +use crate::shell::set_pref; +use crate::ui::*; + +/// the room's lights into the room (all of them, or baking only where `changed` reach) +pub(super) fn send_lights(sp: Sp, changed: Option<Vec<u64>>) { + let lights = sp.lights.peek().clone(); + sp.send(json!({ "cmd": "lights", "lights": lights, "changed": changed })); +} + +/// the save's lights, read again and sent to the room +pub(super) async fn load_lights(api: &Api, sp: Sp) { + let all = match api.call("lights.list", json!({})).await { + Ok(v) => v.as_array().cloned().unwrap_or_default(), + // a hub from before lights: none + Err(_) => Vec::new(), + }; + let mut l = sp.lights; + l.set(all); + send_lights(sp, None); +} + +/// a slider for a reach: 0–100 for 0.5 to 200 units, evenly in log +fn reach_to_slider(v: f64) -> f64 { + ((v.clamp(0.5, 200.0) / 0.5).ln() / 400f64.ln() * 100.0).round() +} +fn slider_to_reach(s: f64) -> f64 { + ((0.5 * 400f64.powf(s / 100.0)) * 10.0).round() / 10.0 +} + +/// a direction as yaw (degrees round the upright, 0 looking along −z) and pitch (degrees up) +fn yaw_pitch(d: &Value) -> (f64, f64) { + let (x, y, z) = ( + d[0].as_f64().unwrap_or(0.0), + d[1].as_f64().unwrap_or(-1.0), + d[2].as_f64().unwrap_or(0.0), + ); + let yaw = (-x).atan2(-z).to_degrees().rem_euclid(360.0); + let pitch = y.clamp(-1.0, 1.0).asin().to_degrees(); + // no "-0°" + (yaw.round().abs() % 360.0, pitch.round() + 0.0) +} +fn dir_of(yaw: f64, pitch: f64) -> Value { + let (y, p) = (yaw.to_radians(), pitch.to_radians()); + let r = |v: f64| (v * 1000.0).round() / 1000.0; + json!([r(-y.sin() * p.cos()), r(p.sin()), r(-y.cos() * p.cos())]) +} + +fn kind_words(k: &str) -> &'static str { + match k { + "ambient" => "ambient", + "directional" => "sun", + "point" => "point", + "spot" => "cone", + _ => "light", + } +} + +#[component] +pub(super) fn Lights(sp: Sp) -> Element { + let ui = ui(); + let api = api(); + let mut picked: Signal<Option<u64>> = use_signal(|| None); + // a marker clicked in the room picks its light here + use_effect(move || { + if let Some(id) = (sp.lightpick)() { + picked.set(Some(id)); + } + }); + let mut armed = use_signal(|| false); + // the markers show while the window is open, the picked one bigger + use_effect(move || { + let p = picked(); + sp.send(json!({ "cmd": "showlights", "on": true, "picked": p })); + }); + // however the window closes + use_drop(move || sp.send(json!({ "cmd": "showlights", "on": false }))); + let lights = (sp.lights)(); + let now = picked().and_then(|id| lights.iter().find(|l| l["id"].as_u64() == Some(id)).cloned()); + + // a field of the picked light changed: shown at once, kept when `keep` + let api_c = api.clone(); + let change = move |id: u64, k: &'static str, v: Value, keep: bool| { + let mut ls = sp.lights; + if let Some(l) = ls.write().iter_mut().find(|l| l["id"].as_u64() == Some(id)) { + l[k] = v.clone(); + } + send_lights(sp, Some(vec![id])); + if keep { + let api = api_c.clone(); + spawn(async move { + if let Err(e) = api.call("lights.set", json!({ "id": id, k: v })).await { + ui.fail(e); + } + }); + } + }; + let add = move |kind: &'static str| sp.send(json!({ "cmd": "lightspot", "want": { "kind": kind } })); + + rsx! { + Win { + id: "lights", + at: (8.0, 120.0), + on_close: move |_| set_pref(ui, |p| p.space.show_lights = false), + title: rsx! { + span { class: "win-title", + Icon { name: "sun" } + "lights" + span { class: "dim small", style: "font-weight: 400;", + {match lights.len() { 0 => "none: faces are shaded by their direction".to_string(), 1 => "1 light".to_string(), n => format!("{n} lights") }} + } + } + }, + div { class: "row wrap lt-add", + span { class: "small", "add" } + button { class: "btn small", title: "light from everywhere, so nothing is black", onclick: move |_| add("ambient"), "ambient" } + button { class: "btn small", title: "light from one way, the way you look", onclick: move |_| add("directional"), "sun" } + button { class: "btn small", title: "a light all round, a little ahead of you", onclick: move |_| add("point"), "point" } + button { class: "btn small", title: "a cone of light ahead of you, shining the way you look", onclick: move |_| add("spot"), "cone" } + } + div { class: "lt-list", + for l in lights.iter() { + { + let id = l["id"].as_u64().unwrap_or(0); + let colour = l["colour"].as_str().unwrap_or("#ffffff").to_string(); + let k = kind_words(l["kind"].as_str().unwrap_or("")); + let i = l["intensity"].as_f64().unwrap_or(1.0); + rsx! { + button { key: "{id}", class: if picked() == Some(id) { "lt-row on" } else { "lt-row" }, + onclick: move |_| { picked.set(Some(id)); armed.set(false); }, + span { class: "lt-swatch", style: "background: {colour};" } + span { "{k}" } + span { class: "dim small", {format!("strength {i:.2}")} } + } + } + } + } + } + if let Some(l) = now { + { + let id = l["id"].as_u64().unwrap_or(0); + let kind = l["kind"].as_str().unwrap_or("ambient").to_string(); + let placed = kind == "point" || kind == "spot"; + let aimed = kind == "directional" || kind == "spot"; + let (yaw, pitch) = yaw_pitch(&l["dir"]); + let range = l["range"].as_f64().unwrap_or(10.0); + let api = api.clone(); + let change2 = change.clone(); + let change3 = change.clone(); + let change4 = change.clone(); + let change5 = change.clone(); + let change6 = change.clone(); + let change7 = change.clone(); + let change8 = change.clone(); + rsx! { + div { class: "lt-edit", + div { class: "row", + b { {kind_words(&kind)} } + input { r#type: "color", value: l["colour"].as_str().unwrap_or("#ffffff"), "aria-label": "its colour", + oninput: { let c = change.clone(); move |e: FormEvent| c(id, "colour", json!(e.value()), false) }, + onchange: { let c = change.clone(); move |e: FormEvent| c(id, "colour", json!(e.value()), true) } } + } + label { class: "lt-slider", span { "strength" } + input { r#type: "range", min: "0", max: "5", step: "0.05", value: "{l[\"intensity\"].as_f64().unwrap_or(1.0)}", + oninput: move |e| change2(id, "intensity", json!(e.value().parse::<f64>().unwrap_or(1.0)), false), + onchange: move |e| change3(id, "intensity", json!(e.value().parse::<f64>().unwrap_or(1.0)), true) } + span { class: "dim small", {format!("{:.2}", l["intensity"].as_f64().unwrap_or(1.0))} } + } + if placed { + label { class: "lt-slider", span { "reach" } + input { r#type: "range", min: "0", max: "100", step: "1", value: "{reach_to_slider(range)}", + oninput: move |e| change4(id, "range", json!(slider_to_reach(e.value().parse().unwrap_or(50.0))), false), + onchange: move |e| change5(id, "range", json!(slider_to_reach(e.value().parse().unwrap_or(50.0))), true) } + span { class: "dim small", {format!("{range:.1} units")} } + } + } + if aimed { + label { class: "lt-slider", span { "round" } + input { r#type: "range", min: "0", max: "359", step: "1", value: "{yaw}", + oninput: { let c = change6.clone(); move |e: FormEvent| c(id, "dir", dir_of(e.value().parse().unwrap_or(0.0), pitch), false) }, + onchange: { let c = change6.clone(); move |e: FormEvent| c(id, "dir", dir_of(e.value().parse().unwrap_or(0.0), pitch), true) } } + span { class: "dim small", "{yaw}°" } + } + label { class: "lt-slider", span { "up/down" } + input { r#type: "range", min: "-90", max: "90", step: "1", value: "{pitch}", + oninput: { let c = change7.clone(); move |e: FormEvent| c(id, "dir", dir_of(yaw, e.value().parse().unwrap_or(-45.0)), false) }, + onchange: { let c = change7.clone(); move |e: FormEvent| c(id, "dir", dir_of(yaw, e.value().parse().unwrap_or(-45.0)), true) } } + span { class: "dim small", "{pitch}°" } + } + } + if kind == "spot" { + label { class: "lt-slider", span { "cone" } + input { r#type: "range", min: "1", max: "89", step: "1", value: "{l[\"angle\"].as_f64().unwrap_or(30.0)}", + oninput: { let c = change8.clone(); move |e: FormEvent| c(id, "angle", json!(e.value().parse::<f64>().unwrap_or(30.0)), false) }, + onchange: { let c = change8.clone(); move |e: FormEvent| c(id, "angle", json!(e.value().parse::<f64>().unwrap_or(30.0)), true) } } + span { class: "dim small", {format!("{:.0}°", l["angle"].as_f64().unwrap_or(30.0))} } + } + label { class: "lt-slider", span { "soft edge" } + input { r#type: "range", min: "0", max: "1", step: "0.05", value: "{l[\"softness\"].as_f64().unwrap_or(0.3)}", + oninput: { let c = change8.clone(); move |e: FormEvent| c(id, "softness", json!(e.value().parse::<f64>().unwrap_or(0.3)), false) }, + onchange: { let c = change8.clone(); move |e: FormEvent| c(id, "softness", json!(e.value().parse::<f64>().unwrap_or(0.3)), true) } } + } + } + div { class: "row wrap", + if placed || aimed { + button { class: "btn small", title: if placed { "to a little ahead of you, shining the way you look" } else { "shining the way you look" }, + onclick: move |_| sp.send(json!({ "cmd": "lightspot", "want": { "move": id, "placed": placed } })), + if placed { "move it here" } else { "the way I look" } } + } + button { + class: if armed() { "armed small" } else { "plain small" }, + title: "delete the light (click twice)", + onclick: move |_| { + if !armed() { + armed.set(true); + return; + } + armed.set(false); + picked.set(None); + let api = api.clone(); + spawn(async move { + match api.call("lights.delete", json!({ "id": id })).await { + Ok(_) => { + let mut ls = sp.lights; + ls.write().retain(|l| l["id"].as_u64() != Some(id)); + send_lights(sp, Some(vec![id])); + ui.say("light deleted"); + } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "delete" } + if armed() { "delete?" } + } + } + } + } + } + } else if !lights.is_empty() { + p { class: "dim small", "Pick a light to change it. Point and cone lights show as dots in the room while this window is open." } + } else { + p { class: "dim small", "Lights are baked onto the blocks: worked out when a light or a block changes, not every frame, and without shadows. Texts aren't lit." } + } + } + } +} + +/// what the room answered for a new light's place: add it, or move the one asked for +pub(super) fn light_spot(ui: Ui, api: Api, sp: Sp, data: Value) { + spawn_forever(async move { + let want = &data["want"]; + let dir = data["dir"].clone(); + let at = json!({ "x": data["x"], "y": data["y"], "z": data["z"] }); + if let Some(id) = want["move"].as_u64() { + let mut args = json!({ "id": id, "dir": dir }); + if want["placed"].as_bool() == Some(true) { + for k in ["x", "y", "z"] { + args[k] = at[k].clone(); + } + } + match api.call("lights.set", args).await { + Ok(l) => { + let mut ls = sp.lights; + if let Some(x) = ls.write().iter_mut().find(|x| x["id"].as_u64() == Some(id)) { + *x = l; + } + send_lights(sp, Some(vec![id])); + } + Err(e) => ui.fail(e), + } + return; + } + let kind = want["kind"].as_str().unwrap_or("point"); + let mut light = json!({ "kind": kind, "x": at["x"], "y": at["y"], "z": at["z"], "dir": dir }); + match kind { + "ambient" => light["intensity"] = json!(0.6), + // a sun shines down whichever way one looks + "directional" => { + let d = &light["dir"]; + let (x, z) = (d[0].as_f64().unwrap_or(0.0), d[2].as_f64().unwrap_or(-1.0)); + light["dir"] = json!([x, -1.0, z]); + light["intensity"] = json!(0.8); + } + "spot" => light["intensity"] = json!(2.0), + _ => light["intensity"] = json!(1.5), + } + match api.call("lights.add", light).await { + Ok(l) => { + let id = l["id"].as_u64(); + let mut ls = sp.lights; + ls.write().push(l); + send_lights(sp, id.map(|i| vec![i])); + ui.say("a light · pick it in the lights window to change it"); + } + Err(e) => ui.fail(e), + } + }); +} + +fn spawn_forever(f: impl std::future::Future<Output = ()> + 'static) { + dioxus::dioxus_core::spawn_forever(f); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn directions_round_trip() { + for (yaw, pitch) in [(0.0, -45.0), (90.0, 10.0), (200.0, -80.0), (359.0, 0.0)] { + let (y, p) = yaw_pitch(&dir_of(yaw, pitch)); + assert!( + (y - yaw).abs() <= 1.0 && (p - pitch).abs() <= 1.0, + "{yaw} {pitch} → {y} {p}" + ); + } + assert!((slider_to_reach(reach_to_slider(10.0)) - 10.0).abs() < 0.7); + } +} diff --git a/app/src/views/space/native_room.rs b/app/src/views/space/native_room.rs new file mode 100644 index 00000000..a579dbf7 --- /dev/null +++ b/app/src/views/space/native_room.rs @@ -0,0 +1,358 @@ +//! The room in Rust: space.js's place is taken by `anend_render::room::Room`, which takes the +//! same commands and sends the same events. It's drawn by `anend-render`: on the Linux +//! desktop under the see-through webview (crate::native), on macOS and Windows into the page +//! as frames (crate::picture), and on the web straight into a canvas with WebGPU. The pointer +//! and keys come to the room through Dioxus's own handlers. No JavaScript is involved. + +use std::cell::RefCell; +use std::rc::Rc; + +use anend_render::room::{Mods, Room}; +use dioxus::prelude::*; +use serde_json::Value; + +use super::SpaceEvent; + +thread_local! { + static ROOM: Rc<RefCell<Room>> = Rc::new(RefCell::new(Room::new())); + static HOST: RefCell<Option<Rc<MountedData>>> = const { RefCell::new(None) }; + static RECT: RefCell<(f64, f64, f64, f64)> = const { RefCell::new((0.0, 0.0, 0.0, 0.0)) }; + /// whether the space is the view on screen + static SHOWN: std::cell::Cell<bool> = const { std::cell::Cell::new(false) }; + /// the newest frame shown in the page (the picture path), and the signal its img reads + static FRAME: std::cell::Cell<u64> = const { std::cell::Cell::new(0) }; + static FRAME_SIG: RefCell<Option<Signal<u64>>> = const { RefCell::new(None) }; +} + +fn room() -> Rc<RefCell<Room>> { + ROOM.with(|r| r.clone()) +} + +/// what differs between the desktop and the web: where the picture goes, the clock, sounds +/// and the prefab pictures +#[cfg(feature = "desktop")] +mod gpu { + use super::*; + + pub fn install() { + // on Linux the picture goes under the page (GTK); elsewhere, into it (an img) + #[cfg(target_os = "linux")] + if !crate::picture::enabled() { + let d = dioxus::desktop::window(); + crate::native::install(&d.window, &d.webview); + } + } + + pub fn now() -> f64 { + thread_local! { static T0: std::time::Instant = std::time::Instant::now(); } + T0.with(|t| t.elapsed().as_secs_f64()) + } + + pub fn thumbs(jobs: Vec<(Value, anend_render::Scene, anend_render::Camera)>, tx: &std::sync::mpsc::Sender<Value>) { + crate::picture::thumbs(jobs, tx.clone()); + } + + pub fn audio(cmds: Vec<anend_render::room::Audio>) { + crate::native_audio::play(cmds); + } + + /// whether the picture is an img in the page + pub fn picture() -> bool { + crate::picture::enabled() + } + + pub fn draw(scene: anend_render::Scene, camera: anend_render::Camera, x: f64, y: f64, w: u32, h: u32) { + let _ = (x, y); + if crate::picture::enabled() { + crate::picture::draw(crate::picture::Job { scene, camera, w, h }); + } else { + #[cfg(target_os = "linux")] + crate::native::draw(crate::native::Job { + scene, + camera, + x, + y, + w, + h, + }); + } + } + + pub fn shown(on: bool) { + #[cfg(target_os = "linux")] + if !crate::picture::enabled() { + crate::native::show(on); + } + let _ = on; + } + + pub fn window_colour(hex: &str) { + #[cfg(target_os = "linux")] + crate::native::set_window_colour(hex); + let _ = hex; + } + + pub fn frame_no() -> u64 { + crate::picture::frame_no() + } + + pub fn frame_url(n: u64) -> String { + crate::picture::frame_url(n) + } +} + +#[cfg(not(feature = "desktop"))] +mod gpu { + use super::*; + use std::cell::Cell; + use wasm_bindgen::JsCast; + + thread_local! { + static RENDERER: RefCell<Option<anend_render::Renderer>> = const { RefCell::new(None) }; + static STARTED: Cell<bool> = const { Cell::new(false) }; + } + + pub fn install() {} + + pub fn now() -> f64 { + js_sys::Date::now() / 1000.0 + } + + /// the prefab pictures need a picture read back, which WebGPU only gives later: not yet + pub fn thumbs(_: Vec<(Value, anend_render::Scene, anend_render::Camera)>, _: &std::sync::mpsc::Sender<Value>) {} + + /// sounds on the web aren't mixed yet + pub fn audio(_: Vec<anend_render::room::Audio>) {} + + pub fn picture() -> bool { + false + } + + fn canvas() -> Option<web_sys::HtmlCanvasElement> { + web_sys::window()? + .document()? + .get_element_by_id("space-canvas")? + .dyn_into() + .ok() + } + + /// draws into the canvas (made the first time, once the canvas is on the page) + pub fn draw(scene: anend_render::Scene, camera: anend_render::Camera, _x: f64, _y: f64, w: u32, h: u32) { + let Some(c) = canvas() else { return }; + if c.width() != w || c.height() != h { + c.set_width(w); + c.set_height(h); + } + let ready = RENDERER.with(|r| r.borrow().is_some()); + if !ready { + if !STARTED.with(|s| s.replace(true)) { + spawn(async move { + match anend_render::Renderer::for_canvas(c).await { + Ok(r) => { + web_sys::console::log_1( + &format!("anend: the room draws with WebGPU ({})", r.adapter_name).into(), + ); + RENDERER.with(|x| *x.borrow_mut() = Some(r)); + } + Err(e) => { + web_sys::console::warn_1(&format!("anend: the room can't draw with WebGPU: {e}").into()) + } + } + }); + } + return; + } + RENDERER.with(|r| { + if let Some(r) = r.borrow_mut().as_mut() { + r.resize(w, h); + if let Err(e) = r.present(&scene, &camera) { + web_sys::console::warn_1(&format!("anend: {e}").into()); + } + } + }); + } + + pub fn shown(_: bool) {} + + pub fn window_colour(_: &str) {} + + pub fn frame_no() -> u64 { + 0 + } + + pub fn frame_url(_: u64) -> String { + String::new() + } +} + +/// the room's loop: the commands Rust sends, a step of the room, its events, its picture +pub fn run(mut rx: futures_channel::mpsc::UnboundedReceiver<Value>, on_event: impl Fn(SpaceEvent) + 'static) { + gpu::install(); + spawn(async move { + let mut last = gpu::now(); + let mut tick = 0u32; + let (thumbs_tx, thumbs_rx) = std::sync::mpsc::channel::<Value>(); + loop { + crate::ui::sleep_ms(15).await; + let r = room(); + // the prefabs' pictures, drawn off this thread + let jobs = r.borrow_mut().take_thumbs(); + gpu::thumbs(jobs, &thumbs_tx); + while let Ok(data) = thumbs_rx.try_recv() { + if let Ok(e) = + serde_json::from_value::<SpaceEvent>(serde_json::json!({ "kind": "thumbs", "data": data })) + { + on_event(e); + } + } + loop { + match rx.try_recv() { + Ok(c) => { + // the room's element takes the keys + if c["cmd"] == "focus" + && let Some(m) = HOST.with(|h| h.borrow().clone()) + { + spawn(async move { + let _ = m.set_focus(true).await; + }); + } + r.borrow_mut().command(&c) + } + Err(futures_channel::mpsc::TryRecvError::Closed) => return, + Err(_) => break, + } + } + let now = gpu::now(); + let dt = (now - last) as f32; + last = now; + r.borrow_mut().frame(dt); + let audio = r.borrow_mut().take_audio(); + gpu::audio(audio); + let evs = r.borrow_mut().take_events(); + for e in evs { + if let Ok(e) = serde_json::from_value::<SpaceEvent>(e) { + on_event(e); + } + } + // where the room's element is (it moves with the window's size) + tick += 1; + if tick % 20 == 1 + && let Some(m) = HOST.with(|h| h.borrow().clone()) + && let Ok(rc) = m.get_client_rect().await + { + RECT.with(|x| *x.borrow_mut() = (rc.origin.x, rc.origin.y, rc.size.width, rc.size.height)); + } + let (x, y, w, h) = RECT.with(|x| *x.borrow()); + if w < 2.0 || h < 2.0 { + continue; + } + let mut rm = r.borrow_mut(); + rm.resize(w as f32, h as f32); + if SHOWN.with(|s| s.get()) && (rm.dirty || tick.is_multiple_of(30)) { + let scene = rm.scene(); + let camera = rm.camera(); + drop(rm); + gpu::draw(scene, camera, x, y, w as u32, h as u32); + } + // a new frame in the page: the img asks for it + if gpu::picture() { + let n = gpu::frame_no(); + if FRAME.with(|f| f.get()) != n { + FRAME.with(|f| f.set(n)); + if let Some(mut sig) = FRAME_SIG.with(|f| *f.borrow()) { + sig.set(n); + } + } + } + } + }); +} + +fn mods(m: dioxus::html::Modifiers) -> Mods { + Mods { + shift: m.shift(), + ctrl: m.ctrl() || m.meta(), + alt: m.alt(), + } +} + +fn button(e: &MouseEvent) -> u8 { + use dioxus::html::input_data::MouseButton; + match e.trigger_button() { + Some(MouseButton::Secondary) => 2, + Some(MouseButton::Auxiliary) => 1, + _ => 0, + } +} + +/// the room's element: empty and see-through, its pointer and keys for the room +#[component] +pub fn NativeHost() -> Element { + let ui = crate::ui::ui(); + // the room shows while the space is the view on screen (views are kept once built) + let open = (ui.view)() == crate::ui::View::Space; + let picture = gpu::picture(); + let frame = use_signal(|| 0u64); + use_hook(move || FRAME_SIG.with(|f| *f.borrow_mut() = Some(frame))); + use_effect(move || { + let on = (ui.view)() == crate::ui::View::Space; + SHOWN.with(|s| s.set(on)); + gpu::shown(on); + }); + use_drop(move || { + SHOWN.with(|s| s.set(false)); + gpu::shown(false); + }); + use_effect(move || { + let p = ui.prefs.read(); + gpu::window_colour(&crate::theme::colour(&p.palette, &p.colours, "window")); + }); + let at = |e: &MouseEvent| { + let p = e.element_coordinates(); + (p.x as f32, p.y as f32) + }; + rsx! { + // the page is see-through where the room is: the window's colour is painted under it + if open && !picture && cfg!(feature = "desktop") { + style { "html, body, #main, .app, .view.space, .space {{ background: transparent !important; }}" } + } + div { id: "space-host", class: "space-host native", tabindex: "0", + "aria-label": "the space: right drag looks, W A S D fly, arrows hop between texts", + onmounted: move |e| HOST.with(|h| *h.borrow_mut() = Some(e.data())), + onkeydown: move |e: KeyboardEvent| { + let code = e.code().to_string(); + if code.starts_with("Arrow") || code == "Space" { + e.prevent_default(); + } + room().borrow_mut().key_down(&code, mods(e.modifiers())); + }, + onkeyup: move |e: KeyboardEvent| room().borrow_mut().key_up(&e.code().to_string()), + onblur: move |_| room().borrow_mut().blur(), + onmousedown: move |e: MouseEvent| { + let (x, y) = at(&e); + room().borrow_mut().pointer_down(x, y, button(&e), mods(e.modifiers())); + }, + onmousemove: move |e: MouseEvent| { + let (x, y) = at(&e); + room().borrow_mut().pointer_move(x, y, mods(e.modifiers())); + }, + onmouseup: move |e: MouseEvent| { + let (x, y) = at(&e); + room().borrow_mut().pointer_up(x, y, button(&e), mods(e.modifiers())); + }, + onwheel: move |e: WheelEvent| { + e.prevent_default(); + let d = e.delta().strip_units(); + let (x, y) = { let p = e.element_coordinates(); (p.x as f32, p.y as f32) }; + room().borrow_mut().wheel(x, y, d.y as f32); + }, + oncontextmenu: move |e| e.prevent_default(), + if picture { + img { class: "space-frame", src: "{gpu::frame_url(frame())}", alt: "", draggable: "false" } + } + if !cfg!(feature = "desktop") { + canvas { id: "space-canvas", class: "space-frame" } + } + } + } +} diff --git a/app/src/views/space/prefabwin.rs b/app/src/views/space/prefabwin.rs new file mode 100644 index 00000000..df3eb5fb --- /dev/null +++ b/app/src/views/space/prefabwin.rs @@ -0,0 +1,518 @@ +//! The prefabs window: subassemblies (core's `graph::prefabs`, `ops::prefabs`). Pick blocks +//! in the room and group them into a prefab (their textures, turns, wirings, animations +//! and the links between them go with it); the menu shows the save's prefabs with a +//! picture of each, to place a copy ahead of you, rename or delete. A part of a copy, +//! selected, shows its copy here: move, turn and size the whole copy, take its own changes +//! back, make them the prefab's (every copy following, or the others kept as they were), +//! detach it into ordinary blocks, or remove it. A part moved, resized or retextured by +//! hand changes in its copy only. + +use std::collections::HashMap; + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use super::{Sp, Win, dress, load_blocks}; +use crate::shell::set_pref; +use crate::ui::*; + +/// the save's prefabs, and their pictures drawn by the room +/// whether an id is a prefab's copy (not one of its parts) +pub(super) fn is_copy(id: &str) -> bool { + id.starts_with("prefab:") && !id.contains('/') +} + +/// the selected copy moved or turned in the room (a drag, or an undo of one) +pub(super) fn copy_set(ui: Ui, api: Api, sp: Sp, data: Value) { + dioxus::dioxus_core::spawn_forever(async move { + match api.call("prefabs.set", data).await { + Ok(r) => { + show(ui, &api, sp, &r).await; + load_prefabs(ui, &api, sp).await; + } + Err(e) => ui.fail(e), + } + }); +} + +/// a removed copy put back (an undo) +pub(super) fn copy_restore(ui: Ui, api: Api, sp: Sp, restore: Value) { + dioxus::dioxus_core::spawn_forever(async move { + match api.call("prefabs.place", restore).await { + Ok(r) => { + show(ui, &api, sp, &r).await; + load_prefabs(ui, &api, sp).await; + sp.send(json!({ "cmd": "pickcopy", "id": r["copy"]["id"] })); + ui.say("the copy is back"); + } + Err(e) => ui.fail(e), + } + }); +} + +/// the selected copy taken away, as a whole (Ctrl+Z puts it back) +pub(super) fn copy_remove(ui: Ui, api: Api, sp: Sp, id: String) { + dioxus::dioxus_core::spawn_forever(async move { + match api.call("prefabs.remove", json!({ "id": id })).await { + Ok(r) => { + sp.send(json!({ "cmd": "copygone", "ids": r["removed"], "restore": r["restore"] })); + let mut b = sp.block; + b.set(None); + load_prefabs(ui, &api, sp).await; + ui.say("the copy is gone · Ctrl+Z puts it back"); + } + Err(e) => ui.fail(e), + } + }); +} + +/// another copy beside the selected one, with its own values +pub(super) fn copy_duplicate(ui: Ui, api: Api, sp: Sp, id: String) { + dioxus::dioxus_core::spawn_forever(async move { + match api.call("prefabs.duplicate", json!({ "id": id })).await { + Ok(r) => { + show(ui, &api, sp, &r).await; + load_prefabs(ui, &api, sp).await; + sp.send(json!({ "cmd": "pickcopy", "id": r["copy"]["id"] })); + ui.say("a copy of the copy, beside it, with its own changes"); + } + Err(e) => ui.fail(e), + } + }); +} + +pub(super) async fn load_prefabs(ui: Ui, api: &Api, sp: Sp) { + let r = match api.call("prefabs.list", json!({})).await { + Ok(r) => r, + // a hub from before prefabs + Err(_) => return, + }; + let list = r["prefabs"].as_array().cloned().unwrap_or_default(); + let textures = dress(ui, api, r["textures"].clone()).await; + let want: Vec<Value> = list + .iter() + .map(|p| json!({ "id": p["id"], "parts": p["parts"] })) + .collect(); + sp.send(json!({ "cmd": "thumbs", "prefabs": want, "textures": textures })); + let mut l = sp.prefabs; + l.set(list); + let copies = api + .call("prefabs.copies", json!({})) + .await + .ok() + .and_then(|v| v.as_array().cloned()) + .unwrap_or_default(); + sp.send(json!({ "cmd": "copies", "list": copies })); + let mut c = sp.copies; + c.set(copies); +} + +/// a new copy of a prefab where the room says (ahead of you, or at the selected text) +pub(super) fn place_at(ui: Ui, api: Api, sp: Sp, data: Value) { + dioxus::dioxus_core::spawn_forever(async move { + let args = json!({ "prefab": data["want"], "x": data["x"], "y": data["y"], "z": data["z"] }); + match api.call("prefabs.place", args).await { + Ok(r) => { + show(ui, &api, sp, &r).await; + load_prefabs(ui, &api, sp).await; + sp.send(json!({ "cmd": "pickcopy", "id": r["copy"]["id"] })); + ui.say("a copy, selected as one: drag it to move it, its rings turn it · double-click a part to edit the parts"); + } + Err(e) => ui.fail(e), + } + }); +} + +/// a copy just where the hand put it (the ghost), turned as it was +pub(super) fn place_exactly(ui: Ui, api: Api, sp: Sp, data: Value) { + dioxus::dioxus_core::spawn_forever(async move { + let args = + json!({ "prefab": data["prefab"], "x": data["x"], "y": data["y"], "z": data["z"], "rot": data["rot"] }); + match api.call("prefabs.place", args).await { + Ok(r) => { + show(ui, &api, sp, &r).await; + load_prefabs(ui, &api, sp).await; + } + Err(e) => ui.fail(e), + } + }); +} + +/// a prefab to place by hand: its ghost follows where you look +async fn ghost(ui: Ui, api: &Api, sp: Sp, p: &Value) { + let r = match api.call("prefabs.list", json!({})).await { + Ok(r) => r, + Err(e) => return ui.fail(e), + }; + let textures = dress(ui, api, r["textures"].clone()).await; + sp.send(json!({ "cmd": "ghost", "prefab": p["id"], "parts": p["parts"], "textures": textures, "name": p["name"] })); + ui.say(format!( + "placing {}: it follows where you look · the wheel turns it · click places · Shift: off the grid · Esc stops", + p["name"].as_str().unwrap_or("") + )); +} + +/// blocks an answer brings, into the room +async fn show(ui: Ui, api: &Api, sp: Sp, r: &Value) { + if r["removed"].as_array().is_some_and(|a| !a.is_empty()) { + sp.send(json!({ "cmd": "unblock", "ids": r["removed"] })); + } + if r["blocks"].as_array().is_some_and(|a| !a.is_empty()) { + let textures = dress(ui, api, r["textures"].clone()).await; + sp.send(json!({ "cmd": "blocks", "blocks": r["blocks"], "textures": textures })); + } +} + +fn short(id: &str) -> String { + // a prefab copy's part: its address inside, and which copy + if let Some((copy, inner)) = id.strip_prefix("prefab:").and_then(|r| r.split_once('/')) { + let n = copy.rsplit_once('#').map_or(copy, |x| x.1); + return format!("{} in copy {n}", short(inner)); + } + let (k, n) = id.rsplit_once('#').unwrap_or((id, "")); + let k = k.split_once(':').map_or(k, |(_, t)| t); + let k = if k.chars().count() > 14 { + format!("{}…", k.chars().take(12).collect::<String>()) + } else { + k.to_string() + }; + if n.is_empty() { k } else { format!("{k} #{n}") } +} + +#[component] +pub(super) fn Prefabs(sp: Sp) -> Element { + let ui = ui(); + let api = api(); + let mut grouping = use_signal(|| false); + let mut group: Signal<Vec<String>> = use_signal(Vec::new); + let mut name = use_signal(String::new); + let mut renaming: Signal<Option<u64>> = use_signal(|| None); + let mut rename_to = use_signal(String::new); + let mut deleting: Signal<Option<u64>> = use_signal(|| None); + let mut busy = use_signal(|| false); + + let api_l = api.clone(); + use_hook(move || { + let api = api_l.clone(); + spawn(async move { load_prefabs(ui, &api, sp).await }); + }); + + let sel = (sp.block)(); + let sel_id = sel.as_ref().and_then(|b| b["id"].as_str().map(str::to_string)); + // picking blocks to group: each one selected joins (a copy's parts can't, yet) + use_effect(use_reactive!(|sel_id| { + let Some(id) = sel_id else { return }; + if !*grouping.peek() || id.starts_with("prefab:") { + return; + } + if !group.peek().contains(&id) { + group.write().push(id); + } + })); + let copy_id = sel.as_ref().and_then(|b| b["part_of"].as_str().map(str::to_string)); + let list = (sp.prefabs)(); + let thumbs: HashMap<u64, String> = (sp.thumbs)(); + let copy = copy_id.as_ref().and_then(|c| { + let scene: u64 = c.strip_prefix("prefab:")?.split('#').next()?.parse().ok()?; + list.iter() + .find(|p| p["id"].as_u64() == Some(scene)) + .cloned() + .map(|p| (c.clone(), p)) + }); + + // an op on the selected copy; `reload`: the room reads every block again after + let api_c = api.clone(); + let on_copy = use_callback( + move |(op, args, reload, said): (&'static str, Value, bool, &'static str)| { + let api = api_c.clone(); + busy.set(true); + spawn(async move { + match api.call(op, args).await { + Ok(r) => { + if reload { + load_blocks(ui, api.clone(), sp).await; + } else { + show(ui, &api, sp, &r).await; + } + load_prefabs(ui, &api, sp).await; + super::wirewin::load_wires(&api, sp).await; + if !said.is_empty() { + ui.say(said.to_string()); + } + } + Err(e) => ui.fail(e), + } + busy.set(false); + }); + }, + ); + let api_m = api.clone(); + let make = move |_| { + let ids = group.peek().clone(); + let n = name.peek().trim().to_string(); + let api = api_m.clone(); + spawn(async move { + match api.call("prefabs.make", json!({ "name": n, "ids": ids })).await { + Ok(_) => { + group.set(Vec::new()); + grouping.set(false); + name.set(String::new()); + load_blocks(ui, api.clone(), sp).await; + load_prefabs(ui, &api, sp).await; + super::wirewin::load_wires(&api, sp).await; + ui.say("a prefab · its copy stands where the blocks were; place more from the menu".to_string()); + } + Err(e) => ui.fail(e), + } + }); + }; + + rsx! { + Win { + id: "prefabs", + at: (8.0, 160.0), + on_close: move |_| { grouping.set(false); set_pref(ui, |p| p.space.show_prefabs = false) }, + title: rsx! { + span { class: "win-title", + Icon { name: "prefab" } + "prefabs" + span { class: "dim small", style: "font-weight: 400;", "grouped blocks, placed as copies" } + } + }, + if let Some((cid, p)) = copy.clone() { + { + let c = cid.clone(); + let own = (sp.copies)().iter().find(|x| x["id"].as_str() == Some(c.as_str())).and_then(|x| x["own"].as_u64()).unwrap_or(0); + let pname = p["name"].as_str().unwrap_or("").to_string(); + let copies = p["copies"].as_u64().unwrap_or(1); + let mv = |by: [f64; 3]| { let c = c.clone(); move |_| on_copy.call(("prefabs.set", json!({ "id": c, "by": by }), false, "")) }; + rsx! { + div { class: "wire-sec pf-copy", + span { class: "small", "the selected part's copy of " b { "{pname}" } } + div { class: "row wrap", + span { class: "small", "move" } + button { class: "btn small", title: "along −x", onclick: mv([-1.0, 0.0, 0.0]), "←" } + button { class: "btn small", title: "along +x", onclick: mv([1.0, 0.0, 0.0]), "→" } + button { class: "btn small", title: "along −z (away)", onclick: mv([0.0, 0.0, -1.0]), "↑" } + button { class: "btn small", title: "along +z (near)", onclick: mv([0.0, 0.0, 1.0]), "↓" } + button { class: "btn small", title: "up", onclick: mv([0.0, 1.0, 0.0]), "up" } + button { class: "btn small", title: "down", onclick: mv([0.0, -1.0, 0.0]), "down" } + } + div { class: "row wrap", + span { class: "small", "turn" } + button { class: "btn small", title: "a quarter turn to the left", onclick: { let c = c.clone(); move |_| on_copy.call(("prefabs.set", json!({ "id": c, "turn": 1 }), false, "")) }, "⟲" } + button { class: "btn small", title: "a quarter turn to the right", onclick: { let c = c.clone(); move |_| on_copy.call(("prefabs.set", json!({ "id": c, "turn": -1 }), false, "")) }, "⟳" } + span { class: "small", "size" } + { + let sc = (sp.copies)().iter().find(|x| x["id"].as_str() == Some(c.as_str())).and_then(|x| x["scale"].as_f64()).unwrap_or(1.0); + let (c1, c2) = (c.clone(), c.clone()); + rsx! { + button { class: "btn small", onclick: move |_| on_copy.call(("prefabs.set", json!({ "id": c1, "scale": sc / 1.25 }), false, "")), "−" } + span { class: "dim small", {format!("×{sc:.2}")} } + button { class: "btn small", onclick: move |_| on_copy.call(("prefabs.set", json!({ "id": c2, "scale": sc * 1.25 }), false, "")), "+" } + } + } + } + if own > 0 { + span { class: "small", {format!("its own changes to {own} part{} (moved, resized, retextured or rewired here)", if own == 1 { "" } else { "s" })} } + div { class: "row wrap", + button { class: "btn small", title: "it shows the prefab as it is again", + onclick: { let c = c.clone(); move |_| on_copy.call(("prefabs.reset", json!({ "id": c }), true, "back to the prefab")) }, "take them back" } + button { class: "btn small", disabled: busy(), title: "the prefab becomes this copy; every copy shows it", + onclick: { let c = c.clone(); move |_| on_copy.call(("prefabs.apply", json!({ "id": c, "others": true }), true, "the prefab changed; every copy follows")) }, "make them the prefab's" } + if copies > 1 { + button { class: "btn small", disabled: busy(), title: "the prefab becomes this copy; the other copies keep it as it was (a prefab of its own)", + onclick: { let c = c.clone(); move |_| on_copy.call(("prefabs.apply", json!({ "id": c, "others": false }), true, "the prefab changed; the other copies kept it as it was")) }, "…but not the other copies" } + } + } + } + div { class: "row wrap", + button { class: "btn small", title: "its parts become ordinary blocks; it stops following the prefab", + onclick: { let c = c.clone(); move |_| on_copy.call(("prefabs.detach", json!({ "id": c }), true, "detached: ordinary blocks now")) }, "detach" } + button { class: "btn small", + onclick: { let c = c.clone(); move |_| on_copy.call(("prefabs.remove", json!({ "id": c }), false, "copy removed")) }, "remove this copy" } + } + } + } + } + } + div { class: "wire-sec", + span { class: "small", "group blocks into a prefab" } + div { class: "row wrap", + button { class: if grouping() { "btn small primary" } else { "btn small" }, + onclick: move |_| { + let now = grouping(); + grouping.set(!now); + // the selected block (if any) starts the group + if !now + && let Some(id) = (sp.block)().and_then(|b| b["id"].as_str().map(str::to_string)).filter(|i| !i.starts_with("prefab:")) + && !group.peek().contains(&id) + { + group.write().push(id); + } + }, + if grouping() { "done picking" } else { "pick blocks in the room" } + } + if !group().is_empty() { + button { class: "btn small", onclick: move |_| group.set(Vec::new()), "clear" } + } + } + if grouping() { + p { class: "dim small", "Click the blocks to group; each one joins." } + } + div { class: "wire-targets", + for t in group() { + { + let t2 = t.clone(); + rsx! { + span { key: "{t}", class: "chip small", {short(&t)} + button { class: "plain", "aria-label": "leave it out", onclick: move |_| group.write().retain(|x| x != &t2), "×" } + } + } + } + } + } + if !group().is_empty() { + div { class: "row", + input { r#type: "text", placeholder: "its name", value: "{name}", "aria-label": "the prefab's name", + oninput: move |e: FormEvent| name.set(e.value()) } + button { class: "btn small primary", disabled: name().trim().is_empty(), onclick: make, "make it" } + } + } + } + div { class: "wire-sec", + span { class: "small", if list.is_empty() { "no prefabs yet" } else { "the menu: place a copy ahead of you" } } + button { class: "btn small", + title: "a switch, AND, OR, XOR and NOT gates, a latch, a lamp and a door, run by s programs (notes tagged s); placed in a row at one height, each one's ray reaches the next", + onclick: { + let api = api.clone(); + move |_| { + let api = api.clone(); + spawn(async move { + match api.call("prefabs.starters", json!({})).await { + Ok(r) => { + load_prefabs(ui, &api, sp).await; + let n = r["prefabs"].as_array().map_or(0, |a| a.len()); + ui.say(if n == 0 { "the starters are here already".to_string() } else { format!("{n} starter prefabs · place them in a row at one height, then play: click a switch") }); + } + Err(e) => ui.fail(e), + } + }); + } + }, + "add the starters: switch, gates, lamp, door" + } + div { class: "pf-grid", + for p in list.iter() { + { + let id = p["id"].as_u64().unwrap_or(0); + let pname = p["name"].as_str().unwrap_or("").to_string(); + let n = p["copies"].as_u64().unwrap_or(0); + let parts = p["parts"].as_array().map_or(0, |a| a.len()); + let src = thumbs.get(&id).cloned(); + let api_r = api.clone(); + let api_d = api.clone(); + rsx! { + div { key: "{id}", class: "pf-card", + button { class: "pf-thumb", title: "place a copy of {pname} ahead of you", + onclick: move |_| sp.send(json!({ "cmd": "prefabspot", "want": id })), + if let Some(s) = src { img { src: "{s}", alt: "{pname}" } } else { Icon { name: "cube" } } + } + if renaming() == Some(id) { + input { r#type: "text", value: "{rename_to}", "aria-label": "its new name", + oninput: move |e: FormEvent| rename_to.set(e.value()), + onkeydown: move |e: KeyboardEvent| { + if e.key() == Key::Enter { + let api = api_r.clone(); + let to = rename_to.peek().clone(); + renaming.set(None); + spawn(async move { + match api.call("prefabs.rename", json!({ "prefab": id, "name": to })).await { + Ok(_) => load_prefabs(ui, &api, sp).await, + Err(e) => ui.fail(e), + } + }); + } else if e.key() == Key::Escape { renaming.set(None); } + } + } + } else { + b { class: "small", ondoubleclick: { let pn = pname.clone(); move |_| { rename_to.set(pn.clone()); renaming.set(Some(id)); } }, title: "double click to rename", "{pname}" } + } + span { class: "dim small", {format!("{parts} block{} · {n} cop{}", if parts == 1 { "" } else { "s" }, if n == 1 { "y" } else { "ies" })} } + div { class: "row wrap", + button { class: "btn small", onclick: move |_| sp.send(json!({ "cmd": "prefabspot", "want": id })), "place" } + button { class: "btn small", title: "place copies by hand: the prefab follows where you look, flying or walking; the wheel turns it, a click places it, Esc stops", + onclick: { let api = api.clone(); let p = p.clone(); move |_| { let api = api.clone(); let p = p.clone(); spawn(async move { ghost(ui, &api, sp, &p).await }); } }, + "by hand" + } + button { class: if deleting() == Some(id) { "btn small primary" } else { "btn small" }, + onclick: move |_| { + if deleting() != Some(id) { deleting.set(Some(id)); return; } + deleting.set(None); + let api = api_d.clone(); + spawn(async move { + match api.call("prefabs.delete", json!({ "prefab": id })).await { + Ok(r) => { + sp.send(json!({ "cmd": "unblock", "ids": r["removed"] })); + load_prefabs(ui, &api, sp).await; + super::wirewin::load_wires(&api, sp).await; + } + Err(e) => ui.fail(e), + } + }); + }, + if deleting() == Some(id) { if n > 0 { "and its copies?" } else { "sure?" } } else { "delete" } + } + } + } + } + } + } + } + } + } + } +} + +/// a copy's menu (a right click on it): it's one group +#[component] +pub(super) fn CopyMenu(c: Value, x: f64, y: f64, sp: Sp) -> Element { + let ui = ui(); + let api = api(); + let mut menu = sp.bmenu; + let mut close = move || menu.set(None); + let id = c["id"].as_str().unwrap_or("").to_string(); + let name = c["name"].as_str().unwrap_or("a prefab").to_string(); + let (a1, a2, a3, a4) = (api.clone(), api.clone(), api.clone(), api.clone()); + let (i1, i2, i3, i4, i5) = (id.clone(), id.clone(), id.clone(), id.clone(), id.clone()); + rsx! { + div { class: "backdrop", onclick: move |_| close(), oncontextmenu: move |e| { e.prevent_default(); close() } } + div { class: "menu smenu", role: "menu", + style: "left: min({x}px, calc(100vw - 330px)); top: max(8px, min({y}px, calc(100vh - 300px)));", + div { class: "title", "a copy of {name}" } + div { class: "title dim small", "one group: it moves, turns, copies and goes as a whole" } + button { role: "menuitem", onclick: move |_| { sp.send(json!({ "cmd": "opencopy", "id": i1 })); close(); }, + Icon { name: "edit" } "open it to edit its parts" kbd { "double-click" } } + button { role: "menuitem", onclick: move |_| { copy_set(ui, a1.clone(), sp, json!({ "id": i2, "turn": 1 })); close(); }, + Icon { name: "refresh" } "a quarter turn about the upright" } + button { role: "menuitem", onclick: move |_| { copy_duplicate(ui, a2.clone(), sp, i3.clone()); close(); }, + Icon { name: "copy" } "a copy beside it" } + button { role: "menuitem", onclick: move |_| { set_pref(ui, |p| p.space.show_prefabs = true); close(); }, + Icon { name: "prefab" } "its prefab…" span { class: "dim small", " (the prefabs window: size, own changes)" } } + button { role: "menuitem", + onclick: move |_| { + let (api, id) = (a3.clone(), i4.clone()); + spawn(async move { + match api.call("prefabs.detach", json!({ "id": id })).await { + Ok(r) => { show(ui, &api, sp, &r).await; load_prefabs(ui, &api, sp).await; ui.say("detached: ordinary blocks now"); } + Err(e) => ui.fail(e), + } + }); + close(); + }, + Icon { name: "cube" } "detach it into blocks" } + button { role: "menuitem", onclick: move |_| { copy_remove(ui, a4.clone(), sp, i5.clone()); close(); }, + Icon { name: "delete" } "remove it" kbd { "{ui.key_of(crate::keys::Action::DeleteText)}" } } + } + } +} diff --git a/app/src/views/space/soundwin.rs b/app/src/views/space/soundwin.rs new file mode 100644 index 00000000..2e9d4ee3 --- /dev/null +++ b/app/src/views/space/soundwin.rs @@ -0,0 +1,226 @@ +//! The sounds window: the save's sounds (core's `graph::sounds`, `ops::sounds`) and the +//! selected block's emitter. Add sound files (WAV, OGG, MP3, FLAC, WebM or M4A), hear one +//! with ▶, rename (a double click) or delete one. The selected block plays a sound of +//! the save: how loud, how far it carries (it fades to nothing there), and whether it +//! loops. While the room plays (the wiring window's ▶ play), looping sounds play from the +//! start and the others when a program prints `sound`; each is heard from where it is. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use super::{Sp, Win, dress}; +use crate::shell::set_pref; +use crate::ui::*; + +#[component] +pub(super) fn Sounds(sp: Sp) -> Element { + let ui = ui(); + let api = api(); + let mut list: Signal<Vec<Value>> = use_signal(Vec::new); + let mut rev = use_signal(|| 0u64); + let mut busy = use_signal(|| 0usize); + let mut renaming: Signal<Option<String>> = use_signal(|| None); + let mut rename_to = use_signal(String::new); + let mut deleting: Signal<Option<String>> = use_signal(|| None); + + let api_l = api.clone(); + use_effect(move || { + let _ = rev(); + let api = api_l.clone(); + spawn(async move { + if let Ok(v) = api.call("sounds.list", json!({})).await { + list.set(v.as_array().cloned().unwrap_or_default()); + } + }); + }); + + let take = { + let api = api.clone(); + move |files: Vec<dioxus::html::FileData>| { + let api = api.clone(); + async move { + for f in files { + busy += 1; + let name = f.name(); + match f.read_bytes().await { + Ok(b) => match api + .call( + "sounds.add", + json!({ "data": anend_core::classifiers::base64(&b), "name": name }), + ) + .await + { + Ok(v) => ui.say(if v["new"] == true { + format!("{name} is in") + } else { + format!("the save had {name} already") + }), + Err(e) => ui.fail(format!("{name}: {e}")), + }, + Err(e) => ui.fail(format!("couldn't read {name}: {e}")), + } + busy -= 1; + } + rev += 1; + } + } + }; + + let block = (sp.block)().filter(|b| b["copy"] != true); + let bid = block.as_ref().and_then(|b| b["id"].as_str().map(str::to_string)); + let em = block.as_ref().map(|b| b["sound"].clone()).unwrap_or(Value::Null); + // the selected block's emitter changed: kept, and the room shows it + let api_s = api.clone(); + let set_sound = move |v: Value| { + let Some(id) = bid.clone() else { return }; + let api = api_s.clone(); + spawn(async move { + match api.call("blocks.set", json!({ "id": id, "sound": v })).await { + Ok(r) => { + let textures = dress(ui, &api, r["textures"].clone()).await; + sp.send(json!({ "cmd": "blocks", "blocks": r["blocks"], "textures": textures })); + if let Some(b) = r["blocks"].as_array().and_then(|a| a.first()) { + let mut s = sp.block; + let mut v = b.clone(); + if let Some(old) = s.peek().as_ref() { + v["about"] = old["about"].clone(); + } + s.set(Some(v)); + } + } + Err(e) => ui.fail(e), + } + }); + }; + let sounds = list(); + let field = |k: &str, d: f64| em.get(k).and_then(Value::as_f64).unwrap_or(d); + let (vol, range, looped) = (field("volume", 1.0), field("range", 20.0), em["loop"] == true); + let cur = em["id"].as_str().map(str::to_string); + + rsx! { + Win { + id: "sounds", + at: (8.0, 180.0), + on_close: move |_| set_pref(ui, |p| p.space.show_sounds = false), + title: rsx! { + span { class: "win-title", + Icon { name: "sound" } + "sounds" + span { class: "dim small", style: "font-weight: 400;", "emitters in the room" } + } + }, + if let Some(id) = block.as_ref().and_then(|b| b["id"].as_str()) { + div { class: "wire-sec", + span { class: "small", "the selected block " b { {id.rsplit_once('/').map_or(id, |x| x.1).to_string()} } " plays" } + select { "aria-label": "the sound it plays", + onchange: { + let set_sound = set_sound.clone(); + move |e: FormEvent| { + let v = e.value(); + set_sound(if v.is_empty() { Value::Null } else { json!({ "id": v, "volume": vol, "range": range, "loop": looped }) }); + } + }, + option { value: "", selected: cur.is_none(), "no sound" } + for s in sounds.iter() { + { + let sid = s["id"].as_str().unwrap_or("").to_string(); + let name = s["name"].as_str().filter(|n| !n.is_empty()).unwrap_or(&sid[..8.min(sid.len())]).to_string(); + rsx! { option { key: "{sid}", value: "{sid}", selected: cur.as_deref() == Some(sid.as_str()), "{name}" } } + } + } + } + if let Some(c) = cur.clone() { + label { class: "lt-slider", span { "volume" } + input { r#type: "range", min: "0", max: "200", value: "{(vol * 100.0).round()}", + onchange: { let set_sound = set_sound.clone(); let c = c.clone(); move |e: FormEvent| { let v = e.value().parse::<f64>().unwrap_or(100.0) / 100.0; set_sound(json!({ "id": c, "volume": v, "range": range, "loop": looped })); } } + } + span { class: "dim small", {format!("{:.0}%", vol * 100.0)} } + } + label { class: "lt-slider", span { "reach" } + input { r#type: "range", min: "1", max: "200", value: "{range.round()}", + onchange: { let set_sound = set_sound.clone(); let c = c.clone(); move |e: FormEvent| { let v = e.value().parse::<f64>().unwrap_or(20.0); set_sound(json!({ "id": c, "volume": vol, "range": v, "loop": looped })); } } + } + span { class: "dim small", {format!("{range:.0}")} } + } + label { class: "check small", + input { r#type: "checkbox", checked: looped, + onchange: { let set_sound = set_sound.clone(); let c = c.clone(); move |e: FormEvent| set_sound(json!({ "id": c, "volume": vol, "range": range, "loop": e.checked() })) } + } + "loops (plays from the start while the room plays)" + } + p { class: "dim small", "Not looping, it plays when a program prints sound (and stops at hush), while the room plays." } + } + } + } else { + p { class: "dim small", "Select a block to make it a sound emitter." } + } + div { class: "wire-sec", + div { class: "row", + span { class: "small", if sounds.is_empty() { "no sounds yet" } else { "the save's sounds" } } + span { class: "grow" } + if busy() > 0 { span { class: "dim small", "adding…" } } + label { class: "button btn small", "data-tip": "WAV, OGG, MP3, FLAC, WebM or M4A files", + Icon { name: "upload" } "add sounds" + input { r#type: "file", accept: "audio/*,.wav,.ogg,.mp3,.flac,.webm,.m4a", multiple: true, style: "display: none;", + "aria-label": "sounds to add", + onchange: move |e: FormEvent| { let take = take.clone(); async move { take(e.files()).await } }, + } + } + } + for s in sounds.iter() { + { + let sid = s["id"].as_str().unwrap_or("").to_string(); + let name = s["name"].as_str().unwrap_or("").to_string(); + let secs = s["seconds"].as_f64().map(|x| format!("{x:.1} s · ")).unwrap_or_default(); + let kb = s["size"].as_u64().unwrap_or(0).div_ceil(1024); + let mime = s["mime"].as_str().unwrap_or("").trim_start_matches("audio/").to_string(); + let (s1, s2, s3, s4) = (sid.clone(), sid.clone(), sid.clone(), sid.clone()); + let (api_r, api_d) = (api.clone(), api.clone()); + rsx! { + div { key: "{sid}", class: "row snd-row", + button { class: "btn small", title: "hear it", "aria-label": "hear {name}", onclick: move |_| sp.send(json!({ "cmd": "soundpreview", "id": s1 })), "▶" } + if renaming().as_deref() == Some(sid.as_str()) { + input { r#type: "text", value: "{rename_to}", "aria-label": "its new name", + oninput: move |e: FormEvent| rename_to.set(e.value()), + onkeydown: move |e: KeyboardEvent| { + if e.key() == Key::Enter { + let (api, id, to) = (api_r.clone(), s2.clone(), rename_to.peek().clone()); + renaming.set(None); + spawn(async move { + match api.call("sounds.name", json!({ "id": id, "name": to })).await { + Ok(_) => rev += 1, + Err(e) => ui.fail(e), + } + }); + } else if e.key() == Key::Escape { renaming.set(None); } + } + } + } else { + span { class: "grow snd-name", title: "double click to rename", + ondoubleclick: { let n = name.clone(); move |_| { rename_to.set(n.clone()); renaming.set(Some(s3.clone())); } }, + b { class: "small", if name.is_empty() { "(no name)" } else { "{name}" } } + span { class: "dim small", " {secs}{mime} · {kb} KB" } + } + } + button { class: if deleting().as_deref() == Some(sid.as_str()) { "btn small primary" } else { "btn small" }, + onclick: move |_| { + if deleting().as_deref() != Some(s4.as_str()) { deleting.set(Some(s4.clone())); return; } + deleting.set(None); + let (api, id) = (api_d.clone(), s4.clone()); + spawn(async move { + match api.call("sounds.delete", json!({ "id": id })).await { + Ok(_) => rev += 1, + Err(e) => ui.fail(e), + } + }); + }, + if deleting().as_deref() == Some(sid.as_str()) { "sure?" } else { "delete" } + } + } + } + } + } + } + } + } +} diff --git a/app/src/views/space/texwin.rs b/app/src/views/space/texwin.rs new file mode 100644 index 00000000..418435ac --- /dev/null +++ b/app/src/views/space/texwin.rs @@ -0,0 +1,683 @@ +//! The textures window: texture recipes (core's `graph::textures`) built step by step, as a +//! pipeline from a source to where it's used, each step with a preview drawn by the room +//! itself (`space.js` `preview`), so what the window shows is what blocks show. +//! +//! Source (a picture of the save, the selected text, or a colour) → crop (drag a box on the +//! source) → tile (its size in units, its offset, a quarter turn, a mirror, a tint) → +//! variants (how many, shuffled by a seed) → use (on the selected block, on one of its +//! faces, as the sky, on a new block). Recipes are kept by their content hash, so making +//! the same one twice keeps one; the saved ones are listed at the top to pick up again. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use super::{Previews, SpaceEvent, Win, add_block_from, dress, native_space}; +use crate::gem::{self, Mode}; +use crate::shell::set_pref; +use crate::ui::*; + +/// a preview the room draws: into a canvas (space.js), or as a picture the native room +/// drew (its PNG, by the canvas's id) +#[component] +fn Preview(id: String, w: f64, h: f64, class: Option<String>, onclick: Option<EventHandler<MouseEvent>>) -> Element { + let class = class.unwrap_or_default(); + let click = move |e: MouseEvent| { + if let Some(f) = onclick { + f.call(e); + } + }; + if native_space() { + let src = try_use_context::<Previews>() + .and_then(|p| p.0.read().get(&id).cloned()) + .unwrap_or_default(); + rsx! { img { id: "{id}", class: "{class}", src: "{src}", width: "{w.round()}", height: "{h.round()}", alt: "", onclick: click } } + } else { + rsx! { canvas { id: "{id}", class: "{class}", width: "{w.round()}", height: "{h.round()}", onclick: click } } + } +} + +/// the source's shape on screen (a picture's, 240 pixels on its longer side) +fn source_px(src: &Value, pics: &[(String, String, u64, u64)]) -> (f64, f64) { + match src["picture"].as_str().and_then(|p| pics.iter().find(|x| x.0 == p)) { + Some((_, _, w, h)) => { + let (w, h) = (*w as f64, *h as f64); + if w >= h { + (240.0, (240.0 * h / w).max(40.0)) + } else { + ((240.0 * w / h).max(40.0), 240.0) + } + } + None => (240.0, 240.0), + } +} + +/// a fresh recipe: a colour, one unit a tile +fn blank() -> Value { + json!({ + "source": { "plain": "#b49a6c" }, + "crop": [0.0, 0.0, 1.0, 1.0], + "scale": [1.0, 1.0], + "offset": [0.0, 0.0], + "turn": 0, + "mirror": false, + "tint": "#000000", + "tint_amount": 0.0, + "variants": 1, + "seed": 0, + "turn_variants": false, + }) +} + +/// a recipe with every field there (one from the save may leave defaults out) +fn filled(r: &Value) -> Value { + let mut out = blank(); + if let Some(o) = r.as_object() { + for (k, v) in o { + if !v.is_null() { + out[k] = v.clone(); + } + } + } + out +} + +fn f(v: &Value, i: usize) -> f64 { + v.get(i).and_then(Value::as_f64).unwrap_or(0.0) +} + +/// a tile's side on a slider: 0–100 for 0.1 to 10 units, evenly in log +fn side_to_slider(v: f64) -> f64 { + ((v.clamp(0.1, 10.0) / 0.1).ln() / 100f64.ln() * 100.0).round() +} +fn slider_to_side(s: f64) -> f64 { + let v = 0.1 * 100f64.powf(s / 100.0); + (v * 100.0).round() / 100.0 +} + +/// what a recipe's source is, in words +fn source_words(r: &Value, pictures: &[(String, String, u64, u64)], text: &str) -> String { + let s = &r["source"]; + if let Some(c) = s["plain"].as_str() { + format!("the colour {c}") + } else if let Some(p) = s["picture"].as_str() { + let name = pictures + .iter() + .find(|x| x.0 == p) + .map(|x| x.1.clone()) + .unwrap_or_else(|| p[..8.min(p.len())].to_string()); + format!("the picture {name}") + } else if s["text"].is_string() { + format!("the text “{}”", text.chars().take(40).collect::<String>()) + } else { + "nothing yet".into() + } +} + +#[component] +pub(super) fn Textures( + selected: Option<SpaceEvent>, + block: Option<Value>, + on_send: EventHandler<Value>, + on_changed: EventHandler<()>, +) -> Element { + let ui = ui(); + let api = api(); + // the saved recipes, dressed for drawing + let mut saved: Signal<Vec<Value>> = use_signal(Vec::new); + let mut rev = use_signal(|| 0u64); + // pictures: id, name, width, height + let mut pictures: Signal<Vec<(String, String, u64, u64)>> = use_signal(Vec::new); + // the recipe being made, its name, and what its source draws from (a picture's + // thumbnail, a text) + let mut recipe = use_signal(blank); + let mut name = use_signal(String::new); + let src_url = use_signal(String::new); + let mut src_text = use_signal(String::new); + let mut sky = use_signal(String::new); + let mut armed: Signal<Option<String>> = use_signal(|| None); + // a crop being dragged: where it started, as fractions of the source + let mut crop_from: Signal<Option<(f64, f64)>> = use_signal(|| None); + + let api_l = api.clone(); + use_effect(move || { + let _ = rev(); + let api = api_l.clone(); + spawn(async move { + if let Ok(v) = api.call("textures.list", json!({})).await { + let mut all = Vec::new(); + for t in v.as_array().into_iter().flatten() { + let id = t["id"].as_str().unwrap_or("").to_string(); + let dressed = dress(ui, &api, json!({ format!("texture:{id}"): t })).await; + all.push(dressed[format!("texture:{id}")].clone()); + } + saved.set(all); + } + if let Ok(v) = api.call("settings.get", json!({ "name": "space.sky" })).await { + sky.set(v["value"].as_str().unwrap_or("").to_string()); + } + }); + }); + let api_p = api.clone(); + use_hook(move || { + let api = api_p.clone(); + spawn(async move { + if let Ok(v) = api.call("pictures.list", json!({})).await { + let all = v + .as_array() + .into_iter() + .flatten() + .map(|p| { + let id = p["id"].as_str().unwrap_or("").to_string(); + let name = p["name"] + .as_str() + .filter(|n| !n.is_empty()) + .unwrap_or(&id[..id.len().min(8)]) + .to_string(); + ( + id, + name, + p["width"].as_u64().unwrap_or(1), + p["height"].as_u64().unwrap_or(1), + ) + }) + .collect(); + pictures.set(all); + } + }); + }); + + // what the room needs to draw the recipe being made + let about_now = move || { + let r = recipe(); + let mut a = json!({ "recipe": r }); + if r["source"]["picture"].is_string() { + a["src"] = json!(src_url()); + } + if r["source"]["text"].is_string() { + let t = src_text(); + a["colour"] = json!(gem::underline(&t, Mode::Ordinal)); + a["text"] = json!(t); + } + a + }; + // the previews: the whole source (to crop), one tile, a patch of two by two units + // with the variants, and each saved recipe + use_effect(move || { + let a = about_now(); + let mut whole = a.clone(); + whole["recipe"] = json!({ "source": a["recipe"]["source"], "crop": [0, 0, 1, 1] }); + let (w, h) = source_px(&a["recipe"]["source"], &pictures()); + on_send.call( + json!({ "cmd": "preview", "id": "tx-source", "about": whole, "tiles": 1, "w": w.round(), "h": h.round() }), + ); + on_send.call(json!({ "cmd": "preview", "id": "tx-tile", "about": a, "tiles": 1 })); + // one variant: two by two units of it; more: a tile of each, side by side + let sw = f(&a["recipe"]["scale"], 0).max(0.05); + let n = a["recipe"]["variants"].as_u64().unwrap_or(1); + let across = if n > 1 { + (n as f64).sqrt().ceil() + } else { + (2.0 / sw).round().clamp(1.0, 24.0) + }; + on_send.call(json!({ "cmd": "preview", "id": "tx-patch", "about": a, "tiles": across, "variants": n > 1 })); + }); + use_effect(move || { + for t in saved() { + let id = t["id"].as_str().unwrap_or("").to_string(); + on_send.call(json!({ "cmd": "preview", "id": format!("tx-saved-{id}"), "about": t, "tiles": 2 })); + } + }); + + let set = move |k: &str, v: Value| { + let mut recipe = recipe; + let mut r = recipe.write(); + r[k] = v; + }; + let set_at = move |k: &str, i: usize, v: f64| { + let mut recipe = recipe; + let mut r = recipe.write(); + r[k][i] = json!(v); + }; + // a picture as the source: its thumbnail fetched for drawing + let api_s = api.clone(); + let use_picture = move |id: String| { + let api = api_s.clone(); + let (mut recipe, mut src_url) = (recipe, src_url); + recipe.write()["source"] = json!({ "picture": id.clone() }); + recipe.write()["crop"] = json!([0.0, 0.0, 1.0, 1.0]); + spawn(async move { + if let Ok(p) = api.call("pictures.get", json!({ "id": id, "thumb": 512 })).await + && let Some(t) = p["thumb"].as_str() + { + src_url.set(format!("data:image/png;base64,{t}")); + } + }); + }; + let api_k = api.clone(); + // keeps the recipe and answers its id + let keep = move || { + let api = api_k.clone(); + let r = recipe(); + let n = name(); + async move { + match api.call("textures.save", json!({ "recipe": r, "name": n })).await { + Ok(t) => { + rev += 1; + Some(t["id"].as_str().unwrap_or("").to_string()) + } + Err(e) => { + ui.fail(e); + None + } + } + } + }; + + let r = recipe(); + let src = &r["source"]; + let pics = pictures(); + let block_id = block.as_ref().and_then(|b| b["id"].as_str()).map(str::to_string); + let text = selected.clone().filter(|s| !s.free && !s.key.is_empty()); + // the source's shape on screen, so the crop box is drawn over it as it is + let (sw_px, sh_px) = source_px(src, &pics); + let crop = r["crop"].clone(); + let (cl, ct, cr, cb) = (f(&crop, 0), f(&crop, 1), f(&crop, 2), f(&crop, 3)); + let scale = r["scale"].clone(); + let (tw, th) = (f(&scale, 0), f(&scale, 1)); + let offset = r["offset"].clone(); + let turn = r["turn"].as_u64().unwrap_or(0); + let variants = r["variants"].as_u64().unwrap_or(1); + let tint = r["tint"].as_str().unwrap_or("#000000").to_string(); + let tint_amount = r["tint_amount"].as_f64().unwrap_or(0.0); + let sky_now = sky(); + let words = source_words(&r, &pics, &src_text()); + let pic_shape = src["picture"] + .as_str() + .and_then(|p| pics.iter().find(|x| x.0 == p)) + .map(|x| (x.2 as f64, x.3 as f64)); + + rsx! { + Win { + id: "textures", + at: (8.0, 60.0), + on_close: move |_| set_pref(ui, |p| p.space.show_textures = false), + title: rsx! { + span { class: "win-title", + Icon { name: "image" } + "textures" + span { class: "dim small", style: "font-weight: 400;", {match saved.read().len() { 0 => "no recipes yet".to_string(), 1 => "1 recipe".to_string(), n => format!("{n} recipes") }} } + } + }, + if !saved.read().is_empty() { + div { class: "tx-saved", + for t in saved() { + { + let id = t["id"].as_str().unwrap_or("").to_string(); + let label = t["name"].as_str().filter(|n| !n.is_empty()).map(str::to_string).unwrap_or_else(|| id[..8].to_string()); + let is_sky = sky_now == id; + rsx! { + div { key: "{id}", class: "tx-item", title: "{label}: open it to change or use it", + Preview { id: "tx-saved-{id}", w: 56.0, h: 56.0, + onclick: { + let t = t.clone(); + let use_picture = use_picture.clone(); + move |_| { + recipe.set(filled(&t["recipe"])); + name.set(t["name"].as_str().unwrap_or("").to_string()); + src_text.set(t["text"].as_str().unwrap_or("").to_string()); + if let Some(p) = t["recipe"]["source"]["picture"].as_str() { + let crop = t["recipe"]["crop"].clone(); + use_picture(p.to_string()); + recipe.write()["crop"] = crop; + } + } + }, + } + span { class: "small", if is_sky { "☁ " } "{label}" } + button { + class: if armed() == Some(id.clone()) { "armed small" } else { "plain small" }, + title: "delete the recipe (blocks showing it draw grey)", + onclick: { + let id = id.clone(); + let api = api.clone(); + move |_| { + if armed() == Some(id.clone()) { + armed.set(None); + let (api, id) = (api.clone(), id.clone()); + spawn(async move { + match api.call("textures.delete", json!({ "id": id })).await { + Ok(_) => { rev += 1; ui.say("recipe deleted"); } + Err(e) => ui.fail(e), + } + }); + } else { + armed.set(Some(id.clone())); + } + } + }, + Icon { name: "delete" } + } + } + } + } + } + } + } + div { class: "tx-steps", + // 1. the source + div { class: "tx-step", + div { class: "tx-step-head", span { class: "tx-n", "1" } b { "source" } span { class: "dim small", "{words}" } } + div { class: "row wrap", + if !pics.is_empty() { + select { + "aria-label": "a picture", + onchange: { let use_picture = use_picture.clone(); move |e: FormEvent| { let v = e.value(); if !v.is_empty() { use_picture(v) } } }, + option { value: "", selected: !src["picture"].is_string(), "a picture…" } + for (id , n , _ , _) in pics.iter() { + option { key: "{id}", value: "{id}", selected: src["picture"].as_str() == Some(id.as_str()), "{n}" } + } + } + } + button { class: "btn small", disabled: text.is_none(), title: "the text selected in the room, drawn as a text block draws it", + onclick: { + let text = text.clone(); + move |_| if let Some(t) = &text { + recipe.write()["source"] = json!({ "text": t.key.clone() }); + recipe.write()["crop"] = json!([0.0, 0.0, 1.0, 1.0]); + src_text.set(t.text.clone()); + } + }, + Icon { name: "text" } "the selected text" } + label { class: "row", title: "a plain colour", + input { r#type: "color", value: src["plain"].as_str().unwrap_or("#b49a6c"), + oninput: move |e| { recipe.write()["source"] = json!({ "plain": e.value() }); } } + span { class: "small", "colour" } + } + } + } + div { class: "tx-arrow", "↓" } + // 2. the crop + div { class: "tx-step", + div { class: "tx-step-head", span { class: "tx-n", "2" } b { "crop" } + span { class: "dim small", + if src["plain"].is_string() { "a colour has nothing to crop" } else { "drag a box over the part to use" } + } + } + div { class: "tx-crop", hidden: src["plain"].is_string(), style: "width: {sw_px}px; height: {sh_px}px;", + Preview { id: "tx-source", w: sw_px, h: sh_px } + div { class: "tx-cropbox", style: "left: {cl * 100.0}%; top: {ct * 100.0}%; width: {(cr - cl) * 100.0}%; height: {(cb - ct) * 100.0}%;" } + div { class: "tx-crop-grip", + onpointerdown: move |e| { + if recipe.peek()["source"]["plain"].is_string() { return; } + e.prevent_default(); + let o = e.element_coordinates(); + let (x, y) = ((o.x / sw_px).clamp(0.0, 1.0), (o.y / sh_px).clamp(0.0, 1.0)); + crop_from.set(Some((x, y))); + recipe.write()["crop"] = json!([x, y, (x + 0.01).min(1.0), (y + 0.01).min(1.0)]); + }, + onpointermove: move |e| { + if let Some((x0, y0)) = crop_from() { + let o = e.element_coordinates(); + let (x, y) = ((o.x / sw_px).clamp(0.0, 1.0), (o.y / sh_px).clamp(0.0, 1.0)); + let r4 = |v: f64| (v * 1000.0).round() / 1000.0; + recipe.write()["crop"] = json!([r4(x0.min(x)), r4(y0.min(y)), r4(x0.max(x)), r4(y0.max(y))]); + } + }, + onpointerup: move |_| crop_from.set(None), + onpointerleave: move |_| crop_from.set(None), + } + } + div { class: "row", + span { class: "dim small", {format!("{:.0}% × {:.0}% of it", (cr - cl) * 100.0, (cb - ct) * 100.0)} } + button { class: "plain small", onclick: move |_| set("crop", json!([0.0, 0.0, 1.0, 1.0])), "all of it" } + } + } + div { class: "tx-arrow", "↓" } + // 3. the tile + div { class: "tx-step", + div { class: "tx-step-head", span { class: "tx-n", "3" } b { "tile" } span { class: "dim small", {format!("{tw:.2} × {th:.2} units")} } } + div { class: "tx-tile-row", + Preview { id: "tx-tile", w: 96.0, h: 96.0 } + div { class: "tx-sliders", + label { span { "width" } input { r#type: "range", min: "0", max: "100", step: "1", value: "{side_to_slider(tw)}", oninput: move |e| set_at("scale", 0, slider_to_side(e.value().parse().unwrap_or(50.0))) } } + label { span { "height" } input { r#type: "range", min: "0", max: "100", step: "1", value: "{side_to_slider(th)}", oninput: move |e| set_at("scale", 1, slider_to_side(e.value().parse().unwrap_or(50.0))) } } + label { span { "across" } input { r#type: "range", min: "0", max: "1", step: "0.01", value: "{f(&offset, 0)}", oninput: move |e| set_at("offset", 0, e.value().parse().unwrap_or(0.0)) } } + label { span { "down" } input { r#type: "range", min: "0", max: "1", step: "0.01", value: "{f(&offset, 1)}", oninput: move |e| set_at("offset", 1, e.value().parse().unwrap_or(0.0)) } } + } + } + div { class: "row wrap", + for (q , label) in [(0u64, "0°"), (1, "90°"), (2, "180°"), (3, "270°")] { + button { key: "{q}", class: if turn == q { "btn small on" } else { "plain small" }, title: "turn the tile", onclick: move |_| set("turn", json!(q)), "{label}" } + } + label { class: "row small", input { r#type: "checkbox", checked: r["mirror"].as_bool().unwrap_or(false), oninput: move |e| set("mirror", json!(e.checked())) } "mirror" } + } + div { class: "row wrap", + if let Some((pw, ph)) = pic_shape { + button { class: "plain small", title: "the tile's height from its width, so the crop keeps its shape", + onclick: move |_| { + let r = recipe.peek().clone(); + let (cw, ch) = ((f(&r["crop"], 2) - f(&r["crop"], 0)) * pw, (f(&r["crop"], 3) - f(&r["crop"], 1)) * ph); + let w = f(&r["scale"], 0); + if cw > 0.0 { set_at("scale", 1, ((w * ch / cw) * 100.0).round() / 100.0) } + }, + "keep the crop's shape" } + } + span { class: "small", "tint" } + input { r#type: "color", value: "{tint}", "aria-label": "the tint", oninput: move |e| set("tint", json!(e.value())) } + input { r#type: "range", min: "0", max: "1", step: "0.01", value: "{tint_amount}", "aria-label": "how strong the tint is", oninput: move |e| set("tint_amount", json!(e.value().parse::<f64>().unwrap_or(0.0))) } + span { class: "dim small", {format!("{:.0}%", tint_amount * 100.0)} } + } + } + div { class: "tx-arrow", "↓" } + // 4. the variants + div { class: "tx-step", + div { class: "tx-step-head", span { class: "tx-n", "4" } b { "variants" } + span { class: "dim small", if variants <= 1 { "every block the same" } else { "{variants}, each block picks one" } } + } + div { class: "row wrap", + input { r#type: "range", min: "1", max: "16", step: "1", value: "{variants}", "aria-label": "how many variants", oninput: move |e| set("variants", json!(e.value().parse::<u64>().unwrap_or(1))) } + button { class: "plain small", disabled: variants <= 1, title: "another seed: the blocks pick again", + onclick: move |_| { let s = (js_random() * 4_294_967_295.0) as u64; set("seed", json!(s)) }, "shuffle" } + label { class: "row small", input { r#type: "checkbox", checked: r["turn_variants"].as_bool().unwrap_or(false), disabled: variants <= 1, oninput: move |e| set("turn_variants", json!(e.checked())) } "turned too" } + } + div { class: "dim small", if variants <= 1 { "two by two units, as a block shows it:" } else { "a tile of each variant (a block shows one all over):" } } + Preview { id: "tx-patch", class: "tx-patch", w: 200.0, h: 200.0 } + } + div { class: "tx-arrow", "↓" } + // 5. where it's used + div { class: "tx-step", + div { class: "tx-step-head", span { class: "tx-n", "5" } b { "use" } + input { r#type: "text", class: "tx-name", placeholder: "its name (optional)", value: "{name}", oninput: move |e| name.set(e.value()) } + } + div { class: "row wrap", + button { class: "btn small", title: "keep the recipe in the save", + onclick: { let keep = keep.clone(); move |_| { let k = keep(); spawn(async move { if k.await.is_some() { ui.say("recipe kept") } }); } }, + Icon { name: "save" } "keep" } + button { class: "btn small", title: "a new block showing it, ahead of you", + onclick: { let keep = keep.clone(); move |_| { let k = keep(); spawn(async move { if let Some(id) = k.await { add_block_from(on_send, "texture", &id) } }); } }, + Icon { name: "cube" } "a new block" } + button { class: "btn small", disabled: block_id.is_none(), title: "the selected block shows it (on every face that has no recipe of its own)", + onclick: { + let keep = keep.clone(); + let api = api.clone(); + let bid = block_id.clone(); + move |_| { + let (k, api, bid) = (keep(), api.clone(), bid.clone()); + spawn(async move { + let (Some(id), Some(bid)) = (k.await, bid) else { return }; + match api.call("blocks.retexture", json!({ "id": bid, "kind": "texture", "texture": id })).await { + Ok(r) => { + let textures = dress(ui, &api, r["textures"].clone()).await; + on_send.call(json!({ "cmd": "unblock", "ids": [bid] })); + on_send.call(json!({ "cmd": "blocks", "blocks": r["blocks"], "textures": textures, "select": r["ids"][0] })); + on_changed.call(()); + ui.say("the block shows the recipe"); + } + Err(e) => ui.fail(e), + } + }); + } + }, + Icon { name: "image" } "on the selected block" } + } + if let Some(b) = block.clone() { + div { class: "row wrap tx-faces", + span { class: "small", "on one face:" } + for (i , face) in ["right", "left", "top", "bottom", "front", "back"].into_iter().enumerate() { + { + let has = b["faces"].get(i).is_some_and(|v| !v.is_null()); + let keep = keep.clone(); + let api = api.clone(); + let b = b.clone(); + rsx! { + button { key: "{face}", class: if has { "btn small on" } else { "plain small" }, + title: if has { "this face has a recipe of its own; click to put this one there" } else { "put the recipe on this face only" }, + onclick: move |_| { + let (k, api, b) = (keep(), api.clone(), b.clone()); + spawn(async move { + let Some(id) = k.await else { return }; + let mut faces = b["faces"].as_array().cloned().unwrap_or_else(|| vec![Value::Null; 6]); + faces.resize(6, Value::Null); + faces[i] = json!(id); + set_faces(ui, api, on_send, &b, Value::Array(faces)).await; + }); + }, + "{face}" } + } + } + } + if b["faces"].as_array().is_some_and(|a| a.iter().any(|v| !v.is_null())) { + button { class: "plain small", title: "every face shows the block's own texture again", + onclick: { let api = api.clone(); let b = b.clone(); move |_| { let (api, b) = (api.clone(), b.clone()); spawn(async move { set_faces(ui, api, on_send, &b, Value::Null).await }); } }, + "clear the faces" } + } + } + } + div { class: "row wrap", + button { class: "btn small", title: "the room's sky: the recipe all round, far off", + onclick: { + let keep = keep.clone(); + let api = api.clone(); + move |_| { + let (k, api) = (keep(), api.clone()); + spawn(async move { + let Some(id) = k.await else { return }; + set_sky(ui, &api, on_send, &id).await; + sky.set(id); + }); + } + }, + "☁ as the sky" } + if !sky_now.is_empty() { + button { class: "plain small", title: "no sky: the room's colour again", + onclick: { let api = api.clone(); move |_| { let api = api.clone(); spawn(async move { set_sky(ui, &api, on_send, "").await; sky.set(String::new()); }); } }, + "no sky" } + } + } + } + } + } + } +} + +/// a random number in [0, 1) (the clock has no time in a browser's wasm; Math.random does) +#[cfg(target_arch = "wasm32")] +fn js_random() -> f64 { + js_sys::Math::random() +} + +/// a random number in [0, 1) +#[cfg(not(target_arch = "wasm32"))] +fn js_random() -> f64 { + let t = std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .map(|d| d.subsec_nanos()) + .unwrap_or(7); + let mut x = t as u64 ^ 0x9e37_79b9_7f4a_7c15; + x ^= x >> 33; + x = x.wrapping_mul(0xff51_afd7_ed55_8ccd); + x ^= x >> 33; + (x >> 11) as f64 / (1u64 << 53) as f64 +} + +/// a block's faces set (null clears them), and the room told +async fn set_faces(ui: Ui, api: Api, on_send: EventHandler<Value>, b: &Value, faces: Value) { + let id = b["id"].as_str().unwrap_or("").to_string(); + match api.call("blocks.set", json!({ "id": id, "faces": faces })).await { + Ok(r) => { + let textures = dress(ui, &api, r["textures"].clone()).await; + on_send.call(json!({ "cmd": "blocks", "blocks": r["blocks"], "textures": textures, "select": id })); + ui.say(if faces.is_null() { + "the faces show the block's texture again" + } else { + "the face shows the recipe" + }); + } + Err(e) => ui.fail(e), + } +} + +/// the room's sky: a recipe's id in the save's settings (`space.sky`), "" for none; the +/// room is told +pub(super) async fn set_sky(ui: Ui, api: &Api, on_send: EventHandler<Value>, id: &str) { + if let Err(e) = api + .call("settings.set", json!({ "name": "space.sky", "value": id })) + .await + { + return ui.fail(e); + } + send_sky(ui, api, on_send, id).await; + ui.say(if id.is_empty() { + "no sky" + } else { + "the sky shows the recipe" + }); +} + +/// the room's sky drawn from the save's setting (on opening the room) +pub(super) async fn load_sky(ui: Ui, api: &Api, on_send: EventHandler<Value>) { + let id = match api.call("settings.get", json!({ "name": "space.sky" })).await { + Ok(v) => v["value"].as_str().unwrap_or("").to_string(), + Err(_) => String::new(), + }; + send_sky(ui, api, on_send, &id).await; +} + +async fn send_sky(ui: Ui, api: &Api, on_send: EventHandler<Value>, id: &str) { + if id.is_empty() { + on_send.call(json!({ "cmd": "sky", "about": null })); + return; + } + let Ok(all) = api.call("textures.list", json!({})).await else { + return; + }; + let Some(t) = all + .as_array() + .into_iter() + .flatten() + .find(|t| t["id"].as_str() == Some(id)) + .cloned() + else { + on_send.call(json!({ "cmd": "sky", "about": null })); + return; + }; + let dressed = dress(ui, api, json!({ format!("texture:{id}"): t })).await; + on_send.call(json!({ "cmd": "sky", "about": dressed[format!("texture:{id}")] })); +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn sides_on_a_slider() { + for v in [0.1, 0.5, 1.0, 2.0, 10.0] { + assert!((slider_to_side(side_to_slider(v)) - v).abs() < v * 0.06, "{v}"); + } + assert_eq!(slider_to_side(50.0), 1.0); + assert_eq!( + filled(&json!({ "source": { "plain": "#000000" }, "turn": 2 }))["scale"], + json!([1.0, 1.0]) + ); + } +} diff --git a/app/src/views/space/wirewin.rs b/app/src/views/space/wirewin.rs new file mode 100644 index 00000000..d6cbcfe7 --- /dev/null +++ b/app/src/views/space/wirewin.rs @@ -0,0 +1,487 @@ +//! The wiring window: blocks that cast rays and run programs (core's `graph::wiring`, +//! `ops::wiring`). For the selected block: the events it listens for (a click, a ray's +//! hit, a text coming into or leaving its zone, a timer, a named signal), the s program +//! it runs then (a note tagged `s`), and its ray: none, fixed (a direction out of the +//! block, registering the first, last, nth or all of what it crosses, of the kinds it +//! sees, and optionally sticking to what it first hits) or sticky (to target blocks, +//! picked in the room). "play" makes the room live: a click on a wired block fires it +//! (instead of selecting it), timers run, zones report texts coming and going. "try it" +//! fires the block once. The window lists what the last cause set off. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use super::{Sp, Win, dress}; +use crate::shell::set_pref; +use crate::ui::*; + +const EVENTS: [(&str, &str); 6] = [ + ("click", "a click (while playing)"), + ("hit", "another block's ray"), + ("enter", "a text coming into its zone"), + ("leave", "a text leaving its zone"), + ("timer", "a timer"), + ("signal", "a signal by name"), +]; + +const DIRS: [(&str, [f64; 3]); 6] = [ + ("front", [0.0, 0.0, 1.0]), + ("back", [0.0, 0.0, -1.0]), + ("right", [1.0, 0.0, 0.0]), + ("left", [-1.0, 0.0, 0.0]), + ("up", [0.0, 1.0, 0.0]), + ("down", [0.0, -1.0, 0.0]), +]; + +/// the wired blocks, into the room (what each listens for), and whether it's live +pub(super) async fn load_wires(api: &Api, sp: Sp) { + let list = match api.call("wiring.list", json!({})).await { + Ok(v) => v.as_array().cloned().unwrap_or_default(), + // a hub from before wiring + Err(_) => Vec::new(), + }; + let wires: Vec<Value> = list + .iter() + .map(|w| json!({ "id": w["id"], "on": w["wiring"]["on"], "every": w["wiring"]["every"], "links": w["links"] })) + .collect(); + let live = *sp.live.peek(); + sp.send(json!({ "cmd": "wires", "wires": wires, "live": live })); +} + +/// fires a block: the room shows what changed, its rays and what was said +pub(super) fn fire(ui: Ui, api: Api, sp: Sp, id: String, event: &'static str, from: String) { + dioxus::dioxus_core::spawn_forever(async move { + match api + .call("wiring.fire", json!({ "id": id, "event": event, "from": from })) + .await + { + Ok(r) => { + if r["removed"].as_array().is_some_and(|a| !a.is_empty()) { + sp.send(json!({ "cmd": "unblock", "ids": r["removed"] })); + } + if r["blocks"].as_array().is_some_and(|a| !a.is_empty()) { + let textures = dress(ui, &api, r["textures"].clone()).await; + sp.send(json!({ "cmd": "blocks", "blocks": r["blocks"], "textures": textures })); + } + sp.send(json!({ "cmd": "rays", "rays": r["rays"] })); + if r["sounds"].as_array().is_some_and(|a| !a.is_empty()) { + sp.send(json!({ "cmd": "sounds", "sounds": r["sounds"] })); + } + for s in r["says"].as_array().into_iter().flatten() { + ui.say(s.as_str().unwrap_or("").to_string()); + } + let errs: Vec<String> = r["events"] + .as_array() + .into_iter() + .flatten() + .filter_map(|e| { + e["err"] + .as_str() + .map(|x| format!("{}: {x}", e["block"].as_str().unwrap_or(""))) + }) + .collect(); + if let Some(e) = errs.first() { + ui.fail(e.clone()); + } + if r["cut"] == true { + ui.say("stopped: one cause sets off at most 200 events, in one budget of steps".to_string()); + } + let mut f = sp.fired; + f.set(r["events"].as_array().cloned().unwrap_or_default()); + if r["removed"].as_array().is_some_and(|a| !a.is_empty()) + || r["events"] + .as_array() + .is_some_and(|e| e.iter().any(|x| x["block"] != x["from"])) + { + load_wires(&api, sp).await; + } + } + Err(e) => ui.fail(e), + } + }); +} + +fn has(w: &Value, ev: &str) -> bool { + w["on"].as_array().is_some_and(|a| a.iter().any(|x| x == ev)) +} + +fn short(id: &str) -> String { + // a prefab copy's part: its address inside, and which copy + if let Some((copy, inner)) = id.strip_prefix("prefab:").and_then(|r| r.split_once('/')) { + let n = copy.rsplit_once('#').map_or(copy, |x| x.1); + return format!("{} in copy {n}", short(inner)); + } + let (k, n) = id.rsplit_once('#').unwrap_or((id, "")); + let k = k.split_once(':').map_or(k, |(_, t)| t); + let k = if k.chars().count() > 14 { + format!("{}…", k.chars().take(12).collect::<String>()) + } else { + k.to_string() + }; + if n.is_empty() { k } else { format!("{k} #{n}") } +} + +#[component] +pub(super) fn Wires(sp: Sp) -> Element { + let ui = ui(); + let api = api(); + // the block being wired: the selected one, held while targets are picked + let mut wired: Signal<Option<String>> = use_signal(|| None); + let mut picking = use_signal(|| false); + let mut w: Signal<Value> = use_signal(|| Value::Null); + let mut dirty = use_signal(|| false); + let mut programs: Signal<Vec<String>> = use_signal(Vec::new); + let sel = (sp.block)() + .filter(|b| b["copy"] != true) + .and_then(|b| b["id"].as_str().map(str::to_string)); + + // the programs to choose from + let api_p = api.clone(); + use_hook(move || { + let api = api_p.clone(); + spawn(async move { + if let Ok(v) = api.call("s.programs", json!({})).await { + programs.set( + v.as_array() + .into_iter() + .flatten() + .filter_map(|p| p["title"].as_str().map(str::to_string)) + .collect(), + ); + } + }); + }); + + // the selection: picked as a target, or the block to wire + let api_s = api.clone(); + use_effect(use_reactive!(|sel| { + let Some(id) = sel else { return }; + if *picking.peek() { + if wired.peek().as_deref() != Some(id.as_str()) { + let mut v = w.peek().clone(); + let ts = v["ray"]["targets"].as_array().cloned().unwrap_or_default(); + if !ts.iter().any(|t| t == &json!(id)) { + let mut ts = ts; + ts.push(json!(id)); + v["ray"]["targets"] = json!(ts); + w.set(v); + dirty.set(true); + } + } + return; + } + if wired.peek().as_deref() == Some(id.as_str()) { + return; + } + wired.set(Some(id.clone())); + dirty.set(false); + let api = api_s.clone(); + spawn(async move { + match api.call("wiring.get", json!({ "id": id })).await { + Ok(v) => w.set(v), + Err(e) => ui.fail(e), + } + }); + })); + + let api_k = api.clone(); + let keep = move |v: Value| { + let Some(id) = wired.peek().clone() else { return }; + let api = api_k.clone(); + spawn(async move { + match api.call("wiring.set", json!({ "id": id, "wiring": v })).await { + Ok(r) => { + w.set(r["wiring"].clone()); + dirty.set(false); + load_wires(&api, sp).await; + ui.say( + if r["wiring"].is_null() { + "unwired" + } else { + "wired · \"try it\" fires it once; \"play\" makes the room live" + } + .to_string(), + ); + } + Err(e) => ui.fail(e), + } + }); + }; + let keep2 = keep.clone(); + + let cur = w(); + let on = !cur.is_null(); + let ray = cur["ray"].clone(); + let aim = if ray.is_null() { + "none" + } else if ray["targets"].as_array().is_some_and(|a| !a.is_empty()) || *picking.read() { + "sticky" + } else { + "fixed" + }; + let mode = ray["mode"].as_str().unwrap_or("first").to_string(); + let live = (sp.live)(); + let fired = (sp.fired)(); + let mut set = move |f: &dyn Fn(&mut Value)| { + let mut v = w.peek().clone(); + if v.is_null() { + v = json!({ "on": [] }); + } + f(&mut v); + w.set(v); + dirty.set(true); + }; + + rsx! { + Win { + id: "wiring", + at: (8.0, 140.0), + on_close: move |_| set_pref(ui, |p| p.space.show_wiring = false), + title: rsx! { + span { class: "win-title", + Icon { name: "bolt" } + "wiring" + span { class: "dim small", style: "font-weight: 400;", "rays and programs" } + } + }, + div { class: "row wrap", + button { class: if live { "btn small primary" } else { "btn small" }, + "aria-pressed": "{live}", + title: "play: a click on a wired block fires it, timers run, zones tell of texts coming and going", + onclick: { + let api = api.clone(); + move |_| { + let mut l = sp.live; + l.set(!live); + let api = api.clone(); + spawn(async move { load_wires(&api, sp).await }); + } + }, + if live { "■ stop playing" } else { "▶ play" } + } + button { class: if (sp.wiremode)() { "btn small primary" } else { "btn small" }, + "aria-pressed": "{(sp.wiremode)()}", + title: "drag from one block to another to wire them; every block shows a port while it's on (J)", + onclick: move |_| sp.send(json!({ "cmd": "wiremode", "toggle": true })), + "connect by dragging" } + if let Some(id) = wired() { + span { class: "small", "wiring " b { {short(&id)} } } + } + } + if wired().is_none() { + p { class: "dim small", "Select a block to wire it." } + } else { + div { class: "wire-sec", + span { class: "small", "it listens for" } + div { class: "row wrap", + for (ev, what) in EVENTS { + label { key: "{ev}", class: "check small", title: "{what}", + input { r#type: "checkbox", checked: has(&cur, ev), + onchange: move |e: FormEvent| { + let yes = e.checked(); + set(&|v: &mut Value| { + let mut a: Vec<Value> = v["on"].as_array().cloned().unwrap_or_default(); + a.retain(|x| x != ev); + if yes { a.push(json!(ev)); } + v["on"] = json!(a); + }); + } + } + "{ev}" + } + } + } + if has(&cur, "timer") { + label { class: "lt-slider", span { "every (s)" } + input { r#type: "number", min: "0.2", step: "0.1", value: "{cur[\"every\"].as_f64().unwrap_or(1.0)}", + oninput: move |e: FormEvent| { let x = e.value().parse::<f64>().unwrap_or(1.0); set(&|v: &mut Value| v["every"] = json!(x)); } + } + } + } + if has(&cur, "signal") { + label { class: "lt-slider", span { "signal" } + input { r#type: "text", placeholder: "its name", value: "{cur[\"signal\"].as_str().unwrap_or(\"\")}", + oninput: move |e: FormEvent| { let x = e.value(); set(&|v: &mut Value| v["signal"] = json!(x.clone())); } + } + } + } + } + div { class: "wire-sec", + label { class: "lt-slider", span { "program" } + select { + "aria-label": "the s program it runs", + onchange: move |e: FormEvent| { let x = e.value(); set(&|v: &mut Value| v["program"] = json!(x.clone())); }, + option { value: "", selected: cur["program"].as_str().unwrap_or("").is_empty(), "none: it casts its ray" } + for p in programs() { + option { key: "{p}", value: "{p}", selected: cur["program"].as_str() == Some(p.as_str()), "{p}" } + } + } + } + if programs().is_empty() { + p { class: "dim small", "Programs are notes tagged s (the notes view's s button)." } + } + } + div { class: "wire-sec", + span { class: "small", "its ray" } + div { class: "row wrap", + for a in ["none", "fixed", "sticky"] { + button { key: "{a}", class: if aim == a { "btn small on" } else { "btn small" }, + onclick: move |_| { + picking.set(a == "sticky"); + set(&|v: &mut Value| match a { + "none" => { if let Some(o) = v.as_object_mut() { o.remove("ray"); } } + "fixed" => { let mut r = v["ray"].clone(); if r.is_null() { r = json!({}); } r["targets"] = json!([]); v["ray"] = r; } + _ => { if v["ray"].is_null() { v["ray"] = json!({ "targets": [] }); } } + }); + }, + "{a}" + } + } + } + if aim == "fixed" { + div { class: "row wrap", + span { class: "small", "out of its" } + for (name, d) in DIRS { + { + let now: Vec<f64> = ray["dir"].as_array().map(|a| a.iter().filter_map(Value::as_f64).collect()).unwrap_or(vec![0.0, 0.0, 1.0]); + let on = now.len() == 3 && (0..3).all(|i| (now[i] - d[i]).abs() < 1e-3); + rsx! { + button { key: "{name}", class: if on { "btn small on" } else { "btn small" }, + onclick: move |_| set(&|v: &mut Value| v["ray"]["dir"] = json!(d)), + "{name}" + } + } + } + } + } + div { class: "row wrap", + span { class: "small", "registers" } + for m in ["first", "last", "all", "nth"] { + button { key: "{m}", class: if mode == m { "btn small on" } else { "btn small" }, + onclick: move |_| set(&|v: &mut Value| v["ray"]["mode"] = json!(m)), + "{m}" + } + } + if mode == "nth" { + input { r#type: "number", min: "1", style: "width: 4em;", value: "{ray[\"n\"].as_u64().unwrap_or(1)}", + "aria-label": "which one it registers", + oninput: move |e: FormEvent| { let n = e.value().parse::<u64>().unwrap_or(1).max(1); set(&|v: &mut Value| v["ray"]["n"] = json!(n)); } + } + } + } + label { class: "lt-slider", span { "reach" } + input { r#type: "range", min: "1", max: "200", value: "{ray[\"range\"].as_f64().unwrap_or(50.0)}", + oninput: move |e: FormEvent| { let x = e.value().parse::<f64>().unwrap_or(50.0); set(&|v: &mut Value| v["ray"]["range"] = json!(x)); } + } + span { class: "dim small", {format!("{:.0}", ray["range"].as_f64().unwrap_or(50.0))} } + } + div { class: "row wrap", + span { class: "small", "sees" } + for k in ["text", "picture", "plain", "texture"] { + { + let sees: Vec<Value> = ray["sees"].as_array().cloned().unwrap_or_default(); + let on = sees.is_empty() || sees.iter().any(|x| x == k); + rsx! { + label { key: "{k}", class: "check small", + input { r#type: "checkbox", checked: on, + onchange: move |e: FormEvent| { + let yes = e.checked(); + set(&|v: &mut Value| { + let mut s: Vec<Value> = v["ray"]["sees"].as_array().cloned().unwrap_or_default(); + if s.is_empty() { s = ["text", "picture", "plain", "texture"].iter().map(|x| json!(x)).collect(); } + s.retain(|x| x != k); + if yes { s.push(json!(k)); } + if s.len() == 4 { s.clear(); } + v["ray"]["sees"] = json!(s); + }); + } + } + "{k}" + } + } + } + } + } + label { class: "check small", + input { r#type: "checkbox", checked: ray["stick"] == true, + onchange: move |e: FormEvent| { let yes = e.checked(); set(&|v: &mut Value| v["ray"]["stick"] = json!(yes)); } + } + "become sticky on its first hit" + } + } + if aim == "sticky" { + div { class: "wire-targets", + for t in ray["targets"].as_array().cloned().unwrap_or_default() { + { + let t = t.as_str().unwrap_or("").to_string(); + let t2 = t.clone(); + rsx! { + span { key: "{t}", class: "chip small", {short(&t)} + button { class: "plain", "aria-label": "not this target", + onclick: move |_| { let t = t2.clone(); set(&|v: &mut Value| { if let Some(a) = v["ray"]["targets"].as_array_mut() { a.retain(|x| x != &json!(t)); } }); }, + "×" + } + } + } + } + } + } + button { class: if picking() { "btn small primary" } else { "btn small" }, + onclick: move |_| { + let now = picking(); + picking.set(!now); + if now && let Some(id) = wired.peek().clone() { + // back to the wired block + sp.send(json!({ "cmd": "pickblock", "id": id })); + } + }, + if picking() { "done picking" } else { "pick targets in the room" } + } + if picking() { + p { class: "dim small", "Click the blocks it should hit; each becomes a target." } + } + } + } + div { class: "row wrap", + button { class: if dirty() { "btn small primary" } else { "btn small" }, disabled: !dirty(), + onclick: move |_| { picking.set(false); keep(w.peek().clone()); }, + "keep" + } + button { class: "btn small", disabled: !on, + title: "fire it once, as a click would", + onclick: { + let api = api.clone(); + move |_| { + if let Some(id) = wired.peek().clone() { + fire(ui, api.clone(), sp, id.clone(), "click", String::new()); + } + } + }, + "try it" + } + button { class: "btn small", disabled: !on, + onclick: move |_| keep2(Value::Null), + "unwire" + } + } + if !fired.is_empty() { + div { class: "wire-log", + span { class: "small", "what the last cause set off" } + for (i, e) in fired.iter().enumerate() { + div { key: "{i}", class: "small", + b { {short(e["block"].as_str().unwrap_or(""))} } + " · {e[\"event\"].as_str().unwrap_or(\"\")}" + if let Some(o) = e["out"].as_str().filter(|o| !o.is_empty()) { + pre { class: "s-out", "{o}" } + } + if let Some(x) = e["err"].as_str() { + div { class: "s-err", "{x}" } + } + } + } + } + } + } + } + } +} diff --git a/app/src/views/specs.rs b/app/src/views/specs.rs new file mode 100644 index 00000000..36767f31 --- /dev/null +++ b/app/src/views/specs.rs @@ -0,0 +1,1037 @@ +//! Spec models: models made from a declarative spec (docs/models.md, `models.*` in +//! docs/app-api.md), the second tab of the models view. The same view on the desktop and +//! the web, through the backend. +//! +//! The left column lists them; "new" starts one from a template (a classifier, a tagger, +//! a generator) filled in with the save's lists. A model's page has its spec in the +//! builder (`builder.rs`: a control for every field) and in a JSON editor, the same text +//! under both (checked as you type, a broken rule shown where it is; Ctrl+Enter saves), +//! its training (epochs, progress, cancel, the metrics), a run card (the command bar's +//! text through every head as you type) and, for a generator, a write card: candidates +//! judged by its critics, each critic's score shown (Enter in the bar writes after the +//! bar's text). + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use super::classifiers::{Metrics, Progress, hue, pct, strs}; + +mod builder; +use crate::backend::ListInfo; +use crate::ui::*; + +/// what the models view shares with this tab: the open model, whether "new" is open, and +/// a count the bar's Enter bumps (the write card writes after the bar's text) +#[derive(Clone, Copy, PartialEq)] +pub struct SpecState { + pub chosen: Signal<Option<String>>, + pub new: Signal<bool>, + pub enter: Signal<u64>, +} + +impl SpecState { + pub fn new() -> SpecState { + SpecState { + chosen: Signal::new(None), + new: Signal::new(false), + enter: Signal::new(0), + } + } + + /// Escape: closes "new", else the open model + pub fn escape(mut self) { + if *self.new.peek() { + self.new.set(false); + } else { + self.chosen.set(None); + } + } +} + +#[component] +pub fn SpecModels(state: SpecState) -> Element { + let ui = ui(); + let api = api(); + let SpecState { + mut chosen, mut new, .. + } = state; + let mut rev = use_signal(|| 0u64); + let api_r = api.clone(); + let models = use_resource(move || { + let api = api_r.clone(); + let _ = ((ui.changed)(), rev()); + async move { api.spec_models().await } + }); + let (list, note): (Vec<Value>, Option<String>) = match &*models.read() { + Some(Ok(v)) => (v.clone(), None), + Some(Err(e)) => (vec![], Some(e.clone())), + None => (vec![], None), + }; + let open = chosen().or_else(|| { + (!new()) + .then(|| list.first().and_then(|m| m["name"].as_str().map(str::to_string))) + .flatten() + }); + let on_made = move |name: String| { + new.set(false); + chosen.set(Some(name)); + rev += 1; + }; + rsx! { + if let Some(n) = note { + div { class: "card bad", "{n}" } + } + div { class: "cls-layout", + div { class: "card cls-list", role: "listbox", "aria-label": "spec models", + button { class: if new() { "cls-item on" } else { "cls-item" }, onclick: move |_| new.set(!new()), + b { Icon { name: "new" } " new" } span { class: "small", "from a template" } } + if list.is_empty() { + span { class: "dim small", "none yet" } + } + for m in list.iter().cloned() { + { + let name = m["name"].as_str().unwrap_or("").to_string(); + let on = open.as_deref() == Some(name.as_str()) && !new(); + let heads: Vec<String> = m["heads"].as_array().into_iter().flatten() + .map(|h| format!("{} ({})", h["name"].as_str().unwrap_or(""), h["kind"].as_str().unwrap_or(""))).collect(); + let state = if m["training"] == true { "training…".to_string() } + else if m["trained"] == true { trained_line(&m) } + else { "not trained yet".to_string() }; + rsx! { + button { key: "{name}", role: "option", "aria-selected": "{on}", + class: if on { "cls-item on" } else { "cls-item" }, + onclick: { let n = name.clone(); move |_| { chosen.set(Some(n.clone())); new.set(false); } }, + b { "{name}" } + span { class: "small", {heads.join(" · ")} } + span { class: "small state", "{state}" } + } + } + } + } + } + div { class: "cls-main", + if new() { + NewSpec { on_made } + } else { + match open { + Some(name) => rsx! { SpecPage { key: "{name}", name: name.clone(), enter: state.enter, + on_gone: move |_| { chosen.set(None); rev += 1; }, + on_renamed: move |n: String| { chosen.set(Some(n)); rev += 1; } } }, + None => rsx! { + div { class: "card empty", + p { "A spec model is a model described as plain data: what it reads, how big it is, what comes out (classes, labels, numbers, or text it writes), what it learns from in this save, and for a writer, which other models judge what it writes." } + p { "Press " b { "new" } " to start from a template, then edit its spec, train it, and try it from the command bar." } + } + }, + } + } + } + } + } +} + +fn trained_line(m: &Value) -> String { + let mut s = "trained".to_string(); + if let Some(a) = m["accuracy"].as_f64() { + s += &format!(" · {}", pct(a)); + } + if let Some(b) = m["bits_per_byte"].as_f64() { + s += &format!(" · {b:.2} bits/byte"); + } + s +} + +// ------------------------------------------------------------------ templates + +#[derive(Clone, Copy, PartialEq)] +enum Template { + Classifier, + Tagger, + Generator, + Pictures, +} + +impl Template { + const ALL: [Template; 4] = [ + Template::Classifier, + Template::Tagger, + Template::Generator, + Template::Pictures, + ]; + + fn name(self) -> &'static str { + match self { + Template::Classifier => "classifier", + Template::Tagger => "tagger", + Template::Generator => "generator", + Template::Pictures => "pictures", + } + } + + fn about(self) -> &'static str { + match self { + Template::Classifier => "one class of several for a text: each list a class", + Template::Tagger => "any of several labels for a text, each from a list", + Template::Generator => "writes texts like a list's, judged by another model", + Template::Pictures => "one class of several for a picture: each picture list a class", + } + } +} + +/// a judge a generator can use: a model's name, its head and a class of it +pub type Judge = (String, String, String); + +/// a template's spec, filled in with the save's lists (by name), its picture lists and a +/// judge if there is one +fn template(t: Template, lists: &[ListInfo], judge: Option<&Judge>, plists: &[String]) -> String { + let names: Vec<String> = lists.iter().filter(|l| l.count > 0).map(|l| l.name.clone()).collect(); + let pick = |n: usize| -> Vec<String> { + let mut v: Vec<String> = names.iter().take(n).cloned().collect(); + for i in v.len()..n.min(2).max(v.len()) { + v.push(format!("list {}", i + 1)); + } + v + }; + // written by hand so the fields keep the order docs/models.md gives them + let q = |s: &str| serde_json::to_string(s).unwrap_or_default(); + let classes = |c: &[String]| c.iter().map(|x| q(x)).collect::<Vec<_>>().join(", "); + let data = |head: &str, c: &[String]| { + c.iter() + .map(|x| { + format!( + " {{\"from\": \"list\", \"list\": {}, \"head\": {}, \"class\": {}}}", + q(x), + q(head), + q(x) + ) + }) + .collect::<Vec<_>>() + .join(",\n") + }; + match t { + Template::Pictures => { + let mut c: Vec<String> = plists.iter().take(3).cloned().collect(); + for i in c.len()..2 { + c.push(format!("pictures {}", i + 1)); + } + let d = c + .iter() + .map(|x| { + format!( + " {{\"from\": \"pictures\", \"list\": {}, \"head\": \"what\", \"class\": {}}}", + q(x), + q(x) + ) + }) + .collect::<Vec<_>>() + .join(",\n"); + format!( + "{{\n \"name\": \"what it shows\",\n \"input\": {{\"type\": \"image\", \"width\": 32, \"height\": 32, \"patch\": 8, \"codes\": 64}},\n \"trunk\": {{\"preset\": \"compact\"}},\n \"heads\": [\n {{\"name\": \"what\", \"kind\": \"classify\", \"classes\": [{cl}]}}\n ],\n \"data\": [\n{d}\n ],\n \"train\": {{\"epochs\": 30, \"batch\": 8}}\n}}\n", + cl = classes(&c), + ) + } + Template::Classifier | Template::Tagger => { + let c = pick(3); + let (name, kind) = if t == Template::Classifier { + ("kind", "classify") + } else { + ("tags", "multi") + }; + format!( + "{{\n \"name\": {n},\n \"input\": {{\"type\": \"text\"}},\n \"trunk\": {{\"preset\": \"compact\"}},\n \"heads\": [\n {{\"name\": {n}, \"kind\": \"{kind}\", \"classes\": [{cl}]}}\n ],\n \"data\": [\n{d}\n ],\n \"train\": {{\"epochs\": 20}}\n}}\n", + n = q(name), + cl = classes(&c), + d = data(name, &c), + ) + } + Template::Generator => { + let l = pick(1).into_iter().next().unwrap_or_else(|| "list 1".into()); + let critics = match judge { + Some((m, h, c)) => format!( + " \"critics\": [\n {{\"model\": {}, \"head\": {}, \"want\": {{\"class\": {}}}}}\n ],\n", + q(m), + q(h), + q(c) + ), + None => String::new(), + }; + format!( + "{{\n \"name\": \"writer\",\n \"input\": {{\"type\": \"text\"}},\n \"trunk\": {{\"preset\": \"compact\", \"max_len\": 96}},\n \"heads\": [\n {{\"name\": \"next\", \"kind\": \"generate\"}}\n ],\n \"data\": [\n {{\"from\": \"list\", \"list\": {l}, \"head\": \"next\"}}\n ],\n{critics} \"constraints\": {{\"max_len\": 120}},\n \"sampling\": {{\"temperature\": 0.7, \"top_p\": 0.9, \"max_len\": 60, \"seed\": 1}},\n \"train\": {{\"epochs\": 80, \"batch\": 8, \"lr\": 0.003}}\n}}\n", + l = q(&l), + ) + } + } +} + +#[component] +fn NewSpec(on_made: EventHandler<String>) -> Element { + let ui = ui(); + let api = api(); + let mut which = use_signal(|| Template::Classifier); + // the spec as edited (None: the template as it is) + let mut text: Signal<Option<String>> = use_signal(|| None); + let mut form = use_signal(|| 0u64); + let mut busy = use_signal(|| false); + let api_l = api.clone(); + let ctx = use_resource(move || { + let api = api_l.clone(); + async move { + let lists = api.lists().await.map(|l| l.lists).unwrap_or_default(); + // a judge for a writer: a trained classifier, else a spec model's classify head + let mut judge: Option<Judge> = None; + if let Ok(cls) = api.models().await + && let Some(c) = cls.iter().find(|c| c.trained && !c.classes.is_empty()) + { + judge = Some((c.name.clone(), c.name.clone(), c.classes[0].clone())); + } + if judge.is_none() + && let Ok(ms) = api.spec_models().await + { + judge = ms.iter().find_map(|m| { + let h = m["heads"].as_array()?.iter().find(|h| h["kind"] == "classify")?; + Some(( + m["name"].as_str()?.to_string(), + h["name"].as_str()?.to_string(), + h["classes"][0].as_str()?.to_string(), + )) + }); + } + let plists: Vec<String> = api + .picture_lists() + .await + .unwrap_or_default() + .iter() + .filter_map(|l| l["list"].as_str().map(str::to_string)) + .collect(); + (lists, judge, plists) + } + }); + let Some((lists, judge, plists)) = ctx.read().clone() else { + return rsx! { div { class: "card dim", "…" } }; + }; + let shown = text + .peek() + .clone() + .unwrap_or_else(|| template(*which.peek(), &lists, judge.as_ref(), &plists)); + let create = { + let api = api.clone(); + let (lists, judge, plists) = (lists.clone(), judge.clone(), plists.clone()); + move || { + let api = api.clone(); + let t = text + .peek() + .clone() + .unwrap_or_else(|| template(*which.peek(), &lists, judge.as_ref(), &plists)); + busy.set(true); + dioxus::dioxus_core::spawn_forever(async move { + match api.create_spec(&t).await { + Ok(v) => { + let n = v["name"].as_str().unwrap_or("").to_string(); + ui.say(format!("made {n}; train it next")); + on_made.call(n); + } + Err(e) => ui.fail(e), + } + busy.set(false); + }); + } + }; + let create2 = create.clone(); + rsx! { + div { class: "card cls-new", + h3 { Icon { name: "new" } "a new spec model" } + div { class: "row", + for t in Template::ALL { + button { key: "{t.name()}", class: if which() == t { "chip on" } else { "chip" }, "aria-pressed": "{which() == t}", + "data-tip": "{t.about()}", + onclick: move |_| { + which.set(t); + text.set(None); + form += 1; + }, + "{t.name()}" } + } + span { class: "dim small", {which().about()} } + } + for g in [form()] { + SpecBoth { key: "{g}", text: shown.clone(), on_change: move |t: String| text.set(Some(t)), on_save: { let mut c = create2.clone(); move |_| c() } } + } + div { class: "row", + span { class: "dim small", "lists are named by their names; docs/models.md has every field" } + span { class: "grow" } + button { class: "primary", disabled: busy(), onclick: { let mut c = create.clone(); move |_| c() }, Icon { name: "check" } "make it" } + } + } + } +} + +// ------------------------------------------------------------------ the editor + +/// a spec two ways: the builder (every part a control; the default) and the JSON, the +/// same text under both, so a change in one shows in the other; a broken rule shows on +/// the builder's control it concerns +#[component] +fn SpecBoth(text: String, on_change: EventHandler<String>, on_save: EventHandler<()>) -> Element { + let api = api(); + let mut cur = use_signal(|| text.clone()); + let mut as_json = use_signal(|| false); + let mut jgen = use_signal(|| 0u64); + let checked = use_resource(move || { + let api = api.clone(); + let t = cur(); + async move { + sleep_ms(250).await; + api.check_spec(&t).await.ok() + } + }); + let rule = match &*checked.read() { + Some(Some(v)) if v["ok"] == false => Some(( + v["path"].as_str().unwrap_or("").to_string(), + v["message"].as_str().unwrap_or("").to_string(), + )), + _ => None, + }; + let now = cur(); + rsx! { + div { class: "row sb-tabs", role: "tablist", + button { role: "tab", class: if !as_json() { "tab on" } else { "tab" }, "aria-selected": "{!as_json()}", + onclick: move |_| as_json.set(false), Icon { name: "sliders" } "builder" } + button { role: "tab", class: if as_json() { "tab on" } else { "tab" }, "aria-selected": "{as_json()}", + onclick: move |_| { jgen += 1; as_json.set(true); }, Icon { name: "editor" } "JSON" } + span { class: "dim small", "the same spec two ways: a change in one shows in the other" } + } + if as_json() { + for g in [jgen()] { + SpecEditor { key: "{g}", text: now.clone(), on_change: move |t: String| { cur.set(t.clone()); on_change.call(t); }, on_save } + } + } else { + builder::SpecBuilder { text: now.clone(), on_change: move |t: String| { cur.set(t.clone()); on_change.call(t); }, err: rule } + } + } +} + +/// a spec's JSON in a monospace textarea, checked a beat after typing stops: a broken +/// rule shows under it with where in the spec it is; Ctrl+Enter saves +#[component] +fn SpecEditor(text: String, on_change: EventHandler<String>, on_save: EventHandler<()>) -> Element { + let api = api(); + let mut cur = use_signal(|| text.clone()); + let rows = text.lines().count().clamp(8, 40); + let check = use_resource(move || { + let api = api.clone(); + let t = cur(); + async move { + sleep_ms(300).await; + api.check_spec(&t).await + } + }); + let verdict = check.read().clone(); + rsx! { + div { class: "spec-editor", + textarea { + class: "spec-text", + rows: "{rows}", + spellcheck: "false", + "aria-label": "the model's spec (JSON)", + initial_value: "{text}", + oninput: move |e| { let v = e.value(); cur.set(v.clone()); on_change.call(v); }, + onkeydown: move |e: KeyboardEvent| { + if e.key() == Key::Enter && (e.modifiers().ctrl() || e.modifiers().meta()) { + e.prevent_default(); + on_save.call(()); + } + }, + } + match verdict { + Some(Ok(v)) if v["ok"] == true => rsx! { div { class: "spec-ok small", Icon { name: "check" } "the spec reads" } }, + Some(Ok(v)) => rsx! { + div { class: "spec-err small", role: "alert", + Icon { name: "alert" } + if let Some(p) = v["path"].as_str().filter(|p| !p.is_empty()) { code { "{p}" } } + span { {v["message"].as_str().unwrap_or("").to_string()} } + } + }, + Some(Err(e)) => rsx! { div { class: "spec-err small", "{e}" } }, + None => rsx! {}, + } + } + } +} + +// ------------------------------------------------------------------ one model + +#[component] +fn SpecPage(name: String, enter: Signal<u64>, on_gone: EventHandler<()>, on_renamed: EventHandler<String>) -> Element { + let ui = ui(); + let api = api(); + let mut rev = use_signal(|| 0u64); + let mut armed = use_signal(|| false); + let mut job: Signal<Option<Value>> = use_signal(|| None); + let mut watching = use_signal(|| true); + // the spec as edited (None: as stored) + let mut text: Signal<Option<String>> = use_signal(|| None); + let mut form = use_signal(|| 0u64); + let n0 = name.clone(); + let api_d = api.clone(); + let details = use_resource(move || { + let (api, n) = (api_d.clone(), n0.clone()); + let _ = ((ui.changed)(), rev()); + async move { api.spec_model(&n).await } + }); + { + let (api, n) = (api.clone(), name.clone()); + use_future(move || { + let (api, n) = (api.clone(), n.clone()); + async move { + let mut was_running = false; + loop { + if *watching.peek() { + match api.spec_job(&n).await { + Ok(j) => { + let running = j["state"] == "running"; + if !running { + watching.set(false); + if was_running { + match j["state"].as_str() { + Some("done") => ui.say(format!("{n} is trained")), + Some("failed") => ui.fail(format!( + "{n}: {}", + j["error"].as_str().unwrap_or("training failed") + )), + Some(s) => ui.say(format!("{n}: {s}")), + None => {} + } + rev += 1; + ui.touched(); + } + } + was_running = running; + job.set(Some(j)); + } + Err(_) => watching.set(false), + } + } + sleep_ms(if was_running { 350 } else { 600 }).await; + } + } + }); + } + let d = match &*details.read() { + Some(Ok(v)) => v.clone(), + Some(Err(e)) => return rsx! { div { class: "card bad", "{e}" } }, + None => return rsx! { div { class: "card dim", "…" } }, + }; + let source = d["source"].as_str().unwrap_or("").to_string(); + let trained = d["trained"] == true; + let running = job().is_some_and(|j| j["state"] == "running"); + let generates = d["generates"] == true; + let heads: Vec<Value> = d["heads"].as_array().cloned().unwrap_or_default(); + let edited = text().is_some_and(|t| t != source); + let shown = text.peek().clone().unwrap_or_else(|| source.clone()); + let save = { + let (api, n, source) = (api.clone(), name.clone(), source.clone()); + move || { + let (api, n) = (api.clone(), n.clone()); + let t = text.peek().clone().unwrap_or_else(|| source.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.update_spec(&n, &t).await { + Ok(v) => { + let new = v["name"].as_str().unwrap_or("").to_string(); + let kept = if v["weights_kept"] == true { + "; its training stays" + } else if v["trained"] == false && trained { + "; its shape changed, so it trains anew" + } else { + "" + }; + ui.say(format!("saved {new}{kept}")); + text.set(None); + ui.touched(); + if new != n { + on_renamed.call(new); + } else { + rev += 1; + } + } + Err(e) => ui.fail(e), + } + }); + } + }; + let save2 = save.clone(); + let api_del = api.clone(); + let n_del = name.clone(); + rsx! { + div { class: "cls-page", + div { class: "card cls-head", + div { class: "row", + h2 { "{name}" } + for (i , h) in heads.iter().enumerate() { + span { key: "{i}", class: "chip cls-class", style: "--hue: {hue(i, heads.len())};", + title: strs(&h["classes"]).join(" · "), + {format!("{} · {}", h["name"].as_str().unwrap_or(""), h["kind"].as_str().unwrap_or(""))} } + } + span { class: "grow" } + button { + class: if armed() { "armed" } else { "plain" }, + "data-tip": "delete it (its lists stay); click twice", + "aria-label": "delete the model", + disabled: running, + onclick: move |_| { + if !armed() { armed.set(true); return; } + let (api, n) = (api_del.clone(), n_del.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.delete_spec(&n).await { + Ok(()) => { ui.say(format!("deleted {n}")); ui.touched(); on_gone.call(()); } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "delete" } + if armed() { "delete it?" } + } + } + div { class: "dim small", + {format!("reads {} · version {}{}{}{}", + d["input"].as_str().unwrap_or("text"), + d["version"], + d["pretrained"].as_str().map(|p| format!(" · from {p}")).unwrap_or_default(), + if d["critics"].as_array().is_some_and(|c| !c.is_empty()) { format!(" · judged by {}", strs(&d["critics"]).join(", ")) } else { String::new() }, + if trained { format!(" · {} steps trained", d["steps"]) } else { " · not trained yet".into() }, + )} + } + } + div { class: "card", + div { class: "row", + h3 { Icon { name: "editor" } "spec" } + span { class: "dim small", if edited { "edited · Ctrl+Enter saves" } else { "as stored" } } + span { class: "grow" } + button { disabled: !edited, onclick: move |_| { text.set(None); form += 1; }, Icon { name: "undo" } "as stored" } + button { class: "primary", disabled: !edited || running, onclick: { let c = save.clone(); move |_| c() }, Icon { name: "save" } "save" } + } + for g in [form()] { + SpecBoth { key: "{g}", text: shown.clone(), on_change: move |t: String| text.set(Some(t)), on_save: { let c = save2.clone(); move |_| c() } } + } + } + SpecTrain { name: name.clone(), details: d.clone(), job: job(), on_start: move |j: Value| { job.set(Some(j)); watching.set(true); } } + SpecRun { name: name.clone(), trained } + if generates { + SpecWrite { name: name.clone(), enter } + } + } + } +} + +// ------------------------------------------------------------------ training + +#[component] +fn SpecTrain(name: String, details: Value, job: Option<Value>, on_start: EventHandler<Value>) -> Element { + let ui = ui(); + let api = api(); + let mut epochs: Signal<Option<u32>> = use_signal(|| None); + let mut fresh = use_signal(|| false); + let device = use_signal(|| details["spec"]["device"].as_str().unwrap_or("cpu").to_string()); + let state = job + .as_ref() + .and_then(|j| j["state"].as_str()) + .unwrap_or("idle") + .to_string(); + let running = state == "running"; + let trained = details["trained"] == true; + let last = details["history"].as_array().and_then(|h| h.last()).cloned(); + let (api_t, n_t, api_c, n_c) = (api.clone(), name.clone(), api.clone(), name.clone()); + let start = move |_| { + let (api, n) = (api_t.clone(), n_t.clone()); + let (e, f, d) = (*epochs.peek(), *fresh.peek(), device.peek().clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api + .call( + "models.train", + json!({ "name": n, "epochs": e, "fresh": f, "device": d }), + ) + .await + { + Ok(j) => { + ui.say(format!("training {n}…")); + on_start.call(j); + ui.touched(); + } + Err(e) => ui.fail(e), + } + }); + }; + let cancel = move |_| { + let (api, n) = (api_c.clone(), n_c.clone()); + dioxus::dioxus_core::spawn_forever(async move { + if let Err(e) = api.cancel_spec(&n).await { + ui.fail(e); + } + }); + }; + rsx! { + div { class: "card", + div { class: "row", + h3 { Icon { name: "play" } "training" } + span { class: "grow" } + if !running { + label { class: "row small", title: "the spec's train.epochs when left empty", "epochs" + input { r#type: "number", min: "1", max: "1000", style: "width: 64px;", placeholder: "spec", + oninput: move |e| epochs.set(e.value().parse::<u32>().ok().map(|v| v.clamp(1, 1000))) } + } + if trained { + label { class: "row small", title: "from new weights instead of going on from these", + input { r#type: "checkbox", checked: fresh(), onchange: move |e| fresh.set(e.checked()) } "from scratch" } + } + crate::views::classifiers::DevicePick { device } + button { class: "primary", onclick: start, Icon { name: "play" } if trained { "train more" } else { "train" } } + } else { + button { onclick: cancel, Icon { name: "pause" } "cancel" } + } + } + if let Some(j) = job.as_ref().filter(|_| running) { + Progress { job: j.clone() } + } else { + if state == "failed" { + div { class: "bad small", {job.as_ref().and_then(|j| j["error"].as_str()).unwrap_or("it failed").to_string()} } + } + if state == "cancelled" { + div { class: "dim small", "the last run was cancelled; nothing was written" } + } + if let Some(t) = last { + TrainedFigures { t, heads: details["heads"].as_array().cloned().unwrap_or_default() } + } else { + div { class: "dim small", "It learns from what its data queries find in this save when training starts (a list's members, a tag's entries)." } + } + } + } + } +} + +#[component] +fn TrainedFigures(t: Value, heads: Vec<Value>) -> Element { + // the spec's heads, for their class names + let decls = heads; + let heads: Vec<Value> = t["heads"].as_array().cloned().unwrap_or_default(); + rsx! { + div { class: "figures", + if let Some(l) = t["loss"].as_f64() { div { b { {format!("{l:.3}")} } "loss" } } + if let Some(b) = t["bits_per_byte"].as_f64() { div { b { {format!("{b:.2}")} } "bits per byte (held out)" } } + div { b { "{t[\"examples\"]}" } {format!("examples · {} held out", t["val_examples"])} } + div { b { {format!("{:.0} s", t["seconds"].as_f64().unwrap_or(0.0))} } "{t[\"steps\"]} steps" } + div { b { {format!("{:.0}", t["tokens_per_sec"].as_f64().unwrap_or(0.0))} } "tokens/s" } + if t["weights"].as_u64().is_some_and(|w| w > 0) { div { b { {weights(t["weights"].as_u64().unwrap_or(0))} } "weights" } } + } + if heads.is_empty() && t["val_examples"] == 0 { + div { class: "dim small", "no examples were held out, so there are no metrics (train.val_fraction in the spec)" } + } + for h in heads { + { + let name = h[0].as_str().unwrap_or("").to_string(); + let m = h[1].clone(); + let classes: Vec<String> = decls.iter().find(|d| d["name"] == name.as_str()) + .map(|d| strs(&d["classes"])).unwrap_or_default(); + let ev = json!({ "metrics": m, "examples": t["examples"], "seconds": t["seconds"], "steps": t["steps"] }); + rsx! { + div { key: "{name}", class: "spec-head", + h4 { "head {name}" } + Metrics { event: ev, classes } + } + } + } + } + } +} + +fn weights(n: u64) -> String { + if n >= 1_000_000 { + format!("{:.1} M", n as f64 / 1e6) + } else if n >= 1000 { + format!("{:.0} k", n as f64 / 1e3) + } else { + n.to_string() + } +} + +// ------------------------------------------------------------------ running it + +/// every head's answer on the command bar's text, as you type +#[component] +fn SpecRun(name: String, trained: bool) -> Element { + let ui = ui(); + let api = api(); + let n0 = name.clone(); + let out = use_resource(move || { + let (api, n) = (api.clone(), n0.clone()); + let t = ui.bar.read().trim().to_string(); + let shown = (ui.view)() == View::Models; + let _ = (ui.changed)(); + async move { + if t.is_empty() || !shown { + return None; + } + sleep_ms(200).await; + Some((t.clone(), api.run_spec(&n, &t).await)) + } + }); + let (text, v) = match &*out.read() { + Some(Some((t, Ok(v)))) => (t.clone(), v.clone()), + Some(Some((_, Err(e)))) => return rsx! { div { class: "card bad", "{e}" } }, + _ => { + return rsx! { + div { class: "card", + h3 { Icon { name: "text" } "run it" } + div { class: "dim", "Type a text in the command bar below: every head's answer shows here as you type." } + } + }; + } + }; + let outputs: Vec<(String, Value)> = v["outputs"] + .as_object() + .map(|o| o.iter().map(|(k, v)| (k.clone(), v.clone())).collect()) + .unwrap_or_default(); + rsx! { + div { class: "card", + div { class: "row", + h3 { Icon { name: "text" } "run it" } + span { class: "dim small t", "“{text}”" } + if !trained { span { class: "dim small", "untrained: its starting weights answer" } } + } + for (head , a) in outputs { + div { key: "{head}", class: "spec-head", + h4 { "{head}" } + {answer(&a)} + } + } + } + } +} + +fn answer(a: &Value) -> Element { + match a["kind"].as_str() { + Some("classes") => { + let probs: Vec<(String, f64)> = a["probs"] + .as_object() + .map(|o| o.iter().map(|(k, v)| (k.clone(), v.as_f64().unwrap_or(0.0))).collect()) + .unwrap_or_default(); + let top = a["top"].as_str().unwrap_or("").to_string(); + let members = strs(&a["members"]); + let n = probs.len(); + rsx! { + div { class: "results", + for (i , (c , p)) in probs.into_iter().enumerate() { + div { key: "{c}", class: if c == top { "result best" } else { "result" }, + span { class: "t", style: "--hue: {hue(i, n)};", span { class: "swatch" } "{c}" + if members.contains(&c) { span { class: "dim small", " · in it" } } } + span { class: "probbar wide", span { style: "width: {p * 100.0:.1}%; background: hsl({hue(i, n)} 45% 55%);" } } + span { class: "p", {pct(p)} } + } + } + } + } + } + Some("values") => rsx! { + div { class: "figures", + for (k , v) in a["values"].as_object().cloned().unwrap_or_default() { + div { key: "{k}", b { {format!("{:.3}", v.as_f64().unwrap_or(0.0))} } "{k}" } + } + } + }, + _ => { + if let Some(png) = a["image"]["png"].as_str() { + rsx! { img { class: "spec-img", src: "data:image/png;base64,{png}", alt: "what it drew" } } + } else { + let t = a["text"] + .as_str() + .map(str::to_string) + .unwrap_or_else(|| a["numbers"].to_string()); + if t.is_empty() { + rsx! { div { class: "dim small", "nothing: it ended at once" } } + } else { + rsx! { div { class: "spec-out", "{t}" } } + } + } + } + } +} + +// ------------------------------------------------------------------ writing + +#[component] +fn SpecWrite(name: String, enter: Signal<u64>) -> Element { + let ui = ui(); + let api = api(); + let mut prompt = use_signal(String::new); + let mut candidates = use_signal(|| 8u32); + let mut length: Signal<Option<u32>> = use_signal(|| None); + let mut temperature: Signal<Option<f64>> = use_signal(|| None); + let mut seed = use_signal(|| 1u64); + let mut guided = use_signal(|| false); + let mut busy = use_signal(|| false); + let mut got: Signal<Option<Value>> = use_signal(|| None); + let mut form = use_signal(|| 0u64); + let write = { + let (api, n) = (api.clone(), name.clone()); + move || { + let (api, n) = (api.clone(), n.clone()); + let mut opts = json!({ "candidates": *candidates.peek(), "seed": *seed.peek(), "guided": *guided.peek() }); + if let Some(l) = *length.peek() { + opts["max_len"] = json!(l); + } + if let Some(t) = *temperature.peek() { + opts["temperature"] = json!(t); + } + let p = prompt.peek().clone(); + busy.set(true); + dioxus::dioxus_core::spawn_forever(async move { + match api.generate_spec(&n, &p, opts).await { + Ok(v) => got.set(Some(v)), + Err(e) => ui.fail(e), + } + busy.set(false); + }); + } + }; + // Enter in the bar: write after the bar's text + { + let mut write = write.clone(); + let mut seen = use_signal(|| *enter.peek()); + use_effect(move || { + let n = enter(); + if n != *seen.peek() { + seen.set(n); + prompt.set(ui.bar.peek().trim().to_string()); + form += 1; + write(); + } + }); + } + let write2 = write.clone(); + let res = got(); + let critics: Vec<String> = res + .as_ref() + .map(|r| { + r["critics"] + .as_array() + .into_iter() + .flatten() + .map(|c| { + let want = &c["want"]; + let w = want + .as_object() + .and_then(|o| o.iter().next()) + .map(|(k, v)| { + format!( + "{k} {}", + v.as_str().map(str::to_string).unwrap_or_else(|| v.to_string()) + ) + }) + .unwrap_or_default(); + format!("{} ({w})", c["model"].as_str().unwrap_or("")) + }) + .collect() + }) + .unwrap_or_default(); + rsx! { + div { class: "card", + div { class: "row", + h3 { Icon { name: "edit" } "write" } + span { class: "dim small", "candidates judged by its critics; the same seed writes the same ones · Enter in the bar writes after its text" } + } + for g in [form()] { + div { key: "{g}", class: "row wrap", + input { r#type: "text", style: "flex: 1; min-width: 160px;", placeholder: "a start to go on from (empty: from nothing)", + "aria-label": "the start", initial_value: "{prompt}", oninput: move |e| prompt.set(e.value()) } + label { class: "row small", "candidates" + input { r#type: "number", min: "1", max: "32", style: "width: 56px;", initial_value: "{candidates}", + oninput: move |e| if let Ok(v) = e.value().parse::<u32>() { candidates.set(v.clamp(1, 32)) } } } + label { class: "row small", "length" + input { r#type: "number", min: "1", max: "2000", style: "width: 64px;", placeholder: "spec", + oninput: move |e| length.set(e.value().parse::<u32>().ok().map(|v| v.clamp(1, 2000))) } } + label { class: "row small", "temperature" + input { r#type: "number", min: "0", max: "3", step: "0.1", style: "width: 60px;", placeholder: "spec", + oninput: move |e| temperature.set(e.value().parse::<f64>().ok().map(|v| v.clamp(0.0, 3.0))) } } + label { class: "row small", "seed" + input { r#type: "number", min: "0", style: "width: 64px;", initial_value: "{seed}", + oninput: move |e| if let Ok(v) = e.value().parse::<u64>() { seed.set(v) } } } + label { class: "row small", title: "steer each byte toward what the critics want (slower)", + input { r#type: "checkbox", checked: guided(), onchange: move |e| guided.set(e.checked()) } "guided" } + button { class: "primary", disabled: busy(), onclick: { let mut c = write2.clone(); move |_| c() }, Icon { name: "play" } if busy() { "writing…" } else { "write" } } + } + } + if let Some(r) = res { + div { class: "dim small", + {format!("{} candidates in {:.1} s, seed {}", r["candidates"].as_array().map_or(0, |c| c.len()), r["seconds"].as_f64().unwrap_or(0.0), r["seed"])} + if !critics.is_empty() { {format!(" · judged by {}", critics.join(", "))} } else { " · no critics in its spec" } + } + div { class: "results cands", + for c in r["candidates"].as_array().cloned().unwrap_or_default() { + Candidate { key: "{c[\"index\"]}", c: c.clone(), critics: critics.clone() } + } + } + } + } + } +} + +#[component] +fn Candidate(c: Value, critics: Vec<String>) -> Element { + let ui = ui(); + let text = c["text"].as_str().unwrap_or("").to_string(); + let kept = c["kept"] == true; + // the score is a weighted mean log; its exp is a geometric mean probability + let score = c["score"].as_f64().unwrap_or(0.0).exp(); + let scores: Vec<f64> = c["scores"] + .as_array() + .into_iter() + .flatten() + .filter_map(Value::as_f64) + .collect(); + let broken = strs(&c["broken"]); + let t = text.clone(); + rsx! { + div { class: if kept { "cand" } else { "cand broken" }, + div { class: "row", + if !critics.is_empty() { + span { class: "probbar", title: "the critics' score", span { style: "width: {score * 100.0:.1}%;" } } + span { class: "p small", {pct(score)} } + } + span { class: "cand-text", "{text}" } + button { class: "plain", "aria-label": "into the bar", "data-tip": "into the bar", onclick: move |_| ui.set_bar(&t), Icon { name: "text" } } + } + div { class: "row small dim", + for (i , s) in scores.iter().enumerate() { + span { key: "{i}", class: "chip", {format!("{} {}", critics.get(i).map(|c| c.split(' ').next().unwrap_or("")).unwrap_or(""), pct(*s))} } + } + span { {format!("log p {:.1}", c["logp"].as_f64().unwrap_or(0.0))} } + if !broken.is_empty() { span { class: "bad", {format!("left out: {}", broken.join("; "))} } } + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn every_template_is_a_spec() { + let lists: Vec<ListInfo> = ["fruit", "rocks \"and\" stones"] + .iter() + .map(|n| ListInfo { + name: n.to_string(), + count: 3, + ..Default::default() + }) + .collect(); + let judge = ("kind".to_string(), "kind".to_string(), "fruit".to_string()); + for t in Template::ALL { + for (l, j) in [(&lists[..], Some(&judge)), (&[][..], None)] { + let s = template(t, l, j, &["cats".to_string(), "dogs".to_string()]); + let spec = anend_core::classify::spec::ModelSpec::parse(&s, true) + .unwrap_or_else(|e| panic!("{}: {e:?}\n{s}", t.name())); + assert!(s.find("\"name\"") < s.find("\"data\""), "{s}"); + assert_eq!(spec.critics.len(), usize::from(t == Template::Generator && j.is_some())); + } + } + } +} diff --git a/app/src/views/specs/builder.rs b/app/src/views/specs/builder.rs new file mode 100644 index 00000000..bff21c72 --- /dev/null +++ b/app/src/views/specs/builder.rs @@ -0,0 +1,1274 @@ +//! The spec builder: every part of a model spec (docs/models.md) as a control, so a model +//! is made without typing JSON. It edits the same JSON the JSON view shows (each change is +//! written back to it, and a change in the JSON view shows here), so the two stay in step. +//! +//! The parts: the model (name, version, seed, where it runs, a pretrained start), what it +//! reads (text with its feature channels, bytes, pictures with their size and patches, +//! named numbers with their width), the trunk (a preset and any size of its own), the heads +//! (each with its kind, classes and weight), the data (the save's lists, tags, list pairs, +//! picture lists, or examples written in, picked from what the save has), and for a +//! generator its critics (other models and what they should say), its constraints and how +//! it samples; then training. A diagram shows how the parts connect. A broken rule shows +//! on the control it concerns (and at the top, with where it is). +//! +//! [`COVERED`] lists every field the spec has, as a path; a test in this file walks a spec +//! that uses every part and checks each field it finds is here and has a control. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use crate::ui::*; + +/// every field of the spec that has a control, as a path (`[]` for any index) +#[cfg_attr(not(test), allow(dead_code))] +pub const COVERED: &[&str] = &[ + "version", + "name", + "seed", + "device", + "from.pretrained", + "input.type", + "input.features", + "input.width", + "input.height", + "input.patch", + "input.codes", + "input.names", + "input.codec.digits", + "input.codec.decimals", + "input.codec.signed", + "trunk.preset", + "trunk.d_model", + "trunk.layers", + "trunk.heads", + "trunk.head_dim", + "trunk.d_ff", + "trunk.max_len", + "trunk.causal", + "trunk.pooling", + "trunk.dropout", + "heads[].name", + "heads[].kind", + "heads[].classes", + "heads[].weight", + "data[].from", + "data[].list", + "data[].tag", + "data[].input", + "data[].output", + "data[].head", + "data[].class", + "data[].value", + "data[].items[].input.text", + "data[].items[].input.bytes", + "data[].items[].input.numbers", + "data[].items[].input.image.width", + "data[].items[].input.image.height", + "data[].items[].input.image.rgb", + "data[].items[].head", + "data[].items[].class", + "data[].items[].value", + "critics[].model", + "critics[].head", + "critics[].weight", + "critics[].want.class", + "critics[].want.not", + "critics[].want.near.value", + "critics[].want.near.target", + "critics[].want.near.scale", + "critics[].want.range.value", + "critics[].want.range.lo", + "critics[].want.range.hi", + "critics[].want.range.scale", + "constraints.min_len", + "constraints.max_len", + "constraints.gates[].critic", + "constraints.gates[].class", + "constraints.gates[].member", + "constraints.sums[].measure", + "constraints.sums[].lo", + "constraints.sums[].hi", + "constraints.sums[].modulo", + "constraints.contains", + "constraints.excludes", + "sampling.temperature", + "sampling.top_k", + "sampling.top_p", + "sampling.max_len", + "sampling.stop", + "sampling.seed", + "train.epochs", + "train.batch", + "train.lr", + "train.val_fraction", + "train.patience", + "train.max_steps", + "train.threads", + "train.budget_seconds", +]; + +// ------------------------------------------------------------------ paths + +enum Seg { + Key(String), + Idx(usize), +} + +/// `a.b[2].c` as its steps +fn parts(path: &str) -> Vec<Seg> { + let mut out = Vec::new(); + for piece in path.split('.') { + let (key, rest) = piece.split_once('[').map_or((piece, ""), |(k, r)| (k, r)); + if !key.is_empty() { + out.push(Seg::Key(key.to_string())); + } + for i in rest.split('[') { + if let Ok(n) = i.trim_end_matches(']').parse() { + out.push(Seg::Idx(n)); + } + } + } + out +} + +/// the value at a path (null when it isn't there) +fn at<'a>(v: &'a Value, path: &str) -> &'a Value { + let mut cur = v; + for s in parts(path) { + cur = match s { + Seg::Key(k) => &cur[k.as_str()], + Seg::Idx(i) => &cur[i], + }; + } + cur +} + +/// sets the value at a path, making what's missing on the way; null takes a key out +fn put(v: &mut Value, path: &str, val: Value) { + let ps = parts(path); + let mut cur = v; + for (n, s) in ps.iter().enumerate() { + let last = n + 1 == ps.len(); + match s { + Seg::Key(k) => { + if !cur.is_object() { + *cur = json!({}); + } + let o = cur.as_object_mut().expect("an object"); + if last { + if val.is_null() { + o.remove(k); + } else { + o.insert(k.clone(), val); + } + return; + } + cur = o.entry(k.clone()).or_insert(Value::Null); + } + Seg::Idx(i) => { + if !cur.is_array() { + *cur = json!([]); + } + let a = cur.as_array_mut().expect("an array"); + while a.len() <= *i { + a.push(Value::Null); + } + if last { + a[*i] = val; + return; + } + cur = &mut a[*i]; + } + } + } +} + +/// takes item `i` out of the array at a path +fn remove_at(v: &mut Value, path: &str, i: usize) { + if let Some(a) = at_mut(v, path).and_then(Value::as_array_mut) + && i < a.len() + { + a.remove(i); + } +} + +fn at_mut<'a>(v: &'a mut Value, path: &str) -> Option<&'a mut Value> { + let mut cur = v; + for s in parts(path) { + cur = match s { + Seg::Key(k) => cur.get_mut(k.as_str())?, + Seg::Idx(i) => cur.get_mut(i)?, + }; + } + Some(cur) +} + +fn strings(v: &Value) -> Vec<String> { + v.as_array() + .map(|a| a.iter().filter_map(|x| x.as_str().map(str::to_string)).collect()) + .unwrap_or_default() +} + +/// a change to the spec: set a path, take one out (null), or edit it whole +#[derive(Clone, PartialEq)] +enum Change { + Set(String, Value), + Remove(String, usize), + Push(String, Value), +} + +/// the broken rule, when it's on this path +fn err_here(err: &Option<(String, String)>, path: &str) -> Option<String> { + err.as_ref().filter(|(p, _)| p == path).map(|(_, m)| m.clone()) +} + +// ------------------------------------------------------------------ the save's names + +/// a model's head: its name, kind and classes +type HeadInfo = (String, String, Vec<String>); + +#[derive(Clone, PartialEq, Default)] +struct Names { + lists: Vec<String>, + tags: Vec<String>, + picture_lists: Vec<String>, + /// pictures: id and name + pictures: Vec<(String, String)>, + /// other spec models: name and heads (name, kind, classes) + models: Vec<(String, Vec<HeadInfo>)>, + /// pretrained folders on a shared hub; any folder when `any_folder` + folders: Vec<String>, + any_folder: bool, +} + +// ------------------------------------------------------------------ the controls + +/// a labelled control, with its help and, when it's broken, the rule +fn row(label: &str, help: &str, err: Option<String>, body: Element) -> Element { + rsx! { + div { class: if err.is_some() { "sb-row bad" } else { "sb-row" }, + span { class: "sb-label", "{label}" } + div { class: "sb-ctl", + {body} + if !help.is_empty() { span { class: "sb-help", "{help}" } } + if let Some(e) = err.clone() { span { class: "sb-err", role: "alert", Icon { name: "alert" } "{e}" } } + } + } + } +} + +/// a whole number (empty: left out, the default) +fn num(v: &Value, path: String, min: f64, max: f64, step: f64, placeholder: &str, ch: EventHandler<Change>) -> Element { + let cur = at(v, &path); + let shown = cur.as_f64().map(|x| x.to_string()).unwrap_or_default(); + let int = step >= 1.0; + rsx! { + input { r#type: "number", class: "sb-num", min: "{min}", max: "{max}", step: "{step}", placeholder: "{placeholder}", value: "{shown}", + "aria-label": "{path}", + onchange: move |e| { + let t = e.value(); + let val = match t.trim().parse::<f64>() { + Ok(x) if int => json!(x.clamp(min, max).round() as i64), + Ok(x) => json!(x.clamp(min, max)), + Err(_) => Value::Null, + }; + ch.call(Change::Set(path.clone(), val)); + } } + } +} + +/// a slider with its value beside it, and "default" to leave it out when `optional` +fn slide( + v: &Value, + path: String, + (min, max, step, def): (f64, f64, f64, f64), + optional: bool, + ch: EventHandler<Change>, +) -> Element { + let cur = at(v, &path).as_f64(); + let shown = cur.unwrap_or(def); + let p2 = path.clone(); + rsx! { + span { class: "sb-slide", + input { r#type: "range", min: "{min}", max: "{max}", step: "{step}", value: "{shown}", "aria-label": "{path}", + oninput: move |e| ch.call(Change::Set(path.clone(), json!(e.value().parse::<f64>().unwrap_or(def)))) } + span { class: "sb-val", if cur.is_some() || !optional { {fmt(shown)} } else { "default" } } + if optional && cur.is_some() { + button { class: "plain small", title: "leave it to the default", onclick: move |_| ch.call(Change::Set(p2.clone(), Value::Null)), "default" } + } + } + } +} + +fn fmt(x: f64) -> String { + if x.fract() == 0.0 && x.abs() < 1e9 { + format!("{x:.0}") + } else { + format!("{x:.3}").trim_end_matches('0').to_string() + } +} + +/// one of `options` (value, words), kept as text; `none` (when given) leaves it out +fn pick( + v: &Value, + path: String, + options: Vec<(String, String)>, + none: Option<&str>, + ch: EventHandler<Change>, +) -> Element { + choose(v, path, options, none, false, ch) +} + +/// the same, its values numbers or true / false +fn pick_json( + v: &Value, + path: String, + options: Vec<(String, String)>, + none: Option<&str>, + ch: EventHandler<Change>, +) -> Element { + choose(v, path, options, none, true, ch) +} + +fn choose( + v: &Value, + path: String, + options: Vec<(String, String)>, + none: Option<&str>, + typed: bool, + ch: EventHandler<Change>, +) -> Element { + let cur = at(v, &path); + let now = match cur { + Value::String(s) => s.clone(), + Value::Null => String::new(), + other => other.to_string(), + }; + let known = options.iter().any(|(o, _)| *o == now); + rsx! { + select { class: "sb-pick", "aria-label": "{path}", + onchange: move |e| { + let t = e.value(); + let val = if t.is_empty() { + Value::Null + } else if typed { + serde_json::from_str::<Value>(&t).unwrap_or(Value::String(t)) + } else { + Value::String(t) + }; + ch.call(Change::Set(path.clone(), val)); + }, + if let Some(n) = none { option { value: "", selected: now.is_empty(), "{n}" } } + if !known && !now.is_empty() { option { value: "{now}", selected: true, "{now}" } } + for (o , w) in options.iter() { + option { key: "{o}", value: "{o}", selected: *o == now, "{w}" } + } + } + } +} + +/// a line of text (empty: left out when `optional`) +fn line(v: &Value, path: String, placeholder: &str, optional: bool, ch: EventHandler<Change>) -> Element { + let shown = at(v, &path).as_str().unwrap_or("").to_string(); + rsx! { + input { r#type: "text", class: "sb-text", placeholder: "{placeholder}", value: "{shown}", "aria-label": "{path}", + onchange: move |e| { + let t = e.value(); + ch.call(Change::Set(path.clone(), if t.is_empty() && optional { Value::Null } else { json!(t) })); + } } + } +} + +/// on or off +fn tick(v: &Value, path: String, words: &str, ch: EventHandler<Change>) -> Element { + let on = at(v, &path).as_bool().unwrap_or(false); + rsx! { + label { class: "sb-tick", + input { r#type: "checkbox", checked: on, "aria-label": "{path}", oninput: move |e| ch.call(Change::Set(path.clone(), json!(e.checked()))) } + "{words}" + } + } +} + +/// a list of words as chips: × takes one out, Enter adds what's typed +fn chips(v: &Value, path: String, placeholder: &str, ch: EventHandler<Change>) -> Element { + let all = strings(at(v, &path)); + let p_add = path.clone(); + rsx! { + span { class: "sb-chips", + for (i , w) in all.iter().enumerate() { + span { key: "{i}-{w}", class: "chip", + "{w}" + button { class: "plain small", "aria-label": "take {w} out", onclick: { let p = path.clone(); move |_| ch.call(Change::Remove(p.clone(), i)) }, "×" } + } + } + input { r#type: "text", class: "sb-chip-in", placeholder: "{placeholder}", "aria-label": "{path}: add one", + onkeydown: move |e: KeyboardEvent| { + if e.key() == Key::Enter { + e.prevent_default(); + } + }, + onchange: move |e| { + let t = e.value().trim().to_string(); + if !t.is_empty() { + ch.call(Change::Push(p_add.clone(), json!(t))); + } + } } + } + } +} + +/// byte strings (constraints' contains / excludes) as chips of text +fn byte_chips(v: &Value, path: String, placeholder: &str, ch: EventHandler<Change>) -> Element { + let all: Vec<String> = at(v, &path) + .as_array() + .map(|a| { + a.iter() + .map(|b| { + let bytes: Vec<u8> = b + .as_array() + .map(|x| x.iter().filter_map(|n| n.as_u64().map(|n| n as u8)).collect()) + .unwrap_or_default(); + String::from_utf8_lossy(&bytes).into_owned() + }) + .collect() + }) + .unwrap_or_default(); + let p_add = path.clone(); + rsx! { + span { class: "sb-chips", + for (i , w) in all.iter().enumerate() { + span { key: "{i}-{w}", class: "chip", + "“{w}”" + button { class: "plain small", "aria-label": "take it out", onclick: { let p = path.clone(); move |_| ch.call(Change::Remove(p.clone(), i)) }, "×" } + } + } + input { r#type: "text", class: "sb-chip-in", placeholder: "{placeholder}", "aria-label": "{path}: add one", + onchange: move |e| { + let t = e.value(); + if !t.is_empty() { + ch.call(Change::Push(p_add.clone(), json!(t.as_bytes()))); + } + } } + } + } +} + +/// one number per name (a regress head's values) +fn values(v: &Value, path: String, names: &[String], ch: EventHandler<Change>) -> Element { + let cur: Vec<f64> = at(v, &path) + .as_array() + .map(|a| a.iter().map(|x| x.as_f64().unwrap_or(0.0)).collect()) + .unwrap_or_default(); + let n = names.len().max(1); + rsx! { + span { class: "sb-values", + for i in 0..n { + label { key: "{i}", class: "sb-value", + span { class: "dim small", {names.get(i).cloned().unwrap_or_else(|| "value".into())} } + input { r#type: "number", class: "sb-num", step: "any", value: "{cur.get(i).copied().unwrap_or(0.0)}", "aria-label": "{path}[{i}]", + onchange: { + let path = path.clone(); + let cur = cur.clone(); + move |e: FormEvent| { + let mut all = cur.clone(); + all.resize(n, 0.0); + all[i] = e.value().parse().unwrap_or(0.0); + ch.call(Change::Set(path.clone(), json!(all))); + } + } } + } + } + } + } +} + +fn opts(xs: &[&str]) -> Vec<(String, String)> { + xs.iter().map(|x| (x.to_string(), x.replace('_', " "))).collect() +} + +fn named(xs: &[String]) -> Vec<(String, String)> { + xs.iter().map(|x| (x.clone(), x.clone())).collect() +} + +/// what an inline picture example's input holds, written whole from a picture of the save +/// (`pictures.get` with `rgb`) +#[allow(dead_code)] +const IMAGE_FIELDS: [&str; 3] = [ + "data[].items[].input.image.width", + "data[].items[].input.image.height", + "data[].items[].input.image.rgb", +]; + +// ------------------------------------------------------------------ the builder + +#[component] +pub fn SpecBuilder(text: String, on_change: EventHandler<String>, err: Option<(String, String)>) -> Element { + let api = api(); + let spec = use_memo(use_reactive!(|text| serde_json::from_str::<Value>(&text).ok())); + // the save's lists, tags, pictures, other models and pretrained folders, for the pickers + let names = use_resource(move || { + let api = api.clone(); + async move { + let mut n = Names::default(); + if let Ok(l) = api.lists().await { + n.lists = l.lists.into_iter().map(|x| x.name).collect(); + } + if let Ok(t) = api.call("tags.all", json!({})).await { + n.tags = t + .as_array() + .into_iter() + .flatten() + .filter_map(|x| x["tag"].as_str().map(str::to_string)) + .collect(); + } + if let Ok(p) = api.picture_lists().await { + n.picture_lists = p + .iter() + .filter_map(|x| x["list"].as_str().map(str::to_string)) + .collect(); + } + if let Ok(p) = api.call("pictures.list", json!({})).await { + n.pictures = p + .as_array() + .into_iter() + .flatten() + .map(|x| { + let id = x["id"].as_str().unwrap_or("").to_string(); + let name = x["name"] + .as_str() + .filter(|s| !s.is_empty()) + .map(str::to_string) + .unwrap_or_else(|| id.chars().take(8).collect()); + (id, name) + }) + .collect(); + } + if let Ok(ms) = api.spec_models().await { + n.models = ms + .iter() + .map(|m| { + let heads = m["heads"] + .as_array() + .into_iter() + .flatten() + .map(|h| { + ( + h["name"].as_str().unwrap_or("").to_string(), + h["kind"].as_str().unwrap_or("").to_string(), + strings(&h["classes"]), + ) + }) + .collect(); + (m["name"].as_str().unwrap_or("").to_string(), heads) + }) + .collect(); + } + if let Ok(p) = api.call("models.pretrained", json!({})).await { + n.any_folder = p["any"].as_bool().unwrap_or(false); + n.folders = strings(&p["folders"]); + } + n + } + }); + let ch: EventHandler<Change> = use_callback(move |c: Change| { + let Some(mut v) = spec.peek().clone() else { return }; + match c { + Change::Set(p, val) => put(&mut v, &p, val), + Change::Remove(p, i) => remove_at(&mut v, &p, i), + Change::Push(p, val) => { + let mut a = at(&v, &p).as_array().cloned().unwrap_or_default(); + a.push(val); + put(&mut v, &p, Value::Array(a)); + } + } + on_change.call(serde_json::to_string_pretty(&v).unwrap_or_default()); + }); + let Some(v) = spec() else { + return rsx! { div { class: "card sb", p { class: "spec-err small", Icon { name: "alert" } "The JSON doesn't read; fix it in the JSON view, and the builder comes back." } } }; + }; + let n = names.read().clone().unwrap_or_default(); + let heads: Vec<Value> = v["heads"].as_array().cloned().unwrap_or_default(); + let head_names: Vec<String> = heads + .iter() + .filter_map(|h| h["name"].as_str().map(str::to_string)) + .collect(); + let generates = heads.iter().any(|h| h["kind"] == "generate"); + let itype = v["input"]["type"].as_str().unwrap_or("text").to_string(); + let e = |p: &str| err_here(&err, p); + + rsx! { + div { class: "sb", + if let Some((p, m)) = err.clone() { + div { class: "spec-err small sb-top-err", role: "alert", Icon { name: "alert" } code { "{p}" } span { "{m}" } } + } + Diagram { v: v.clone() } + + // the model + div { class: "sb-sec", + h4 { "the model" } + {row("name", "other models' critics name it by this", e("name"), line(&v, "name".into(), "its name", false, ch))} + {row("version", "the spec format's version", e("version"), pick_json(&v, "version".into(), vec![("1".into(), "1".into())], Some("1 (the default)"), ch))} + {row("seed", "the weights' and the data split's seed", e("seed"), num(&v, "seed".into(), 0.0, 4294967295.0, 1.0, "0", ch))} + {row("runs on", "where training and writing run", e("device"), pick(&v, "device".into(), vec![("gpu".into(), "the GPU, exact".into()), ("gpu_fast".into(), "the GPU, fast".into())], Some("the CPU (the default)"), ch))} + {row("starts from", "a pretrained model folder (its trunk and vocabulary), or new weights", e("from.pretrained") .or(e("from")), + if n.any_folder { + line(&v, "from.pretrained".into(), "a model folder on this machine (empty: new weights)", true, ch) + } else { + pick(&v, "from.pretrained".into(), named(&n.folders), Some("new weights"), ch) + })} + } + + // what it reads + div { class: "sb-sec", + h4 { "what it reads" } + {row("input", "", e("input.type").or(e("input")), rsx! { + select { class: "sb-pick", "aria-label": "input.type", + onchange: move |ev| { + let t = ev.value(); + let fresh = match t.as_str() { + "image" => json!({ "type": "image", "width": 32, "height": 32, "patch": 8, "codes": 128 }), + "numbers" => json!({ "type": "numbers", "names": ["a"], "codec": { "digits": 3, "decimals": 1, "signed": false } }), + other => json!({ "type": other }), + }; + ch.call(Change::Set("input".into(), fresh)); + }, + for (o , w) in [("text", "text"), ("bytes", "bytes"), ("image", "pictures"), ("numbers", "numbers")] { + option { key: "{o}", value: "{o}", selected: itype == o, "{w}" } + } + } + })} + if itype == "text" { + {row("channels", "gematria and shape features beside the bytes (all off by default)", e("input.features"), rsx! { + span { class: "sb-ticks", + for (f , w) in [("letters", "letter values"), ("word_sums", "word sums"), ("side", "whole-text measures")] { + { + let has = strings(&v["input"]["features"]).contains(&f.to_string()); + let all = strings(&v["input"]["features"]); + rsx! { + label { key: "{f}", class: "sb-tick", + input { r#type: "checkbox", checked: has, "aria-label": "input.features {f}", + oninput: move |ev| { + let mut a = all.clone(); + a.retain(|x| x != f); + if ev.checked() { a.push(f.to_string()); } + ch.call(Change::Set("input.features".into(), json!(a))); + } } + "{w}" + } + } + } + } + } + })} + } + if itype == "image" { + {row("size", "pixels; each a multiple of the patch", e("input.width").or(e("input.height")), rsx! { + span { class: "sb-pair", {num(&v, "input.width".into(), 8.0, 1024.0, 8.0, "32", ch)} "×" {num(&v, "input.height".into(), 8.0, 1024.0, 8.0, "32", ch)} } + })} + {row("patch", "a patch's side in pixels: one token each", e("input.patch"), num(&v, "input.patch".into(), 1.0, 64.0, 1.0, "8", ch))} + {row("codes", "how many learned patch prototypes (at most 255)", e("input.codes"), slide(&v, "input.codes".into(), (2.0, 255.0, 1.0, 128.0), true, ch))} + } + if itype == "numbers" { + {row("names", "one per number the model reads", e("input.names"), chips(&v, "input.names".into(), "a name, Enter", ch))} + {row("width", "digits before and after the point", e("input.codec.digits").or(e("input.codec.decimals")), rsx! { + span { class: "sb-pair", {num(&v, "input.codec.digits".into(), 1.0, 12.0, 1.0, "3", ch)} "." {num(&v, "input.codec.decimals".into(), 0.0, 8.0, 1.0, "1", ch)} } + })} + {row("signed", "", e("input.codec.signed"), tick(&v, "input.codec.signed".into(), "numbers can be below zero", ch))} + } + } + + // the trunk + div { class: "sb-sec", + h4 { "the trunk" } + {row("preset", "the sizes; any set below override it", e("trunk.preset"), pick(&v, "trunk.preset".into(), opts(&["compact", "small", "base", "auto", "test"]), Some("the default"), ch))} + details { class: "sb-more", + summary { "sizes of its own" } + {row("width", "d_model", e("trunk.d_model"), num(&v, "trunk.d_model".into(), 8.0, 4096.0, 8.0, "from the preset", ch))} + {row("layers", "", e("trunk.layers"), num(&v, "trunk.layers".into(), 1.0, 48.0, 1.0, "from the preset", ch))} + {row("attention heads", "", e("trunk.heads"), num(&v, "trunk.heads".into(), 1.0, 64.0, 1.0, "from the preset", ch))} + {row("head size", "head_dim", e("trunk.head_dim"), num(&v, "trunk.head_dim".into(), 4.0, 512.0, 4.0, "from the preset", ch))} + {row("feed-forward", "d_ff", e("trunk.d_ff"), num(&v, "trunk.d_ff".into(), 8.0, 16384.0, 8.0, "from the preset", ch))} + {row("window", "tokens per window, CLS and SEP included", e("trunk.max_len"), num(&v, "trunk.max_len".into(), 8.0, 8192.0, 1.0, "from the preset", ch))} + {row("causal", "on by default when there's a generate head", e("trunk.causal"), pick_json(&v, "trunk.causal".into(), vec![("true".into(), "causal".into()), ("false".into(), "not causal".into())], Some("the default"), ch))} + {row("pooling", "how the tokens become one vector for the heads", e("trunk.pooling"), pick(&v, "trunk.pooling".into(), vec![("Cls".into(), "CLS token".into()), ("Mean".into(), "mean".into()), ("ClsMean".into(), "CLS and mean".into()), ("Attention".into(), "attention".into())], Some("the default"), ch))} + {row("dropout", "", e("trunk.dropout"), slide(&v, "trunk.dropout".into(), (0.0, 0.5, 0.01, 0.1), true, ch))} + } + } + + // the heads + div { class: "sb-sec", + h4 { "the heads" span { class: "dim small", " what comes out" } } + for (i , h) in heads.iter().enumerate() { + { + let kind = h["kind"].as_str().unwrap_or("classify").to_string(); + rsx! { + div { key: "{i}", class: "sb-item", + div { class: "sb-item-head", + span { class: "sb-n", "{i + 1}" } + {line(&v, format!("heads[{i}].name"), "its name", false, ch)} + {pick(&v, format!("heads[{i}].kind"), vec![("classify".into(), "one class of several".into()), ("multi".into(), "any of several labels".into()), ("regress".into(), "numbers".into()), ("generate".into(), "writes (the next byte)".into())], None, ch)} + button { class: "plain small", title: "take this head out", onclick: move |_| ch.call(Change::Remove("heads".into(), i)), Icon { name: "delete" } } + } + if let Some(m) = e(&format!("heads[{i}].name")).or(e(&format!("heads[{i}].kind"))).or(e(&format!("heads[{i}]"))) { span { class: "sb-err", Icon { name: "alert" } "{m}" } } + if kind != "generate" { + {row(if kind == "regress" { "values" } else { "classes" }, if kind == "regress" { "a name per number it gives" } else { "" }, e(&format!("heads[{i}].classes")), chips(&v, format!("heads[{i}].classes"), "add one, Enter", ch))} + } + {row("weight", "its share of the loss when heads train together", e(&format!("heads[{i}].weight")), slide(&v, format!("heads[{i}].weight"), (0.0, 5.0, 0.05, 1.0), true, ch))} + } + } + } + } + button { class: "btn small", onclick: move |_| ch.call(Change::Push("heads".into(), json!({ "name": format!("head {}", heads.len() + 1), "kind": "classify", "classes": ["yes", "no"] }))), + Icon { name: "new" } "a head" } + } + + // the data + DataSection { v: v.clone(), names: n.clone(), head_names: head_names.clone(), itype: itype.clone(), err: err.clone(), ch } + + // a generator's critics, constraints and sampling + if generates || v["critics"].as_array().is_some_and(|a| !a.is_empty()) { + CriticSection { v: v.clone(), names: n.clone(), err: err.clone(), ch } + } + if generates { + div { class: "sb-sec", + h4 { "what it writes" span { class: "dim small", " a candidate breaking these is dropped" } } + {row("length", "bytes, at least and at most (empty: no limit)", e("constraints.min_len").or(e("constraints.max_len")), rsx! { + span { class: "sb-pair", {num(&v, "constraints.min_len".into(), 0.0, 100000.0, 1.0, "0", ch)} "to" {num(&v, "constraints.max_len".into(), 0.0, 100000.0, 1.0, "no limit", ch)} } + })} + {row("must contain", "each of these", e("constraints.contains"), byte_chips(&v, "constraints.contains".into(), "a text, Enter", ch))} + {row("must not contain", "any of these", e("constraints.excludes"), byte_chips(&v, "constraints.excludes".into(), "a text, Enter", ch))} + for (g , _) in v["constraints"]["sums"].as_array().cloned().unwrap_or_default().iter().enumerate() { + div { key: "sum{g}", class: "sb-item", + div { class: "sb-item-head", + span { class: "small", "a sum:" } + {pick(&v, format!("constraints.sums[{g}].measure"), vec![("bytes".into(), "bytes (Σ byte + 1)".into()), ("bytes_reversed".into(), "bytes reversed".into()), ("ordinal".into(), "ordinal".into()), ("reversed".into(), "reversed".into()), ("length".into(), "length".into())], None, ch)} + {num(&v, format!("constraints.sums[{g}].lo"), 0.0, 1e12, 1.0, "from", ch)} + "to" + {num(&v, format!("constraints.sums[{g}].hi"), 0.0, 1e12, 1.0, "to", ch)} + "mod" + {num(&v, format!("constraints.sums[{g}].modulo"), 0.0, 1e12, 1.0, "none", ch)} + button { class: "plain small", onclick: move |_| ch.call(Change::Remove("constraints.sums".into(), g)), Icon { name: "delete" } } + } + if let Some(m) = e(&format!("constraints.sums[{g}]")) { span { class: "sb-err", Icon { name: "alert" } "{m}" } } + } + } + button { class: "btn small", onclick: move |_| ch.call(Change::Push("constraints.sums".into(), json!({ "measure": "ordinal", "lo": 0, "hi": 1000 }))), Icon { name: "new" } "a sum it must fall in" } + GateRows { v: v.clone(), names: n.clone(), err: err.clone(), ch } + h4 { class: "sb-sub", "sampling" } + {row("temperature", "0 always picks the likeliest byte", e("sampling.temperature"), slide(&v, "sampling.temperature".into(), (0.0, 2.0, 0.05, 0.8), true, ch))} + {row("top k", "keep only the k likeliest bytes (0: all)", e("sampling.top_k"), num(&v, "sampling.top_k".into(), 0.0, 256.0, 1.0, "0", ch))} + {row("top p", "keep the fewest likeliest bytes reaching p", e("sampling.top_p"), slide(&v, "sampling.top_p".into(), (0.0, 1.0, 0.01, 0.95), true, ch))} + {row("at most", "bytes written", e("sampling.max_len"), num(&v, "sampling.max_len".into(), 1.0, 100000.0, 1.0, "200", ch))} + {row("stops at", "a character that ends what it writes", e("sampling.stop"), rsx! { + input { r#type: "text", class: "sb-text sb-short", maxlength: "1", placeholder: "none", "aria-label": "sampling.stop", + value: v["sampling"]["stop"].as_u64().map(|b| (b as u8 as char).to_string()).unwrap_or_default(), + onchange: move |ev| { + let t = ev.value(); + ch.call(Change::Set("sampling.stop".into(), t.bytes().next().map_or(Value::Null, |b| json!(b)))); + } } + })} + {row("seed", "", e("sampling.seed"), num(&v, "sampling.seed".into(), 0.0, 4294967295.0, 1.0, "0", ch))} + } + } + + // training + div { class: "sb-sec", + h4 { "training" } + {row("epochs", "", e("train.epochs"), num(&v, "train.epochs".into(), 1.0, 10000.0, 1.0, "the default", ch))} + {row("batch", "", e("train.batch"), num(&v, "train.batch".into(), 1.0, 4096.0, 1.0, "the default", ch))} + {row("learning rate", "", e("train.lr"), num(&v, "train.lr".into(), 0.000001, 1.0, 0.0001, "the default", ch))} + {row("held out", "the share of the data kept for checking", e("train.val_fraction"), slide(&v, "train.val_fraction".into(), (0.0, 0.5, 0.01, 0.1), true, ch))} + {row("patience", "epochs without improving before it stops", e("train.patience"), num(&v, "train.patience".into(), 0.0, 1000.0, 1.0, "the default", ch))} + {row("steps at most", "", e("train.max_steps"), num(&v, "train.max_steps".into(), 1.0, 1e9, 1.0, "no limit", ch))} + {row("threads", "", e("train.threads"), num(&v, "train.threads".into(), 1.0, 256.0, 1.0, "the default", ch))} + {row("time budget", "seconds an \"auto\" trunk is sized for", e("train.budget_seconds"), num(&v, "train.budget_seconds".into(), 1.0, 1e6, 1.0, "none", ch))} + } + } + } +} + +/// the data rows: where each head's examples come from +#[component] +fn DataSection( + v: Value, + names: Names, + head_names: Vec<String>, + itype: String, + err: Option<(String, String)>, + ch: EventHandler<Change>, +) -> Element { + let api = api(); + let u = ui(); + let hn_add = head_names.clone(); + let data: Vec<Value> = v["data"].as_array().cloned().unwrap_or_default(); + let e = |p: &str| err_here(&err, p); + let classes_of = |head: &str| -> (String, Vec<String>) { + v["heads"] + .as_array() + .into_iter() + .flatten() + .find(|h| h["name"] == head) + .map(|h| (h["kind"].as_str().unwrap_or("").to_string(), strings(&h["classes"]))) + .unwrap_or_default() + }; + // a head and its class or values, as the head's kind needs + let target = |prefix: String, d: &Value| -> Element { + let head = d["head"].as_str().unwrap_or("").to_string(); + let (kind, classes) = classes_of(&head); + rsx! { + {pick(&v, format!("{prefix}.head"), named(&head_names), Some("which head?"), ch)} + if kind == "classify" || kind == "multi" { + {pick(&v, format!("{prefix}.class"), named(&classes), Some("which class?"), ch)} + } + if kind == "regress" { + {values(&v, format!("{prefix}.value"), &classes, ch)} + } + } + }; + rsx! { + div { class: "sb-sec", + h4 { "the data" span { class: "dim small", " what each head learns from" } } + for (i , d) in data.iter().enumerate() { + { + let from = d["from"].as_str().unwrap_or("list").to_string(); + let head = d["head"].clone(); + rsx! { + div { key: "{i}", class: "sb-item", + div { class: "sb-item-head", + span { class: "sb-n", "{i + 1}" } + select { class: "sb-pick", "aria-label": "data[{i}].from", + onchange: move |ev| { + let f = ev.value(); + let mut fresh = json!({ "from": f }); + if f != "inline" && !head.is_null() { fresh["head"] = head.clone(); } + if f == "inline" { fresh["items"] = json!([]); } + ch.call(Change::Set(format!("data[{i}]"), fresh)); + }, + for (o , w) in [("list", "a list's members"), ("tagged", "texts with a tag"), ("pairs", "pairs of two lists"), ("pictures", "pictures"), ("inline", "examples written here")] { + option { key: "{o}", value: "{o}", selected: from == o, "{w}" } + } + } + button { class: "plain small", title: "take this out", onclick: move |_| ch.call(Change::Remove("data".into(), i)), Icon { name: "delete" } } + } + if let Some(m) = e(&format!("data[{i}]")).or(e(&format!("data[{i}].from"))) { span { class: "sb-err", Icon { name: "alert" } "{m}" } } + match from.as_str() { + "list" => rsx! { + {row("list", "", e(&format!("data[{i}].list")), pick(&v, format!("data[{i}].list"), named(&names.lists), Some("which list?"), ch))} + {row("for", "the head, and what its members are", e(&format!("data[{i}].head")).or(e(&format!("data[{i}].class"))).or(e(&format!("data[{i}].value"))), target(format!("data[{i}]"), d))} + }, + "tagged" => rsx! { + {row("tag", "", e(&format!("data[{i}].tag")), pick(&v, format!("data[{i}].tag"), named(&names.tags), Some("which tag?"), ch))} + {row("for", "", e(&format!("data[{i}].head")).or(e(&format!("data[{i}].class"))).or(e(&format!("data[{i}].value"))), target(format!("data[{i}]"), d))} + }, + "pairs" => rsx! { + {row("in", "what it reads", e(&format!("data[{i}].input")), pick(&v, format!("data[{i}].input"), named(&names.lists), Some("which list?"), ch))} + {row("out", "what it learns to write after it, member by member", e(&format!("data[{i}].output")), pick(&v, format!("data[{i}].output"), named(&names.lists), Some("which list?"), ch))} + {row("head", "a generate head", e(&format!("data[{i}].head")), pick(&v, format!("data[{i}].head"), named(&head_names), Some("which head?"), ch))} + }, + "pictures" => rsx! { + {row("pictures", "each scaled to the input's size", e(&format!("data[{i}].list")), pick(&v, format!("data[{i}].list"), named(&names.picture_lists), Some("all of the save's pictures"), ch))} + {row("for", "", e(&format!("data[{i}].head")).or(e(&format!("data[{i}].class"))).or(e(&format!("data[{i}].value"))), target(format!("data[{i}]"), d))} + }, + _ => rsx! { + for (j , item) in d["items"].as_array().cloned().unwrap_or_default().iter().enumerate() { + div { key: "{j}", class: "sb-inline", + span { class: "dim small", "{j + 1}" } + match itype.as_str() { + "numbers" => rsx! { + {values(&v, format!("data[{i}].items[{j}].input.numbers"), &strings(&v["input"]["names"]), ch)} + }, + "image" => { + let w = item["input"]["image"]["width"].as_u64().unwrap_or(0); + let h = item["input"]["image"]["height"].as_u64().unwrap_or(0); + let api = api.clone(); + let (iw, ih) = (v["input"]["width"].as_u64().unwrap_or(32), v["input"]["height"].as_u64().unwrap_or(32)); + rsx! { + span { class: "small", if w > 0 { "a picture, {w} × {h}" } else { "no picture yet" } } + select { class: "sb-pick", "aria-label": "data[{i}].items[{j}].input.image", + onchange: move |ev| { + let id = ev.value(); + if id.is_empty() { return; } + let api = api.clone(); + spawn(async move { + // the picture as the item's input: IMAGE_FIELDS + match api.call("pictures.get", json!({ "id": id, "rgb": { "width": iw, "height": ih } })).await { + Ok(p) => ch.call(Change::Set(format!("data[{i}].items[{j}].input"), json!({ "image": p["image"] }))), + Err(err) => u.fail(err), + } + }); + }, + option { value: "", "from a picture…" } + for (id , nm) in names.pictures.iter() { option { key: "{id}", value: "{id}", "{nm}" } } + } + } + } + "bytes" => rsx! { + input { r#type: "text", class: "sb-text", placeholder: "its bytes, as text", "aria-label": "data[{i}].items[{j}].input.bytes", + value: String::from_utf8_lossy(&item["input"]["bytes"].as_array().map(|a| a.iter().filter_map(|x| x.as_u64().map(|b| b as u8)).collect::<Vec<u8>>()).unwrap_or_default()).into_owned(), + onchange: move |ev| ch.call(Change::Set(format!("data[{i}].items[{j}].input"), json!({ "bytes": ev.value().as_bytes() }))) } + }, + _ => rsx! { + input { r#type: "text", class: "sb-text", placeholder: "its text", "aria-label": "data[{i}].items[{j}].input.text", + value: item["input"]["text"].as_str().unwrap_or("").to_string(), + onchange: move |ev| ch.call(Change::Set(format!("data[{i}].items[{j}].input"), json!({ "text": ev.value() }))) } + }, + } + {target(format!("data[{i}].items[{j}]"), item)} + if let Some(m) = e(&format!("data[{i}].items[{j}].head")).or(e(&format!("data[{i}].items[{j}].class"))).or(e(&format!("data[{i}].items[{j}].value"))).or(e(&format!("data[{i}].items[{j}].input"))) { + span { class: "sb-err", Icon { name: "alert" } "{m}" } + } + button { class: "plain small", onclick: move |_| ch.call(Change::Remove(format!("data[{i}].items"), j)), "×" } + } + } + button { class: "plain small", onclick: { + let (itype, head_names) = (itype.clone(), head_names.clone()); + move |_| { + let input = match itype.as_str() { + "numbers" => json!({ "numbers": [] }), + "bytes" => json!({ "bytes": [] }), + "image" => json!({ "image": { "width": 0, "height": 0, "rgb": [] } }), + _ => json!({ "text": "" }), + }; + ch.call(Change::Push(format!("data[{i}].items"), json!({ "input": input, "head": head_names.first().cloned().unwrap_or_default() }))); + } }, + Icon { name: "new" } "an example" } + }, + } + } + } + } + } + button { class: "btn small", onclick: move |_| ch.call(Change::Push("data".into(), json!({ "from": "list", "head": hn_add.first().cloned().unwrap_or_default() }))), Icon { name: "new" } "data" } + } + } +} + +/// a generator's critics: another model, its head, and what it should say +#[component] +fn CriticSection(v: Value, names: Names, err: Option<(String, String)>, ch: EventHandler<Change>) -> Element { + let critics: Vec<Value> = v["critics"].as_array().cloned().unwrap_or_default(); + let e = |p: &str| err_here(&err, p); + let me = v["name"].as_str().unwrap_or("").to_string(); + let models: Vec<String> = names.models.iter().map(|m| m.0.clone()).filter(|m| *m != me).collect(); + rsx! { + div { class: "sb-sec", + h4 { "critics" span { class: "dim small", " other models judging what it writes" } } + for (k , c) in critics.iter().enumerate() { + { + let model = c["model"].as_str().unwrap_or("").to_string(); + let heads = names.models.iter().find(|m| m.0 == model).map(|m| m.1.clone()).unwrap_or_default(); + let head = c["head"].as_str().unwrap_or("").to_string(); + let (hkind, classes) = heads.iter().find(|h| h.0 == head).map(|h| (h.1.clone(), h.2.clone())).unwrap_or_default(); + let want_kind = c["want"].as_object().and_then(|o| o.keys().next().cloned()).unwrap_or_else(|| "class".into()); + let wk = want_kind.clone(); + rsx! { + div { key: "{k}", class: "sb-item", + div { class: "sb-item-head", + span { class: "sb-n", "{k + 1}" } + {pick(&v, format!("critics[{k}].model"), named(&models), Some("which model?"), ch)} + {pick(&v, format!("critics[{k}].head"), heads.iter().map(|h| (h.0.clone(), format!("{} ({})", h.0, h.1))).collect(), Some("which head?"), ch)} + button { class: "plain small", onclick: move |_| ch.call(Change::Remove("critics".into(), k)), Icon { name: "delete" } } + } + if let Some(m) = e(&format!("critics[{k}]")).or(e(&format!("critics[{k}].model"))).or(e(&format!("critics[{k}].head"))) { span { class: "sb-err", Icon { name: "alert" } "{m}" } } + {row("wants", "", e(&format!("critics[{k}].want")), rsx! { + select { class: "sb-pick", "aria-label": "critics[{k}].want", + onchange: move |ev| { + let w = match ev.value().as_str() { + "not" => json!({ "not": "" }), + "near" => json!({ "near": { "value": "", "target": 0.0, "scale": 1.0 } }), + "range" => json!({ "range": { "value": "", "lo": 0.0, "hi": 1.0, "scale": 1.0 } }), + _ => json!({ "class": "" }), + }; + ch.call(Change::Set(format!("critics[{k}].want"), w)); + }, + for (o , w) in [("class", "a class"), ("not", "not a class"), ("near", "a value near"), ("range", "a value between")] { + option { key: "{o}", value: "{o}", selected: wk == o, "{w}" } + } + } + match want_kind.as_str() { + "not" => pick(&v, format!("critics[{k}].want.not"), named(&classes), Some("which class?"), ch), + "near" => rsx! { + {pick(&v, format!("critics[{k}].want.near.value"), named(&classes), Some("which value?"), ch)} + "near" {num(&v, format!("critics[{k}].want.near.target"), -1e9, 1e9, 0.01, "target", ch)} + "within" {num(&v, format!("critics[{k}].want.near.scale"), 0.0001, 1e9, 0.01, "scale", ch)} + }, + "range" => rsx! { + {pick(&v, format!("critics[{k}].want.range.value"), named(&classes), Some("which value?"), ch)} + {num(&v, format!("critics[{k}].want.range.lo"), -1e9, 1e9, 0.01, "from", ch)} + "to" {num(&v, format!("critics[{k}].want.range.hi"), -1e9, 1e9, 0.01, "to", ch)} + "softness" {num(&v, format!("critics[{k}].want.range.scale"), 0.0001, 1e9, 0.01, "scale", ch)} + }, + _ => pick(&v, format!("critics[{k}].want.class"), named(&classes), Some("which class?"), ch), + } + if !hkind.is_empty() { span { class: "dim small", "({hkind})" } } + })} + {row("weight", "its share of the score", e(&format!("critics[{k}].weight")), slide(&v, format!("critics[{k}].weight"), (0.0, 5.0, 0.05, 1.0), true, ch))} + } + } + } + } + button { class: "btn small", disabled: models.is_empty(), title: if models.is_empty() { "make another model first: a critic is another model" } else { "another model judging what this one writes" }, + onclick: move |_| ch.call(Change::Push("critics".into(), json!({ "model": "", "head": "", "want": { "class": "" } }))), + Icon { name: "new" } "a critic" } + } + } +} + +/// gates: a critic's class that must (or must not) be among what it says +#[component] +fn GateRows(v: Value, names: Names, err: Option<(String, String)>, ch: EventHandler<Change>) -> Element { + let critics: Vec<Value> = v["critics"].as_array().cloned().unwrap_or_default(); + let gates: Vec<Value> = v["constraints"]["gates"].as_array().cloned().unwrap_or_default(); + let e = |p: &str| err_here(&err, p); + let classes_of = |ci: usize| -> Vec<String> { + let Some(c) = critics.get(ci) else { return vec![] }; + names + .models + .iter() + .find(|m| m.0 == c["model"].as_str().unwrap_or("")) + .and_then(|m| m.1.iter().find(|h| h.0 == c["head"].as_str().unwrap_or(""))) + .map(|h| h.2.clone()) + .unwrap_or_default() + }; + rsx! { + for (g , gate) in gates.iter().enumerate() { + { + let ci = gate["critic"].as_u64().unwrap_or(0) as usize; + let classes = classes_of(ci); + rsx! { + div { key: "gate{g}", class: "sb-item", + div { class: "sb-item-head", + span { class: "small", "critic" } + {pick_json(&v, format!("constraints.gates[{g}].critic"), critics.iter().enumerate().map(|(i, c)| (i.to_string(), format!("{} {}", i + 1, c["model"].as_str().unwrap_or("")))).collect(), None, ch)} + {pick_json(&v, format!("constraints.gates[{g}].member"), vec![("true".into(), "must say".into()), ("false".into(), "must not say".into())], None, ch)} + {pick_json(&v, format!("constraints.gates[{g}].class"), classes.iter().enumerate().map(|(i, c)| (i.to_string(), c.clone())).collect(), None, ch)} + button { class: "plain small", onclick: move |_| ch.call(Change::Remove("constraints.gates".into(), g)), Icon { name: "delete" } } + } + if let Some(m) = e(&format!("constraints.gates[{g}]")) { span { class: "sb-err", Icon { name: "alert" } "{m}" } } + } + } + } + } + button { class: "btn small", disabled: critics.is_empty(), title: "a critic's class that must, or must not, be among what it says", + onclick: move |_| ch.call(Change::Push("constraints.gates".into(), json!({ "critic": 0, "class": 0, "member": true }))), + Icon { name: "new" } "a gate" } + } +} + +/// how the parts connect: the data into the heads, the input through the trunk to the +/// heads, the critics judging a generate head +#[component] +fn Diagram(v: Value) -> Element { + let heads: Vec<(String, String)> = v["heads"] + .as_array() + .into_iter() + .flatten() + .map(|h| { + ( + h["name"].as_str().unwrap_or("").to_string(), + h["kind"].as_str().unwrap_or("").to_string(), + ) + }) + .collect(); + let data: Vec<(String, String)> = v["data"] + .as_array() + .into_iter() + .flatten() + .map(|d| { + let what = match d["from"].as_str().unwrap_or("") { + "list" => format!("list {}", d["list"].as_str().unwrap_or("?")), + "tagged" => format!("tag {}", d["tag"].as_str().unwrap_or("?")), + "pairs" => format!( + "{} → {}", + d["input"].as_str().unwrap_or("?"), + d["output"].as_str().unwrap_or("?") + ), + "pictures" => d["list"] + .as_str() + .map_or("all pictures".to_string(), |l| format!("pictures {l}")), + _ => format!("{} examples", d["items"].as_array().map_or(0, |a| a.len())), + }; + (what, d["head"].as_str().unwrap_or("").to_string()) + }) + .collect(); + let critics: Vec<String> = v["critics"] + .as_array() + .into_iter() + .flatten() + .map(|c| c["model"].as_str().unwrap_or("?").to_string()) + .collect(); + let input = match v["input"]["type"].as_str().unwrap_or("text") { + "image" => format!("pictures {}×{}", v["input"]["width"], v["input"]["height"]), + "numbers" => format!("{} numbers", v["input"]["names"].as_array().map_or(0, |a| a.len())), + t => t.to_string(), + }; + let trunk = format!( + "trunk · {}{}", + v["trunk"]["preset"].as_str().unwrap_or("default"), + v["from"]["pretrained"].as_str().map(|_| " · pretrained").unwrap_or("") + ); + let rows = heads.len().max(data.len()).max(critics.len()).max(1); + let h = 26.0 * rows as f64 + 20.0; + let y = |i: usize, n: usize| -> f64 { 10.0 + (h - 20.0) * (i as f64 + 0.5) / n.max(1) as f64 }; + let short = |s: &str| -> String { + if s.chars().count() > 18 { + format!("{}…", s.chars().take(17).collect::<String>()) + } else { + s.to_string() + } + }; + let head_y = |name: &str| heads.iter().position(|h| h.0 == name).map(|i| y(i, heads.len())); + let gen_y = heads.iter().position(|h| h.1 == "generate").map(|i| y(i, heads.len())); + rsx! { + svg { class: "sb-diagram", view_box: "0 0 640 {h}", width: "100%", height: "{h}", role: "img", "aria-label": "how the spec's parts connect", + // the data feeding the heads they teach + for (i , (what , head)) in data.iter().enumerate() { + g { key: "d{i}", + rect { x: "4", y: "{y(i, data.len()) - 11.0}", width: "120", height: "22", rx: "5", class: "sb-d-data" } + text { x: "64", y: "{y(i, data.len()) + 4.0}", "text-anchor": "middle", {short(what)} } + if let Some(hy) = head_y(head) { + path { d: "M124 {y(i, data.len())} C 300 {y(i, data.len()) - 60.0}, 380 {hy + 40.0}, 460 {hy}", class: "sb-d-teach" } + } + } + } + // the input and the trunk in the middle + rect { x: "150", y: "{h / 2.0 - 13.0}", width: "110", height: "26", rx: "5", class: "sb-d-in" } + text { x: "205", y: "{h / 2.0 + 4.0}", "text-anchor": "middle", {short(&input)} } + line { x1: "260", y1: "{h / 2.0}", x2: "290", y2: "{h / 2.0}", class: "sb-d-line" } + rect { x: "290", y: "{h / 2.0 - 13.0}", width: "130", height: "26", rx: "5", class: "sb-d-trunk" } + text { x: "355", y: "{h / 2.0 + 4.0}", "text-anchor": "middle", {short(&trunk)} } + for (i , (name , kind)) in heads.iter().enumerate() { + g { key: "h{i}", + line { x1: "420", y1: "{h / 2.0}", x2: "460", y2: "{y(i, heads.len())}", class: "sb-d-line" } + rect { x: "460", y: "{y(i, heads.len()) - 11.0}", width: "100", height: "22", rx: "5", class: "sb-d-head" } + text { x: "510", y: "{y(i, heads.len()) + 4.0}", "text-anchor": "middle", {short(&format!("{name} · {kind}"))} } + } + } + // the critics judging the generate head + if let Some(gy) = gen_y { + for (i , c) in critics.iter().enumerate() { + g { key: "c{i}", + rect { x: "580", y: "{y(i, critics.len()) - 11.0}", width: "56", height: "22", rx: "5", class: "sb-d-critic" } + text { x: "608", y: "{y(i, critics.len()) + 4.0}", "text-anchor": "middle", {short(c).chars().take(8).collect::<String>()} } + line { x1: "580", y1: "{y(i, critics.len())}", x2: "560", y2: "{gy}", class: "sb-d-judge" } + } + } + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + + /// every path in a value, arrays as `[]` (scalars and arrays of scalars are leaves) + fn walk(v: &Value, at: &str, out: &mut Vec<String>) { + match v { + Value::Object(o) => { + for (k, x) in o { + let p = if at.is_empty() { k.clone() } else { format!("{at}.{k}") }; + walk(x, &p, out); + } + } + // an empty list says nothing about what its items hold + Value::Array(a) if a.is_empty() => {} + Value::Array(a) if a.iter().any(Value::is_object) => { + for x in a { + walk(x, &format!("{at}[]"), out); + } + } + _ => out.push(at.to_string()), + } + } + + /// specs using every part of the format, read by the core (so every field is real) + fn every_part() -> Vec<Value> { + use anend_core::classify::spec::ModelSpec; + let full = r#"{ + "version": 1, "name": "all", "seed": 3, "device": "gpu_fast", + "from": {"pretrained": "folder"}, + "input": {"type": "text", "features": ["letters", "word_sums", "side"]}, + "trunk": {"preset": "small", "d_model": 64, "layers": 2, "heads": 4, "head_dim": 16, "d_ff": 128, + "max_len": 64, "causal": true, "pooling": "Mean", "dropout": 0.1}, + "heads": [{"name": "c", "kind": "classify", "classes": ["a", "b"], "weight": 1.0}, + {"name": "r", "kind": "regress", "classes": ["x"], "weight": 0.5}, + {"name": "g", "kind": "generate"}], + "data": [ + {"from": "list", "list": "l", "head": "c", "class": "a", "value": [1.0]}, + {"from": "tagged", "tag": "t", "head": "r", "value": [1.0]}, + {"from": "pairs", "input": "i", "output": "o", "head": "g"}, + {"from": "pictures", "list": "p", "head": "c", "class": "b"}, + {"from": "inline", "items": [ + {"input": {"text": "x"}, "head": "c", "class": "a", "value": [1.0]}, + {"input": {"bytes": [1, 2]}, "head": "c", "class": "b"}, + {"input": {"numbers": [1.0]}, "head": "r", "value": [2.0]}, + {"input": {"image": {"width": 1, "height": 1, "rgb": [0, 0, 0]}}, "head": "c", "class": "a"} + ]} + ], + "critics": [ + {"model": "m", "head": "h", "want": {"class": "a"}, "weight": 1.0}, + {"model": "m", "head": "h", "want": {"not": "a"}}, + {"model": "m", "head": "h", "want": {"near": {"value": "v", "target": 1.0, "scale": 1.0}}}, + {"model": "m", "head": "h", "want": {"range": {"value": "v", "lo": 0.0, "hi": 1.0, "scale": 1.0}}} + ], + "constraints": {"min_len": 1, "max_len": 9, "gates": [{"critic": 0, "class": 0, "member": true}], + "sums": [{"measure": "ordinal", "lo": 0, "hi": 9, "modulo": 0}], + "contains": [[97]], "excludes": [[98]]}, + "sampling": {"temperature": 0.5, "top_k": 2, "top_p": 0.9, "max_len": 10, "stop": 10, "seed": 1}, + "train": {"epochs": 1, "batch": 2, "lr": 0.001, "val_fraction": 0.1, "patience": 2, "max_steps": 9, + "threads": 1, "budget_seconds": 5.0} + }"#; + let image = r#"{"name": "i", "input": {"type": "image", "width": 16, "height": 16, "patch": 8, "codes": 16}, + "heads": [{"name": "c", "kind": "classify", "classes": ["a", "b"]}]}"#; + let numbers = r#"{"name": "n", "input": {"type": "numbers", "names": ["a"], "codec": {"digits": 2, "decimals": 1, "signed": true}}, + "heads": [{"name": "y", "kind": "regress", "classes": ["s"]}]}"#; + let bytes = r#"{"name": "b", "input": {"type": "bytes"}, "heads": [{"name": "g", "kind": "generate"}]}"#; + [full, image, numbers, bytes] + .iter() + .map(|s| { + let spec: ModelSpec = serde_json::from_str(s).unwrap_or_else(|e| panic!("{e}: {s}")); + serde_json::to_value(spec).unwrap() + }) + .collect() + } + + #[test] + fn every_field_of_the_spec_has_a_control() { + let mut found = Vec::new(); + for v in every_part() { + walk(&v, "", &mut found); + } + found.sort(); + found.dedup(); + // `from: {pretrained}` and the value enums are objects of one key; the walk finds + // them as their inner paths + let missing: Vec<&String> = found.iter().filter(|p| !COVERED.contains(&p.as_str())).collect(); + assert!(missing.is_empty(), "fields without a control: {missing:?}"); + // and each path in COVERED is one the builder writes (indices as `[{i}]` there) + let src = include_str!("builder.rs"); + let body = &src[src + .find("// ------------------------------------------------------------------ paths") + .expect("the code")..src.find("#[cfg(test)]").expect("the tests")]; + let norm = ["{i}", "{j}", "{k}", "{g}"] + .iter() + .fold(body.to_string(), |s, x| s.replace(&format!("[{x}]"), "[]")); + for p in COVERED { + assert!(norm.contains(&format!("\"{p}")), "no control writes {p}"); + } + } + + #[test] + fn paths_set_and_read() { + let mut v = json!({}); + put(&mut v, "heads[1].classes", json!(["a"])); + put(&mut v, "trunk.d_model", json!(64)); + assert_eq!(at(&v, "heads[1].classes"), &json!(["a"])); + assert_eq!(v["heads"][0], Value::Null); + put(&mut v, "trunk.d_model", Value::Null); + assert_eq!(v["trunk"], json!({})); + remove_at(&mut v, "heads", 0); + assert_eq!(v["heads"], json!([{ "classes": ["a"] }])); + } +} diff --git a/app/src/views/stats.rs b/app/src/views/stats.rs new file mode 100644 index 00000000..aedecc31 --- /dev/null +++ b/app/src/views/stats.rs @@ -0,0 +1,101 @@ +//! Stats for the whole app: entries, texts and notes, versions, edges by relation, kinds, +//! how much is stored as borrowings, the sums' spread, lists and tags. + +use dioxus::prelude::*; + +use crate::gem::Mode; +use crate::ui::*; + +#[component] +pub fn Stats() -> Element { + let ui = ui(); + let api = api(); + let api1 = api.clone(); + let raw = use_resource(move || { + let api = api1.clone(); + let _ = (ui.changed)(); + async move { api.call("stats", serde_json::json!({})).await } + }); + let api2 = api.clone(); + let more = use_resource(move || { + let api = api2.clone(); + let _ = (ui.changed)(); + async move { + let lists = api.lists().await.map(|l| l.lists).unwrap_or_default(); + let tags = api.all_tags().await.unwrap_or_default(); + let buckets = api.bucket_counts(Mode::Ordinal).await.unwrap_or_default(); + (lists, tags, buckets) + } + }); + let v = match &*raw.read() { + Some(Ok(v)) => v.clone(), + Some(Err(e)) => return rsx! { div { class: "page", div { class: "card bad", "{e}" } } }, + None => return rsx! { div { class: "page", div { class: "card dim", "…" } } }, + }; + let n = |k: &str| v[k].as_u64().unwrap_or(0); + let date = |k: &str| { + v[k].as_str() + .and_then(|s| chrono::DateTime::parse_from_rfc3339(s).ok()) + .map(|t| t.format("%d %b %Y").to_string()) + .unwrap_or_else(|| "–".into()) + }; + let pairs = |k: &str| -> Vec<(String, u64)> { + v[k].as_array() + .into_iter() + .flatten() + .filter_map(|p| Some((p.get(0)?.as_str()?.to_string(), p.get(1)?.as_u64()?))) + .collect() + }; + let (lists, tags, buckets) = more.read().clone().unwrap_or_default(); + let biggest = buckets.iter().max_by_key(|b| b.count).cloned(); + let edges = pairs("edges"); + let kinds = pairs("by_mime"); + let emax = edges.iter().map(|e| e.1).max().unwrap_or(1).max(1); + let tmax = tags.iter().map(|e| e.1).max().unwrap_or(1).max(1); + rsx! { + div { class: "page", + div { class: "row", h2 { "stats" } span { class: "dim small", "the whole save" } } + div { class: "card stats-grid", + div { class: "stat", b { {n("entries").to_string()} } span { "entries" } } + div { class: "stat", b { {n("memories").to_string()} } span { "texts" } } + div { class: "stat", b { {n("notes").to_string()} } span { "notes" } } + div { class: "stat", b { {n("words").to_string()} } span { "words in notes" } } + div { class: "stat", b { {n("versions").to_string()} } span { "past versions" } } + div { class: "stat", b { "{lists.len()}" } span { "lists" } } + div { class: "stat", b { "{tags.len()}" } span { "tags" } } + div { class: "stat", b { "{buckets.len()}" } span { "ordinal sums in use" } } + div { class: "stat", b { {n("borrowing").to_string()} } span { "stored as borrowings" } } + div { class: "stat", b { {format!("{} kB", n("body_bytes") / 1024)} } span { "packed text" } } + div { class: "stat", b { {date("first")} } span { "the first" } } + div { class: "stat", b { {date("latest")} } span { "the latest" } } + } + if let Some(b) = biggest { + div { class: "card", "The fullest ordinal sum is " b { "{b.sum}" } ", holding {b.count} texts." } + } + div { class: "card", + h3 { "relations" } + div { class: "bars", + for (name , c) in edges { + div { key: "{name}", class: "hbar", span { "{name}" } span { class: "track", span { class: "fill", style: "width: {c as f64 / emax as f64 * 100.0:.1}%;" } } span { class: "n", "{c}" } } + } + } + h3 { style: "margin-top: 10px;", "kinds" } + div { class: "bars", + for (name , c) in kinds { + div { key: "{name}", class: "hbar", span { "{name}" } span { class: "track" } span { class: "n", "{c}" } } + } + } + } + if !tags.is_empty() { + div { class: "card", + h3 { "tags" } + div { class: "bars", + for (t , c) in tags.into_iter().take(30) { + div { key: "{t}", class: "hbar", button { class: "plain tag-open", "data-tip": "see the entries tagged #{t}", onclick: { let t = t.clone(); move |_| { let mut pt = ui.pick_tag; pt.set(Some(t.clone())); crate::shell::go(ui, View::Tags); } }, "#{t}" } span { class: "track", span { class: "fill", style: "width: {c as f64 / tmax as f64 * 100.0:.1}%;" } } span { class: "n", "{c}" } } + } + } + } + } + } + } +} diff --git a/app/src/views/tags.rs b/app/src/views/tags.rs new file mode 100644 index 00000000..821a6db7 --- /dev/null +++ b/app/src/views/tags.rs @@ -0,0 +1,122 @@ +//! Tags: every tag (on any entry, texts and notes alike) with its count; click picks one, +//! Ctrl or Shift+click adds or drops it; all or any decides how several combine. The +//! entries carrying them show beside. The bar narrows the tags; Enter picks the first. + +use dioxus::prelude::*; + +use crate::ui::*; +use crate::views::use_keys; + +#[component] +pub fn Tags() -> Element { + let ui = ui(); + let api = api(); + let mut picked: Signal<Vec<String>> = use_signal(Vec::new); + let mut any = use_signal(|| false); + // a tag another view asked for (the stats' tags) + use_effect(move || { + if let Some(t) = (ui.pick_tag)() { + let mut pt = ui.pick_tag; + pt.set(None); + picked.set(vec![t]); + } + }); + let api_t = api.clone(); + let tags = use_resource(move || { + let api = api_t.clone(); + let _ = (ui.changed)(); + async move { api.all_tags().await.unwrap_or_default() } + }); + let api_e = api.clone(); + let found = use_resource(move || { + let api = api_e.clone(); + let p = picked(); + let a = any(); + let _ = (ui.changed)(); + async move { + if p.is_empty() { + Ok(vec![]) + } else { + api.tagged(&p, a).await + } + } + }); + let q = ui.bar.read().trim().to_lowercase(); + let all: Vec<(String, u64)> = tags.read().clone().unwrap_or_default(); + let shown: Vec<(String, u64)> = all + .into_iter() + .filter(|(t, _)| q.is_empty() || t.to_lowercase().contains(&q)) + .collect(); + let first = shown.first().map(|t| t.0.clone()); + use_keys(View::Tags, move |k: KeyPress| { + if k.bar && k.key == "Enter" { + if let Some(t) = first.clone() { + let mut p = picked.write(); + if !p.contains(&t) { + p.push(t); + } + drop(p); + ui.set_bar(""); + } + return true; + } + false + }); + let hits = match &*found.read() { + Some(Ok(h)) => h.clone(), + _ => vec![], + }; + rsx! { + div { class: "page", + div { class: "row", + h2 { "tags" } + button { class: if !any() { "chip on" } else { "chip" }, onclick: move |_| any.set(false), "data-tip": "entries with every picked tag", "all" } + button { class: if any() { "chip on" } else { "chip" }, onclick: move |_| any.set(true), "data-tip": "entries with any picked tag", "any" } + if !picked().is_empty() { + button { class: "plain", onclick: move |_| picked.set(vec![]), Icon { name: "close" } "clear" } + } + } + div { class: "card taglist", role: "group", "aria-label": "tags", + if shown.is_empty() { + span { class: "dim", "No tags yet: right-click a text in the memory view and pick “tag…”, or give a note tags." } + } + for (t , n) in shown { + button { + key: "{t}", + class: if picked().contains(&t) { "chip on" } else { "chip" }, + "aria-pressed": "{picked().contains(&t)}", + title: "click: just this · Ctrl/Shift+click: add or drop", + onclick: move |e: MouseEvent| { + let m = e.modifiers(); + let mut p = picked.write(); + if m.ctrl() || m.shift() || m.meta() { + if let Some(i) = p.iter().position(|x| *x == t) { p.remove(i); } else { p.push(t.clone()); } + } else { + *p = vec![t.clone()]; + } + }, + "{t} " + span { class: "dim", "{n}" } + } + } + } + if !picked().is_empty() { + div { class: "card", + h3 { {format!("{} carrying {}", hits.len(), picked().join(if any() { " or " } else { " and " }))} } + div { class: "results", + for h in hits { + div { key: "{h.key}", class: "result", + span { class: "p", "{h.key}" } + span { class: "t", title: if h.note { "open it in the editor" } else { "into the bar" }, + onclick: { let h = h.clone(); move |_| if h.note { let mut o = ui.open_note; o.set(Some(h.key.clone())); crate::shell::go(ui, View::Notes); } else { ui.set_bar(&h.text) } }, + if h.note { "✎ " } "{h.text}" } + button { class: "plain", "data-tip": "into the bar", "aria-label": "into the bar", + onclick: { let t = h.text.clone(); move |_| ui.set_bar(&t) }, Icon { name: "text" } } + } + } + } + } + } + } + } +} diff --git a/app/src/views/tagsets.rs b/app/src/views/tagsets.rs new file mode 100644 index 00000000..bf73c0c8 --- /dev/null +++ b/app/src/views/tagsets.rs @@ -0,0 +1,453 @@ +//! Tag sets (queued requests #13, #10; `tagsets.*` in docs/app-api.md): word types of +//! one's own, the models view's fourth tab. A set's page shows its types and their +//! colours, how many words each has marked, how well it reads words it didn't train on +//! (precision and recall per type), and a try card: a text's words labelled by the set, +//! where clicking a word picks its right type (which marks it, and teaches the set when it +//! is trained). A checker set marks words right or wrong and offers the nearest right +//! words for a wrong one. The built-in English set is shown read-only. + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use crate::ui::*; +use crate::views::classifiers::pct; + +const PALETTE: [&str; 8] = [ + "#e07a3f", "#3f7ae0", "#3fae6a", "#b05cc8", "#d6453d", "#c9a227", "#2bb3b1", "#8a6d5a", +]; + +#[component] +pub fn TagSets() -> Element { + let ui = ui(); + let api = api(); + let mut chosen: Signal<Option<String>> = use_signal(|| None); + let mut making = use_signal(|| false); + let mut rev = use_signal(|| 0u64); + let list = use_resource(move || { + let api = api.clone(); + let _ = ((ui.changed)(), rev()); + async move { api.call("tagsets.list", json!({})).await } + }); + let (items, note): (Vec<Value>, Option<String>) = match &*list.read() { + Some(Ok(v)) => (v.as_array().cloned().unwrap_or_default(), None), + Some(Err(e)) => (vec![], Some(e.clone())), + None => (vec![], None), + }; + let open = chosen().unwrap_or_else(|| "english".to_string()); + let current = items + .iter() + .find(|t| t["builtin"] == true && open == "english" || t["set"]["name"] == open.as_str()) + .cloned(); + rsx! { + if let Some(n) = note { + div { class: "card bad", "{n}" } + } + div { class: "cls-layout", + div { class: "card cls-list", role: "listbox", "aria-label": "tag sets", + button { class: if making() { "cls-item on" } else { "cls-item" }, onclick: move |_| making.set(!making()), + b { Icon { name: "new" } " new" } } + for t in items.iter().cloned() { + { + let builtin = t["builtin"] == true; + let name = if builtin { "english".to_string() } else { t["set"]["name"].as_str().unwrap_or("").to_string() }; + let on = !making() && open == name; + let sub = if builtin { + "by rule, on English".to_string() + } else if t["set"]["check"] == true { + "a checker: right or wrong".to_string() + } else { + t["set"]["types"].as_array().into_iter().flatten().filter_map(|x| x["name"].as_str()).collect::<Vec<_>>().join(" · ") + }; + rsx! { + button { key: "{name}", role: "option", "aria-selected": "{on}", class: if on { "cls-item on" } else { "cls-item" }, + onclick: { let n = name.clone(); move |_| { chosen.set(Some(n.clone())); making.set(false); } }, + b { "{name}" } + span { class: "small", "{sub}" } + } + } + } + } + } + div { class: "cls-main", + if making() { + SetEditor { set: Value::Null, on_saved: move |n: String| { making.set(false); chosen.set(Some(n)); rev += 1; } } + } else if let Some(t) = current { + if t["builtin"] == true { + English { types: crate::views::classifiers::strs(&t["types"]) } + } else { + SetPage { key: "{open}", set: t["set"].clone(), on_changed: move |_| rev += 1, on_gone: move |_| { chosen.set(None); rev += 1; } } + } + } + } + } + } +} + +#[component] +fn English(types: Vec<String>) -> Element { + rsx! { + div { class: "card", + h3 { "english" span { class: "dim small", " built in" } } + p { "Word types by rule, for texts that read as English (most of their words are English ones). The memory view's word types (T) use it. Texts in other languages get no English types; make a tag set for them, and say which texts it's for." } + div { class: "row wrap", + for t in types { span { key: "{t}", class: "tw t-{t}", b { "{t}" } } } + } + } + } +} + +/// a new set, or a set's types, threshold and which texts it's for +#[component] +fn SetEditor(set: Value, on_saved: EventHandler<String>) -> Element { + let ui = ui(); + let api = api(); + let fresh = set.is_null(); + let mut draft = use_signal(|| { + if set.is_null() { + json!({ "name": "", "types": [ + { "name": "", "colour": PALETTE[0] }, { "name": "", "colour": PALETTE[1] } + ], "check": false, "threshold": 0.5 }) + } else { + set.clone() + } + }); + let api_c = api.clone(); + let models = use_resource(move || { + let api = api_c.clone(); + async move { api.models().await.unwrap_or_default() } + }); + let models = models.read().clone().unwrap_or_default(); + let d = draft(); + let check = d["check"] == true; + let types: Vec<Value> = d["types"].as_array().cloned().unwrap_or_default(); + let ft_cls = d["for_texts"]["classifier"].as_str().unwrap_or("").to_string(); + let ft_class = d["for_texts"]["class"].as_str().unwrap_or("").to_string(); + let classes: Vec<String> = models + .iter() + .find(|m| m.name == ft_cls) + .map(|m| m.classes.clone()) + .unwrap_or_default(); + let was = set["name"].as_str().unwrap_or("").to_string(); + rsx! { + div { class: "card cls-new", + h3 { Icon { name: "new" } if fresh { "a new tag set" } else { "its types" } } + div { class: "form", + if fresh { + label { r#for: "ts-name", "name" } + input { r#type: "text", id: "ts-name", placeholder: "elvish, sacred words…", value: "{d[\"name\"].as_str().unwrap_or(\"\")}", + oninput: move |e| draft.write()["name"] = json!(e.value()) } + label { "kind" } + div { class: "row", + button { class: if !check { "chip on" } else { "chip" }, onclick: move |_| draft.write()["check"] = json!(false), "word types" } + button { class: if check { "chip on" } else { "chip" }, "data-tip": "for a language of one's own: words marked right or wrong, wrong ones flagged with suggestions", + onclick: move |_| draft.write()["check"] = json!(true), "a checker" } + } + } + if !check { + label { "types" } + div { class: "col", + for (i , t) in types.iter().cloned().enumerate() { + div { key: "{i}", class: "row", + input { r#type: "color", "aria-label": "its colour", value: "{t[\"colour\"].as_str().unwrap_or(\"#888888\")}", + oninput: move |e| draft.write()["types"][i]["colour"] = json!(e.value()) } + input { r#type: "text", "aria-label": "the type's name", placeholder: "a type", value: "{t[\"name\"].as_str().unwrap_or(\"\")}", + oninput: move |e| draft.write()["types"][i]["name"] = json!(e.value()) } + input { r#type: "text", class: "grow", "aria-label": "what it is", placeholder: "what it is (optional)", value: "{t[\"about\"].as_str().unwrap_or(\"\")}", + oninput: move |e| draft.write()["types"][i]["about"] = json!(e.value()) } + if types.len() > 2 { + button { class: "plain ibtn", "aria-label": "remove it", onclick: move |_| { if let Some(a) = draft.write()["types"].as_array_mut() { a.remove(i); } }, Icon { name: "close" } } + } + } + } + button { class: "plain", onclick: move |_| { + let n = draft.peek()["types"].as_array().map(|a| a.len()).unwrap_or(0); + if let Some(a) = draft.write()["types"].as_array_mut() { a.push(json!({ "name": "", "colour": PALETTE[n % PALETTE.len()] })); } + }, Icon { name: "new" } "a type" } + } + } + label { "for texts" } + div { class: "row wrap", + select { "aria-label": "the classifier that says which texts", value: "{ft_cls}", + onchange: move |e| { let v = e.value(); if v.is_empty() { if let Some(o) = draft.write().as_object_mut() { o.remove("for_texts"); } } else { draft.write()["for_texts"] = json!({ "classifier": v, "class": "" }); } }, + option { value: "", selected: ft_cls.is_empty(), "any text I pick it for" } + for m in models.iter() { option { key: "{m.name}", value: "{m.name}", selected: m.name == ft_cls, "{m.name} says…" } } + } + if !ft_cls.is_empty() { + select { "aria-label": "the class", value: "{ft_class}", + onchange: move |e| draft.write()["for_texts"]["class"] = json!(e.value()), + option { value: "", "which class…" } + for c in classes { option { key: "{c}", value: "{c}", selected: c == ft_class, "{c}" } } + } + } + } + label { r#for: "ts-th", "show a type from" } + div { class: "row", + input { r#type: "range", id: "ts-th", min: "0", max: "1", step: "0.05", value: "{d[\"threshold\"].as_f64().unwrap_or(0.5)}", + oninput: move |e| draft.write()["threshold"] = json!(e.value().parse::<f64>().unwrap_or(0.5)) } + span { class: "dim small", {format!("{} sure", pct(d["threshold"].as_f64().unwrap_or(0.5)))} } + } + } + div { class: "row", + button { class: "primary", + onclick: move |_| { + let api = api.clone(); + let mut set = draft(); + if let Some(a) = set["types"].as_array_mut() { + a.retain(|t| !t["name"].as_str().unwrap_or("").trim().is_empty()); + } + let mut args = json!({ "set": set }); + if fresh { args["new"] = json!(true); } else { args["was"] = json!(was.clone()); } + spawn(async move { + match api.call("tagsets.save", args).await { + Ok(v) => { + ui.say("saved: mark some words of each type in the try card, then train it"); + on_saved.call(v["set"]["name"].as_str().unwrap_or("").to_string()); + } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "save" } if fresh { "make it" } else { "save" } } + } + } + } +} + +#[component] +fn SetPage(set: Value, on_changed: EventHandler<()>, on_gone: EventHandler<()>) -> Element { + let ui = ui(); + let api = api(); + let name = set["name"].as_str().unwrap_or("").to_string(); + let mut rev = use_signal(|| 0u64); + let mut editing = use_signal(|| false); + let mut sure = use_signal(|| false); + let (api_s, n_s) = (api.clone(), name.clone()); + let score = use_resource(move || { + let (api, n) = (api_s.clone(), n_s.clone()); + let _ = ((ui.changed)(), rev()); + async move { api.call("tagsets.score", json!({ "name": n })).await } + }); + let sc = score.read().clone().and_then(|r| r.ok()).unwrap_or(Value::Null); + let training = sc["training"] == true; + // while it trains, look again now and then + use_future(move || async move { + loop { + crate::ui::sleep_ms(1500).await; + if score + .peek() + .as_ref() + .and_then(|r| r.as_ref().ok()) + .is_some_and(|v| v["training"] == true) + { + rev += 1; + } + } + }); + let colour = |ty: &str| { + set["types"] + .as_array() + .into_iter() + .flatten() + .find(|t| t["name"] == ty) + .and_then(|t| t["colour"].as_str()) + .unwrap_or("#888") + .to_string() + }; + let check = set["check"] == true; + let (api_t, n_t) = (api.clone(), name.clone()); + let train = move |_| { + let (api, n) = (api_t.clone(), n_t.clone()); + spawn(async move { + match api.call("tagsets.train", json!({ "name": n })).await { + Ok(_) => { + ui.say("training: it reads its marked words, and how well it reads unseen ones shows here"); + rev += 1; + } + Err(e) => ui.fail(e), + } + }); + }; + let (api_d, n_d) = (api.clone(), name.clone()); + rsx! { + div { class: "cls-page", + div { class: "card cls-head", + div { class: "row", + h2 { "{name}" } + for t in set["types"].as_array().cloned().unwrap_or_default() { + span { key: "{t[\"name\"]}", class: "chip ts-type", style: "--c: {t[\"colour\"].as_str().unwrap_or(\"#888\")};", title: "{t[\"about\"].as_str().unwrap_or(\"\")}", "{t[\"name\"].as_str().unwrap_or(\"\")}" } + } + span { class: "grow" } + button { class: if editing() { "on" } else { "" }, onclick: move |_| editing.set(!editing()), Icon { name: "edit" } "types" } + button { class: if sure() { "danger" } else { "" }, + onclick: move |_| { + if !sure() { sure.set(true); return; } + let (api, n) = (api_d.clone(), n_d.clone()); + spawn(async move { + match api.call("tagsets.delete", json!({ "name": n })).await { + Ok(_) => { ui.say("deleted the set and its classifier (the marked words' lists stay)"); on_gone.call(()); } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "delete" } if sure() { "sure? delete" } else { "delete" } } + } + if let Some(f) = set["for_texts"].as_object() { + span { class: "dim small", {format!("for texts {} puts in {}", f.get("classifier").or(f.get("taxonomy")).and_then(|x| x.as_str()).unwrap_or(""), f.get("class").and_then(|x| x.as_str()).unwrap_or(""))} } + } else { + span { class: "dim small", "for any text it's picked for" } + } + } + if editing() { + SetEditor { set: set.clone(), on_saved: move |_| { editing.set(false); on_changed.call(()); rev += 1; } } + } + div { class: "card", + h3 { Icon { name: "classifier" } "how it reads" + span { class: "grow" } + button { class: "primary", disabled: training, onclick: train, Icon { name: "play" } if training { "training…" } else if sc["trained"] == true { "train again" } else { "train it" } } + } + table { class: "confusion", + thead { tr { th { "type" } th { "words marked" } th { "precision" } th { "recall" } } } + tbody { + for m in sc["marked"].as_array().cloned().unwrap_or_default() { + { + let ty = m["type"].as_str().unwrap_or("").to_string(); + let st = sc["types"].as_array().into_iter().flatten().find(|x| x["type"] == ty.as_str()).cloned().unwrap_or(Value::Null); + let some: Vec<String> = crate::views::classifiers::strs(&m["some"]); + rsx! { + tr { key: "{ty}", + th { span { class: "swatch-dot", style: "background: {colour(&ty)};" } " {ty}" } + td { title: "{some.join(\", \")}", "{m[\"words\"]}" } + td { {st["precision"].as_f64().map(pct).unwrap_or_else(|| "—".into())} } + td { {st["recall"].as_f64().map(pct).unwrap_or_else(|| "—".into())} } + } + } + } + } + } + } + p { class: "dim small", + if let Some(a) = sc["accuracy"].as_f64() { + if sc["measured_on"] == "held out" { + {format!("{} right on marked words it didn't train on", pct(a))} + } else { + {format!("{} right on the words it trained on: with forty or more marked, a fifth are held out to measure it on words it hasn't seen", pct(a))} + } + } + else { "Mark two words or more of each type in the try card, then train it." } + } + } + TryTags { name: name.clone(), set: set.clone(), check, on_marked: move |_| rev += 1 } + } + } +} + +/// a text's words as the set labels them; clicking a word picks its right type +#[component] +fn TryTags(name: String, set: Value, check: bool, on_marked: EventHandler<()>) -> Element { + let ui = ui(); + let api = api(); + let mut text = use_signal(String::new); + let mut got: Signal<Option<Value>> = use_signal(|| None); + let mut picking: Signal<Option<usize>> = use_signal(|| None); + let tag = { + let (api, name) = (api.clone(), name.clone()); + move || { + let (api, name) = (api.clone(), name.clone()); + let t = text.peek().clone(); + if t.trim().is_empty() { + return; + } + spawn(async move { + match api.call("tagsets.tag", json!({ "name": name, "text": t })).await { + Ok(v) => { + picking.set(None); + got.set(Some(v)); + } + Err(e) => { + got.set(None); + ui.fail(e) + } + } + }); + } + }; + let types: Vec<(String, String)> = set["types"] + .as_array() + .into_iter() + .flatten() + .map(|t| { + ( + t["name"].as_str().unwrap_or("").to_string(), + t["colour"].as_str().unwrap_or("#888").to_string(), + ) + }) + .collect(); + let words: Vec<Value> = got().and_then(|v| v["words"].as_array().cloned()).unwrap_or_default(); + rsx! { + div { class: "card", + h3 { Icon { name: "text" } "try a text" span { class: "dim small", " click a word to say which type it is" } } + div { class: "row", + input { r#type: "text", class: "grow", "aria-label": "a text to tag", placeholder: "a text in the set's language", value: "{text}", + oninput: move |e| text.set(e.value()), + onkeydown: { let tag = tag.clone(); move |e: KeyboardEvent| if e.key() == Key::Enter { tag() } } } + button { onclick: { let tag = tag.clone(); move |_| tag() }, Icon { name: "play" } "tag it" } + } + div { class: "ts-words", + for (i , w) in words.iter().cloned().enumerate() { + { + let word = w["word"].as_str().unwrap_or("").to_string(); + let ty = w["type"].as_str().map(String::from); + let c = w["colour"].as_str().unwrap_or("transparent").to_string(); + let suggest = crate::views::classifiers::strs(&w["suggest"]); + rsx! { + span { key: "{i}", class: if check && ty.as_deref() == Some("wrong") { "ts-word flagged" } else { "ts-word" }, + button { class: "plain", style: "--c: {c};", "aria-label": "{word}: say which type", + title: {format!("{} · {}", ty.clone().unwrap_or_else(|| "no type".into()), pct(w["prob"].as_f64().unwrap_or(0.0)))}, + onclick: move |_| picking.set(if picking() == Some(i) { None } else { Some(i) }), + span { class: "w", "{word}" } + span { class: "l", {ty.clone().unwrap_or_else(|| "?".into())} } + } + if !suggest.is_empty() { + span { class: "ts-suggest", + for s in suggest { + button { key: "{s}", class: "chip", "data-tip": "use it", + onclick: { let (s, word, tag) = (s.clone(), word.clone(), tag.clone()); move |_| { let t = text.peek().replacen(&word, &s, 1); text.set(t); tag(); } }, + "{s}" } + } + } + } + if picking() == Some(i) { + span { class: "ts-pick", + for (tn , tc) in types.iter().cloned() { + button { key: "{tn}", class: "chip ts-type", style: "--c: {tc};", + onclick: { + let (api, name, word, tag, tn) = (api.clone(), name.clone(), word.clone(), tag.clone(), tn.clone()); + move |_| { + let (api, name, word, tag, tn) = (api.clone(), name.clone(), word.clone(), tag.clone(), tn.clone()); + spawn(async move { + match api.call("tagsets.mark", json!({ "name": name, "word": word, "type": tn })).await { + Ok(v) => { + ui.say(if v["taught"] == true { format!("“{word}” is {tn}: marked, and the set was told") } else { format!("“{word}” is {tn}: marked (train it to learn from the marks)") }); + on_marked.call(()); + tag(); + } + Err(e) => ui.fail(e), + } + }); + } + }, + "{tn}" } + } + } + } + } + } + } + } + } + if got().is_some() && words.is_empty() { + p { class: "dim small", "no words" } + } + } + } +} diff --git a/app/src/views/taxonomy.rs b/app/src/views/taxonomy.rs new file mode 100644 index 00000000..66fb6f50 --- /dev/null +++ b/app/src/views/taxonomy.rs @@ -0,0 +1,495 @@ +//! Taxonomies: the save's classifiers in a tree (docs/architecture.md, part 1; +//! `taxonomy.*` in docs/app-api.md). The models view's third tab. +//! +//! The left column lists them. A taxonomy's page edits its tree (each node a classifier, +//! each of its classes either the end or the next classifier), shows each node's +//! held-out accuracy and its count marked by hand, and has a try card: a text routed down +//! the tree, each step marked right or wrong (wrong asks which class it was), which counts +//! at that node and tells its classifier. + +use std::collections::BTreeMap; + +use dioxus::prelude::*; +use serde_json::{Value, json}; + +use crate::ui::*; +use crate::views::classifiers::pct; + +fn path_of(v: &Value) -> Vec<String> { + crate::views::classifiers::strs(v) +} + +/// the node at `path` in a taxonomy's JSON tree +fn node_mut<'a>(root: &'a mut Value, path: &[String]) -> Option<&'a mut Value> { + match path.split_first() { + None => Some(root), + Some((c, rest)) => node_mut(root.get_mut("routes")?.get_mut(c)?, rest), + } +} + +/// held out and by hand, for a node's line +fn scores(n: &Value) -> String { + let mut s = Vec::new(); + match n["held_out"].as_f64() { + Some(a) => s.push(format!("held out {}", pct(a))), + None if n["trained"] == false => s.push("not trained yet".into()), + None => {} + } + let (r, w) = (n["right"].as_u64().unwrap_or(0), n["wrong"].as_u64().unwrap_or(0)); + if r + w > 0 { + s.push(format!("by hand {} ({r} of {})", pct(r as f64 / (r + w) as f64), r + w)); + } else { + s.push("not marked yet".into()); + } + s.join(" · ") +} + +#[component] +pub fn Taxonomies(bar: Signal<(u64, String)>) -> Element { + let ui = ui(); + let api = api(); + let mut chosen: Signal<Option<String>> = use_signal(|| None); + let mut making = use_signal(|| false); + let mut rev = use_signal(|| 0u64); + let api_l = api.clone(); + let list = use_resource(move || { + let api = api_l.clone(); + let _ = ((ui.changed)(), rev()); + async move { api.call("taxonomy.list", json!({})).await } + }); + let api_m = api.clone(); + let models = use_resource(move || { + let api = api_m.clone(); + let _ = ((ui.changed)(), rev()); + async move { api.models().await } + }); + let (items, note): (Vec<Value>, Option<String>) = match &*list.read() { + Some(Ok(v)) => (v.as_array().cloned().unwrap_or_default(), None), + Some(Err(e)) => (vec![], Some(e.clone())), + None => (vec![], None), + }; + let classifiers: BTreeMap<String, Vec<String>> = match &*models.read() { + Some(Ok(l)) => l.iter().map(|m| (m.name.clone(), m.classes.clone())).collect(), + _ => BTreeMap::new(), + }; + let open = chosen().or_else(|| { + (!making()) + .then(|| items.first().and_then(|t| t["name"].as_str().map(String::from))) + .flatten() + }); + rsx! { + if let Some(n) = note { + div { class: "card bad", "{n}" } + } + div { class: "cls-layout", + div { class: "card cls-list", role: "listbox", "aria-label": "taxonomies", + button { class: if making() { "cls-item on" } else { "cls-item" }, onclick: move |_| making.set(!making()), + b { Icon { name: "new" } " new" } } + if items.is_empty() { + span { class: "dim small", "none yet" } + } + for t in items.iter().cloned() { + { + let name = t["name"].as_str().unwrap_or("").to_string(); + let on = open.as_deref() == Some(name.as_str()) && !making(); + let (r, w) = (t["right"].as_u64().unwrap_or(0), t["wrong"].as_u64().unwrap_or(0)); + rsx! { + button { key: "{name}", role: "option", "aria-selected": "{on}", + class: if on { "cls-item on" } else { "cls-item" }, + onclick: { let n = name.clone(); move |_| { chosen.set(Some(n.clone())); making.set(false); } }, + b { "{name}" } + span { class: "small", {format!("{} · {} node{}", t["root"].as_str().unwrap_or(""), t["nodes"], if t["nodes"] == 1 { "" } else { "s" })} } + span { class: "small state", + if r + w > 0 { {format!("{} right by hand", pct(r as f64 / (r + w) as f64))} } else { "not marked yet" } + } + } + } + } + } + } + div { class: "cls-main", + if making() { + NewTaxonomy { classifiers: classifiers.clone(), on_made: move |name: String| { making.set(false); chosen.set(Some(name)); rev += 1; } } + } else if let Some(name) = open { + TaxonomyPage { key: "{name}", name: name.clone(), classifiers: classifiers.clone(), bar, + on_saved: move |name: String| { chosen.set(Some(name)); rev += 1; }, + on_gone: move |_| { chosen.set(None); rev += 1; } } + } else { + div { class: "card empty", + p { "A taxonomy puts classifiers in a tree. The first one reads a text; each of its classes can end there or send the text on to a further classifier, so a question like \"English or not?\" decides which classifier reads the text next." } + p { "Mark each step of a routing right or wrong as you try texts: each node counts its marks beside its classifier's held-out accuracy, and every mark is that classifier's feedback too. Nothing is stored about the texts themselves." } + if classifiers.is_empty() { + p { "Make a classifier first (the classifiers tab)." } + } else { + p { button { onclick: move |_| making.set(true), Icon { name: "new" } "new taxonomy" } } + } + } + } + } + } + } +} + +#[component] +fn NewTaxonomy(classifiers: BTreeMap<String, Vec<String>>, on_made: EventHandler<String>) -> Element { + let ui = ui(); + let api = api(); + let mut name = use_signal(String::new); + let first = classifiers.keys().next().cloned().unwrap_or_default(); + let mut root = use_signal(move || first); + rsx! { + div { class: "card cls-new", + h3 { Icon { name: "new" } "a new taxonomy" } + div { class: "form", + label { r#for: "tax-name", "name" } + input { r#type: "text", id: "tax-name", value: "{name}", placeholder: "languages, kinds of thing…", oninput: move |e| name.set(e.value()) } + label { r#for: "tax-root", "first classifier" } + select { id: "tax-root", value: "{root}", onchange: move |e| root.set(e.value()), + for c in classifiers.keys() { + option { key: "{c}", value: "{c}", selected: *c == root(), "{c}" } + } + } + } + div { class: "row", + button { disabled: name().trim().is_empty() || root().is_empty(), + onclick: move |_| { + let api = api.clone(); + let t = json!({ "name": name().trim(), "root": { "classifier": root() } }); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("taxonomy.save", json!({ "taxonomy": t, "new": true })).await { + Ok(v) => { + ui.say("made: now send its classes on to further classifiers"); + on_made.call(v["taxonomy"]["name"].as_str().unwrap_or("").to_string()); + } + Err(e) => ui.fail(e), + } + }); + }, + Icon { name: "save" } "make it" } + } + } + } +} + +#[component] +fn TaxonomyPage( + name: String, + classifiers: BTreeMap<String, Vec<String>>, + bar: Signal<(u64, String)>, + on_saved: EventHandler<String>, + on_gone: EventHandler<()>, +) -> Element { + let ui = ui(); + let api = api(); + let mut rev = use_signal(|| 0u64); + let api_g = api.clone(); + let n_g = name.clone(); + let got = use_resource(move || { + let (api, n) = (api_g.clone(), n_g.clone()); + let _ = rev(); + async move { api.call("taxonomy.get", json!({ "name": n })).await } + }); + // the tree as edited, and as saved + let mut draft: Signal<Option<Value>> = use_signal(|| None); + let mut saved: Signal<Option<Value>> = use_signal(|| None); + use_effect(move || { + if let Some(Ok(v)) = &*got.read() { + draft.set(Some(v["taxonomy"].clone())); + saved.set(Some(v["taxonomy"].clone())); + } + }); + let mut sure = use_signal(|| false); + let nodes: Vec<Value> = match &*got.read() { + Some(Ok(v)) => v["nodes"].as_array().cloned().unwrap_or_default(), + Some(Err(e)) => return rsx! { div { class: "card bad", "{e}" } }, + None => return rsx! { div { class: "card dim", "…" } }, + }; + let Some(t) = draft() else { + return rsx! { div { class: "card dim", "…" } }; + }; + let stats: BTreeMap<Vec<String>, Value> = nodes.iter().map(|n| (path_of(&n["path"]), n.clone())).collect(); + let dirty = draft() != saved(); + let save = { + let api = api.clone(); + let was = name.clone(); + move |_| { + let (api, was) = (api.clone(), was.clone()); + let Some(t) = draft() else { return }; + dioxus::dioxus_core::spawn_forever(async move { + match api.call("taxonomy.save", json!({ "taxonomy": t, "was": was })).await { + Ok(v) => { + ui.say("saved"); + let n = v["taxonomy"]["name"].as_str().unwrap_or("").to_string(); + if n == was { + rev += 1; + } + on_saved.call(n); + } + Err(e) => ui.fail(e), + } + }); + } + }; + let delete = { + let api = api.clone(); + let n = name.clone(); + move |_| { + if !sure() { + sure.set(true); + return; + } + let (api, n) = (api.clone(), n.clone()); + dioxus::dioxus_core::spawn_forever(async move { + match api.call("taxonomy.delete", json!({ "name": n })).await { + Ok(_) => { + ui.say(format!("deleted the taxonomy {n} (its classifiers stay)")); + on_gone.call(()); + } + Err(e) => ui.fail(e), + } + }); + } + }; + rsx! { + div { class: "cls-page", + div { class: "card cls-head", + div { class: "row", + input { r#type: "text", class: "tax-title", "aria-label": "the taxonomy's name", value: "{t[\"name\"].as_str().unwrap_or(\"\")}", + oninput: move |e| { if let Some(d) = draft.write().as_mut() { d["name"] = json!(e.value()); } } } + span { class: "grow" } + button { disabled: !dirty, class: if dirty { "on" } else { "" }, "data-tip": "save the tree (marks stay where the same classifier stands)", onclick: save, + Icon { name: "save" } "save" } + if dirty { + button { onclick: move |_| draft.set(saved()), Icon { name: "undo" } "as saved" } + } + button { class: if sure() { "danger" } else { "" }, onclick: delete, + Icon { name: "delete" } if sure() { "sure? delete" } else { "delete" } } + } + input { r#type: "text", class: "tax-about", placeholder: "what it sorts (optional)", "aria-label": "what it sorts", + value: "{t[\"about\"].as_str().unwrap_or(\"\")}", + oninput: move |e| { if let Some(d) = draft.write().as_mut() { d["about"] = json!(e.value()); } } } + } + div { class: "card", + h3 { Icon { name: "classifier" } "the tree" } + p { class: "dim small", "Each classifier's classes end the routing, or send the text on to the next classifier." } + {node_view(Vec::new(), &t["root"], &classifiers, &stats, draft)} + } + TryRoute { name: name.clone(), classifiers: classifiers.clone(), dirty, bar, on_marked: move |_| rev += 1 } + } + } +} + +/// a node of the tree being edited, with its classes and where each goes +fn node_view( + path: Vec<String>, + node: &Value, + classifiers: &BTreeMap<String, Vec<String>>, + stats: &BTreeMap<Vec<String>, Value>, + mut draft: Signal<Option<Value>>, +) -> Element { + let cls = node["classifier"].as_str().unwrap_or("").to_string(); + let classes = classifiers.get(&cls).cloned().unwrap_or_default(); + let score = stats.get(&path).map(scores).unwrap_or_else(|| "not saved yet".into()); + let missing = !classifiers.contains_key(&cls); + let p_set = path.clone(); + rsx! { + div { class: "tax-node", + div { class: "row", + select { "aria-label": "the classifier here", value: "{cls}", + onchange: move |e| { + let v = e.value(); + if let Some(d) = draft.write().as_mut() + && let Some(n) = node_mut(&mut d["root"], &p_set) + { + n["classifier"] = json!(v); + if let Some(r) = n.get_mut("routes").and_then(Value::as_object_mut) { + r.clear(); + } + } + }, + if missing { + option { value: "{cls}", selected: true, "{cls} (missing)" } + } + for c in classifiers.keys() { + option { key: "{c}", value: "{c}", selected: *c == cls, "{c}" } + } + } + span { class: "dim small", "{score}" } + } + for class in classes.iter().cloned() { + { + let next = node["routes"].get(&class).cloned(); + let goes = next.as_ref().and_then(|n| n["classifier"].as_str()).unwrap_or("").to_string(); + let mut sub = path.clone(); + sub.push(class.clone()); + let p_route = path.clone(); + let c_route = class.clone(); + rsx! { + div { key: "{class}", class: "tax-route", + div { class: "row", + span { class: "tax-class", "{class}" } + span { class: "dim", "→" } + select { "aria-label": "where {class} goes", value: "{goes}", + onchange: move |e| { + let v = e.value(); + if let Some(d) = draft.write().as_mut() + && let Some(n) = node_mut(&mut d["root"], &p_route) + { + if v.is_empty() { + if let Some(r) = n.get_mut("routes").and_then(Value::as_object_mut) { + r.remove(&c_route); + } + } else { + if !n["routes"].is_object() { + n["routes"] = json!({}); + } + n["routes"][&c_route] = json!({ "classifier": v }); + } + } + }, + option { value: "", selected: goes.is_empty(), "ends here" } + for c in classifiers.keys() { + option { key: "{c}", value: "{c}", selected: *c == goes, "{c}" } + } + } + } + if let Some(n) = next { + div { class: "tax-sub", {node_view(sub, &n, classifiers, stats, draft)} } + } + } + } + } + } + } + } +} + +/// a text routed down the saved tree, each step marked right or wrong +#[component] +fn TryRoute( + name: String, + classifiers: BTreeMap<String, Vec<String>>, + dirty: bool, + bar: Signal<(u64, String)>, + on_marked: EventHandler<()>, +) -> Element { + let ui = ui(); + let api = api(); + let mut text = use_signal(String::new); + let mut got: Signal<Option<Value>> = use_signal(|| None); + // the step being told which class it was + let mut asking: Signal<Option<usize>> = use_signal(|| None); + let route = { + let (api, name) = (api.clone(), name.clone()); + move || { + let (api, name) = (api.clone(), name.clone()); + let t = text.peek().clone(); + if t.trim().is_empty() { + return; + } + dioxus::dioxus_core::spawn_forever(async move { + match api.call("taxonomy.route", json!({ "name": name, "text": t })).await { + Ok(v) => { + asking.set(None); + got.set(Some(v)); + } + Err(e) => ui.fail(e), + } + }); + } + }; + let mark = { + let (api, name) = (api.clone(), name.clone()); + let route = route.clone(); + move |path: Value, right: bool, class: Option<String>| { + let (api, name, route) = (api.clone(), name.clone(), route.clone()); + let mut a = json!({ "name": name, "text": text(), "path": path, "right": right }); + if let Some(c) = &class { + a["class"] = json!(c); + } + dioxus::dioxus_core::spawn_forever(async move { + match api.call("taxonomy.mark", a).await { + Ok(_) => { + ui.say(match (right, class) { + (true, _) => { + "marked right: the node counts it, and its classifier was told yes".to_string() + } + (false, Some(c)) => format!("marked wrong: it was {c}; its classifier was told so"), + (false, None) => "marked wrong: its classifier was told no".to_string(), + }); + ui.touched(); + on_marked.call(()); + route(); + } + Err(e) => ui.fail(e), + } + }); + } + }; + // Enter in the bar routes its text (the first time it changes after this card opened) + let seen = use_hook(|| bar.peek().0); + { + let route = route.clone(); + use_effect(move || { + let (n, t) = bar(); + if n != seen && !t.is_empty() { + text.set(t); + route(); + } + }); + } + let steps: Vec<Value> = got().and_then(|v| v["steps"].as_array().cloned()).unwrap_or_default(); + let reached = got().is_some_and(|v| v["reached"] == true); + rsx! { + div { class: "card", + h3 { Icon { name: "search" } "try a text" } + if dirty { + p { class: "dim small", "Routing uses the tree as saved." } + } + div { class: "row", + input { r#type: "text", class: "grow", placeholder: "a text to route", "aria-label": "a text to route", value: "{text}", + oninput: move |e| text.set(e.value()), + onkeydown: { let route = route.clone(); move |e: KeyboardEvent| if e.key() == Key::Enter { route() } } } + button { onclick: { let route = route.clone(); move |_| route() }, Icon { name: "play" } "route it" } + } + for (i , st) in steps.iter().cloned().enumerate() { + { + let cls = st["classifier"].as_str().unwrap_or("").to_string(); + let class = st["class"].as_str().unwrap_or("—").to_string(); + let trained = st["trained"] == true; + let others: Vec<String> = classifiers.get(&cls).cloned().unwrap_or_default().into_iter().filter(|c| *c != class).collect(); + let path = st["path"].clone(); + let (m1, m2, m3) = (mark.clone(), mark.clone(), mark.clone()); + let (p1, p2, p3) = (path.clone(), path.clone(), path.clone()); + rsx! { + div { key: "{i}", class: "result tax-step", + span { class: "num", "{i + 1}" } + span { class: "t", b { "{cls}" } " → " if trained { "{class}" } else { span { class: "dim", "not trained yet" } } } + span { class: "p", if trained { {pct(st["prob"].as_f64().unwrap_or(0.0))} } } + span { class: "dim small", {scores(&st)} } + if trained { + button { class: "plain", "aria-label": "right: it is {class}", "data-tip": "right", onclick: move |_| m1(p1.clone(), true, None), Icon { name: "check" } } + button { class: "plain", "aria-label": "wrong: it isn't {class}", "data-tip": "wrong: which was it?", + onclick: move |_| asking.set(if asking() == Some(i) { None } else { Some(i) }), Icon { name: "close" } } + } + } + if asking() == Some(i) { + div { class: "row tax-which", + span { class: "dim small", "it was:" } + for o in others.iter().cloned() { + button { key: "{o}", class: "chip", onclick: { let (m, p, o) = (m2.clone(), p2.clone(), o.clone()); move |_| m(p.clone(), false, Some(o.clone())) }, "{o}" } + } + button { class: "plain", onclick: move |_| m3(p3.clone(), false, None), "none of these" } + } + } + } + } + } + if let Some(v) = got() { + p { class: "small", + if reached { {format!("ends in {}", v["class"].as_str().unwrap_or("—"))} } else { "stopped: a classifier on the way isn't trained" } + } + } + } + } +} diff --git a/hub/web/vendor/three.LICENSE b/app/vendor/three.LICENSE similarity index 100% rename from hub/web/vendor/three.LICENSE rename to app/vendor/three.LICENSE diff --git a/hub/web/vendor/three.module.min.js b/app/vendor/three.module.min.js similarity index 100% rename from hub/web/vendor/three.module.min.js rename to app/vendor/three.module.min.js diff --git a/app/web/.gitignore b/app/web/.gitignore new file mode 100644 index 00000000..43ce0264 --- /dev/null +++ b/app/web/.gitignore @@ -0,0 +1,2 @@ +dist/* +!dist/.gitkeep diff --git a/app/web/boot.js b/app/web/boot.js new file mode 100644 index 00000000..3687c904 --- /dev/null +++ b/app/web/boot.js @@ -0,0 +1,4 @@ +// starts the web app (a file of its own, so the hub's content security policy needn't +// allow inline scripts) +import init from './anend-app.js'; +init(); diff --git a/app/web/build.sh b/app/web/build.sh new file mode 100755 index 00000000..fc2c9776 --- /dev/null +++ b/app/web/build.sh @@ -0,0 +1,14 @@ +#!/bin/sh +# builds the web app into app/web/dist: the wasm, its bindings, the page and the icon. +# Serve dist where the hub answers /app/ws (the hub's app API), e.g. beside it. +set -e +here=$(cd "$(dirname "$0")" && pwd) +root=$(cd "$here/../.." && pwd) +target=${CARGO_TARGET_DIR:-$root/target} +cargo build -p anend-app --target wasm32-unknown-unknown --no-default-features --features web --release +mkdir -p "$here/dist" +wasm-bindgen --target web --no-typescript --out-dir "$here/dist" "$target/wasm32-unknown-unknown/release/anend-app.wasm" +cp "$here/index.html" "$here/dist/index.html" +cp "$here/boot.js" "$here/dist/boot.js" +cp "$root/assets/icon.svg" "$here/dist/icon.svg" +echo "built $here/dist" diff --git a/app/web/dist/.gitkeep b/app/web/dist/.gitkeep new file mode 100644 index 00000000..e69de29b diff --git a/app/web/index.html b/app/web/index.html new file mode 100644 index 00000000..d0c57f21 --- /dev/null +++ b/app/web/index.html @@ -0,0 +1,14 @@ +<!doctype html> +<html lang="en"> +<head> +<meta charset="utf-8"> +<meta name="viewport" content="width=device-width, initial-scale=1"> +<title>anend + + + + +
+ + + diff --git a/assets/fonts/FiraMono-LICENSE b/assets/fonts/FiraMono-LICENSE new file mode 100644 index 00000000..5e4608f2 --- /dev/null +++ b/assets/fonts/FiraMono-LICENSE @@ -0,0 +1,93 @@ +Digitized data copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +http://scripts.sil.org/OFL + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/assets/fonts/FiraMono-Medium.woff2 b/assets/fonts/FiraMono-Medium.woff2 new file mode 100644 index 00000000..6c2fd823 Binary files /dev/null and b/assets/fonts/FiraMono-Medium.woff2 differ diff --git a/assets/fonts/FiraSans-Bold.woff2 b/assets/fonts/FiraSans-Bold.woff2 new file mode 100644 index 00000000..2731a71f Binary files /dev/null and b/assets/fonts/FiraSans-Bold.woff2 differ diff --git a/assets/fonts/FiraSans-Italic.woff2 b/assets/fonts/FiraSans-Italic.woff2 new file mode 100644 index 00000000..eea61e4f Binary files /dev/null and b/assets/fonts/FiraSans-Italic.woff2 differ diff --git a/assets/fonts/FiraSans-License.txt b/assets/fonts/FiraSans-License.txt new file mode 100644 index 00000000..0d0213ad --- /dev/null +++ b/assets/fonts/FiraSans-License.txt @@ -0,0 +1,93 @@ +Copyright (c) 2012-2015, The Mozilla Foundation and Telefonica S.A. + +This Font Software is licensed under the SIL Open Font License, Version 1.1. +This license is copied below, and is also available with a FAQ at: +https://openfontlicense.org + + +----------------------------------------------------------- +SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 +----------------------------------------------------------- + +PREAMBLE +The goals of the Open Font License (OFL) are to stimulate worldwide +development of collaborative font projects, to support the font creation +efforts of academic and linguistic communities, and to provide a free and +open framework in which fonts may be shared and improved in partnership +with others. + +The OFL allows the licensed fonts to be used, studied, modified and +redistributed freely as long as they are not sold by themselves. The +fonts, including any derivative works, can be bundled, embedded, +redistributed and/or sold with any software provided that any reserved +names are not used by derivative works. The fonts and derivatives, +however, cannot be released under any other type of license. The +requirement for fonts to remain under this license does not apply +to any document created using the fonts or their derivatives. + +DEFINITIONS +"Font Software" refers to the set of files released by the Copyright +Holder(s) under this license and clearly marked as such. This may +include source files, build scripts and documentation. + +"Reserved Font Name" refers to any names specified as such after the +copyright statement(s). + +"Original Version" refers to the collection of Font Software components as +distributed by the Copyright Holder(s). + +"Modified Version" refers to any derivative made by adding to, deleting, +or substituting -- in part or in whole -- any of the components of the +Original Version, by changing formats or by porting the Font Software to a +new environment. + +"Author" refers to any designer, engineer, programmer, technical +writer or other person who contributed to the Font Software. + +PERMISSION & CONDITIONS +Permission is hereby granted, free of charge, to any person obtaining +a copy of the Font Software, to use, study, copy, merge, embed, modify, +redistribute, and sell modified and unmodified copies of the Font +Software, subject to the following conditions: + +1) Neither the Font Software nor any of its individual components, +in Original or Modified Versions, may be sold by itself. + +2) Original or Modified Versions of the Font Software may be bundled, +redistributed and/or sold with any software, provided that each copy +contains the above copyright notice and this license. These can be +included either as stand-alone text files, human-readable headers or +in the appropriate machine-readable metadata fields within text or +binary files as long as those fields can be easily viewed by the user. + +3) No Modified Version of the Font Software may use the Reserved Font +Name(s) unless explicit written permission is granted by the corresponding +Copyright Holder. This restriction only applies to the primary font name as +presented to the users. + +4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font +Software shall not be used to promote, endorse or advertise any +Modified Version, except to acknowledge the contribution(s) of the +Copyright Holder(s) and the Author(s) or with their explicit written +permission. + +5) The Font Software, modified or unmodified, in part or in whole, +must be distributed entirely under this license, and must not be +distributed under any other license. The requirement for fonts to +remain under this license does not apply to any document created +using the Font Software. + +TERMINATION +This license becomes null and void if any of the above conditions are +not met. + +DISCLAIMER +THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF +MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT +OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE +COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL +DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM +OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/assets/fonts/FiraSans-Regular.woff2 b/assets/fonts/FiraSans-Regular.woff2 new file mode 100644 index 00000000..6d4def9d Binary files /dev/null and b/assets/fonts/FiraSans-Regular.woff2 differ diff --git a/assets/icons/cube.svg b/assets/icons/cube.svg new file mode 100644 index 00000000..886811ad --- /dev/null +++ b/assets/icons/cube.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/assets/icons/image.svg b/assets/icons/image.svg new file mode 100644 index 00000000..35a337e2 --- /dev/null +++ b/assets/icons/image.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/png/alert.png b/assets/icons/png/alert.png deleted file mode 100644 index bd3f4df3..00000000 Binary files a/assets/icons/png/alert.png and /dev/null differ diff --git a/assets/icons/png/and.png b/assets/icons/png/and.png deleted file mode 100644 index eefa8cb7..00000000 Binary files a/assets/icons/png/and.png and /dev/null differ diff --git a/assets/icons/png/bolt.png b/assets/icons/png/bolt.png deleted file mode 100644 index 3afe4502..00000000 Binary files a/assets/icons/png/bolt.png and /dev/null differ diff --git a/assets/icons/png/bucket.png b/assets/icons/png/bucket.png deleted file mode 100644 index 9039f17f..00000000 Binary files a/assets/icons/png/bucket.png and /dev/null differ diff --git a/assets/icons/png/check.png b/assets/icons/png/check.png deleted file mode 100644 index bf0bfb8f..00000000 Binary files a/assets/icons/png/check.png and /dev/null differ diff --git a/assets/icons/png/chevron-left.png b/assets/icons/png/chevron-left.png deleted file mode 100644 index fe40ae5c..00000000 Binary files a/assets/icons/png/chevron-left.png and /dev/null differ diff --git a/assets/icons/png/chevron-right.png b/assets/icons/png/chevron-right.png deleted file mode 100644 index 12b147ee..00000000 Binary files a/assets/icons/png/chevron-right.png and /dev/null differ diff --git a/assets/icons/png/classifier.png b/assets/icons/png/classifier.png deleted file mode 100644 index f8efc2c9..00000000 Binary files a/assets/icons/png/classifier.png and /dev/null differ diff --git a/assets/icons/png/close.png b/assets/icons/png/close.png deleted file mode 100644 index ff46007e..00000000 Binary files a/assets/icons/png/close.png and /dev/null differ diff --git a/assets/icons/png/copy.png b/assets/icons/png/copy.png deleted file mode 100644 index da3a2819..00000000 Binary files a/assets/icons/png/copy.png and /dev/null differ diff --git a/assets/icons/png/delete.png b/assets/icons/png/delete.png deleted file mode 100644 index b55abdc7..00000000 Binary files a/assets/icons/png/delete.png and /dev/null differ diff --git a/assets/icons/png/download.png b/assets/icons/png/download.png deleted file mode 100644 index 5480f6db..00000000 Binary files a/assets/icons/png/download.png and /dev/null differ diff --git a/assets/icons/png/edit.png b/assets/icons/png/edit.png deleted file mode 100644 index a4db1afa..00000000 Binary files a/assets/icons/png/edit.png and /dev/null differ diff --git a/assets/icons/png/editor.png b/assets/icons/png/editor.png deleted file mode 100644 index f914661e..00000000 Binary files a/assets/icons/png/editor.png and /dev/null differ diff --git a/assets/icons/png/export.png b/assets/icons/png/export.png deleted file mode 100644 index c690f06c..00000000 Binary files a/assets/icons/png/export.png and /dev/null differ diff --git a/assets/icons/png/eye-off.png b/assets/icons/png/eye-off.png deleted file mode 100644 index 03e9b9e1..00000000 Binary files a/assets/icons/png/eye-off.png and /dev/null differ diff --git a/assets/icons/png/filter.png b/assets/icons/png/filter.png deleted file mode 100644 index 2c819ee5..00000000 Binary files a/assets/icons/png/filter.png and /dev/null differ diff --git a/assets/icons/png/folder.png b/assets/icons/png/folder.png deleted file mode 100644 index cc350aba..00000000 Binary files a/assets/icons/png/folder.png and /dev/null differ diff --git a/assets/icons/png/font.png b/assets/icons/png/font.png deleted file mode 100644 index ec26210a..00000000 Binary files a/assets/icons/png/font.png and /dev/null differ diff --git a/assets/icons/png/forge.png b/assets/icons/png/forge.png deleted file mode 100644 index e793450e..00000000 Binary files a/assets/icons/png/forge.png and /dev/null differ diff --git a/assets/icons/png/hash.png b/assets/icons/png/hash.png deleted file mode 100644 index 95c005e2..00000000 Binary files a/assets/icons/png/hash.png and /dev/null differ diff --git a/assets/icons/png/help.png b/assets/icons/png/help.png deleted file mode 100644 index 44c22022..00000000 Binary files a/assets/icons/png/help.png and /dev/null differ diff --git a/assets/icons/png/home.png b/assets/icons/png/home.png deleted file mode 100644 index 1359b16b..00000000 Binary files a/assets/icons/png/home.png and /dev/null differ diff --git a/assets/icons/png/hub.png b/assets/icons/png/hub.png deleted file mode 100644 index 765ecf45..00000000 Binary files a/assets/icons/png/hub.png and /dev/null differ diff --git a/assets/icons/png/keys.png b/assets/icons/png/keys.png deleted file mode 100644 index 91881bb2..00000000 Binary files a/assets/icons/png/keys.png and /dev/null differ diff --git a/assets/icons/png/link.png b/assets/icons/png/link.png deleted file mode 100644 index ce047ff0..00000000 Binary files a/assets/icons/png/link.png and /dev/null differ diff --git a/assets/icons/png/list.png b/assets/icons/png/list.png deleted file mode 100644 index 1420147d..00000000 Binary files a/assets/icons/png/list.png and /dev/null differ diff --git a/assets/icons/png/memory.png b/assets/icons/png/memory.png deleted file mode 100644 index 2e1f08dc..00000000 Binary files a/assets/icons/png/memory.png and /dev/null differ diff --git a/assets/icons/png/merge.png b/assets/icons/png/merge.png deleted file mode 100644 index 06e72511..00000000 Binary files a/assets/icons/png/merge.png and /dev/null differ diff --git a/assets/icons/png/near.png b/assets/icons/png/near.png deleted file mode 100644 index 69c7e732..00000000 Binary files a/assets/icons/png/near.png and /dev/null differ diff --git a/assets/icons/png/new.png b/assets/icons/png/new.png deleted file mode 100644 index 4252f338..00000000 Binary files a/assets/icons/png/new.png and /dev/null differ diff --git a/assets/icons/png/not.png b/assets/icons/png/not.png deleted file mode 100644 index b234df73..00000000 Binary files a/assets/icons/png/not.png and /dev/null differ diff --git a/assets/icons/png/open.png b/assets/icons/png/open.png deleted file mode 100644 index 1d489f18..00000000 Binary files a/assets/icons/png/open.png and /dev/null differ diff --git a/assets/icons/png/or.png b/assets/icons/png/or.png deleted file mode 100644 index 0202e9f7..00000000 Binary files a/assets/icons/png/or.png and /dev/null differ diff --git a/assets/icons/png/palette.png b/assets/icons/png/palette.png deleted file mode 100644 index 2019fc4c..00000000 Binary files a/assets/icons/png/palette.png and /dev/null differ diff --git a/assets/icons/png/pause.png b/assets/icons/png/pause.png deleted file mode 100644 index cba2af55..00000000 Binary files a/assets/icons/png/pause.png and /dev/null differ diff --git a/assets/icons/png/pick.png b/assets/icons/png/pick.png deleted file mode 100644 index 25770cab..00000000 Binary files a/assets/icons/png/pick.png and /dev/null differ diff --git a/assets/icons/png/pin.png b/assets/icons/png/pin.png deleted file mode 100644 index ce49311c..00000000 Binary files a/assets/icons/png/pin.png and /dev/null differ diff --git a/assets/icons/png/play.png b/assets/icons/png/play.png deleted file mode 100644 index 84989a8e..00000000 Binary files a/assets/icons/png/play.png and /dev/null differ diff --git a/assets/icons/png/reader.png b/assets/icons/png/reader.png deleted file mode 100644 index 1eecb7ad..00000000 Binary files a/assets/icons/png/reader.png and /dev/null differ diff --git a/assets/icons/png/refresh.png b/assets/icons/png/refresh.png deleted file mode 100644 index 8e4de9c7..00000000 Binary files a/assets/icons/png/refresh.png and /dev/null differ diff --git a/assets/icons/png/rename.png b/assets/icons/png/rename.png deleted file mode 100644 index bb0dc888..00000000 Binary files a/assets/icons/png/rename.png and /dev/null differ diff --git a/assets/icons/png/save.png b/assets/icons/png/save.png deleted file mode 100644 index 3e9c4a12..00000000 Binary files a/assets/icons/png/save.png and /dev/null differ diff --git a/assets/icons/png/search.png b/assets/icons/png/search.png deleted file mode 100644 index e6756e22..00000000 Binary files a/assets/icons/png/search.png and /dev/null differ diff --git a/assets/icons/png/settings.png b/assets/icons/png/settings.png deleted file mode 100644 index 4a8ce345..00000000 Binary files a/assets/icons/png/settings.png and /dev/null differ diff --git a/assets/icons/png/shield.png b/assets/icons/png/shield.png deleted file mode 100644 index 99aa93bf..00000000 Binary files a/assets/icons/png/shield.png and /dev/null differ diff --git a/assets/icons/png/sidebar.png b/assets/icons/png/sidebar.png deleted file mode 100644 index 7021295f..00000000 Binary files a/assets/icons/png/sidebar.png and /dev/null differ diff --git a/assets/icons/png/sliders.png b/assets/icons/png/sliders.png deleted file mode 100644 index ccd96bb3..00000000 Binary files a/assets/icons/png/sliders.png and /dev/null differ diff --git a/assets/icons/png/sort.png b/assets/icons/png/sort.png deleted file mode 100644 index f7964c6e..00000000 Binary files a/assets/icons/png/sort.png and /dev/null differ diff --git a/assets/icons/png/space.png b/assets/icons/png/space.png deleted file mode 100644 index 0f39ad8c..00000000 Binary files a/assets/icons/png/space.png and /dev/null differ diff --git a/assets/icons/png/star.png b/assets/icons/png/star.png deleted file mode 100644 index 9f873fc9..00000000 Binary files a/assets/icons/png/star.png and /dev/null differ diff --git a/assets/icons/png/stats.png b/assets/icons/png/stats.png deleted file mode 100644 index a5d6102a..00000000 Binary files a/assets/icons/png/stats.png and /dev/null differ diff --git a/assets/icons/png/sun.png b/assets/icons/png/sun.png deleted file mode 100644 index c51d8a7e..00000000 Binary files a/assets/icons/png/sun.png and /dev/null differ diff --git a/assets/icons/png/swap.png b/assets/icons/png/swap.png deleted file mode 100644 index 441a21ab..00000000 Binary files a/assets/icons/png/swap.png and /dev/null differ diff --git a/assets/icons/png/tag.png b/assets/icons/png/tag.png deleted file mode 100644 index 3e036900..00000000 Binary files a/assets/icons/png/tag.png and /dev/null differ diff --git a/assets/icons/png/tags.png b/assets/icons/png/tags.png deleted file mode 100644 index b9c5cdfa..00000000 Binary files a/assets/icons/png/tags.png and /dev/null differ diff --git a/assets/icons/png/text.png b/assets/icons/png/text.png deleted file mode 100644 index 79d41b0d..00000000 Binary files a/assets/icons/png/text.png and /dev/null differ diff --git a/assets/icons/png/undo.png b/assets/icons/png/undo.png deleted file mode 100644 index feb2bfe2..00000000 Binary files a/assets/icons/png/undo.png and /dev/null differ diff --git a/assets/icons/png/upload.png b/assets/icons/png/upload.png deleted file mode 100644 index 4b7b0346..00000000 Binary files a/assets/icons/png/upload.png and /dev/null differ diff --git a/assets/icons/png/view.png b/assets/icons/png/view.png deleted file mode 100644 index d42d67d2..00000000 Binary files a/assets/icons/png/view.png and /dev/null differ diff --git a/assets/icons/png/zen.png b/assets/icons/png/zen.png deleted file mode 100644 index 67150be4..00000000 Binary files a/assets/icons/png/zen.png and /dev/null differ diff --git a/assets/icons/prefab.svg b/assets/icons/prefab.svg new file mode 100644 index 00000000..66d0fe2b --- /dev/null +++ b/assets/icons/prefab.svg @@ -0,0 +1 @@ + diff --git a/assets/icons/sound.svg b/assets/icons/sound.svg new file mode 100644 index 00000000..7366527b --- /dev/null +++ b/assets/icons/sound.svg @@ -0,0 +1 @@ + diff --git a/core/Cargo.toml b/core/Cargo.toml index 3a8344b3..4e06f963 100644 --- a/core/Cargo.toml +++ b/core/Cargo.toml @@ -11,4 +11,29 @@ chrono = "0.4" redb = "4.3" serde = { version = "1", features = ["derive"] } serde_json = "1" +serde_path_to_error = "0.1" pulldown-cmark = { version = "0.13", default-features = false } +# the GPU compute backend (classify::gpu), off by default so the default build and +# wasm stay std only; `cargo test -p anend-core --features gpu` +wgpu = { version = "30", optional = true } +pollster = { version = "0.4", optional = true } + +[features] +gpu = ["dep:wgpu", "dep:pollster"] +# fetching public-domain texts for the starter classifiers (`starters::http_get`): the +# desktop and the hub; the browser build asks the hub +fetch = ["dep:ureq"] + +[[example]] +name = "gpu_bench" +required-features = ["gpu"] + +[[example]] +name = "gpu_profile" +required-features = ["gpu"] + +# pictures (`ops::pictures`): decoding, checking and thumbnails of PNG and JPEG; not in +# the browser build, which reaches pictures through the hub +[target.'cfg(not(target_arch = "wasm32"))'.dependencies] +ureq = { version = "3", default-features = false, features = ["rustls"], optional = true } +image = { version = "0.25", default-features = false, features = ["png", "jpeg"] } diff --git a/core/examples/generate.rs b/core/examples/generate.rs new file mode 100644 index 00000000..0838e355 --- /dev/null +++ b/core/examples/generate.rs @@ -0,0 +1,231 @@ +//! Generators shaped by a classifier: per author of core/corpus/authors, a small +//! byte-level generator learns to write like them; an author classifier is the critic. +//! For each author the example draws passages plainly, with the critic reranking, with +//! the critic guiding sampling, and after one reinforcement round on the critic's +//! scores, and reports how often the critic agrees the passage is that author's, with +//! timings. +//! +//! `cargo run --release -p anend-core --example generate [scale] [authors]` +//! `scale` multiplies training steps (default 1: a few minutes on 4 cores); +//! `authors` limits how many authors get a generator (default all 6). +//! +//! The sizes are chosen to finish in minutes on a 4-core CPU, a measured compute limit +//! (see `bench`), not a capability limit: larger generators write better and cost more. + +use std::time::Instant; + +use anend_core::classify::generate::{self, Constraints, Critic, GenOpts, Guidance, ReinforceOpts, Sampling, Want}; +use anend_core::classify::{ + Classifier, Config, Example, Flow, GenSpec, HeadSpec, Pool, Pooling, TrainOpts, kernels, pool, train, +}; + +const AUTHORS: [&str; 6] = ["austen", "chesterton", "melville", "milton", "shakespeare", "whitman"]; + +fn passages(text: &str, len: usize, step: usize) -> Vec { + let mut v = Vec::new(); + for region in text.split("\n* * *\n") { + let b = region.trim().as_bytes(); + let mut at = 0; + while at + len <= b.len() { + v.push(String::from_utf8_lossy(&b[at..at + len]).into_owned()); + at += step; + } + } + v +} + +fn agreement(critic: &Classifier, c: usize, cands: &[generate::Candidate]) -> f64 { + let hits = cands + .iter() + .filter(|k| critic.predict(&k.text(), &[])[0].top == c) + .count(); + hits as f64 / cands.len().max(1) as f64 +} + +fn main() { + let args: Vec = std::env::args().collect(); + let scale: f64 = args.get(1).and_then(|s| s.parse().ok()).unwrap_or(1.0); + let n_authors: usize = args.get(2).and_then(|s| s.parse().ok()).unwrap_or(6).min(6); + let dir = concat!(env!("CARGO_MANIFEST_DIR"), "/corpus/authors"); + let texts: Vec = AUTHORS + .iter() + .map(|a| std::fs::read_to_string(format!("{dir}/{a}.txt")).expect("corpus")) + .collect(); + println!( + "{} threads, {} kernels, scale {scale}", + pool::available(), + kernels::simd_name() + ); + + // the critic: an author classifier (no gematria features: a general transformer) + let t0 = Instant::now(); + let mut data = Vec::new(); + for (c, t) in texts.iter().enumerate() { + data.extend(passages(t, 200, 150).into_iter().map(|p| Example::class(&p, c))); + } + let ccfg = Config { + d_model: 96, + head_dim: 32, + heads: 3, + layers: 3, + d_ff: 256, + max_len: 128, + stride: 63, + dropout: 0.1, + ..Config::small().gematria(false) + }; + let mut critic = Classifier::new(ccfg, &[HeadSpec::single("author", &AUTHORS)], 7).unwrap(); + let o = TrainOpts { + epochs: 6, + batch: 16, + lr: 2e-3, + val_fraction: 0.1, + max_steps: (900.0 * scale) as usize, + ..TrainOpts::default() + }; + let rep = train::train(&mut critic, &data, &o, |_| Flow::Go).unwrap(); + println!( + "critic: {} weights, {} steps in {:.1}s, validation accuracy {:.1}%", + critic.net.weight_count(), + rep.steps, + t0.elapsed().as_secs_f64(), + 100.0 * rep.eval.as_ref().map_or(0.0, |e| e.accuracy()) + ); + + let gcfg = Config { + d_model: 128, + head_dim: 32, + heads: 4, + layers: 3, + d_ff: 352, + max_len: 128, + stride: 63, + dropout: 0.05, + causal: true, + pooling: Pooling::Mean, + ..Config::small().gematria(false) + }; + let mut totals = [0f64; 4]; + for (c, t) in texts.iter().enumerate().take(n_authors) { + let t1 = Instant::now(); + let corpus: Vec = passages(t, 400, 200).iter().map(|p| Example::generate(p)).collect(); + let mut g = Classifier::with_gen(gcfg.clone(), &[], Some(GenSpec::new("next")), 11 + c as u64).unwrap(); + let o = TrainOpts { + epochs: 30, + batch: 16, + lr: 2e-3, + val_fraction: 0.05, + patience: 0, + label_smoothing: 0.0, + max_steps: (500.0 * scale) as usize, + ..TrainOpts::default() + }; + let rep = train::train(&mut g, &corpus, &o, |_| Flow::Go).unwrap(); + let bpb = rep.eval.as_ref().and_then(|e| e.bits_per_byte).unwrap_or(f64::NAN); + println!( + "\n== {} == generator {} weights, {} steps in {:.1}s ({:.0} tokens/s), held-out {:.2} bits/byte", + AUTHORS[c], + g.net.weight_count(), + rep.steps, + t1.elapsed().as_secs_f64(), + rep.tokens_per_sec, + bpb + ); + let critics = [Critic::new(&critic, 0, Want::Class(c), 1.0)]; + let opts = GenOpts { + prompt: b"The ".to_vec(), + sampling: Sampling { + temperature: 0.8, + top_p: 0.95, + max_len: 120, + seed: 5, + ..Sampling::default() + }, + candidates: 12, + ..GenOpts::default() + }; + let none = Constraints::default(); + let t2 = Instant::now(); + let plain = generate::draw(&g, &critics, &none, &opts).unwrap(); + let tp = t2.elapsed().as_secs_f64(); + let ranked = generate::generate(&g, &critics, &none, &opts).unwrap(); + let t3 = Instant::now(); + let guided = generate::draw( + &g, + &critics, + &none, + &GenOpts { + guidance: Some(Guidance { + top_k: 4, + strength: 3.0, + every: 4, + }), + ..opts.clone() + }, + ) + .unwrap(); + let tg = t3.elapsed().as_secs_f64(); + let t4 = Instant::now(); + let rw = generate::rewards(&plain, &opts.prompt, 4.0); + let rr = generate::reinforce( + &mut g, + &rw, + &corpus, + &ReinforceOpts { + steps: 12, + lr: 5e-4, + ..ReinforceOpts::default() + }, + ) + .unwrap(); + let after = generate::draw( + &g, + &critics, + &none, + &GenOpts { + sampling: Sampling { + seed: 6, + ..opts.sampling.clone() + }, + ..opts.clone() + }, + ) + .unwrap(); + let tr = t4.elapsed().as_secs_f64(); + let a = [ + agreement(&critic, c, &plain), + agreement(&critic, c, &ranked[..3.min(ranked.len())]), + agreement(&critic, c, &guided), + agreement(&critic, c, &after), + ]; + for (t, x) in totals.iter_mut().zip(a) { + *t += x; + } + println!( + "critic agrees: plain {:.0}% ({:.1}s), top 3 reranked {:.0}%, guided {:.0}% ({:.1}s), after reinforce {:.0}% ({:.1}s; good {:.2}->{:.2}, bad {:.2}->{:.2} nats/byte)", + 100.0 * a[0], + tp, + 100.0 * a[1], + 100.0 * a[2], + tg, + 100.0 * a[3], + tr, + rr.good_before, + rr.good_after, + rr.bad_before, + rr.bad_after + ); + println!("best: The {}", ranked[0].text().replace('\n', " ")); + println!("plain: The {}", plain[0].text().replace('\n', " ")); + println!("guided: The {}", guided[0].text().replace('\n', " ")); + } + let n = n_authors as f64; + println!( + "\nmean agreement over {n_authors} authors: plain {:.0}%, reranked top 3 {:.0}%, guided {:.0}%, after reinforce {:.0}%", + 100.0 * totals[0] / n, + 100.0 * totals[1] / n, + 100.0 * totals[2] / n, + 100.0 * totals[3] / n + ); + let _ = Pool::new(1); +} diff --git a/core/examples/gpu_bench.rs b/core/examples/gpu_bench.rs new file mode 100644 index 00000000..0c4e05e1 --- /dev/null +++ b/core/examples/gpu_bench.rs @@ -0,0 +1,267 @@ +//! Tokens per second on the CPU and on the GPU, for the spec presets, the size the +//! machine profile picks for an "auto" trunk, and a ladder of larger trunks that only +//! stops where the device runs out of memory or a window takes longer than the time +//! limit. Meant for the user's own hardware: +//! +//! ```text +//! cargo run --release -p anend-core --features gpu --example gpu_bench [seconds-per-case] [max-window-seconds] +//! ``` +//! +//! Prints the device, the exactness probe, then per case: weights, window length, +//! forward tokens/s (CPU on every core, GPU exact and fast), whether the GPU's +//! generative logits equal the CPU's bit for bit, decoding tokens/s with the KV cache, +//! and training tokens/s (forward + backward + optimizer, two steps of four windows). + +use std::time::{Duration, Instant}; + +use anend_core::classify::bench::{self, LADDER, Task}; +use anend_core::classify::device::Device; +use anend_core::classify::gpu::{self, Precision, net::GpuDecoder, net::GpuNet}; +use anend_core::classify::model::{Config, Decoder, Gains, GenSpec, Mode, Net, Pooling}; +use anend_core::classify::train::{self, Example, Target, TrainOpts}; +use anend_core::classify::{Classifier, Flow, Pool, pool, text}; + +fn rate(per_case: Duration, mut f: impl FnMut() -> usize) -> f64 { + f(); // warm-up (pipelines compile, buffers settle) + let t = Instant::now(); + let (mut tokens, mut runs) = (0, 0); + while runs == 0 || t.elapsed() < per_case { + tokens += f(); + runs += 1; + } + tokens as f64 / t.elapsed().as_secs_f64() +} + +fn sized(d: usize, layers: usize, heads: usize, ff: usize, max_len: usize) -> Config { + Config { + d_model: d, + head_dim: d / heads, + heads, + layers, + d_ff: ff, + max_len, + stride: max_len / 2, + causal: true, + pooling: Pooling::Mean, + dropout: 0.0, + ..Config::small().gematria(false) + } +} + +fn main() { + let args: Vec = std::env::args().collect(); + let per_case = Duration::from_secs_f64(args.get(1).and_then(|s| s.parse().ok()).unwrap_or(2.0)); + let max_window = args.get(2).and_then(|s| s.parse().ok()).unwrap_or(5.0); + let g = match gpu::shared() { + Ok(g) => g, + Err(e) => { + println!("no GPU: {e}"); + return; + } + }; + println!("device: {}", g.describe()); + println!("largest buffer: {} M floats", g.max_floats() / 1_000_000); + for prec in [Precision::Exact, Precision::Fast] { + print!("{}", gpu::probe::probe(g, prec).summary()); + } + let threads = pool::available(); + let cpu_pool = Pool::new(threads); + println!( + "CPU: {threads} threads, {} kernels", + anend_core::classify::kernels::simd_name() + ); + + let profile = bench::load_or_measure( + &std::env::temp_dir().join("anend-machine-profile.json"), + Duration::from_secs(2), + ); + let auto = bench::suggest( + &profile, + &Task { + examples: 2000, + epochs: 20, + max_len: 256, + seconds: 600.0, + }, + ); + let mut cases: Vec<(String, Config)> = vec![ + ( + "small".into(), + Config { + causal: true, + pooling: Pooling::Mean, + ..Config::small().gematria(false) + }, + ), + ( + "base".into(), + Config { + causal: true, + pooling: Pooling::Mean, + ..Config::base().gematria(false) + }, + ), + ( + format!("auto (d {} × {} layers)", auto.d_model, auto.layers), + Config { + causal: true, + pooling: Pooling::Mean, + ..auto.gematria(false) + }, + ), + ]; + for &(d, l, h, ff) in &LADDER { + cases.push((format!("ladder d {d}"), sized(d, l, h, ff, 256))); + } + for &(d, l, h, ff) in &[ + (384, 8, 6, 1024), + (512, 8, 8, 1408), + (768, 12, 12, 2048), + (1024, 16, 16, 2816), + (1536, 24, 16, 4096), + (2048, 24, 16, 5632), + (3072, 32, 24, 8192), + (4096, 32, 32, 11008), + ] { + cases.push((format!("large d {d} × {l}"), sized(d, l, h, ff, 512))); + } + let text: Vec = (0..20_000) + .map(|i| b"the quick brown fox jumps over a lazy dog. "[i % 43]) + .collect(); + println!( + "\n{:<28} {:>9} {:>5} {:>10} {:>10} {:>10} {:>6} {:>9} {:>9} {:>9} {:>9}", + "case", + "weights", + "len", + "cpu tok/s", + "gpu exact", + "gpu fast", + "same", + "cpu dec/s", + "gpu dec/s", + "cpu trn/s", + "gpu trn/s" + ); + let mut cpu_ok = true; + for (name, cfg) in cases { + let weights_est = cfg.layers * (cfg.d_model * (3 * cfg.d_model + cfg.d_model + 3 * cfg.d_ff)); + if weights_est * 4 * 3 > g.max_floats() * 4 * 8 { + println!("{name:<28} skipped: larger than the device's buffers"); + continue; + } + let net = match Net::with_gen(cfg.clone(), &[], Some(GenSpec::new("next")), 1) { + Ok(n) => n, + Err(e) => { + println!("{name:<28} {e}"); + continue; + } + }; + let n = cfg.max_len; + let w = text::window_with(&text[..cfg.room()], true, false); + let gains = Gains::default(); + let cpu_t = if cpu_ok { + let t = Instant::now(); + let tr = net.forward(&w, &[], &gains, Mode::EVAL, Some(&cpu_pool)); + drop(net.gen_logits(&tr)); + let one = t.elapsed().as_secs_f64(); + if one > max_window { + cpu_ok = false; + f64::NAN + } else { + rate(per_case, || { + let tr = net.forward(&w, &[], &gains, Mode::EVAL, Some(&cpu_pool)); + drop(net.gen_logits(&tr)); + n + }) + } + } else { + f64::NAN + }; + let mut gpu_t = [f64::NAN; 2]; + let mut same = "-"; + let mut gdec = f64::NAN; + for (i, prec) in [Precision::Exact, Precision::Fast].into_iter().enumerate() { + let gn = match GpuNet::new(g, &net, prec) { + Ok(gn) => gn, + Err(e) => { + println!("{name:<28} {e}"); + break; + } + }; + let t = Instant::now(); + let (_, gl) = gn.forward(&net, &w, &gains, true); + if t.elapsed().as_secs_f64() > max_window { + break; + } + if i == 0 && cpu_t.is_finite() { + let tr = net.forward(&w, &[], &gains, Mode::EVAL, Some(&cpu_pool)); + same = if gl.as_deref() == Some(&net.gen_logits(&tr)[..]) { + "yes" + } else { + "no" + }; + } + gpu_t[i] = rate(per_case, || { + drop(gn.forward(&net, &w, &gains, true)); + n + }); + if i == 1 { + gdec = rate(per_case, || { + let mut dec = GpuDecoder::new(&gn, &net, gains, b"the "); + for &b in &text[..32] { + dec.push(b); + } + 36 + }); + } + } + let cdec = if cpu_t.is_finite() { + rate(per_case, || { + let mut dec = Decoder::new(&net, gains, b"the "); + for &b in &text[..32] { + dec.push(b); + } + 36 + }) + } else { + f64::NAN + }; + // training (forward + backward + AdamW) on a few windows, where a forward fits + let train_rate = |device: Device| -> f64 { + let mut clf = Classifier::with_gen(cfg.clone(), &[], Some(GenSpec::new("next")), 1).unwrap(); + let data: Vec = (0..8) + .map(|i| Example::bytes(&text[i * 7..i * 7 + cfg.room()], 0, Target::Next { from: 0 })) + .collect(); + let all: Vec = (0..data.len()).collect(); + let o = TrainOpts { + epochs: 1, + batch: 4, + val_fraction: 0.0, + max_steps: 2, + device, + ..TrainOpts::default() + }; + train::fit(&mut clf, &data, &all, &[], &o, |_| Flow::Go).map_or(f64::NAN, |r| r.tokens_per_sec) + }; + let ctrain = if cpu_t.is_finite() { + train_rate(Device::Cpu) + } else { + f64::NAN + }; + let gtrain = if gpu_t[0].is_finite() { + train_rate(Device::Gpu) + } else { + f64::NAN + }; + println!( + "{name:<28} {:>8.1}M {n:>5} {cpu_t:>10.0} {:>10.0} {:>10.0} {same:>6} {cdec:>9.0} {gdec:>9.0} {ctrain:>9.0} {gtrain:>9.0}", + net.weight_count() as f64 / 1e6, + gpu_t[0], + gpu_t[1], + ); + if gpu_t[1].is_nan() && !cpu_t.is_finite() { + println!("(stopping: windows take longer than {max_window} s on both)"); + break; + } + } +} diff --git a/core/examples/gpu_profile.rs b/core/examples/gpu_profile.rs new file mode 100644 index 00000000..3395ebd1 --- /dev/null +++ b/core/examples/gpu_profile.rs @@ -0,0 +1,113 @@ +//! Where the time goes when classifiers read texts on the GPU: per text, the dispatches, +//! submissions, bind groups and buffers, and the time split between making and writing +//! buffers, encoding and submitting, waiting for the device (its compute and the sync), +//! reading results back, and the rest on the CPU (embedding, windows, recording), next to +//! the CPU reading the same texts. On a software renderer (llvmpipe) only the proportions +//! and the counts say much: its "device" is the same CPU. +//! +//! ```text +//! cargo run --release -p anend-core --features gpu --example gpu_profile [preset] [texts] [bytes each, 0: 20 to 400] +//! ``` + +use std::time::Instant; + +use anend_core::classifiers::preset; +use anend_core::classify::device::{Device, Runner}; +use anend_core::classify::gpu::PROFILE; +use anend_core::classify::{Classifier, HeadSpec, Pool, pool}; + +fn text(i: usize, fixed: usize) -> String { + const W: [&str; 8] = ["river", "stone", "copper", "gear", "heron", "valve", "moss", "lamp"]; + let mut h = (i as u64).wrapping_mul(0x9e37_79b9_7f4a_7c15) | 1; + let len = if fixed > 0 { fixed } else { 20 + (h % 380) as usize }; + let mut s = String::new(); + while s.len() < len { + h ^= h << 13; + h ^= h >> 7; + h ^= h << 17; + s.push_str(W[(h % 8) as usize]); + s.push(' '); + } + s +} + +fn main() { + let args: Vec = std::env::args().collect(); + let size = args.get(1).map(String::as_str).unwrap_or("compact"); + let n: usize = args.get(2).and_then(|s| s.parse().ok()).unwrap_or(500); + let clf = Classifier::new(preset(size).unwrap(), &[HeadSpec::single("p", &["a", "b"])], 3).unwrap(); + let fixed: usize = args.get(3).and_then(|s| s.parse().ok()).unwrap_or(0); + let texts: Vec = (0..n) + .map(|i| { + let mut t = text(i, fixed); + if fixed > 0 { + t.truncate(fixed); + } + t + }) + .collect(); + let refs: Vec<&str> = texts.iter().map(String::as_str).collect(); + let p = Pool::new(pool::available()); + let t = Instant::now(); + let cpu = clf.predict_many(&refs, &[], &p); + let cpu_s = t.elapsed().as_secs_f64(); + println!("{size}, {n} texts; CPU: {:.0} texts/s", n as f64 / cpu_s); + for dev in [Device::Gpu, Device::GpuFast] { + let r = match Runner::open(dev, &clf.net) { + Ok(Some(r)) => r, + Ok(None) | Err(_) => { + println!("no GPU"); + return; + } + }; + // a warm-up pass compiles the pipelines + let warm: Vec<&[u8]> = refs.iter().take(8).map(|t| t.as_bytes()).collect(); + let zero = vec![0f32; clf.net.cfg.extra]; + let ex: Vec<&[f32]> = warm.iter().map(|_| zero.as_slice()).collect(); + r.text_runs(&clf.net, &warm, &ex, &clf.gains()); + PROFILE.take(); + let bytes: Vec<&[u8]> = refs.iter().map(|t| t.as_bytes()).collect(); + let ex: Vec<&[f32]> = bytes.iter().map(|_| zero.as_slice()).collect(); + let t = Instant::now(); + let out = r.text_runs(&clf.net, &bytes, &ex, &clf.gains()); + let s = t.elapsed().as_secs_f64(); + let prof = PROFILE.take(); + let same = out + .iter() + .zip(&cpu) + .filter(|((l, _), c)| clf.read(l)[0].probs == c[0].probs) + .count(); + println!( + "{dev:?}: {:.0} texts/s ({:.2}x the CPU), {same}/{n} equal to the CPU's bits", + n as f64 / s, + cpu_s / s + ); + let get = |k: &str| prof.iter().find(|(n, _)| *n == k).map_or(0, |x| x.1); + let ms = |k: &str| get(k) as f64 / 1e6; + println!( + " per text: {:.1} dispatches, {:.1} bind groups, {:.2} buffers, {:.3} submits", + get("dispatches") as f64 / n as f64, + get("bind_groups") as f64 / n as f64, + get("buffers") as f64 / n as f64, + get("submits") as f64 / n as f64 + ); + let total = s * 1000.0; + let other = total - ms("ns_upload") - ms("ns_encode") - ms("ns_wait") - ms("ns_readback"); + println!( + " ms: total {total:.0} = upload (buffers made and written) {:.0}, encode+submit {:.0}, wait for the device (compute and sync) {:.0}, readback {:.0}, the rest (embedding, recording, heads) {other:.0}", + ms("ns_upload"), + ms("ns_encode"), + ms("ns_wait"), + ms("ns_readback") + ); + let ops = std::mem::take(&mut *anend_core::classify::gpu::OP_NS.lock().unwrap()); + if !ops.is_empty() { + let all: u64 = ops.values().map(|v| v.1).sum(); + let mut v: Vec<_> = ops.into_iter().collect(); + v.sort_by_key(|x| std::cmp::Reverse(x.1.1)); + for (k, (n, ns)) in v { + println!(" {k:<16} {n:>7} dispatches {:>5.1}%", 100.0 * ns as f64 / all as f64); + } + } + } +} diff --git a/core/examples/graph_bench.rs b/core/examples/graph_bench.rs new file mode 100644 index 00000000..55347ec9 --- /dev/null +++ b/core/examples/graph_bench.rs @@ -0,0 +1,391 @@ +//! The entry graph store against the old store, on a deterministic corpus like weum's: +//! about 100k short lowercase texts with many prefix and suffix variants, and 2k longer +//! mixed-case markdown notes. Reports bytes on disk (whole files and per table, against +//! the raw packed bytes), compression on sample corpora, insert/search/render latency, the +//! effect of borrowing, and how long rebuilding the indexes into memory takes. +//! +//! `cargo run --release -p anend-core --example graph_bench [texts] [notes]` + +use std::path::{Path, PathBuf}; +use std::time::Instant; + +use anend_core::graph::codec; +use anend_core::graph::gematria::Mode; +use anend_core::graph::record::mime; +use anend_core::graph::store::{IndexMode, Reader}; +use anend_core::graph::{Graph, query::Page, query::Query}; + +struct Rng(u64); +impl Rng { + fn next(&mut self) -> u64 { + self.0 ^= self.0 << 13; + self.0 ^= self.0 >> 7; + self.0 ^= self.0 << 17; + self.0 + } + fn below(&mut self, n: usize) -> usize { + (self.next() % n.max(1) as u64) as usize + } +} + +fn vocabulary(r: &mut Rng) -> Vec { + let on = [ + "", "b", "c", "d", "f", "g", "h", "l", "m", "n", "p", "r", "s", "t", "th", "st", "w", "sh", "k", + ]; + let nu = ["a", "e", "i", "o", "u", "ea", "ou", "ai", "y"]; + let co = ["", "n", "r", "s", "t", "l", "nd", "ng", "st", "ck", "m"]; + let mut words: Vec = [ + "the", "and", "of", "to", "a", "in", "is", "it", "that", "was", "for", "on", "with", "as", "be", + ] + .iter() + .map(|s| s.to_string()) + .collect(); + while words.len() < 3000 { + let syl = 1 + r.below(3); + let w: String = (0..syl) + .map(|_| { + format!( + "{}{}{}", + on[r.below(on.len())], + nu[r.below(nu.len())], + co[r.below(co.len())] + ) + }) + .collect(); + words.push(w); + } + words +} + +/// a word, common ones more often (roughly Zipf) +fn word<'a>(r: &mut Rng, v: &'a [String]) -> &'a str { + let x = r.below(1000) as f64 / 1000.0; + &v[((x * x * x) * v.len() as f64) as usize % v.len()] +} + +/// `base` plus up to `spread - 1` words +fn phrase(r: &mut Rng, v: &[String], base: usize, spread: usize) -> Vec { + let n = base + r.below(spread); + (0..n).map(|_| word(r, v).to_string()).collect() +} + +fn corpus(n_texts: usize, n_notes: usize) -> (Vec, Vec) { + let mut r = Rng(0x5eed_1234_abcd_0001); + let v = vocabulary(&mut r); + let mut bases: Vec> = Vec::new(); + let mut texts = Vec::with_capacity(n_texts); + while texts.len() < n_texts { + let make_variant = !bases.is_empty() && r.below(100) < 55; + let words = if make_variant { + let b = bases[r.below(bases.len())].clone(); + match r.below(4) { + // a suffix added + 0 | 1 => [b, phrase(&mut r, &v, 1, 4)].concat(), + // a prefix added + 2 => [phrase(&mut r, &v, 1, 3), b].concat(), + // a suffix missing + _ => b[..(b.len() / 2).max(1)].to_vec(), + } + } else { + phrase(&mut r, &v, 2, 8) + }; + if words.len() >= 3 { + bases.push(words.clone()); + } + texts.push(words.join(" ")); + } + let mut notes = Vec::with_capacity(n_notes); + for i in 0..n_notes { + let mut t = String::new(); + let title: Vec = phrase(&mut r, &v, 2, 4) + .into_iter() + .map(|w| { + let mut c = w.chars(); + c.next() + .map(|f| f.to_uppercase().chain(c).collect()) + .unwrap_or_default() + }) + .collect(); + t.push_str(&format!("# {}\n\n", title.join(" "))); + for p in 0..1 + r.below(4) { + let mut words = phrase(&mut r, &v, 30, 120); + words[0] = { + let mut c = words[0].chars(); + c.next() + .map(|f| f.to_uppercase().chain(c).collect()) + .unwrap_or_default() + }; + let k = r.below(words.len()); + words[k] = format!("**{}**", words[k]); + t.push_str(&words.join(" ")); + t.push_str(&format!( + ". Noted {} on day {}.\n\n", + 1900 + (i * 7 + p) % 120, + r.below(365) + )); + if r.below(3) == 0 { + for _ in 0..2 + r.below(4) { + t.push_str(&format!("- {}\n", phrase(&mut r, &v, 2, 5).join(" "))); + } + t.push('\n'); + } + } + notes.push(t); + } + (texts, notes) +} + +fn size(p: &Path) -> u64 { + std::fs::metadata(p).map(|m| m.len()).unwrap_or(0) +} + +fn mb(b: u64) -> String { + format!("{:.2} MB", b as f64 / 1e6) +} + +fn scratch(name: &str) -> PathBuf { + let p = std::env::temp_dir().join(format!("anend-graph-bench-{}-{name}.redb", std::process::id())); + let _ = std::fs::remove_file(&p); + p +} + +fn compression() { + println!("\n## Compression (packed / UTF-8)\n"); + let samples = [ + ("lowercase prose", "the quick brown fox jumps over the lazy dog and keeps on running far away from home into the night where nobody can see it any more".to_string()), + ("mixed case markdown", "# Gardening Plans\n\nPlant **Tomatoes** in March, 2026-03-14.\n- Water them daily\n- NASA says it's fine\n\nSee [the guide](http://example.org/guide) for more.".to_string()), + ("hebrew", "בראשית ברא אלהים את השמים ואת הארץ והארץ היתה תהו ובהו וחשך על פני תהום".to_string()), + ("greek", "Ἐν ἀρχῇ ἦν ὁ λόγος, καὶ ὁ λόγος ἦν πρὸς τὸν θεόν, καὶ θεὸς ἦν ὁ λόγος.".to_string()), + ("russian", "В начале было Слово, и Слово было у Бога, и Слово было Бог.".to_string()), + ("japanese", "初めに言があった。言は神と共にあった。言は神であった。".to_string()), + ("digits", "call 5551234567 at 0900 on 2026-10-14, ref 31415926535".to_string()), + ]; + println!("| corpus | UTF-8 bytes | packed bytes | ratio |\n|---|---|---|---|"); + for (name, t) in samples { + let p = codec::pack_text(&t).len(); + println!("| {name} | {} | {p} | {:.3} |", t.len(), p as f64 / t.len() as f64); + } +} + +fn main() { + let args: Vec = std::env::args().collect(); + let n_texts: usize = args.get(1).and_then(|a| a.parse().ok()).unwrap_or(100_000); + let n_notes: usize = args.get(2).and_then(|a| a.parse().ok()).unwrap_or(2_000); + let (texts, notes) = corpus(n_texts, n_notes); + let utf8: usize = texts.iter().chain(¬es).map(|t| t.len()).sum(); + let packed: usize = texts.iter().chain(¬es).map(|t| codec::pack_text(t).len()).sum(); + println!("# graph_bench: {n_texts} texts, {n_notes} notes\n"); + println!( + "UTF-8 text: {}; packed 5-bit (no borrowing): {} ({:.3})", + mb(utf8 as u64), + mb(packed as u64), + packed as f64 / utf8 as f64 + ); + compression(); + + // ---- the old store + let old_path = scratch("old"); + let t0 = Instant::now(); + { + let mut s = anend_core::store::Store::open(&old_path).unwrap(); + s.saturate_many(&texts).unwrap(); + let ns: Vec = notes + .iter() + .map(|n| { + let (title, body) = n.split_once("\n\n").unwrap_or((n, "")); + anend_core::note::Note { + title: title.trim_start_matches("# ").to_string(), + markdown: body.to_string(), + ..Default::default() + } + }) + .collect(); + s.import(ns).unwrap(); + s.db.compact().unwrap(); + } + let old_time = t0.elapsed(); + let old_size = size(&old_path); + + // ---- the new store, one import transaction, with and without borrowing + let rows: Vec = texts + .iter() + .enumerate() + .map(|(i, t)| serde_json::json!([t, anend_core::graph::record::key_of(i as u64)])) + .collect(); + let json = serde_json::to_string(&rows).unwrap(); + let mut results = Vec::new(); + for (label, borrow, mode) in [ + ("disk indexes, borrowing", true, IndexMode::Disk), + ("disk indexes, no borrowing", false, IndexMode::Disk), + ("memory indexes, borrowing", true, IndexMode::Memory), + ] { + let path = scratch(label.replace([' ', ','], "-").as_str()); + let mut g = Graph::open(&path).unwrap(); + g.set_index_mode(mode).unwrap(); + g.borrow.enabled = borrow; + let t = Instant::now(); + let rep = g.import_texts(&json).unwrap(); + let import = t.elapsed(); + let t = Instant::now(); + g.write(|tx| { + for n in ¬es { + tx.save_text(n, mime::MARKDOWN)?; + } + Ok(()) + }) + .unwrap(); + let notes_time = t.elapsed(); + let before = size(&path); + g.compact().unwrap(); + let after = size(&path); + let stats = g.view().unwrap().stats().unwrap(); + results.push(( + label, + path.clone(), + rep.borrowing, + import, + notes_time, + before, + after, + stats.body_bytes, + )); + if label == "disk indexes, borrowing" { + println!("\n## Tables ({label}, after compaction)\n"); + println!( + "| table | rows | stored | metadata | fragmented | pages | fill | bytes/entry |\n|---|---|---|---|---|---|---|---|" + ); + let n = (n_texts + n_notes) as f64; + for u in g.table_use().unwrap() { + if u.rows == 0 { + continue; + } + println!( + "| {} | {} | {} | {} | {} | {} | {:.0}% | {:.1} |", + u.name, + u.rows, + u.stored, + u.metadata, + u.fragmented, + u.leaf_pages + u.branch_pages, + u.fill() * 100.0, + u.page_bytes() as f64 / n + ); + } + println!("\nraw packed bodies (with borrowing): {}", mb(stats.body_bytes)); + } + drop(g); + } + + println!("\n## Bytes on disk\n"); + println!( + "| store | file (compacted) | before compaction | bodies | entries borrowing | import | notes |\n|---|---|---|---|---|---|---|" + ); + println!( + "| old store (memories + notes) | {} | | | | {:.2?} (both) | |", + mb(old_size), + old_time + ); + for (label, _, borrowing, import, nt, before, after, bodies) in &results { + println!( + "| new: {label} | {} | {} | {} | {borrowing} | {import:.2?} | {nt:.2?} |", + mb(*after), + mb(*before), + mb(*bodies) + ); + } + + // ---- latencies on the first new store + let path = &results[0].1; + let g = Graph::open(path).unwrap(); + println!("\n## Latency (disk indexes, release)\n"); + let t = Instant::now(); + let n = 200; + for i in 0..n { + g.save_text( + &format!("{} and one more time {i}", texts[i * 37 % texts.len()]), + mime::TEXT, + ) + .unwrap(); + } + println!( + "insert, one durable transaction each: {:.1?} per text", + t.elapsed() / n as u32 + ); + let t = Instant::now(); + g.write(|tx| { + for i in 0..1000 { + tx.save_text(&format!("batch {i} {}", texts[i * 13 % texts.len()]), mime::TEXT)?; + } + Ok(()) + }) + .unwrap(); + println!("insert, 1000 in one transaction: {:.1?} per text", t.elapsed() / 1000); + let v = g.view().unwrap(); + let queries: Vec<&str> = texts.iter().step_by(997).take(100).map(|s| s.as_str()).collect(); + let t = Instant::now(); + let mut found = 0; + for q in &queries { + found += v.search_words(q).unwrap().len(); + } + println!( + "word search: {:.1?} per query ({} hits per query)", + t.elapsed() / queries.len() as u32, + found / queries.len() + ); + let t = Instant::now(); + let mut found = 0; + for q in &queries { + let m = anend_core::graph::gematria::Measure::of(q); + found += v.by_sum(Mode::Ordinal, m.ordinal).unwrap().len(); + } + println!( + "sum lookup: {:.1?} per query ({} hits per query)", + t.elapsed() / queries.len() as u32, + found / queries.len() + ); + let t = Instant::now(); + let page = v + .query( + &Query { + words: Some("the".into()), + ..Default::default() + }, + Page::first(100), + ) + .unwrap(); + println!( + "query \"the\", first page of 100 of {}: {:.1?}", + page.total, + t.elapsed() + ); + let ids: Vec = (0..10_000u64).map(|i| i * 7 % n_texts as u64).collect(); + let t = Instant::now(); + let rendered = v.render_many(&ids); + let borrowed = ids + .iter() + .filter(|&&id| v.record(id).unwrap().is_some_and(|r| r.has_refs())) + .count(); + println!( + "render 10k entries ({borrowed} with borrowed parts): {:.2?} per entry", + t.elapsed() / rendered.len() as u32 + ); + let t = Instant::now(); + let text = v.render(ids[1]).unwrap(); + println!("render one: {:.1?} ({} bytes)", t.elapsed(), text.len()); + drop(v); + drop(g); + + // ---- memory mode: what opening costs + let t = Instant::now(); + let g = Graph::open(&results[2].1).unwrap(); + println!( + "\nopen with the indexes rebuilt into memory: {:.2?} (about {} of ids and keys)", + t.elapsed(), + mb(g.memory_index_bytes() as u64) + ); + drop(g); + + for p in results.iter().map(|r| &r.1).chain([&old_path]) { + let _ = std::fs::remove_file(p); + } +} diff --git a/core/examples/pictures.rs b/core/examples/pictures.rs new file mode 100644 index 00000000..a166cfb8 --- /dev/null +++ b/core/examples/pictures.rs @@ -0,0 +1,139 @@ +//! A picture generator from a declarative spec: toy 64×64 pictures (discs, squares, +//! crosses, stripes) are cut into 8×8 patches, each patch one of 128 learned codes (one +//! token), so a picture is 72 tokens. A causal transformer learns to write code +//! sequences; sampled sequences decode back to pictures, written as PNGs. +//! +//! It also measures what limits picture size here: one forward pass at each sequence +//! length a patch size implies (attention grows with the square of the length), and +//! training throughput, so the limit is shown with numbers. +//! +//! `cargo run --release -p anend-core --example pictures [out-dir] [epochs]` + +use std::time::Instant; + +use anend_core::classify::codec::{self, Image, png, toy}; +use anend_core::classify::model::{Config, Gains, HeadSpec, Mode, Net, Pooling}; +use anend_core::classify::spec::{self, Answer, MemSource, ModelSpec, Value}; +use anend_core::classify::{Flow, generate, kernels, pool, text}; + +fn sheet(ims: &[Image], cols: usize, scale: usize) -> Image { + let (w, h) = (ims[0].width * scale, ims[0].height * scale); + let rows = ims.len().div_ceil(cols); + let pad = 4; + let mut out = Image::new(cols * (w + pad) + pad, rows * (h + pad) + pad, [128, 128, 128]); + for (i, im) in ims.iter().enumerate() { + let s = im.scaled(scale); + let (ox, oy) = (pad + (i % cols) * (w + pad), pad + (i / cols) * (h + pad)); + for y in 0..h { + for x in 0..w { + out.set(ox + x, oy + y, s.get(x, y)); + } + } + } + out +} + +fn main() { + let args: Vec = std::env::args().collect(); + let out = std::path::PathBuf::from( + args.get(1) + .cloned() + .unwrap_or_else(|| std::env::temp_dir().display().to_string()), + ); + let epochs: usize = args.get(2).and_then(|s| s.parse().ok()).unwrap_or(60); + std::fs::create_dir_all(&out).expect("out dir"); + println!("{} threads, {} kernels", pool::available(), kernels::simd_name()); + + // what sequence length costs: one forward pass of a 128-wide, 4-block trunk + println!("\nforward pass cost by picture tokenisation (64×64 picture, d_model 128, 4 blocks):"); + let base = Config { + pooling: Pooling::Mean, + causal: true, + ..Config::small().gematria(false) + }; + for (what, len) in [ + ("16×16 patches", 4 * 5), + ("8×8 patches", 8 * 9), + ("4×4 patches", 16 * 17), + ("2×2 patches", 32 * 33), + ("1 byte a pixel (palette)", 64 * 65), + ] { + let net = Net::new( + Config { + max_len: len + 2, + ..base.clone() + }, + &[HeadSpec::single("k", &["a"])], + 1, + ) + .unwrap(); + let w = text::window(&vec![7u8; len]); + let t = Instant::now(); + let mut n = 0; + while n == 0 || t.elapsed().as_secs_f64() < 0.5 { + drop(net.forward(&w, &[], &Gains::default(), Mode::EVAL, None)); + n += 1; + } + let ms = t.elapsed().as_secs_f64() * 1e3 / n as f64; + println!( + " {what:>26}: {len:>5} tokens, {ms:>9.2} ms per pass, {:>7.1} µs per token", + ms * 1e3 / len as f64 + ); + } + + let train_ims: Vec = (0..192).map(|i| Value::Image(toy(64, i % 4, i as u64))).collect(); + let spec = ModelSpec::from_json(&format!( + r#"{{ + "name": "toy pictures", + "input": {{"type": "image", "width": 64, "height": 64, "patch": 8, "codes": 128}}, + "trunk": {{"preset": "small", "dropout": 0.05}}, + "heads": [{{"name": "draw", "kind": "generate"}}], + "data": [{{"from": "list", "list": "toys", "head": "draw"}}], + "sampling": {{"temperature": 0.9, "top_p": 0.95, "max_len": 72, "seed": 1}}, + "train": {{"epochs": {epochs}, "batch": 16, "lr": 0.002, "val_fraction": 0.05, "patience": 0}} + }}"# + )) + .unwrap(); + let src = MemSource::default().with_list("toys", train_ims.clone()); + let t = Instant::now(); + let (m, rep) = spec::train(None, &spec, &src, None, |_| Flow::Go).unwrap(); + println!( + "\ntrained {} weights for {} steps in {:.1}s ({:.0} tokens/s); held-out {:.2} bits per code", + m.clf.net.weight_count(), + rep.steps, + t.elapsed().as_secs_f64(), + rep.tokens_per_sec, + rep.eval.as_ref().and_then(|e| e.bits_per_byte).unwrap_or(f64::NAN) + ); + let cb = m.codebook.as_ref().unwrap(); + let originals: Vec = train_ims[..16] + .iter() + .map(|v| match v { + Value::Image(im) => im.clone(), + _ => unreachable!(), + }) + .collect(); + let through: Vec = originals.iter().map(|im| cb.decode(&cb.encode(im), 64, 64)).collect(); + let t = Instant::now(); + let samples: Vec = (0..16) + .map(|i| { + let (b, _) = generate::sample(&m.clf, &[], &spec.sampling, i); + cb.decode(&b, 64, 64) + }) + .collect(); + println!("sampled 16 pictures in {:.2}s", t.elapsed().as_secs_f64()); + // `run` continues a picture's codes: here from an empty prompt via the generate head + if let Ok(a) = m.run(&Value::Image(toy(64, 0, 999))) { + assert!(a.values().any(|x| matches!(x, Answer::Generated(_)))); + } + for (name, ims) in [ + ("pictures-training.png", &originals), + ("pictures-codebook.png", &through), + ("pictures-sampled.png", &samples), + ] { + let p = out.join(name); + std::fs::write(&p, png(&sheet(ims, 4, 2))).unwrap(); + println!("wrote {}", p.display()); + } + let _ = codec::ROW; +} diff --git a/core/examples/pretrained.rs b/core/examples/pretrained.rs new file mode 100644 index 00000000..16039785 --- /dev/null +++ b/core/examples/pretrained.rs @@ -0,0 +1,217 @@ +//! A pretrained open model in the engine, steered by a classifier of your own. +//! +//! Download a Llama-family model folder first (model hubs are reachable from your +//! machine). Recommended small one: SmolLM2-135M (Apache 2.0, 135 M weights, ~270 MB in +//! bf16, about 0.5 GB of RAM as f32 here): +//! +//! ```sh +//! pip install -U "huggingface_hub[cli]" +//! huggingface-cli download HuggingFaceTB/SmolLM2-135M \ +//! config.json generation_config.json tokenizer.json model.safetensors \ +//! --local-dir models/SmolLM2-135M +//! # or without Python: +//! mkdir -p models/SmolLM2-135M && cd models/SmolLM2-135M && for f in config.json \ +//! generation_config.json tokenizer.json model.safetensors; do \ +//! curl -LO https://huggingface.co/HuggingFaceTB/SmolLM2-135M/resolve/main/$f; done +//! ``` +//! +//! Then `cargo run --release -p anend-core --example pretrained -- models/SmolLM2-135M +//! ["prompt"] [--tune]`. Bigger ones of the same family work the same way +//! (Qwen/Qwen2.5-0.5B, Qwen/Qwen3-0.6B, TinyLlama/TinyLlama-1.1B-Chat-v1.0, +//! meta-llama/Llama-3.2-1B, mistralai/Mistral-7B-v0.1, …), given the memory: weights +//! are held as f32, 4 bytes each. +//! +//! What it does: loads the model (timing it), writes a greedy continuation of the +//! prompt (tokens per second), trains a small byte-level author classifier on +//! `core/corpus/authors` (Austen against Melville, about a minute), draws candidate +//! continuations from the pretrained model and ranks them by the classifier as a +//! critic, then samples with the critic guiding each step. With `--tune` it also +//! fine-tunes the pretrained model a few steps on Austen and reports her passages' +//! bits per token before and after. + +use std::path::Path; +use std::time::Instant; + +use anend_core::classify::generate::{self, Constraints, Critic, GenOpts, Guidance, Sampling, Want}; +use anend_core::classify::pretrained::{self, Options}; +use anend_core::classify::{Classifier, Config, Example, Flow, HeadSpec, TrainOpts, train}; + +fn passages(text: &str, len: usize, step: usize) -> Vec { + let mut v = Vec::new(); + for region in text.split("\n* * *\n") { + let chars: Vec = region.trim().chars().collect(); + let mut at = 0; + while at + len <= chars.len() { + v.push(chars[at..at + len].iter().collect()); + at += step; + } + } + v +} + +fn main() -> Result<(), String> { + let args: Vec = std::env::args().skip(1).collect(); + let tune = args.iter().any(|a| a == "--tune"); + let pos: Vec<&String> = args.iter().filter(|a| !a.starts_with("--")).collect(); + let Some(dir) = pos.first() else { + return Err("usage: pretrained [prompt] [--tune] (see the file's doc for a download)".into()); + }; + let prompt = pos + .get(1) + .map_or("It is a truth universally acknowledged that", |s| s.as_str()); + + let t = Instant::now(); + let folder = pretrained::Folder::open(Path::new(dir.as_str()))?; + let a = folder.arch.clone(); + let mut lm = folder.model(&Options { + max_len: Some(512), + ..Options::default() + })?; + drop(folder); + println!( + "{}: {} blocks, width {}, {} heads ({} key/value), head {}, ff {}, vocab {}, {:.1} M weights; loaded in {:.1} s", + a.model_type, + a.layers, + a.hidden, + a.heads, + a.kv_heads, + a.head_dim, + a.ff, + a.vocab, + lm.net.weight_count() as f64 / 1e6, + t.elapsed().as_secs_f64() + ); + + let t = Instant::now(); + let (out, _) = generate::sample(&lm, prompt.as_bytes(), &Sampling::greedy(160), 0); + let toks = lm + .net + .lexicon + .as_ref() + .unwrap() + .tokenizer + .encode(&String::from_utf8_lossy(&out)) + .len(); + let secs = t.elapsed().as_secs_f64(); + println!( + "\ngreedy ({toks} tokens, {:.1} tokens/s):\n{prompt}{}\n", + toks as f64 / secs, + String::from_utf8_lossy(&out) + ); + + // a critic of our own: Austen (1) against Melville (0), on bytes + let read = + |n: &str| std::fs::read_to_string(format!("core/corpus/authors/{n}.txt")).map_err(|e| format!("{n}: {e}")); + let (austen, melville) = (read("austen")?, read("melville")?); + let (pa, pm) = (passages(&austen, 160, 120), passages(&melville, 160, 120)); + let mut data: Vec = pa.iter().map(|p| Example::class(p, 1)).collect(); + data.extend(pm.iter().map(|p| Example::class(p, 0))); + let mut critic = Classifier::new( + Config { + max_len: 192, + stride: 95, + ..Config::small().gematria(false) + }, + &[HeadSpec::single("author", &["melville", "austen"])], + 1, + )?; + let t = Instant::now(); + let rep = train::train( + &mut critic, + &data, + &TrainOpts { + epochs: 3, + val_fraction: 0.1, + ..TrainOpts::default() + }, + |_| Flow::Go, + )?; + println!( + "critic: {} steps in {:.0} s, validation accuracy {:.0} %", + rep.steps, + t.elapsed().as_secs_f64(), + 100.0 * rep.eval.as_ref().map_or(0.0, |e| e.accuracy()) + ); + + let critics = [Critic::new(&critic, 0, Want::Class(1), 1.0)]; + let opts = GenOpts { + prompt: prompt.as_bytes().to_vec(), + sampling: Sampling { + temperature: 0.9, + top_p: 0.95, + max_len: 160, + seed: 7, + ..Sampling::default() + }, + candidates: 8, + judge_prompt: false, + ..GenOpts::default() + }; + let show = |title: &str, cands: &[generate::Candidate], secs: f64| { + println!("\n{title} ({secs:.1} s):"); + for c in cands.iter().take(3) { + println!(" [austen {:.2}] {}", c.scores[0], c.text().replace('\n', " ")); + } + let mean = cands.iter().map(|c| c.scores[0]).sum::() / cands.len().max(1) as f32; + println!(" mean critic score {mean:.2} over {}", cands.len()); + }; + let t = Instant::now(); + let ranked = generate::generate(&lm, &critics, &Constraints::default(), &opts)?; + show("ranked by the critic", &ranked, t.elapsed().as_secs_f64()); + let t = Instant::now(); + let guided = generate::generate( + &lm, + &critics, + &Constraints::default(), + &GenOpts { + guidance: Some(Guidance { + top_k: 4, + strength: 2.0, + every: 4, + }), + candidates: 4, + ..opts.clone() + }, + )?; + show("guided by the critic", &guided, t.elapsed().as_secs_f64()); + + if tune { + let held: Vec<&String> = pa.iter().step_by(10).take(8).collect(); + let bits = |m: &Classifier| { + let (n, c) = held.iter().fold((0.0, 0), |(n, c), p| { + let (a, b) = train::nll(m, p.as_bytes(), 0); + (n + a, c + b) + }); + n / c.max(1) as f64 / std::f64::consts::LN_2 + }; + let before = bits(&lm); + let tune_data: Vec = pa + .iter() + .skip(1) + .step_by(5) + .take(48) + .map(|p| Example::generate(p)) + .collect(); + let t = Instant::now(); + train::train( + &mut lm, + &tune_data, + &TrainOpts { + epochs: 1, + batch: 8, + lr: 2e-5, + warmup: 0.1, + val_fraction: 0.0, + ..TrainOpts::default() + }, + |_| Flow::Go, + )?; + println!( + "\nfine-tuned on {} Austen passages in {:.0} s: held-out bits per token {before:.3} -> {:.3}", + tune_data.len(), + t.elapsed().as_secs_f64(), + bits(&lm) + ); + } + Ok(()) +} diff --git a/core/examples/starters.rs b/core/examples/starters.rs new file mode 100644 index 00000000..bb52007e --- /dev/null +++ b/core/examples/starters.rs @@ -0,0 +1,72 @@ +//! Each starter classifier trained from scratch and scored on its held-out texts, as the +//! app does it (the preset's training options), printed as a table: +//! +//! ```text +//! cargo run --release -p anend-core --example starters [preset] [epochs] [texts a class] [patience] [starter id] +//! ``` +//! +//! The fetched starter is left out unless its books are in `./starters`. + +use std::time::Instant; + +use anend_core::classifiers::{preset, preset_opts}; +use anend_core::classify::train::{self, Example}; +use anend_core::classify::{Classifier, Flow, HeadSpec, Pool, pool}; +use anend_core::starters::{self, Source, Split}; + +fn main() { + let args: Vec = std::env::args().collect(); + let size = args.get(1).map(String::as_str).unwrap_or("compact"); + let epochs: Option = args.get(2).and_then(|s| s.parse().ok()); + let per: usize = args + .get(3) + .and_then(|s| s.parse().ok()) + .unwrap_or(starters::TRAIN_PER_CLASS); + let patience: Option = args.get(4).and_then(|s| s.parse().ok()); + let only: Option<&str> = args.get(5).map(String::as_str); + let books = std::path::Path::new("starters"); + let p = Pool::new(pool::available()); + println!( + "{:<28} {:>6} {:>6} {:>9} {:>8} {:>7}", + "starter", "train", "held", "held-out", "val acc", "seconds" + ); + for s in starters::STARTERS.iter().filter(|s| only.is_none_or(|o| o == s.id)) { + if s.source == Source::Fetched && !starters::fetched(books) { + println!("{:<28} (its books aren't in ./starters)", s.title); + continue; + } + let train_set = starters::examples_with(s.id, Split::Train, Some(books), per).unwrap(); + let held = starters::examples(s.id, Split::Held, Some(books)).unwrap(); + let cfg = preset(size).expect("a preset").gematria(s.gematria); + let mut clf = Classifier::new(cfg, &[HeadSpec::single(s.id, s.classes)], 1).unwrap(); + let mut o = preset_opts(size); + if let Some(e) = epochs { + o.epochs = e; + } + if let Some(n) = patience { + o.patience = n; + } + let data: Vec = train_set.iter().map(|(t, c)| Example::class(t, *c)).collect(); + let t = Instant::now(); + let r = train::train(&mut clf, &data, &o, |_| Flow::Go).unwrap(); + let secs = t.elapsed().as_secs_f64(); + let texts: Vec<&str> = held.iter().map(|(t, _)| t.as_str()).collect(); + let outs = clf.predict_many(&texts, &[], &p); + let right = held.iter().zip(&outs).filter(|((_, c), o)| o[0].top == *c).count(); + let val = r + .eval + .as_ref() + .and_then(|e| e.heads.first().cloned().flatten()) + .map(|m| m.accuracy) + .unwrap_or(f64::NAN); + println!( + "{:<28} {:>6} {:>6} {:>8.1}% {:>7.1}% {:>7.1}", + s.title, + train_set.len(), + held.len(), + 100.0 * right as f64 / held.len() as f64, + 100.0 * val, + secs + ); + } +} diff --git a/core/src/classifiers.rs b/core/src/classifiers.rs index f1b4ebeb..c6ba74e2 100644 --- a/core/src/classifiers.rs +++ b/core/src/classifiers.rs @@ -24,6 +24,7 @@ use serde::{Deserialize, Serialize}; use std::collections::{BTreeMap, HashMap}; use crate::classify::compose::{Contribution, Edge, Graph, StackReport}; +use crate::classify::device::{self, Choice, Reading, Runner}; use crate::classify::grow::{self, Grower}; use crate::classify::metrics::Metrics; use crate::classify::steer::Output; @@ -38,6 +39,11 @@ use crate::store::{NOTES, Store, StoreResult}; pub const DEFINITIONS: TableDefinition<&str, &[u8]> = TableDefinition::new("classifiers"); pub const WEIGHTS: TableDefinition<&str, &[u8]> = TableDefinition::new("classifier weights"); pub const FEEDBACK: TableDefinition<(&str, u64), &[u8]> = TableDefinition::new("classifier feedback"); +/// (name, n) -> what a yes/no on that classifier changed, to take it back (`Undo`) +pub const UNDO: TableDefinition<(&str, u64), &[u8]> = TableDefinition::new("classifier undo"); + +/// how many yes/no answers on a classifier can be taken back +pub const UNDO_KEPT: u64 = 20; /// how many history events a definition keeps (oldest dropped first) pub const HISTORY_KEPT: usize = 200; @@ -50,9 +56,18 @@ pub fn create_tables(txn: &WriteTransaction) -> StoreResult<()> { txn.open_table(DEFINITIONS).map_err(err)?; txn.open_table(WEIGHTS).map_err(err)?; txn.open_table(FEEDBACK).map_err(err)?; + txn.open_table(UNDO).map_err(err)?; Ok(()) } +/// what one yes/no changed: the feedback it logged, and each classifier it wrote as it +/// was before (its definition's JSON and its weights in base64) +#[derive(Serialize, Deserialize)] +struct Undo { + feedback: u64, + was: Vec<(String, String, Option)>, +} + // ---------------------------------------------------------------- what's stored /// a class: a list, by its head's label, and the list's name when it was chosen @@ -108,6 +123,10 @@ pub struct Definition { pub head: HeadKind, /// "tiny", "compact", "small" or "base" (see `preset`) pub preset: String, + /// the gematria input channels (letter values, word sums, the side vector): opt-in, + /// off for new classifiers; definitions saved before it was optional had them on + #[serde(default = "yes")] + pub gematria: bool, pub steer: Steer, #[serde(default)] pub inputs: Vec, @@ -120,6 +139,9 @@ pub struct Definition { /// bumped by every write of the weights #[serde(default)] pub version: u64, + /// the starter it was made from (`starters`), whose held-out texts score it + #[serde(default, skip_serializing_if = "Option::is_none")] + pub starter: Option, pub seed: u64, pub created: String, pub modified: String, @@ -145,6 +167,10 @@ pub struct FeedbackEntry { pub after: f32, } +fn yes() -> bool { + true +} + /// the sizes on offer, smallest first pub const PRESETS: [&str; 4] = ["tiny", "compact", "small", "base"]; pub const DEFAULT_PRESET: &str = "compact"; @@ -252,6 +278,7 @@ impl Definition { not, head, preset: preset_name.into(), + gematria: false, steer: Steer { gains: Default::default(), heads: vec![], @@ -261,6 +288,7 @@ impl Definition { history: vec![], outputs: BTreeMap::new(), version: 0, + starter: None, created: now.clone(), modified: now, }; @@ -317,7 +345,7 @@ impl Definition { /// a fresh, untrained classifier for this definition; `extra` is the width of its /// upstream inputs pub fn build(&self, extra: usize) -> StoreResult { - let mut cfg = preset(&self.preset).ok_or("unknown preset")?; + let mut cfg = preset(&self.preset).ok_or("unknown preset")?.gematria(self.gematria); cfg.extra = extra; let names = self.class_names(); let names: Vec<&str> = names.iter().map(String::as_str).collect(); @@ -336,6 +364,35 @@ pub struct Stack { pub node: usize, /// definitions in graph order pub defs: Vec, + /// where its texts are read, decided on first use + pub read: Read, +} + +/// where a stack reads texts: the choice it was loaded with, and (on first use) the +/// device that gives and the nets uploaded to it +pub struct Read { + pub choice: Choice, + /// whether the GPU may be used here + pub allowed: bool, + /// the save's classifiers file, naming the uploaded nets + pub origin: String, + state: std::sync::OnceLock<(Reading, Vec>>)>, +} + +impl Read { + pub fn new(choice: Choice, allowed: bool, origin: String) -> Read { + Read { + choice, + allowed, + origin, + state: std::sync::OnceLock::new(), + } + } + + /// the CPU, as the reference + pub fn cpu() -> Read { + Read::new(Choice::Cpu, false, String::new()) + } } impl Stack { @@ -351,13 +408,48 @@ impl Stack { self.defs.iter().map(|d| d.name.clone()).collect() } - /// head 0's steered output for every text, in parallel + /// where this stack reads texts, and the nets on the device for it (opened on first + /// use; a net the device can't take sends the whole stack to the CPU, saying why) + fn reader(&self) -> &(Reading, Vec>>) { + self.read.state.get_or_init(|| { + let nets: Vec<&Classifier> = self.graph.nodes.iter().map(|n| &n.clf).collect(); + let r = device::reading_for(self.read.choice, self.read.allowed, &nets); + if !r.device.is_gpu() { + return (r, vec![]); + } + let mut runners = Vec::new(); + for (d, n) in self.defs.iter().zip(&self.graph.nodes) { + let key = format!("{}\u{0}{}\u{0}{}", self.read.origin, d.name, d.version); + match device::runner(&key, r.device, &n.clf.net) { + Ok(x) => runners.push(x), + Err(e) => { + let note = format!("{:?} doesn't fit the GPU ({e}): read on the CPU", d.name); + return (Reading::cpu(r.choice, Some(note)), vec![]); + } + } + } + (r, runners) + }) + } + + /// where this stack reads texts + pub fn reading(&self) -> &Reading { + &self.reader().0 + } + + /// every node's steered outputs and the judged node's pooled vector for many texts, + /// on the stack's device + pub fn read_many(&self, texts: &[&str], pool: &Pool) -> Vec<(Vec, Vec)> { + let runners: Vec> = self.reader().1.iter().map(|r| r.as_deref()).collect(); + self.graph.read_node_many(self.node, texts, &runners, pool) + } + + /// head 0's steered output for every text, on the stack's device (the pool on the CPU) pub fn outputs(&self, texts: &[&str], pool: &Pool) -> Vec { - let slots: Vec>> = texts.iter().map(|_| Default::default()).collect(); - pool.run(texts.len(), &|i| { - *slots[i].lock().unwrap() = Some(self.graph.predict(self.node, texts[i]).swap_remove(0)); - }); - slots.into_iter().map(|s| s.into_inner().unwrap().unwrap()).collect() + self.read_many(texts, pool) + .into_iter() + .map(|(mut o, _)| o.swap_remove(0)) + .collect() } /// the extra inputs of every text @@ -407,6 +499,8 @@ pub struct Training { pub rounds: usize, /// the version of the weights it started from pub from_version: u64, + /// why it runs on the CPU when a GPU was asked for + pub device_note: Option, } /// what a run did @@ -525,6 +619,9 @@ pub struct TrainArgs { pub rounds: Option, /// start from new weights instead of the trained ones pub fresh: bool, + /// where to train: the CPU (the reference), the GPU exact or fast; a GPU this build + /// or machine doesn't have falls back to the CPU, saying why + pub device: crate::classify::device::Device, } /// what yes/no feedback is about: a text, and the memory or note it came from @@ -602,7 +699,8 @@ impl Store { } /// a new classifier over lists (by label): `classes` the lists, `not` an optional - /// list of texts that are none of them, `inputs` classifiers it builds on + /// list of texts that are none of them, `inputs` classifiers it builds on; no + /// gematria channels (see `create_classifier_with`) pub fn create_classifier( &self, name: &str, @@ -611,6 +709,22 @@ impl Store { head: HeadKind, preset_name: &str, inputs: Vec, + ) -> StoreResult { + self.create_classifier_with(name, classes, not, head, preset_name, inputs, false) + } + + /// `create_classifier`, with the gematria input channels (letter values, word sums, + /// the side vector) on when `gematria` + #[allow(clippy::too_many_arguments)] + pub fn create_classifier_with( + &self, + name: &str, + classes: &[Ref], + not: Option<&Ref>, + head: HeadKind, + preset_name: &str, + inputs: Vec, + gematria: bool, ) -> StoreResult { let name = clean_name(name)?; if self.classifier(&name).is_ok() { @@ -626,6 +740,7 @@ impl Store { let classes = classes.iter().map(class).collect::>>()?; let not = not.map(class).transpose()?; let mut def = Definition::new(&name, classes, not, head, preset_name)?; + def.gematria = gematria; for i in &inputs { if i.from == name { return Err("a classifier can't build on itself".into()); @@ -654,6 +769,8 @@ impl Store { txn.open_table(WEIGHTS).map_err(err)?.remove(name).map_err(err)?; let mut f = txn.open_table(FEEDBACK).map_err(err)?; f.retain_in((name, 0)..=(name, u64::MAX), |_, _| false).map_err(err)?; + let mut u = txn.open_table(UNDO).map_err(err)?; + u.retain_in((name, 0)..=(name, u64::MAX), |_, _| false).map_err(err)?; } txn.commit().map_err(err)?; self.memo_clear(name)?; @@ -726,6 +843,11 @@ impl Store { node: order.len() - 1, graph, defs: order, + read: Read::new( + device::choice(), + self.gpu_reads(), + self.path().to_string_lossy().into_owned(), + ), }) } @@ -733,6 +855,9 @@ impl Store { /// a list's members as stored pub fn list_members(&self, list: &Ref) -> StoreResult> { + if let Some(t) = self.texts() { + return t.members(list); + } let txn = self.db.begin_read().map_err(err)?; let t = txn.open_multimap_table(LISTS).map_err(err)?; let mut out = Vec::new(); @@ -744,6 +869,9 @@ impl Store { /// what a classifier reads of a memory (its text) or a note (title and markdown) pub fn ref_text(&self, r: &Ref) -> StoreResult> { + if let Some(t) = self.texts() { + return t.text(r); + } let txn = self.db.begin_read().map_err(err)?; Ok(match r { Ref::Memory(k) => { @@ -764,6 +892,9 @@ impl Store { /// every memory and note a classifier can rank: (ref, what it reads, what's shown) pub fn candidates(&self, limit: usize) -> StoreResult> { + if let Some(t) = self.texts() { + return t.candidates(limit); + } let mut out: Vec<(Ref, String, String)> = self .all_memories()? .into_iter() @@ -860,6 +991,16 @@ impl Store { // more threads than the machine has only slows it (and each is a real thread) o.threads = a.threads.unwrap_or(o.threads).min(crate::classify::pool::available()); o.seed = crate::classify::math::key(&[def.seed, def.version]); + let device_note = match a.device.check() { + Ok(()) => { + o.device = a.device; + None + } + Err(e) => { + o.device = crate::classify::device::Device::Cpu; + Some(format!("no GPU here ({e}): trained on the CPU")) + } + }; if stack.node > 0 { let pool = o.pool(); data = stack.graph.with_extras(stack.node, &data, &pool); @@ -870,6 +1011,7 @@ impl Store { opts: o, rounds: a.rounds.unwrap_or(1).clamp(1, 50), from_version: def.version, + device_note, }) } @@ -906,6 +1048,8 @@ impl Store { seconds: s.seconds, }); self.put_classifier(&mut def, Some(t.stack.clf()))?; + // the yes/no answers before it can't be taken back past new weights + self.drop_undo(name)?; Ok(def) } @@ -938,9 +1082,9 @@ impl Store { // ---- feedback - fn log_feedback(&self, e: &FeedbackEntry) -> StoreResult<()> { + fn log_feedback(&self, e: &FeedbackEntry) -> StoreResult { let txn = self.db.begin_write().map_err(err)?; - { + let n = { let mut t = txn.open_table(FEEDBACK).map_err(err)?; let name = e.classifier.as_str(); let next = t @@ -952,10 +1096,115 @@ impl Store { .map_or(0, |(k, _)| k.value().1 + 1); let json = serde_json::to_vec(e).map_err(err)?; t.insert((name, next), json.as_slice()).map_err(err)?; + next + }; + txn.commit().map_err(err)?; + Ok(n) + } + + /// the classifiers `names` as they are now, for an [`Undo`] + fn snapshot(&self, names: &[String]) -> StoreResult)>> { + let txn = self.db.begin_read().map_err(err)?; + let d = txn.open_table(DEFINITIONS).map_err(err)?; + let w = txn.open_table(WEIGHTS).map_err(err)?; + let mut out = Vec::new(); + for n in names { + let Some(def) = d.get(n.as_str()).map_err(err)? else { + continue; + }; + let def = String::from_utf8_lossy(def.value()).into_owned(); + let weights = w.get(n.as_str()).map_err(err)?.map(|g| base64(g.value())); + out.push((n.clone(), def, weights)); + } + Ok(out) + } + + /// keeps what a yes/no on `name` changed, the oldest beyond [`UNDO_KEPT`] dropped + fn keep_undo(&self, name: &str, u: &Undo) -> StoreResult<()> { + let txn = self.db.begin_write().map_err(err)?; + { + let mut t = txn.open_table(UNDO).map_err(err)?; + let next = t + .range((name, 0)..=(name, u64::MAX)) + .map_err(err)? + .next_back() + .transpose() + .map_err(err)? + .map_or(0, |(k, _)| k.value().1 + 1); + let json = serde_json::to_vec(u).map_err(err)?; + t.insert((name, next), json.as_slice()).map_err(err)?; + if next >= UNDO_KEPT { + let cut = next - UNDO_KEPT; + t.retain_in((name, 0)..=(name, cut), |_, _| false).map_err(err)?; + } } txn.commit().map_err(err) } + /// forgets what could be taken back on `name`, and every yes/no through a stack + /// that wrote it (its weights changed another way) + pub fn drop_undo(&self, name: &str) -> StoreResult<()> { + let txn = self.db.begin_write().map_err(err)?; + txn.open_table(UNDO) + .map_err(err)? + .retain(|_, v| serde_json::from_slice::(v).is_ok_and(|u| u.was.iter().all(|w| w.0 != name))) + .map_err(err)?; + txn.commit().map_err(err) + } + + /// how many yes/no answers on `name` can be taken back + pub fn undo_count(&self, name: &str) -> StoreResult { + let txn = self.db.begin_read().map_err(err)?; + let t = txn.open_table(UNDO).map_err(err)?; + Ok(t.range((name, 0)..=(name, u64::MAX)).map_err(err)?.count()) + } + + /// takes back the latest yes/no on `name`: every classifier it wrote gets its + /// definition and weights back as they were, and the feedback leaves the log + /// (so training no longer replays it); the entry taken back + pub fn unfeedback(&self, name: &str) -> StoreResult { + self.classifier(name)?; + let txn = self.db.begin_write().map_err(err)?; + let entry = { + let mut t = txn.open_table(UNDO).map_err(err)?; + let last = t + .range((name, 0)..=(name, u64::MAX)) + .map_err(err)? + .next_back() + .transpose() + .map_err(err)? + .map(|(k, v)| (k.value().1, v.value().to_vec())); + let Some((n, bytes)) = last else { + return Err(format!("there's no yes or no on {name:?} to take back")); + }; + t.remove((name, n)).map_err(err)?; + let u: Undo = serde_json::from_slice(&bytes).map_err(err)?; + let mut d = txn.open_table(DEFINITIONS).map_err(err)?; + let mut w = txn.open_table(WEIGHTS).map_err(err)?; + for (n, def, weights) in &u.was { + d.insert(n.as_str(), def.as_bytes()).map_err(err)?; + match weights.as_deref().map(unbase64) { + Some(Some(b)) => { + w.insert(n.as_str(), b.as_slice()).map_err(err)?; + } + Some(None) => return Err("a kept copy of the weights doesn't read".into()), + None => { + w.remove(n.as_str()).map_err(err)?; + } + } + } + let mut f = txn.open_table(FEEDBACK).map_err(err)?; + let e = f.remove((name, u.feedback)).map_err(err)?.map(|g| g.value().to_vec()); + match e { + Some(e) => serde_json::from_slice::(&e).map_err(err)?, + None => return Err("that yes or no isn't in the log any more".into()), + } + }; + txn.commit().map_err(err)?; + // the texts it filed under the classifier answer as before, so the memo stays + Ok(entry) + } + /// a classifier's feedback log, oldest first pub fn classifier_feedback(&self, name: &str) -> StoreResult> { let txn = self.db.begin_read().map_err(err)?; @@ -1031,8 +1280,10 @@ impl Store { before: rep.before[0], after: rep.after[0], }; + let was = self.snapshot(std::slice::from_ref(&def.name))?; self.put_classifier(&mut def, Some(clf))?; - self.log_feedback(&e)?; + let feedback = self.log_feedback(&e)?; + self.keep_undo(&def.name, &Undo { feedback, was })?; Ok(e) } @@ -1067,6 +1318,7 @@ impl Store { }, )?; let mut touched = Vec::new(); + let was = self.snapshot(&stack.names())?; for (i, d) in stack.defs.iter().enumerate() { if rep.grad_norms[i] > 0.0 || i == stack.node { let mut d = self.classifier(&d.name)?; @@ -1094,7 +1346,9 @@ impl Store { before: rep.before, after: rep.after, }; - self.log_feedback(&e)?; + let feedback = self.log_feedback(&e)?; + let was = was.into_iter().filter(|w| touched.contains(&w.0)).collect(); + self.keep_undo(&def.name, &Undo { feedback, was })?; Ok((e, rep, touched)) } @@ -1261,6 +1515,32 @@ pub fn unbase64(s: &str) -> Option> { pub(crate) mod tests { use super::*; + /// new definitions build without gematria; ones saved before the field existed + /// keep the channels they were made with + #[test] + fn gematria_is_opt_in_and_old_definitions_keep_it() { + let classes = vec![ + ClassDef { + name: "a".into(), + list: "a".into(), + }, + ClassDef { + name: "b".into(), + list: "b".into(), + }, + ]; + let d = Definition::new("x", classes, None, HeadKind::Single, DEFAULT_PRESET).unwrap(); + assert!(!d.gematria); + let c = d.build(0).unwrap(); + assert!(!c.net.cfg.letters && !c.net.cfg.words && !c.net.cfg.side); + let mut v = serde_json::to_value(&d).unwrap(); + v.as_object_mut().unwrap().remove("gematria"); + let old: Definition = serde_json::from_value(v).unwrap(); + assert!(old.gematria); + let c = old.build(0).unwrap(); + assert!(c.net.cfg.letters && c.net.cfg.words && c.net.cfg.side); + } + pub fn temp_store(name: &str) -> (Store, std::path::PathBuf) { let path = std::env::temp_dir().join(format!("anend-clf-{}-{name}.redb", std::process::id())); let _ = std::fs::remove_file(&path); @@ -1362,7 +1642,9 @@ pub(crate) mod tests { key: None, text: "apple granite".into(), }; - let e = s.feedback_classifier("kind", &j, "rocks", true, 1.0).unwrap(); + // a firm yes: the replayed list members outweigh one feedback of weight 1 on this + // byte-only (no gematria) tiny model + let e = s.feedback_classifier("kind", &j, "rocks", true, 2.0).unwrap(); assert!(e.after > e.before, "{e:?}"); s.feedback_classifier("kind", &j, "rocks", false, 1.0).unwrap(); let log = s.classifier_feedback("kind").unwrap(); diff --git a/core/src/classify/STATUS.md b/core/src/classify/STATUS.md index fb096fd3..48970c22 100644 --- a/core/src/classify/STATUS.md +++ b/core/src/classify/STATUS.md @@ -101,12 +101,144 @@ buckets/bucket/near/tints/indexed/set_index/validators/disagreements/export/insp import, filters.list/save/delete/run/enlist; docs/app-api.md). The web app uses them all (docs/next.md item 4, "web UI"). Left (hub sharing site, web UI, screenshots): see docs/next.md item 4. +## Phase 4 (in progress, 14 Oct): general models, generation, critics + +The user (14 Oct): transformers are general purpose, not gematria transformers; the byte +sums are a separate measure; a high-level declarative spec is the primary interface; +sizes are honest (tiny is for tests only). + +Done (tested; `cargo test -p anend-core classify` ~12 s in debug): + +| area | where | tests | +|---|---|---| +| byte sums (byte + 1, 256 − byte, digit sums, word sums), standalone, not a model input | `core/src/measure.rs` | `measure::tests` | +| feature channels optional: `Config::{letters, words, side}` (`Config::gematria(on)`); files saved before keep theirs on | model.rs, io.rs | `version_1_files_still_load_bit_exact` (fixture `testdata/v1_tiny.anendcls`) | +| NUM tokens (`text::NUM`, `Window::push_numbers`, `Config::numbers`): row + value × learned direction | text.rs, model.rs | in the generative gradient check | +| causal attention (`Config::causal`, row by row via `attend_row`), causal word channels | model.rs, text.rs | gradient check; `causal_channels_and_numbers` | +| generative head (`GenSpec`, `Net::{generator, gen_w, gen_b}`, `gen_logits`, `backward_gen`), next byte over 256 + END | model.rs | `generative_gradients_match_finite_differences` | +| `Decoder`: KV cache, bit-equal to the full pass, restarts past `max_len` with the last half window | model.rs | `decoder_equals_the_full_pass` | +| multi-output: heads + generative head share a trunk; `Example::and(head, target)`, `HeadSpec::weight` / `GenSpec::weight` loss weights; `Target::{Next{from}, Avoid{from}}`; `Example::raw` bytes; `Evaluation::bits_per_byte`; `train::{tune, nll, gen_loss}` | train.rs | `multi_output_models_train_heads_jointly` | +| file format v2 (adds generator, flags; v1 reads) | io.rs | round trip in the tests above | +| sampling (greedy, temperature, top-k, top-p, max length, stop byte, END), keyed by (seed, index) | generate.rs | `learns_sequences_and_samples_deterministically` (same seed same bytes, threads 2 = 3) | +| critics (`Judge` for `Classifier`, `generate::Node` of a `Graph`, `classifiers::Stack`; `Want::{Class, Not, Near, Range}`), `Constraints` (gates must/must-not, sum ranges over `Measure::{Bytes, BytesReversed, Ordinal, Reversed, Length}`, length, contains/excludes), `draw` / `generate` (rank), `Guidance` (top-k next bytes reweighted by critics), `rewards` (score − mean), `reinforce` (reward-weighted likelihood + unlikelihood, replay), `Rewarded::{yes, no}` | generate.rs | `critics_rank_constrain_guide_and_reinforce` | +| numbers as fixed-width text (`NumberCodec`), pictures as patch-codebook bytes (`Codebook::learn` integer k-means, `ROW` = 255, `encode/decode`), `png` writer (stored deflate), `toy` pictures | codec.rs | `codec::tests` | + +| declarative `ModelSpec` (versioned serde/JSON: input text with opt-in `letters`/`word_sums`/`side` features, bytes, image (patch codebook), numbers (fixed-width text + dense head inputs); trunk preset `test`/`compact`/`small`/`base`/`auto` or sizes, causal by default with a generate head; heads classify/multi/regress/generate with loss weights; data queries `list`/`tagged`/`pairs`/`inline` over a `Source` (`MemSource`); critics by model name; constraints; sampling), `build / train / Model::run / spec::generate`, `Model::{to_bytes, from_bytes, from_classifier}` (spec + codebook kept in `Meta::spec`), checks with clear errors | spec.rs, `docs/models.md` | `spec::tests` (classifier, steered generator, number regressor, picture generator, error messages) | +| machine benchmark: `bench::{measure, load_or_measure, suggest}` (training throughput over a size ladder, forward cost by sequence length); the spec's `"auto"` preset uses it | bench.rs | `suggests_within_budget` | + +Examples (release, this machine: 4 vCPU, AVX2): + +- `cargo run --release -p anend-core --example generate [scale] [authors]`: author critic (359 k + weights, 71 % validation accuracy after 51 s) and one 670 k-weight generator per author (390 + steps, ~55 s, ~14 k tokens/s, 2.1–2.65 held-out bits/byte). The critic agrees a 120-byte + passage is the right author's: plain sampling 61 %, the critic's top 3 of 12 89 %, guided + sampling 72 %, after one reinforce round 74 % (mean over 6 authors; per author 8–100 %, + Melville lowest). Drawing 12 candidates takes 0.1 s, guided 0.8–1.0 s, reinforce ~5 s. +- `cargo run --release -p anend-core --example pictures [out-dir] [epochs]`: 192 toy 64×64 + pictures → 8×8 patches, 128 codes, 72 tokens each; 870 k weights, 720 steps in 69 s, 0.87 + bits per code held out; 16 samples in 0.25 s, written as PNG contact sheets. Forward cost of + one 64×64 picture by tokenisation (d 128, 4 blocks): 16×16 patches 20 tokens 1.5 ms, 8×8 72 + tokens 4.9 ms, 4×4 272 tokens 28 ms, 2×2 1056 tokens 263 ms, a byte a pixel 4160 tokens + 5.3 s (per-token cost ×16 from 72 to 4160 tokens: attention). Samples show the shapes and + backgrounds but are often blank or fragmentary; more data, steps and a critic would help. + +Left: +- NUM tokens are in the engine but not fed from `Example` (numbers reach models as text and as + dense head inputs). +- ~~The entry store's `Source`, the UI editing specs, hub ops for specs and generation~~: + done 19 Oct: `ops::models` (the save's lists by name or key, tags, pairs, snapshotted when + training starts; `models.*` in docs/app-api.md, the same on the desktop and the hub), + stored by `crate::specs` in the save's `.models` file and bundles, and the models view's + spec models tab. Left: the scripting language writing specs. ~~Picture data from the + save~~: done 19 Oct (`{"from": "pictures", "list": ..}` over the save's pictures table, + `ops::pictures`; spec definitions moved into the save's own tables, weights stay in + `.models`). +- A patch-embedding (continuous) input for picture classifiers; images now always go through + the codebook. +- Guidance is per byte and judges partial text; it helped 4 authors of 6 here. Sentence-level + guidance (judge at word or sentence ends) is the obvious next try. +- `git`: commit 79b25ff on the branch duplicates another agent's hub commit (an `--amend` on a + shared working tree); harmless (identical changes, merged cleanly), noted here. + +## Pretrained open models (done in core, 18 Oct; synthetic checkpoints only) + +| area | where | tests | +|---|---|---| +| safetensors: header, F32/F16/BF16/F64 → f32 (halves exact), shards by `model.safetensors.index.json`, tensors read on demand, a writer | safetensors.rs | every half/bfloat16 value round trips; shards; bad headers refused in words | +| regex subset for pre-tokenizers (alternation, groups, `(?i:)`, lookahead, quantifiers, classes, `\p{L}`/`\p{N}`…), leftmost-first backtracking | pattern.rs | GPT-2 and Llama 3 patterns split as the reference; unsupported constructs named | +| BPE from `tokenizer.json`: byte-level and SentencePiece style (byte fallback, ▁), merges as strings or pairs, added/special tokens (lstrip/rstrip), normalizers, pre-tokenizers (ByteLevel, Split, Digits, Metaspace), decoders; `Lexicon` (start/end/stop tokens) | bpe.rs | hand-made fixtures of both kinds: encode, decode, specials, every byte round trips, unsupported parts named | +| engine: grouped key/value heads (`Config::kv_heads`), q/k/v biases (`qkv_bias`), rope scaling (`linear`, `llama3`), a token vocabulary (`vocab_size`, `Net::lexicon`) through windows, crops, losses, evaluation, `Decoder` (`push_token`, `from_tokens`), sampling, guidance, the file format (tokenizer saved; larger shape limits for these models); growth refuses head changes there; byte models bit for bit as before (old fixtures, saved bytes, gradients hashed against the previous commit) | model.rs, train.rs, generate.rs, io.rs, grow.rs | model gradient checks; decoder = full pass with GQA | +| `config.json` of llama / mistral / qwen2 / qwen3 → `Config`, weights mapped (transposed into `[in × out]`, q/k/v side by side, tied heads copied), unsupported fields named; spec `"from": {"pretrained": dir}` | pretrained.rs, spec.rs | four synthetic architectures (GQA, biases + BF16 shards, QK-norm + F16 + odd head_dim, SentencePiece + MHA) match an f64 reference from the transformers code; generate with critics and guidance (threads 1 = 2), fine-tune lowers NLL, save/load equal; a spec trains, runs, generates with a critic model and saves | + +Example for the user's machine: `core/examples/pretrained.rs` (SmolLM2-135M; download +command in its doc). Left: see docs/next.md "Lifting the model ceiling". + +## The GPU backend (done, 18 Oct; tested on llvmpipe, benchmarked there only) + +`core/src/classify/gpu/` behind the cargo feature `gpu` (wgpu 30, WGSL compute shaders; the +core's default build and wasm do not pull wgpu: `cargo tree -p anend-core | grep wgpu` is empty). +Since 19 Oct the desktop app (`desktop` feature) and `anend-hub` (default feature `gpu`) +build with it: `classify.train`/`classify.start` and `models.train` take `"device"` +(`cpu`, `gpu`, `gpu_fast`), the job reports the device it ran on and, when it fell back to +the CPU (no adapter, or a shared hub not started with `--gpu`), why (`device_note`). The +app's training cards have the picker. Test: `ops::classify::devices_fall_back_and_hubs_decide`. + +| area | where | tests (`cargo test -p anend-core --features gpu gpu::`) | +|---|---|---| +| device, buffers, `Run` (dispatches recorded, one submission, reads), shader source with exact/fast preludes | gpu/mod.rs | — | +| kernels: tiled GEMM 64×64 (strided A and B, batched with grouped B, causal row limits, accumulate), per-output GEMM for few rows, 8-lane dot rows, RMSNorm fwd/back + column sums, softmax fwd (causal rows)/back, SwiGLU fwd/back, RoPE fwd/back, causal scores, strided copies, elementwise ops; `math::exp`/sigmoid ported operation for operation | gpu/kernels.wgsl | `kernels_match_the_cpu` | +| `Precision::Exact` (products laundered through an XOR with a uniform zero so they cannot fuse; ÷ and √ correctly rounded in integer arithmetic) and `Fast` (plain operators) | gpu/mod.rs | both probed | +| exactness probe: every kernel on device and CPU, values differing, max ulps, max relative difference | gpu/probe.rs | `kernels_match_the_cpu` | +| `GpuNet`: the trunk resident on the device (grouped KV heads, QKV biases, QK-norm, causal and bidirectional attention, the generative head); embedding, pooling and classification heads on the CPU | gpu/net.rs | `trunk_and_heads_match_the_cpu` | +| `GpuDecoder`: KV cache on the device, `Decoder`'s restarts | gpu/net.rs | `decoder_matches_the_cpu` | +| training: forward with dropout masks, backward through the trunk on the device (per-example sums in example order, like `batch_grad`), embedding/heads/losses/AdamW on the CPU | gpu/train.rs, device.rs | `training_matches_the_cpu` | +| `device::Device::{Cpu, Gpu, GpuFast}`: `TrainOpts::device`, `GenOpts::device`, spec `"device"`; CPU default; a build without the feature refuses with a message | device.rs, train.rs, generate.rs, spec.rs | `devices_parse_and_the_gpu_needs_the_feature` | + +The probe on llvmpipe (LLVM 20, Mesa 25.2, lavapipe Vulkan; the container has no GPU): +**every kernel bit-exact in both precisions** (llvmpipe does not fuse or approximate), and +whole forward passes, decoding and 2 epochs of training with dropout give the CPU's bits +(the tests assert equality wherever the probe reports exact, a tolerance elsewhere). One +fix the probe found: the shader compiler simplified exp's `(x + 1.5·2^23) − 1.5·2^23` +rounding trick away; `keep()` (XOR with the uniform zero) stops that in both precisions. + +`cargo run --release -p anend-core --features gpu --example gpu_bench -- 1 3` on this +container (llvmpipe is software rendering on the same 4 vCPUs, so it measures overhead, +not a GPU): small (0.9 M weights, 256 tokens) forward 10 842 tokens/s CPU vs 560 GPU, +decoding 5090 vs 86, training 4829 vs 175; every GPU row matched the CPU's logits bit +for bit. The numbers that matter come from running it on the user's hardware. + +Left: per-dispatch bind groups and a submission + read per decoding step cost the most on +small models (batch decoding several candidates per submission, and bind group caching, +would cut it); weights are re-uploaded after every optimizer step (AdamW on the device +would avoid it); a subgroup/cooperative-matrix GEMM for large models (still one chain per +output for exactness, so no split-k); classification-only inference (`Model::run`, +`predict`) still on the CPU; pictures/patch paths untouched; the browser (WebGPU) build +needs an async device request and a wasm feature set. + +## Spelling and word choice (a proof of concept, 19 Oct) + +`core/src/grammar`: two logistic regressions (not the transformer: a per-word detector over +hashed features and a ranker over dense ones), trained the first time they're asked for +(about a second in a release build) on deterministic corruptions of `corpus.txt` (2870 +sentences of the project's own prose), with a fifth held out. Measured on the held-out +fifth, corrupted the same way: precision 0.958, recall 0.972 (misspellings 574 of 574, +confused words 178 of 201, repeated words 60 of 60), the first suggestion right for 95.7% +of the caught errors and among the first three for 99.1%, and 7.3 false alarms per 1000 +words of clean held-out text. These are numbers on errors made the way it was trained; +the misspellings are non-words by construction, so a lexicon catches them. In real text +expect more false alarms on names and jargon (the save's own words are exempt) and fewer +confusables caught ("its" before "more", "quiet" before "big" go unflagged in the test +sentence). In the notes editor (`grammar.check`), desktop and web. + ## Next (not done) -- ~~the desktop app's classifiers view~~: done (src/classify_ui.rs, filters_ui.rs, index_panel.rs, tint.rs; see docs/next.md item 4). +- ~~the desktop app's classifiers view~~: done for the Bevy app (retired), and again for + the Dioxus app on 18 Oct (`app/src/views/classifiers.rs`, the memory view's colouring + and classifier search) over one implementation of the ops (`core/src/ops/classify.rs`) + for the desktop and the hub. `classify.unfeedback` undoes a yes/no bit for bit. - JS port of inference for offline use; search filter panel; default classifiers for new saves; filter presets as lists. -- GPU backend behind `kernels` (see its module doc for bit-exactness notes). +- GPU backend: done (above); what is left is listed there. - Row-parallel matmuls are used only for single long windows at inference; training is data-parallel over examples. - JS port of math/kernels with Math.fround. diff --git a/core/src/classify/bench.rs b/core/src/classify/bench.rs new file mode 100644 index 00000000..87a3b389 --- /dev/null +++ b/core/src/classify/bench.rs @@ -0,0 +1,218 @@ +//! A one-time machine benchmark: how fast this computer trains models of a ladder of +//! sizes, and how the cost of a forward pass grows with sequence length. `suggest` +//! turns the measurement into a model size for a task and a time budget, which the +//! declarative spec uses when sizes are left out. +//! +//! Limits here are measured compute, not convenience: a size is suggested when the +//! training it implies fits the budget on this machine. The GPU backend (backlog, see +//! `kernels`) is the main lever that would lift them. + +use std::time::{Duration, Instant}; + +use serde::{Deserialize, Serialize}; + +use super::model::{Config, Gains, HeadSpec, Mode, Net, Pooling}; +use super::pool; +use super::text; +use super::train::{self, Example, TrainOpts}; +use super::{Classifier, Flow}; + +/// one rung of the size ladder +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct Rung { + pub d_model: usize, + pub layers: usize, + pub heads: usize, + pub d_ff: usize, + pub weights: usize, + /// training throughput at 128-token windows, all threads + pub tokens_per_sec: f64, +} + +#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)] +pub struct MachineProfile { + pub threads: usize, + pub simd: String, + pub ladder: Vec, + /// (tokens, milliseconds) for one forward pass of the second rung at that length: + /// attention makes it grow faster than linearly + pub forward_ms: Vec<(usize, f64)>, +} + +/// the sizes measured, smallest first +pub const LADDER: [(usize, usize, usize, usize); 6] = [ + (32, 2, 2, 96), + (64, 2, 2, 176), + (96, 3, 3, 256), + (128, 4, 4, 352), + (192, 4, 6, 512), + (256, 6, 8, 704), +]; + +fn config(d: usize, layers: usize, heads: usize, ff: usize, max_len: usize) -> Config { + Config { + d_model: d, + head_dim: d / heads, + heads, + layers, + d_ff: ff, + max_len, + stride: max_len / 2, + dropout: 0.0, + pooling: Pooling::Mean, + ..Config::tiny().gematria(false) + } +} + +/// measures the ladder, spending about `per_rung` on each size (rungs that take more +/// than four budgets for one step end the ladder: bigger ones would not be suggested) +pub fn measure(per_rung: Duration) -> MachineProfile { + let threads = pool::available(); + let text: String = (0..64).map(|i| format!("word{} ", i * 7919 % 1000)).collect(); + let data: Vec = (0..64).map(|i| Example::class(&text[i..i + 300], i % 2)).collect(); + let mut ladder = Vec::new(); + for &(d, layers, heads, ff) in &LADDER { + let mut clf = Classifier::new( + config(d, layers, heads, ff, 128), + &[HeadSpec::single("k", &["a", "b"])], + 1, + ) + .unwrap(); + let started = Instant::now(); + let mut tokens = 0u64; + let mut steps = 0; + while started.elapsed() < per_rung || steps == 0 { + let o = TrainOpts { + epochs: 1, + batch: 16, + max_steps: 1, + val_fraction: 0.0, + seed: steps, + ..TrainOpts::default() + }; + let r = train::train(&mut clf, &data, &o, |_| Flow::Go).unwrap(); + tokens += r.tokens; + steps += 1; + } + let secs = started.elapsed().as_secs_f64(); + ladder.push(Rung { + d_model: d, + layers, + heads, + d_ff: ff, + weights: clf.net.weight_count(), + tokens_per_sec: tokens as f64 / secs, + }); + if steps == 1 && secs > 4.0 * per_rung.as_secs_f64() { + break; + } + } + let (d, layers, heads, ff) = LADDER[1]; + let mut forward_ms = Vec::new(); + for len in [64usize, 128, 256, 512, 1024] { + let net = Net::new(config(d, layers, heads, ff, len), &[HeadSpec::single("k", &["a"])], 1).unwrap(); + let w = text::window(&vec![b'a'; len - 2]); + let started = Instant::now(); + let mut n = 0; + while n == 0 || started.elapsed() < per_rung / 5 { + drop(net.forward(&w, &[], &Gains::default(), Mode::EVAL, None)); + n += 1; + } + forward_ms.push((len, started.elapsed().as_secs_f64() * 1e3 / n as f64)); + } + MachineProfile { + threads, + simd: super::kernels::simd_name().into(), + ladder, + forward_ms, + } +} + +/// the profile saved at `path`, or a fresh measurement saved there +pub fn load_or_measure(path: &std::path::Path, per_rung: Duration) -> MachineProfile { + if let Some(p) = std::fs::read(path).ok().and_then(|b| serde_json::from_slice(&b).ok()) { + return p; + } + let p = measure(per_rung); + if let Ok(j) = serde_json::to_vec_pretty(&p) { + let _ = std::fs::write(path, j); + } + p +} + +/// what a model is for, to size it +#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)] +pub struct Task { + /// training examples + pub examples: usize, + /// passes over them + pub epochs: usize, + /// tokens per example window + pub max_len: usize, + /// seconds of training the person will wait + pub seconds: f64, +} + +/// the largest measured size whose training (examples × epochs × max_len tokens at the +/// measured rate, scaled for the window length by the forward-pass curve) fits the +/// budget; the smallest rung when none does +pub fn suggest(p: &MachineProfile, t: &Task) -> Config { + let tokens = (t.examples * t.epochs.max(1) * t.max_len) as f64; + // longer windows cost more per token (attention); scale from the 128-token rate + let per_token = |len: usize| -> f64 { + let at = |l: usize| { + p.forward_ms + .iter() + .find(|x| x.0 >= l) + .or(p.forward_ms.last()) + .map_or(1.0, |x| x.1 / x.0 as f64) + }; + at(len) / at(128).max(1e-12) + }; + let slow = per_token(t.max_len).max(1.0); + let mut best = &p.ladder[0]; + for r in &p.ladder { + if tokens * slow / r.tokens_per_sec.max(1e-9) <= t.seconds { + best = r; + } + } + config(best.d_model, best.layers, best.heads, best.d_ff, t.max_len.max(8)) +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn suggests_within_budget() { + let p = MachineProfile { + threads: 4, + simd: "test".into(), + ladder: LADDER + .iter() + .enumerate() + .map(|(i, &(d, l, h, f))| Rung { + d_model: d, + layers: l, + heads: h, + d_ff: f, + weights: 0, + tokens_per_sec: 100_000.0 / (i + 1) as f64, + }) + .collect(), + forward_ms: vec![(64, 1.0), (128, 2.0), (256, 5.0)], + }; + let t = Task { + examples: 1000, + epochs: 10, + max_len: 128, + seconds: 60.0, + }; + // 1.28 M tokens in 60 s needs ≥ 21 k tokens/s: rung 4 (25 k) fits, rung 5 (20 k) doesn't + assert_eq!(suggest(&p, &t).d_model, LADDER[3].0); + assert_eq!(suggest(&p, &Task { seconds: 1.0, ..t }).d_model, LADDER[0].0); + // longer windows cost more per token + assert!(suggest(&p, &Task { max_len: 256, ..t }).d_model < LADDER[3].0); + assert!(suggest(&p, &t).validate().is_ok()); + } +} diff --git a/core/src/classify/bpe.rs b/core/src/classify/bpe.rs new file mode 100644 index 00000000..33924412 --- /dev/null +++ b/core/src/classify/bpe.rs @@ -0,0 +1,1024 @@ +//! A BPE tokenizer read from a HuggingFace `tokenizer.json`, for pretrained models +//! (`pretrained`). The engine's own models read bytes and keep doing so; this is only +//! the vocabulary a pretrained checkpoint was trained with. +//! +//! Supported, which covers the Llama family's tokenizers (GPT-2 style byte-level BPE as +//! in Llama 3, Qwen2/3, SmolLM, Mistral Nemo; SentencePiece style BPE with byte +//! fallback as in Llama 2, TinyLlama, Mistral 7B): +//! +//! - `model`: `BPE` with `vocab`, `merges` (as `"a b"` strings or `["a", "b"]` pairs), +//! `byte_fallback`, `unk_token`, `ignore_merges`; +//! - `added_tokens` (special or not; `lstrip`/`rstrip`), matched in the raw text first; +//! - `normalizer`: `Sequence`, `Prepend`, `Replace` (a string pattern), `Lowercase`, +//! `Strip`, and `NFC` (taken as already composed: text in decomposed form may split +//! differently than the reference implementation); +//! - `pre_tokenizer`: `Sequence`, `ByteLevel` (with or without its GPT-2 regex and +//! prefix space), `Split` (regex or string; isolated, removed, merged with the +//! previous or the next), `Digits`, `Metaspace`; +//! - `decoder`: `ByteLevel`, `Metaspace`, or a `Sequence` of `Replace`, `ByteFallback`, +//! `Fuse` and `Strip`. +//! +//! Anything else (WordPiece or Unigram models, other normalizers, BPE dropout, word +//! prefixes and suffixes) is refused with its name. Regexes go through `pattern`. + +use std::cmp::Reverse; +use std::collections::{BinaryHeap, HashMap}; + +use serde_json::Value as Json; + +use super::pattern::{self, Regex}; + +#[derive(Clone, Debug, PartialEq)] +enum Normalizer { + Prepend(String), + Replace(String, String), + Lowercase, + Strip(bool, bool), +} + +#[derive(Clone, Copy, Debug, PartialEq)] +enum Behavior { + Isolated, + Removed, + MergedWithPrevious, + MergedWithNext, +} + +#[derive(Clone, Debug, PartialEq)] +enum Pre { + ByteLevel { + prefix_space: bool, + regex: Option, + }, + Split { + regex: Regex, + behavior: Behavior, + invert: bool, + }, + Digits { + individual: bool, + }, + Metaspace { + replacement: char, + prepend: Prepend, + split: bool, + }, +} + +#[derive(Clone, Copy, Debug, PartialEq)] +enum Prepend { + Always, + First, + Never, +} + +#[derive(Clone, Debug, PartialEq)] +struct Added { + id: u32, + content: String, + special: bool, + lstrip: bool, + rstrip: bool, +} + +/// a tokenizer: text to token ids and back +#[derive(Clone, Debug, PartialEq)] +pub struct Tokenizer { + /// the `tokenizer.json` it was read from (saved with models, read again on load) + source: String, + /// id → its piece as written in the vocabulary + pieces: Vec, + ids: HashMap, + /// (left, right) → (rank, merged) + merges: HashMap<(u32, u32), (u32, u32)>, + added: Vec, + /// id → index in `added` + added_of: HashMap, + normalizers: Vec, + pre: Vec
,
+    byte_level: bool,
+    byte_fallback: bool,
+    /// `<0xAB>` tokens
+    byte_ids: Vec>,
+    unk: Option,
+    ignore_merges: bool,
+    /// decoding: the metaspace character read as a space, and leading spaces stripped
+    space_char: Option,
+    strip_start: usize,
+    /// id → the bytes it decodes to (computed once)
+    bytes: Vec>,
+}
+
+/// GPT-2's byte ↔ printable character table: bytes that print map to themselves,
+/// the rest to 256, 257, … in order
+pub fn byte_chars() -> [char; 256] {
+    let mut out = ['\0'; 256];
+    let mut n = 0;
+    for b in 0..256u32 {
+        let keep = (33..=126).contains(&b) || (161..=172).contains(&b) || (174..=255).contains(&b);
+        out[b as usize] = if keep {
+            char::from_u32(b).unwrap()
+        } else {
+            n += 1;
+            char::from_u32(255 + n).unwrap()
+        };
+    }
+    out
+}
+
+/// the inverse of `byte_chars`
+pub fn byte_of(c: char) -> Option {
+    let u = c as u32;
+    let kept = (33..=126).contains(&u) || (161..=172).contains(&u) || (174..=255).contains(&u);
+    match u {
+        _ if kept => Some(u as u8),
+        256..=288 => Some((u - 256) as u8),
+        289..=322 => Some((u - 289 + 127) as u8),
+        323 => Some(173),
+        _ => None,
+    }
+}
+
+fn str_of(v: &Json, what: &str) -> Result {
+    v.as_str()
+        .map(String::from)
+        .ok_or(format!("tokenizer.json: {what} is not a string"))
+}
+
+fn kind(v: &Json) -> &str {
+    v["type"].as_str().unwrap_or("")
+}
+
+fn pattern_of(v: &Json, what: &str) -> Result {
+    if let Some(s) = v["String"].as_str() {
+        let escaped: String = s
+            .chars()
+            .flat_map(|c| {
+                let special = "\\.+*?()|[]{}^$".contains(c);
+                special.then_some('\\').into_iter().chain([c])
+            })
+            .collect();
+        Regex::new(&escaped)
+    } else if let Some(s) = v["Regex"].as_str() {
+        Regex::new(s).map_err(|e| format!("tokenizer.json: {what}: {e}"))
+    } else {
+        Err(format!("tokenizer.json: {what}: a pattern is a String or a Regex"))
+    }
+}
+
+fn normalizers(v: &Json, out: &mut Vec) -> Result<(), String> {
+    match kind(v) {
+        "" if v.is_null() => {}
+        "Sequence" => {
+            for n in v["normalizers"]
+                .as_array()
+                .ok_or("tokenizer.json: normalizer Sequence without a list")?
+            {
+                normalizers(n, out)?;
+            }
+        }
+        "Prepend" => out.push(Normalizer::Prepend(str_of(&v["prepend"], "Prepend.prepend")?)),
+        "Replace" => {
+            let p = v["pattern"]["String"]
+                .as_str()
+                .ok_or("tokenizer.json: normalizer Replace with a regex pattern is not supported")?;
+            out.push(Normalizer::Replace(p.into(), str_of(&v["content"], "Replace.content")?));
+        }
+        "Lowercase" => out.push(Normalizer::Lowercase),
+        "Strip" => out.push(Normalizer::Strip(
+            v["strip_left"].as_bool().unwrap_or(true),
+            v["strip_right"].as_bool().unwrap_or(true),
+        )),
+        // composed text is the common case; see the module doc
+        "NFC" => {}
+        other => return Err(format!("tokenizer.json: normalizer {other:?} is not supported")),
+    }
+    Ok(())
+}
+
+fn prepend_of(v: &Json) -> Prepend {
+    match v["prepend_scheme"].as_str() {
+        Some("always") => Prepend::Always,
+        Some("first") => Prepend::First,
+        Some("never") => Prepend::Never,
+        _ => {
+            if v["add_prefix_space"].as_bool().unwrap_or(true) {
+                Prepend::Always
+            } else {
+                Prepend::Never
+            }
+        }
+    }
+}
+
+fn metaspace_char(v: &Json) -> Result {
+    let s = str_of(&v["replacement"], "Metaspace.replacement")?;
+    let mut c = s.chars();
+    match (c.next(), c.next()) {
+        (Some(x), None) => Ok(x),
+        _ => Err("tokenizer.json: Metaspace.replacement must be one character".into()),
+    }
+}
+
+fn pre_tokenizers(v: &Json, out: &mut Vec
) -> Result<(), String> {
+    match kind(v) {
+        "" if v.is_null() => {}
+        "Sequence" => {
+            for p in v["pretokenizers"]
+                .as_array()
+                .ok_or("tokenizer.json: pre_tokenizer Sequence without a list")?
+            {
+                pre_tokenizers(p, out)?;
+            }
+        }
+        "ByteLevel" => out.push(Pre::ByteLevel {
+            prefix_space: v["add_prefix_space"].as_bool().unwrap_or(false),
+            regex: if v["use_regex"].as_bool().unwrap_or(true) {
+                Some(Regex::new(pattern::GPT2)?)
+            } else {
+                None
+            },
+        }),
+        "Split" => {
+            let behavior = match v["behavior"].as_str().unwrap_or("Isolated") {
+                "Isolated" => Behavior::Isolated,
+                "Removed" => Behavior::Removed,
+                "MergedWithPrevious" => Behavior::MergedWithPrevious,
+                "MergedWithNext" => Behavior::MergedWithNext,
+                other => return Err(format!("tokenizer.json: Split behavior {other:?} is not supported")),
+            };
+            out.push(Pre::Split {
+                regex: pattern_of(&v["pattern"], "Split.pattern")?,
+                behavior,
+                invert: v["invert"].as_bool().unwrap_or(false),
+            });
+        }
+        "Digits" => out.push(Pre::Digits {
+            individual: v["individual_digits"].as_bool().unwrap_or(false),
+        }),
+        "Metaspace" => out.push(Pre::Metaspace {
+            replacement: metaspace_char(v)?,
+            prepend: prepend_of(v),
+            split: v["split"].as_bool().unwrap_or(true),
+        }),
+        other => return Err(format!("tokenizer.json: pre_tokenizer {other:?} is not supported")),
+    }
+    Ok(())
+}
+
+/// splits `s` at the matches of a pattern, by `behavior`
+fn split_by(s: &str, ranges: &[(usize, usize)], behavior: Behavior, invert: bool) -> Vec {
+    let chars: Vec = s.chars().collect();
+    // (piece, is_match) covering the whole string
+    let mut parts: Vec<(String, bool)> = Vec::new();
+    let mut at = 0;
+    for &(a, b) in ranges {
+        if a > at {
+            parts.push((chars[at..a].iter().collect(), false));
+        }
+        parts.push((chars[a..b].iter().collect(), true));
+        at = b;
+    }
+    if at < chars.len() {
+        parts.push((chars[at..].iter().collect(), false));
+    }
+    if invert {
+        parts.iter_mut().for_each(|p| p.1 = !p.1);
+    }
+    let mut out: Vec = Vec::new();
+    match behavior {
+        Behavior::Isolated => out = parts.into_iter().map(|p| p.0).collect(),
+        Behavior::Removed => out = parts.into_iter().filter(|p| !p.1).map(|p| p.0).collect(),
+        Behavior::MergedWithPrevious => {
+            for (p, m) in parts {
+                match out.last_mut() {
+                    Some(last) if m => last.push_str(&p),
+                    _ => out.push(p),
+                }
+            }
+        }
+        Behavior::MergedWithNext => {
+            let mut pending = String::new();
+            for (p, m) in parts {
+                if m {
+                    if !pending.is_empty() {
+                        out.push(std::mem::take(&mut pending));
+                    }
+                    pending = p;
+                } else {
+                    pending.push_str(&p);
+                    out.push(std::mem::take(&mut pending));
+                }
+            }
+            if !pending.is_empty() {
+                out.push(pending);
+            }
+        }
+    }
+    out.retain(|p| !p.is_empty());
+    out
+}
+
+impl Tokenizer {
+    /// reads a `tokenizer.json` file
+    pub fn load(path: &std::path::Path) -> Result {
+        let text = std::fs::read_to_string(path).map_err(|e| format!("{}: {e}", path.display()))?;
+        Tokenizer::from_json(&text).map_err(|e| format!("{}: {e}", path.display()))
+    }
+
+    pub fn from_json(text: &str) -> Result {
+        let v: Json = serde_json::from_str(text).map_err(|e| format!("tokenizer.json: {e}"))?;
+        let m = &v["model"];
+        match kind(m) {
+            "BPE" => {}
+            "" if m["merges"].is_array() => {}
+            other => {
+                return Err(format!(
+                    "tokenizer.json: model type {other:?} is not supported (BPE only)"
+                ));
+            }
+        }
+        if m["dropout"].as_f64().is_some_and(|d| d > 0.0) {
+            return Err("tokenizer.json: BPE dropout is not supported (the engine is deterministic)".into());
+        }
+        for f in ["continuing_subword_prefix", "end_of_word_suffix"] {
+            if m[f].as_str().is_some_and(|s| !s.is_empty()) {
+                return Err(format!("tokenizer.json: model.{f} is not supported"));
+            }
+        }
+        let vocab = m["vocab"]
+            .as_object()
+            .ok_or("tokenizer.json: model.vocab is not an object")?;
+        let mut ids: HashMap = HashMap::with_capacity(vocab.len());
+        let mut size = 0usize;
+        for (p, id) in vocab {
+            let id = id.as_u64().ok_or(format!("tokenizer.json: vocab id of {p:?}"))?;
+            let id = u32::try_from(id).map_err(|_| format!("tokenizer.json: vocab id {id} too large"))?;
+            ids.insert(p.clone(), id);
+            size = size.max(id as usize + 1);
+        }
+        let mut added = Vec::new();
+        for a in v["added_tokens"].as_array().into_iter().flatten() {
+            let id = a["id"].as_u64().ok_or("tokenizer.json: an added token without an id")? as u32;
+            size = size.max(id as usize + 1);
+            added.push(Added {
+                id,
+                content: str_of(&a["content"], "added token content")?,
+                special: a["special"].as_bool().unwrap_or(false),
+                lstrip: a["lstrip"].as_bool().unwrap_or(false),
+                rstrip: a["rstrip"].as_bool().unwrap_or(false),
+            });
+        }
+        let mut pieces = vec![String::new(); size];
+        for (p, &id) in &ids {
+            pieces[id as usize] = p.clone();
+        }
+        for a in &added {
+            pieces[a.id as usize] = a.content.clone();
+            ids.entry(a.content.clone()).or_insert(a.id);
+        }
+        // longest first, so a token that starts another one doesn't hide it
+        added.sort_by(|a, b| b.content.len().cmp(&a.content.len()).then(a.id.cmp(&b.id)));
+        let added_of = added.iter().enumerate().map(|(i, a)| (a.id, i)).collect();
+        let mut merges = HashMap::new();
+        for (rank, mg) in m["merges"]
+            .as_array()
+            .ok_or("tokenizer.json: model.merges is not a list")?
+            .iter()
+            .enumerate()
+        {
+            let (a, b) = if let Some(s) = mg.as_str() {
+                let (a, b) = s
+                    .split_once(' ')
+                    .ok_or(format!("tokenizer.json: merge {s:?} is not two pieces"))?;
+                (a.to_string(), b.to_string())
+            } else {
+                match mg.as_array().map(|x| x.as_slice()) {
+                    Some([a, b]) => (str_of(a, "merge")?, str_of(b, "merge")?),
+                    _ => return Err(format!("tokenizer.json: merge {rank} is not two pieces")),
+                }
+            };
+            let id = |p: &str| {
+                ids.get(p).copied().ok_or(format!(
+                    "tokenizer.json: merge {rank} names {p:?}, not in the vocabulary"
+                ))
+            };
+            let (ia, ib) = (id(&a)?, id(&b)?);
+            let merged = id(&format!("{a}{b}"))?;
+            merges.entry((ia, ib)).or_insert((rank as u32, merged));
+        }
+        let mut norm = Vec::new();
+        normalizers(&v["normalizer"], &mut norm)?;
+        let mut pre = Vec::new();
+        pre_tokenizers(&v["pre_tokenizer"], &mut pre)?;
+        let byte_fallback = m["byte_fallback"].as_bool().unwrap_or(false);
+        let mut byte_ids = vec![None; 256];
+        for (b, slot) in byte_ids.iter_mut().enumerate() {
+            *slot = ids.get(&format!("<0x{b:02X}>")).copied();
+        }
+        let unk = match m["unk_token"].as_str() {
+            Some(u) => Some(
+                *ids.get(u)
+                    .ok_or(format!("tokenizer.json: unk_token {u:?} is not in the vocabulary"))?,
+            ),
+            None => None,
+        };
+        // the decoder decides how pieces read back
+        let d = &v["decoder"];
+        let (mut byte_level, mut space_char, mut strip_start) = (false, None, 0);
+        let mut decoder = |d: &Json| -> Result<(), String> {
+            match kind(d) {
+                "ByteLevel" => byte_level = true,
+                "Metaspace" => {
+                    space_char = Some(metaspace_char(d)?);
+                    strip_start = (prepend_of(d) != Prepend::Never) as usize;
+                }
+                "Replace" => {
+                    let p = d["pattern"]["String"]
+                        .as_str()
+                        .ok_or("tokenizer.json: decoder Replace needs a string")?;
+                    let mut c = p.chars();
+                    match (c.next(), c.next(), d["content"].as_str()) {
+                        (Some(x), None, Some(" ")) => space_char = Some(x),
+                        _ => return Err(format!("tokenizer.json: decoder Replace {p:?} is not supported")),
+                    }
+                }
+                "Strip" => {
+                    if d["content"].as_str() != Some(" ") || d["stop"].as_u64().unwrap_or(0) != 0 {
+                        return Err("tokenizer.json: decoder Strip other than leading spaces is not supported".into());
+                    }
+                    strip_start = d["start"].as_u64().unwrap_or(0) as usize;
+                }
+                "ByteFallback" | "Fuse" => {}
+                other => return Err(format!("tokenizer.json: decoder {other:?} is not supported")),
+            }
+            Ok(())
+        };
+        match kind(d) {
+            "" if d.is_null() => {}
+            "Sequence" => {
+                for x in d["decoders"]
+                    .as_array()
+                    .ok_or("tokenizer.json: decoder Sequence without a list")?
+                {
+                    decoder(x)?;
+                }
+            }
+            _ => decoder(d)?,
+        }
+        byte_level |= pre.iter().any(|p| matches!(p, Pre::ByteLevel { .. }));
+        let mut t = Tokenizer {
+            source: text.to_string(),
+            pieces,
+            ids,
+            merges,
+            added,
+            added_of,
+            normalizers: norm,
+            pre,
+            byte_level,
+            byte_fallback,
+            byte_ids,
+            unk,
+            ignore_merges: m["ignore_merges"].as_bool().unwrap_or(false),
+            space_char,
+            strip_start,
+            bytes: Vec::new(),
+        };
+        t.bytes = (0..t.pieces.len() as u32).map(|id| t.piece_bytes(id)).collect();
+        Ok(t)
+    }
+
+    /// the `tokenizer.json` text this was read from
+    pub fn source(&self) -> &str {
+        &self.source
+    }
+
+    /// ids 0 .. size (holes decode to nothing)
+    pub fn size(&self) -> usize {
+        self.pieces.len()
+    }
+
+    /// the id of a piece or added token, as written in the vocabulary
+    pub fn id(&self, piece: &str) -> Option {
+        self.ids.get(piece).copied()
+    }
+
+    pub fn piece(&self, id: u32) -> Option<&str> {
+        self.pieces.get(id as usize).map(String::as_str)
+    }
+
+    pub fn is_special(&self, id: u32) -> bool {
+        self.added_of.get(&id).is_some_and(|&i| self.added[i].special)
+    }
+
+    /// text to ids; added tokens written in the text are recognised (as the reference
+    /// implementation does). Nothing is added at the start or end: models add their
+    /// own start token (`pretrained::Lexicon`).
+    pub fn encode(&self, text: &str) -> Vec {
+        self.encode_with(text, true)
+    }
+
+    /// `encode`, optionally reading added tokens' text as plain text
+    pub fn encode_with(&self, text: &str, added: bool) -> Vec {
+        let mut out = Vec::new();
+        let mut first = true;
+        for seg in self.segments(text, added) {
+            match seg {
+                Seg::Token(id) => out.push(id),
+                Seg::Text(t) => {
+                    self.encode_text(t, first, &mut out);
+                }
+            }
+            first = false;
+        }
+        out
+    }
+
+    /// splits at added tokens, applying their lstrip/rstrip
+    fn segments<'a>(&self, text: &'a str, on: bool) -> Vec> {
+        if !on || self.added.is_empty() {
+            return vec![Seg::Text(text)];
+        }
+        let mut segs = Vec::new();
+        let (mut start, mut i) = (0, 0);
+        let b = text.as_bytes();
+        while i < b.len() {
+            let hit = self
+                .added
+                .iter()
+                .find(|a| !a.content.is_empty() && b[i..].starts_with(a.content.as_bytes()));
+            match hit {
+                Some(a) => {
+                    let mut before = &text[start..i];
+                    if a.lstrip {
+                        before = before.trim_end();
+                    }
+                    if !before.is_empty() {
+                        segs.push(Seg::Text(before));
+                    }
+                    segs.push(Seg::Token(a.id));
+                    i += a.content.len();
+                    if a.rstrip {
+                        while i < b.len() && text[i..].starts_with(char::is_whitespace) {
+                            i += text[i..].chars().next().unwrap().len_utf8();
+                        }
+                    }
+                    start = i;
+                }
+                None => i += 1,
+            }
+        }
+        if start < b.len() {
+            segs.push(Seg::Text(&text[start..]));
+        }
+        segs
+    }
+
+    fn encode_text(&self, text: &str, first: bool, out: &mut Vec) {
+        let mut s = text.to_string();
+        for n in &self.normalizers {
+            s = match n {
+                Normalizer::Prepend(p) if !s.is_empty() => format!("{p}{s}"),
+                Normalizer::Prepend(_) => s,
+                Normalizer::Replace(a, b) => s.replace(a.as_str(), b),
+                Normalizer::Lowercase => s.to_lowercase(),
+                Normalizer::Strip(l, r) => {
+                    let t = if *l { s.trim_start() } else { &s };
+                    (if *r { t.trim_end() } else { t }).to_string()
+                }
+            };
+        }
+        let mut pieces = vec![s];
+        for p in &self.pre {
+            let mut next = Vec::new();
+            for (k, piece) in pieces.into_iter().enumerate() {
+                match p {
+                    Pre::ByteLevel { prefix_space, regex } => {
+                        let piece = if *prefix_space && k == 0 && !piece.starts_with(' ') {
+                            format!(" {piece}")
+                        } else {
+                            piece
+                        };
+                        match regex {
+                            Some(r) => next.extend(r.find_all(&piece).into_iter().map(String::from)),
+                            None => next.push(piece),
+                        }
+                    }
+                    Pre::Split {
+                        regex,
+                        behavior,
+                        invert,
+                    } => {
+                        let chars: Vec = piece.chars().collect();
+                        next.extend(split_by(&piece, ®ex.find_iter(&chars), *behavior, *invert));
+                    }
+                    Pre::Digits { individual } => {
+                        let mut cur = String::new();
+                        let mut digit = false;
+                        for c in piece.chars() {
+                            let d = c.is_ascii_digit();
+                            if !cur.is_empty() && (d != digit || (d && *individual)) {
+                                next.push(std::mem::take(&mut cur));
+                            }
+                            digit = d;
+                            cur.push(c);
+                        }
+                        if !cur.is_empty() {
+                            next.push(cur);
+                        }
+                    }
+                    Pre::Metaspace {
+                        replacement,
+                        prepend,
+                        split,
+                    } => {
+                        let mut t: String = piece.chars().map(|c| if c == ' ' { *replacement } else { c }).collect();
+                        let add = match prepend {
+                            Prepend::Always => true,
+                            Prepend::First => first && k == 0,
+                            Prepend::Never => false,
+                        };
+                        if add && !t.starts_with(*replacement) {
+                            t.insert(0, *replacement);
+                        }
+                        if *split {
+                            let mut cur = String::new();
+                            for c in t.chars() {
+                                if c == *replacement && !cur.is_empty() {
+                                    next.push(std::mem::take(&mut cur));
+                                }
+                                cur.push(c);
+                            }
+                            if !cur.is_empty() {
+                                next.push(cur);
+                            }
+                        } else {
+                            next.push(t);
+                        }
+                    }
+                }
+            }
+            pieces = next;
+        }
+        let map = byte_chars();
+        for piece in pieces {
+            if piece.is_empty() {
+                continue;
+            }
+            let word = if self.byte_level {
+                piece.bytes().map(|b| map[b as usize]).collect()
+            } else {
+                piece
+            };
+            self.bpe(&word, out);
+        }
+    }
+
+    /// one pre-token through the merges (lowest rank first, then leftmost)
+    fn bpe(&self, word: &str, out: &mut Vec) {
+        if self.ignore_merges
+            && let Some(&id) = self.ids.get(word)
+        {
+            out.push(id);
+            return;
+        }
+        let mut syms: Vec = Vec::with_capacity(word.len());
+        let mut buf = [0u8; 4];
+        for c in word.chars() {
+            if let Some(&id) = self.ids.get(c.encode_utf8(&mut buf) as &str) {
+                syms.push(id);
+            } else if self.byte_fallback
+                && c.encode_utf8(&mut buf)
+                    .bytes()
+                    .all(|b| self.byte_ids[b as usize].is_some())
+            {
+                syms.extend(
+                    c.encode_utf8(&mut buf)
+                        .bytes()
+                        .map(|b| self.byte_ids[b as usize].unwrap()),
+                );
+            } else if let Some(u) = self.unk
+                && syms.last() != Some(&u)
+            {
+                syms.push(u);
+            }
+        }
+        if syms.len() < 2 {
+            out.extend(syms);
+            return;
+        }
+        // a linked list of symbols and a heap of candidate merges
+        let n = syms.len();
+        let mut prev: Vec = (0..n).map(|i| i.wrapping_sub(1)).collect();
+        let mut next: Vec = (1..=n).collect();
+        let mut alive = vec![true; n];
+        let mut heap = BinaryHeap::new();
+        let push = |heap: &mut BinaryHeap>, syms: &[u32], i: usize, j: usize| {
+            if let Some(&(rank, m)) = self.merges.get(&(syms[i], syms[j])) {
+                heap.push(Reverse((rank, i, m)));
+            }
+        };
+        for i in 0..n - 1 {
+            push(&mut heap, &syms, i, i + 1);
+        }
+        while let Some(Reverse((_, i, m))) = heap.pop() {
+            let j = next[i];
+            if !alive[i] || j >= n || self.merges.get(&(syms[i], syms[j])).map(|x| x.1) != Some(m) {
+                continue;
+            }
+            syms[i] = m;
+            alive[j] = false;
+            next[i] = next[j];
+            if next[j] < n {
+                prev[next[j]] = i;
+            }
+            if prev[i] < n {
+                push(&mut heap, &syms, prev[i], i);
+            }
+            if next[i] < n {
+                push(&mut heap, &syms, i, next[i]);
+            }
+        }
+        out.extend((0..n).filter(|&i| alive[i]).map(|i| syms[i]));
+    }
+
+    /// the bytes one token stands for (no leading-space stripping)
+    pub fn token_bytes(&self, id: u32) -> Vec {
+        self.bytes.get(id as usize).cloned().unwrap_or_default()
+    }
+
+    fn piece_bytes(&self, id: u32) -> Vec {
+        if let Some(&i) = self.added_of.get(&id) {
+            return self.added[i].content.as_bytes().to_vec();
+        }
+        let Some(p) = self.pieces.get(id as usize) else {
+            return Vec::new();
+        };
+        if self.byte_level {
+            let mut out = Vec::with_capacity(p.len());
+            let mut buf = [0u8; 4];
+            for c in p.chars() {
+                match byte_of(c) {
+                    Some(b) => out.push(b),
+                    None => out.extend_from_slice(c.encode_utf8(&mut buf).as_bytes()),
+                }
+            }
+            return out;
+        }
+        if self.byte_fallback
+            && let Some(b) = p.strip_prefix("<0x").and_then(|r| r.strip_suffix('>'))
+            && b.len() == 2
+            && let Ok(v) = u8::from_str_radix(b, 16)
+        {
+            return vec![v];
+        }
+        match self.space_char {
+            Some(c) => p.replace(c, " ").into_bytes(),
+            None => p.as_bytes().to_vec(),
+        }
+    }
+
+    /// ids back to bytes (special tokens left out when `skip_special`); the leading
+    /// space a SentencePiece-style tokenizer adds is taken off again
+    pub fn decode(&self, ids: &[u32], skip_special: bool) -> Vec {
+        let mut out = Vec::new();
+        for &id in ids {
+            if skip_special && self.is_special(id) {
+                continue;
+            }
+            out.extend(self.token_bytes(id));
+        }
+        let strip = out.iter().take(self.strip_start).take_while(|&&b| b == b' ').count();
+        out.drain(..strip);
+        out
+    }
+
+    /// `decode` as text (invalid UTF-8 replaced)
+    pub fn decode_text(&self, ids: &[u32]) -> String {
+        String::from_utf8_lossy(&self.decode(ids, true)).into_owned()
+    }
+}
+
+/// a tokenizer with the tokens a model starts sequences with and ends them with
+#[derive(Clone, Debug, PartialEq)]
+pub struct Lexicon {
+    pub tokenizer: Tokenizer,
+    /// put before every window (BOS, or the end token for models without one)
+    pub start: u32,
+    /// the end of a text: what training windows end in and the generative head's END
+    pub end: u32,
+    /// tokens that also end generation (chat models have several)
+    pub stops: Vec,
+}
+
+impl Lexicon {
+    /// bytes to ids, `data[..from]` and `data[from..]` encoded apart (a prompt and its
+    /// continuation), with the id index where the second part starts
+    pub fn encode_split(&self, data: &[u8], from: usize) -> (Vec, usize) {
+        let from = from.min(data.len());
+        let mut ids = if from > 0 {
+            self.tokenizer.encode(&String::from_utf8_lossy(&data[..from]))
+        } else {
+            Vec::new()
+        };
+        let at = ids.len();
+        if from < data.len() {
+            ids.extend(self.tokenizer.encode(&String::from_utf8_lossy(&data[from..])));
+        }
+        (ids, at)
+    }
+
+    /// whether a token ends generation
+    pub fn stops(&self, id: u32) -> bool {
+        id == self.end || self.stops.contains(&id)
+    }
+}
+
+enum Seg<'a> {
+    Text(&'a str),
+    Token(u32),
+}
+
+#[cfg(test)]
+pub(crate) mod tests {
+    use super::*;
+
+    /// a tiny GPT-2 style byte-level tokenizer (Llama 3 / Qwen2 shaped): every byte is
+    /// a token, a few merges, two special tokens
+    pub fn byte_level_json() -> String {
+        let map = byte_chars();
+        let mut vocab = serde_json::Map::new();
+        for (b, c) in map.iter().enumerate() {
+            vocab.insert(c.to_string(), b.into());
+        }
+        let merges = [
+            "Ġ t", "h e", "Ġt he", "l l", "ll o", "Ġ w", "o r", "Ġw or", "l d", "Ġwor ld", "1 2",
+        ];
+        let mut next = 256;
+        for m in merges {
+            let (a, b) = m.split_once(' ').unwrap();
+            vocab.insert(format!("{a}{b}"), next.into());
+            next += 1;
+        }
+        serde_json::json!({
+            "version": "1.0",
+            "added_tokens": [
+                {"id": next, "content": "<|endoftext|>", "special": true, "lstrip": false, "rstrip": false, "normalized": false, "single_word": false},
+                {"id": next + 1, "content": "<|im_start|>", "special": true, "lstrip": false, "rstrip": false, "normalized": false, "single_word": false}
+            ],
+            "normalizer": {"type": "NFC"},
+            "pre_tokenizer": {"type": "Sequence", "pretokenizers": [
+                {"type": "Split", "pattern": {"Regex": "(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\\r\\n\\p{L}\\p{N}]?\\p{L}+|\\p{N}| ?[^\\s\\p{L}\\p{N}]+[\\r\\n]*|\\s*[\\r\\n]+|\\s+(?!\\S)|\\s+"},
+                 "behavior": "Isolated", "invert": false},
+                {"type": "ByteLevel", "add_prefix_space": false, "trim_offsets": false, "use_regex": false}
+            ]},
+            "post_processor": {"type": "ByteLevel"},
+            "decoder": {"type": "ByteLevel", "add_prefix_space": true, "trim_offsets": true, "use_regex": true},
+            "model": {"type": "BPE", "dropout": null, "unk_token": null, "byte_fallback": false,
+                      "ignore_merges": false, "vocab": vocab,
+                      "merges": merges.iter().map(|m| { let (a, b) = m.split_once(' ').unwrap(); serde_json::json!([a, b]) }).collect::>()}
+        })
+        .to_string()
+    }
+
+    /// a tiny SentencePiece style tokenizer (Llama 2 / TinyLlama shaped): ▁ for spaces,
+    /// byte fallback, merges written as strings
+    pub fn sentencepiece_json() -> String {
+        let mut vocab = serde_json::Map::new();
+        vocab.insert("".into(), 0.into());
+        vocab.insert("".into(), 1.into());
+        vocab.insert("".into(), 2.into());
+        for b in 0..256 {
+            vocab.insert(format!("<0x{b:02X}>"), (3 + b).into());
+        }
+        let mut next = 259;
+        for p in ["▁", "h", "e", "l", "o", "w", "r", "d", "a", "b"] {
+            vocab.insert(p.into(), next.into());
+            next += 1;
+        }
+        let merges = [
+            "h e",
+            "l l",
+            "▁ he",
+            "▁he ll",
+            "▁hell o",
+            "▁ w",
+            "o r",
+            "▁w or",
+            "▁wor l",
+            "▁worl d",
+        ];
+        for m in merges {
+            let (a, b) = m.split_once(' ').unwrap();
+            vocab.insert(format!("{a}{b}"), next.into());
+            next += 1;
+        }
+        serde_json::json!({
+            "added_tokens": [
+                {"id": 0, "content": "", "special": true},
+                {"id": 1, "content": "", "special": true},
+                {"id": 2, "content": "", "special": true}
+            ],
+            "normalizer": {"type": "Sequence", "normalizers": [
+                {"type": "Prepend", "prepend": "▁"},
+                {"type": "Replace", "pattern": {"String": " "}, "content": "▁"}
+            ]},
+            "pre_tokenizer": null,
+            "decoder": {"type": "Sequence", "decoders": [
+                {"type": "Replace", "pattern": {"String": "▁"}, "content": " "},
+                {"type": "ByteFallback"}, {"type": "Fuse"},
+                {"type": "Strip", "content": " ", "start": 1, "stop": 0}
+            ]},
+            "model": {"type": "BPE", "unk_token": "", "byte_fallback": true, "fuse_unk": true,
+                      "vocab": vocab, "merges": merges}
+        })
+        .to_string()
+    }
+
+    fn pieces(t: &Tokenizer, ids: &[u32]) -> Vec {
+        ids.iter().map(|&i| t.piece(i).unwrap().to_string()).collect()
+    }
+
+    #[test]
+    fn byte_table_inverts() {
+        for (b, c) in byte_chars().iter().enumerate() {
+            assert_eq!(byte_of(*c), Some(b as u8));
+        }
+        assert_eq!(byte_of('Ā'), Some(0));
+        assert_eq!(byte_of('中'), None);
+    }
+
+    #[test]
+    fn byte_level_encodes_and_decodes() {
+        let t = Tokenizer::from_json(&byte_level_json()).unwrap();
+        let ids = t.encode("the world, hello 12!");
+        // pre-tokens "the", " world", ",", " hello", " ", "1", "2", "!" (digits one by one)
+        assert_eq!(
+            pieces(&t, &ids),
+            ["t", "he", "Ġworld", ",", "Ġ", "he", "llo", "Ġ", "1", "2", "!"]
+        );
+        assert_eq!(t.decode(&ids, false), b"the world, hello 12!");
+        // a space merge: " the"
+        assert_eq!(pieces(&t, &t.encode(" the")), ["Ġthe"]);
+        // special tokens in the text, bytes outside ASCII
+        let ids = t.encode("<|im_start|>héllo<|endoftext|>");
+        assert_eq!(ids.first(), t.id("<|im_start|>").as_ref());
+        assert_eq!(ids.last(), t.id("<|endoftext|>").as_ref());
+        assert_eq!(t.decode(&ids, false), "<|im_start|>héllo<|endoftext|>".as_bytes());
+        assert_eq!(t.decode(&ids, true), "héllo".as_bytes());
+        assert!(t.is_special(*ids.last().unwrap()));
+        // read as text, the special token is just bytes
+        assert!(
+            !t.encode_with("<|endoftext|>", false)
+                .contains(&t.id("<|endoftext|>").unwrap())
+        );
+        // every byte string round trips
+        let all: Vec = (0..=255).collect();
+        let s = String::from_utf8_lossy(&all).into_owned();
+        assert_eq!(t.decode(&t.encode(&s), false), s.as_bytes());
+    }
+
+    #[test]
+    fn sentencepiece_style_encodes_and_decodes() {
+        let t = Tokenizer::from_json(&sentencepiece_json()).unwrap();
+        let ids = t.encode("hello world");
+        assert_eq!(pieces(&t, &ids), ["▁hello", "▁world"]);
+        assert_eq!(t.decode(&ids, true), b"hello world");
+        // unknown characters fall back to their bytes
+        let ids = t.encode("hé");
+        assert_eq!(pieces(&t, &ids), ["▁", "h", "<0xC3>", "<0xA9>"]);
+        assert_eq!(t.decode(&ids, true), "hé".as_bytes());
+        // a generated token after a prompt keeps its space
+        assert_eq!(t.token_bytes(t.id("▁world").unwrap()), b" world");
+        assert_eq!(t.decode(&t.encode("ab"), true), b"ab");
+    }
+
+    #[test]
+    fn unsupported_parts_are_named() {
+        let mut v: Json = serde_json::from_str(&byte_level_json()).unwrap();
+        v["model"]["type"] = "WordPiece".into();
+        assert!(
+            Tokenizer::from_json(&v.to_string())
+                .unwrap_err()
+                .contains("model type \"WordPiece\"")
+        );
+        let mut v: Json = serde_json::from_str(&byte_level_json()).unwrap();
+        v["normalizer"] = serde_json::json!({"type": "NFKC"});
+        assert!(
+            Tokenizer::from_json(&v.to_string())
+                .unwrap_err()
+                .contains("normalizer \"NFKC\"")
+        );
+        let mut v: Json = serde_json::from_str(&byte_level_json()).unwrap();
+        v["pre_tokenizer"] = serde_json::json!({"type": "BertPreTokenizer"});
+        assert!(
+            Tokenizer::from_json(&v.to_string())
+                .unwrap_err()
+                .contains("BertPreTokenizer")
+        );
+        let mut v: Json = serde_json::from_str(&byte_level_json()).unwrap();
+        v["model"]["merges"][0] = serde_json::json!(["Ġ", "zz"]);
+        assert!(Tokenizer::from_json(&v.to_string()).unwrap_err().contains("\"zz\""));
+    }
+}
diff --git a/core/src/classify/codec.rs b/core/src/classify/codec.rs
new file mode 100644
index 00000000..e11c941a
--- /dev/null
+++ b/core/src/classify/codec.rs
@@ -0,0 +1,427 @@
+//! Other data as bytes, so the same transformers (classifiers and generators) work on
+//! it: numbers as fixed-width text, pictures as sequences of patch codes. Plus a
+//! minimal PNG writer (no compression, no dependencies) to look at generated pictures.
+//!
+//! Pictures: an image is cut into square patches (8×8 pixels by default) and each
+//! patch is replaced by the nearest entry of a codebook learned from the training
+//! images (k-means, integer arithmetic, so the same images give the same codebook on
+//! any machine). A code is one byte (0..=254), a row of patches ends with `ROW` (255).
+//! A 64×64 picture with 8×8 patches is 64 codes + 8 row ends = 72 tokens instead of
+//! 4096 pixels, which is what makes pictures of useful size affordable for attention,
+//! whose cost grows with the square of the sequence length.
+
+use serde::{Deserialize, Serialize};
+
+use super::math::{Rng, key};
+
+// ---------------------------------------------------------------- numbers
+
+/// numbers as fixed-width ASCII: sign (when signed), `digits` integer digits, and
+/// `decimals` after a point, e.g. `+0042.50`. Fixed width means every digit has a
+/// fixed position, which a model learns more easily than free-form numerals.
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
+pub struct NumberCodec {
+    pub digits: usize,
+    pub decimals: usize,
+    pub signed: bool,
+}
+
+impl NumberCodec {
+    pub fn width(&self) -> usize {
+        self.signed as usize + self.digits + if self.decimals > 0 { 1 + self.decimals } else { 0 }
+    }
+
+    /// the largest magnitude that fits
+    pub fn max(&self) -> f64 {
+        10f64.powi(self.digits as i32) - 10f64.powi(-(self.decimals as i32))
+    }
+
+    /// the encoding of x, clamped to what fits and rounded half away from zero
+    pub fn encode(&self, x: f64) -> Vec {
+        let neg = x < 0.0 && self.signed;
+        let m = x.abs().min(self.max());
+        let scaled = (m * 10f64.powi(self.decimals as i32)).round() as u128;
+        let s = format!("{:0w$}", scaled, w = self.digits + self.decimals);
+        let mut out = Vec::with_capacity(self.width());
+        if self.signed {
+            out.push(if neg { b'-' } else { b'+' });
+        }
+        out.extend_from_slice(&s.as_bytes()[..self.digits]);
+        if self.decimals > 0 {
+            out.push(b'.');
+            out.extend_from_slice(&s.as_bytes()[self.digits..]);
+        }
+        out
+    }
+
+    /// the number in the first `width` bytes, if they are well formed
+    pub fn decode(&self, b: &[u8]) -> Option {
+        let b = b.get(..self.width())?;
+        let (sign, rest) = if self.signed {
+            match b[0] {
+                b'+' => (1.0, &b[1..]),
+                b'-' => (-1.0, &b[1..]),
+                _ => return None,
+            }
+        } else {
+            (1.0, b)
+        };
+        let (int, frac) = rest.split_at(self.digits);
+        if self.decimals > 0 && frac.first() != Some(&b'.') {
+            return None;
+        }
+        let frac = if self.decimals > 0 { &frac[1..] } else { frac };
+        if !int.iter().chain(frac).all(u8::is_ascii_digit) {
+            return None;
+        }
+        let digits = |d: &[u8]| d.iter().fold(0f64, |a, &c| a * 10.0 + (c - b'0') as f64);
+        // one integer, one division: the nearest double to the decimal written
+        Some(sign * (digits(&[int, frac].concat()) / 10f64.powi(self.decimals as i32)))
+    }
+}
+
+// ---------------------------------------------------------------- pictures
+
+/// an RGB picture, 8 bits a channel, rows top to bottom
+#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
+pub struct Image {
+    pub width: usize,
+    pub height: usize,
+    /// width·height·3 bytes
+    pub rgb: Vec,
+}
+
+impl Image {
+    pub fn new(width: usize, height: usize, fill: [u8; 3]) -> Image {
+        Image {
+            width,
+            height,
+            rgb: fill.repeat(width * height),
+        }
+    }
+
+    pub fn get(&self, x: usize, y: usize) -> [u8; 3] {
+        let i = 3 * (y * self.width + x);
+        [self.rgb[i], self.rgb[i + 1], self.rgb[i + 2]]
+    }
+
+    pub fn set(&mut self, x: usize, y: usize, c: [u8; 3]) {
+        if x < self.width && y < self.height {
+            let i = 3 * (y * self.width + x);
+            self.rgb[i..i + 3].copy_from_slice(&c);
+        }
+    }
+
+    /// the pixels of patch (px, py), row-major, p·p·3 bytes
+    fn patch(&self, p: usize, px: usize, py: usize) -> Vec {
+        let mut v = Vec::with_capacity(p * p * 3);
+        for y in py * p..(py + 1) * p {
+            let i = 3 * (y * self.width + px * p);
+            v.extend_from_slice(&self.rgb[i..i + 3 * p]);
+        }
+        v
+    }
+
+    /// each pixel as an s×s block
+    pub fn scaled(&self, s: usize) -> Image {
+        let mut o = Image::new(self.width * s, self.height * s, [0; 3]);
+        for y in 0..o.height {
+            for x in 0..o.width {
+                o.set(x, y, self.get(x / s, y / s));
+            }
+        }
+        o
+    }
+}
+
+/// the end of a row of patches
+pub const ROW: u8 = 255;
+/// codes a codebook may hold (bytes 0..=254)
+pub const MAX_CODES: usize = 255;
+
+/// patch prototypes: `codes` entries of patch·patch·3 bytes
+#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
+pub struct Codebook {
+    pub patch: usize,
+    pub entries: Vec>,
+}
+
+fn dist(a: &[u8], b: &[u8]) -> u64 {
+    a.iter()
+        .zip(b)
+        .map(|(&x, &y)| (x as i64 - y as i64).pow(2) as u64)
+        .sum()
+}
+
+impl Codebook {
+    /// k-means over every patch of `images` (all the same size, multiples of `patch`):
+    /// `codes` starting entries drawn by a seeded shuffle of the distinct patches, then
+    /// `iters` rounds of nearest-entry assignment (ties to the lower code) and integer
+    /// means (rounded half up); an entry left without patches keeps its value
+    pub fn learn(images: &[Image], patch: usize, codes: usize, iters: usize, seed: u64) -> Result {
+        if patch == 0 || codes == 0 || codes > MAX_CODES {
+            return Err(format!(
+                "a codebook has 1 to {MAX_CODES} codes of patches at least 1 pixel wide"
+            ));
+        }
+        let mut all: Vec> = Vec::new();
+        for im in images {
+            if im.width % patch != 0 || im.height % patch != 0 {
+                return Err(format!(
+                    "{}×{} is not a multiple of the {patch} pixel patch",
+                    im.width, im.height
+                ));
+            }
+            for py in 0..im.height / patch {
+                for px in 0..im.width / patch {
+                    all.push(im.patch(patch, px, py));
+                }
+            }
+        }
+        if all.is_empty() {
+            return Err("no pictures to learn patches from".into());
+        }
+        let mut distinct = all.clone();
+        distinct.sort();
+        distinct.dedup();
+        Rng::new(key(&[seed, 0xc0de])).shuffle(&mut distinct);
+        distinct.truncate(codes);
+        let mut cb = Codebook {
+            patch,
+            entries: distinct,
+        };
+        let len = patch * patch * 3;
+        for _ in 0..iters {
+            let mut sums = vec![vec![0u64; len]; cb.entries.len()];
+            let mut counts = vec![0u64; cb.entries.len()];
+            for p in &all {
+                let c = cb.nearest(p) as usize;
+                counts[c] += 1;
+                sums[c].iter_mut().zip(p).for_each(|(s, &v)| *s += v as u64);
+            }
+            for ((e, s), &n) in cb.entries.iter_mut().zip(&sums).zip(&counts) {
+                if n > 0 {
+                    e.iter_mut()
+                        .zip(s)
+                        .for_each(|(v, &t)| *v = ((2 * t + n) / (2 * n)) as u8);
+                }
+            }
+        }
+        Ok(cb)
+    }
+
+    /// the code of the nearest entry (squared distance, ties to the lower code)
+    pub fn nearest(&self, p: &[u8]) -> u8 {
+        let mut best = (u64::MAX, 0usize);
+        for (i, e) in self.entries.iter().enumerate() {
+            let d = dist(e, p);
+            if d < best.0 {
+                best = (d, i);
+            }
+        }
+        best.1 as u8
+    }
+
+    /// the picture as bytes: per row of patches, the codes, then ROW
+    pub fn encode(&self, im: &Image) -> Vec {
+        let p = self.patch;
+        let mut out = Vec::new();
+        for py in 0..im.height / p {
+            for px in 0..im.width / p {
+                out.push(self.nearest(&im.patch(p, px, py)));
+            }
+            out.push(ROW);
+        }
+        out
+    }
+
+    /// bytes back to a width×height picture: rows restart at each ROW, a short row is
+    /// padded with code 0, a long one is cut, codes past the codebook read as code 0
+    pub fn decode(&self, b: &[u8], width: usize, height: usize) -> Image {
+        let p = self.patch;
+        let (cols, rows) = (width / p, height / p);
+        let mut im = Image::new(width, height, [0; 3]);
+        let mut grid: Vec> = b.split(|&c| c == ROW).map(|r| r.to_vec()).collect();
+        grid.resize(rows, Vec::new());
+        for (py, row) in grid.iter().take(rows).enumerate() {
+            for px in 0..cols {
+                let c = row.get(px).copied().unwrap_or(0) as usize;
+                let e = self.entries.get(c).unwrap_or(&self.entries[0]);
+                for y in 0..p {
+                    for x in 0..p {
+                        let i = 3 * (y * p + x);
+                        im.set(px * p + x, py * p + y, [e[i], e[i + 1], e[i + 2]]);
+                    }
+                }
+            }
+        }
+        im
+    }
+
+    /// the tokens a width×height picture takes (codes, row ends)
+    pub fn tokens(&self, width: usize, height: usize) -> usize {
+        (width / self.patch + 1) * (height / self.patch)
+    }
+}
+
+// ---------------------------------------------------------------- PNG
+
+fn crc_table() -> [u32; 256] {
+    let mut t = [0u32; 256];
+    for (n, v) in t.iter_mut().enumerate() {
+        let mut c = n as u32;
+        for _ in 0..8 {
+            c = if c & 1 != 0 { 0xedb8_8320 ^ (c >> 1) } else { c >> 1 };
+        }
+        *v = c;
+    }
+    t
+}
+
+fn crc32(t: &[u32; 256], data: &[u8]) -> u32 {
+    let mut c = 0xffff_ffffu32;
+    for &b in data {
+        c = t[((c ^ b as u32) & 0xff) as usize] ^ (c >> 8);
+    }
+    c ^ 0xffff_ffff
+}
+
+/// a PNG file (RGB, 8 bits) of the picture: zlib with stored (uncompressed) deflate
+/// blocks, so a few lines replace an image library; files are about the raw size
+pub fn png(im: &Image) -> Vec {
+    let t = crc_table();
+    let mut raw = Vec::with_capacity(im.height * (1 + 3 * im.width));
+    for y in 0..im.height {
+        raw.push(0); // filter: none
+        raw.extend_from_slice(&im.rgb[3 * y * im.width..3 * (y + 1) * im.width]);
+    }
+    let mut z = vec![0x78, 0x01];
+    let chunks: Vec<&[u8]> = raw.chunks(65_535).collect();
+    for (i, c) in chunks.iter().enumerate() {
+        z.push((i + 1 == chunks.len()) as u8);
+        z.extend_from_slice(&(c.len() as u16).to_le_bytes());
+        z.extend_from_slice(&(!(c.len() as u16)).to_le_bytes());
+        z.extend_from_slice(c);
+    }
+    let (mut a, mut b) = (1u32, 0u32);
+    for &x in &raw {
+        a = (a + x as u32) % 65_521;
+        b = (b + a) % 65_521;
+    }
+    z.extend_from_slice(&((b << 16) | a).to_be_bytes());
+    let mut out = b"\x89PNG\r\n\x1a\n".to_vec();
+    let mut chunk = |kind: &[u8; 4], data: &[u8]| {
+        out.extend_from_slice(&(data.len() as u32).to_be_bytes());
+        let start = out.len();
+        out.extend_from_slice(kind);
+        out.extend_from_slice(data);
+        let c = crc32(&t, &out[start..]);
+        out.extend_from_slice(&c.to_be_bytes());
+    };
+    let mut ihdr = Vec::new();
+    ihdr.extend_from_slice(&(im.width as u32).to_be_bytes());
+    ihdr.extend_from_slice(&(im.height as u32).to_be_bytes());
+    ihdr.extend_from_slice(&[8, 2, 0, 0, 0]);
+    chunk(b"IHDR", &ihdr);
+    chunk(b"IDAT", &z);
+    chunk(b"IEND", &[]);
+    out
+}
+
+// ---------------------------------------------------------------- toy pictures
+
+/// a toy picture for demos and tests: one of four shapes (0 disc, 1 square, 2 cross,
+/// 3 stripes) in a colour on a background, placed and sized by the seed
+pub fn toy(size: usize, shape: usize, seed: u64) -> Image {
+    let mut r = Rng::new(key(&[seed, 0x70e]));
+    let palette = [
+        [230, 60, 50],
+        [40, 160, 80],
+        [50, 90, 220],
+        [240, 200, 40],
+        [150, 60, 200],
+    ];
+    let bgs = [[250, 248, 240], [30, 30, 40], [200, 220, 235]];
+    let fg = palette[r.below(palette.len())];
+    let bg = bgs[r.below(bgs.len())];
+    let mut im = Image::new(size, size, bg);
+    let s = size as i64;
+    let rad = s / 6 + r.below((s / 6).max(1) as usize) as i64;
+    let cx = rad + r.below((s - 2 * rad).max(1) as usize) as i64;
+    let cy = rad + r.below((s - 2 * rad).max(1) as usize) as i64;
+    for y in 0..s {
+        for x in 0..s {
+            let (dx, dy) = (x - cx, y - cy);
+            let on = match shape % 4 {
+                0 => dx * dx + dy * dy <= rad * rad,
+                1 => dx.abs() <= rad && dy.abs() <= rad,
+                2 => (dx.abs() <= rad / 3 && dy.abs() <= rad) || (dy.abs() <= rad / 3 && dx.abs() <= rad),
+                _ => (y / (rad / 2).max(1)) % 2 == 0,
+            };
+            if on {
+                im.set(x as usize, y as usize, fg);
+            }
+        }
+    }
+    im
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn numbers_round_trip() {
+        let c = NumberCodec {
+            digits: 4,
+            decimals: 2,
+            signed: true,
+        };
+        assert_eq!(c.encode(42.5), b"+0042.50");
+        assert_eq!(c.encode(-2.71), b"-0002.71");
+        assert_eq!(c.encode(1e9), b"+9999.99");
+        assert_eq!(c.width(), 8);
+        assert_eq!(c.decode(b"-0002.71"), Some(-2.71));
+        assert_eq!(c.decode(b"+00x3.14"), None);
+        assert_eq!(c.decode(b"+0003"), None);
+        let u = NumberCodec {
+            digits: 3,
+            decimals: 0,
+            signed: false,
+        };
+        assert_eq!(u.encode(7.0), b"007");
+        assert_eq!(u.decode(b"123rest"), Some(123.0));
+    }
+
+    #[test]
+    fn pictures_through_a_codebook() {
+        let ims: Vec = (0..8).map(|i| toy(32, i % 4, i as u64)).collect();
+        let cb = Codebook::learn(&ims, 8, 24, 4, 1).unwrap();
+        assert_eq!(cb, Codebook::learn(&ims, 8, 24, 4, 1).unwrap());
+        let b = cb.encode(&ims[0]);
+        assert_eq!(b.len(), cb.tokens(32, 32));
+        assert_eq!(b.iter().filter(|&&c| c == ROW).count(), 4);
+        let back = cb.decode(&b, 32, 32);
+        assert_eq!(cb.encode(&back), b);
+        // uniform patches are reproduced exactly when the codebook holds them
+        let flat = Image::new(32, 32, [250, 248, 240]);
+        let cb2 = Codebook::learn(std::slice::from_ref(&flat), 8, 4, 2, 0).unwrap();
+        assert_eq!(cb2.decode(&cb2.encode(&flat), 32, 32), flat);
+        // ragged bytes still decode
+        assert_eq!(cb.decode(&[1, 2, ROW, 3], 32, 32).width, 32);
+        assert!(Codebook::learn(&ims, 7, 4, 1, 0).is_err());
+    }
+
+    #[test]
+    fn png_is_well_formed() {
+        let im = toy(16, 0, 3).scaled(2);
+        let p = png(&im);
+        assert_eq!(&p[..8], b"\x89PNG\r\n\x1a\n");
+        assert_eq!(&p[12..16], b"IHDR");
+        assert_eq!(u32::from_be_bytes(p[16..20].try_into().unwrap()), 32);
+        // the IHDR's CRC as zlib's crc32 gives it
+        let t = crc_table();
+        assert_eq!(crc32(&t, b"123456789"), 0xcbf4_3926);
+        assert!(p.ends_with(&[0xae, 0x42, 0x60, 0x82]));
+    }
+}
diff --git a/core/src/classify/compose.rs b/core/src/classify/compose.rs
index 106de74b..5346ada8 100644
--- a/core/src/classify/compose.rs
+++ b/core/src/classify/compose.rs
@@ -12,6 +12,7 @@
 
 use serde::{Deserialize, Serialize};
 
+use super::device::Runner;
 use super::kernels as k;
 use super::model::{BlockT, HeadKind, Net, Trace};
 use super::pool::Pool;
@@ -163,6 +164,56 @@ impl Graph {
         (clf.read(&r.logits), r.pooled)
     }
 
+    /// `read_node` for many texts: each node reads every text before the next one
+    /// starts, on its runner's device when it has one (all the texts' windows packed),
+    /// else on the pool. The same values as `read_node` text by text, bit for bit on the
+    /// CPU and on a device the probe finds exact.
+    pub fn read_node_many(
+        &self,
+        node: usize,
+        texts: &[&str],
+        runners: &[Option<&Runner>],
+        pool: &Pool,
+    ) -> Vec<(Vec, Vec)> {
+        let need = self.needed(node);
+        let n = texts.len();
+        let mut outs: Vec>>> = vec![vec![None; self.nodes.len()]; n];
+        let mut pooled: Vec> = vec![Vec::new(); n];
+        for i in 0..=node {
+            if !need[i] {
+                continue;
+            }
+            let clf = &self.nodes[i].clf;
+            let gains = clf.gains();
+            let xs: Vec> = outs.iter().map(|o| self.extra_from(i, o)).collect();
+            let runs: Vec<(Vec>, Vec)> = match runners.get(i).copied().flatten() {
+                Some(r) => {
+                    let bytes: Vec<&[u8]> = texts.iter().map(|t| t.as_bytes()).collect();
+                    let xr: Vec<&[f32]> = xs.iter().map(Vec::as_slice).collect();
+                    r.text_runs(&clf.net, &bytes, &xr, &gains)
+                }
+                None => {
+                    let slots: Vec>> = texts.iter().map(|_| Default::default()).collect();
+                    pool.run(n, &|t| {
+                        let r = clf.run(texts[t], &xs[t], &gains, None);
+                        *slots[t].lock().unwrap() = Some((r.logits, r.pooled));
+                    });
+                    slots.into_iter().map(|s| s.into_inner().unwrap().unwrap()).collect()
+                }
+            };
+            for (t, (logits, p)) in runs.into_iter().enumerate() {
+                outs[t][i] = Some(clf.read(&logits));
+                if i == node {
+                    pooled[t] = p;
+                }
+            }
+        }
+        outs.into_iter()
+            .zip(pooled)
+            .map(|(mut o, p)| (o.swap_remove(node).expect("computed"), p))
+            .collect()
+    }
+
     /// the extra inputs `node` gets for a text
     pub fn extra(&self, node: usize, text: &str) -> Vec {
         let outs = self.outputs(node, text);
@@ -191,7 +242,7 @@ impl Graph {
             }
             let clf = &self.nodes[i].clf;
             let x = self.extra_from(i, &outs);
-            let (trs, avg) = train::forward_text(&clf.net, text, &x, &clf.gains());
+            let (trs, avg) = train::forward_text(&clf.net, text.as_bytes(), &x, &clf.gains());
             let o = clf.read(&avg);
             outs[i] = Some(o.clone());
             runs[i] = Some((trs, x, avg, o));
@@ -363,6 +414,8 @@ impl Graph {
             target,
             weight: f.weight,
             extra: x,
+            raw: Vec::new(),
+            also: Vec::new(),
         };
         let m = &mut self.nodes[node].clf.meta;
         m.feedback
diff --git a/core/src/classify/device.rs b/core/src/classify/device.rs
new file mode 100644
index 00000000..cba2adc5
--- /dev/null
+++ b/core/src/classify/device.rs
@@ -0,0 +1,534 @@
+//! Where a run's numbers are computed. The CPU is the default and the reference:
+//! bit-deterministic on every machine. The GPU (cargo feature `gpu`, see `gpu`) is an
+//! explicit choice per run — a training option, a generation option, a spec field —
+//! and never the default, so saved models keep answering on the exact CPU path unless
+//! someone asks otherwise.
+
+use serde::{Deserialize, Serialize};
+
+use super::model::Net;
+use super::train::Example;
+
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum Device {
+    /// the CPU kernels (the reference)
+    #[default]
+    Cpu,
+    /// the GPU in exact precision: the CPU's bits on a device the probe finds exact
+    Gpu,
+    /// the GPU with plain operators: faster, within a small tolerance of the CPU
+    GpuFast,
+}
+
+impl Device {
+    pub fn is_gpu(self) -> bool {
+        self != Device::Cpu
+    }
+
+    /// whether this build and machine can run on the device; the reason when not
+    pub fn check(self) -> Result<(), String> {
+        if !self.is_gpu() {
+            return Ok(());
+        }
+        #[cfg(feature = "gpu")]
+        {
+            super::gpu::shared().map(|_| ())
+        }
+        #[cfg(not(feature = "gpu"))]
+        {
+            Err("this build has no GPU backend (build with the cargo feature `gpu`)".into())
+        }
+    }
+
+    #[cfg(feature = "gpu")]
+    pub fn precision(self) -> super::gpu::Precision {
+        match self {
+            Device::GpuFast => super::gpu::Precision::Fast,
+            _ => super::gpu::Precision::Exact,
+        }
+    }
+}
+
+/// a net's training state on the device (uninhabited in builds without the GPU)
+#[cfg(feature = "gpu")]
+pub struct Trainer {
+    t: super::gpu::train::Trainer,
+    buf: Net,
+}
+
+#[cfg(not(feature = "gpu"))]
+pub enum Trainer {}
+
+impl Trainer {
+    /// the device's trainer for a run on `device`, None on the CPU
+    pub fn open(device: Device, net: &Net) -> Result, String> {
+        device.check()?;
+        if !device.is_gpu() {
+            return Ok(None);
+        }
+        #[cfg(feature = "gpu")]
+        {
+            let g = super::gpu::shared()?;
+            Ok(Some(Trainer {
+                t: super::gpu::train::Trainer::new(g, net, device.precision())?,
+                buf: net.zeros_like(),
+            }))
+        }
+        #[cfg(not(feature = "gpu"))]
+        {
+            let _ = net;
+            unreachable!("checked")
+        }
+    }
+
+    /// a batch of cropped examples (index, coefficient, crop key) on the device: the
+    /// gradient into `total`, as `train::batch_grad` sums it; returns (Σ coef·loss, tokens)
+    pub fn batch(
+        &mut self,
+        net: &Net,
+        data: &[Example],
+        items: &[(usize, f32, u64)],
+        smoothing: f32,
+        total: &mut Net,
+    ) -> (f64, usize) {
+        #[cfg(feature = "gpu")]
+        {
+            use super::model::Mode;
+            use super::train::{crop_seq, sequence_of};
+            total.fill(0.0);
+            self.t.begin(net);
+            let (mut loss, mut tokens) = (0f64, 0usize);
+            for &(i, coef, kk) in items {
+                let ex = &data[i];
+                let buf = &mut self.buf;
+                buf.fill(0.0);
+                let extra = if ex.extra.is_empty() {
+                    vec![0.0; net.cfg.extra]
+                } else {
+                    ex.extra.clone()
+                };
+                let (ts, targets) = sequence_of(net, ex);
+                let (w, start) = crop_seq(net, &ts, kk);
+                let mode = Mode {
+                    dropout: net.cfg.dropout,
+                    key: kk,
+                };
+                let (l, t) = self.t.example(
+                    net,
+                    &w,
+                    start,
+                    targets.iter().map(|(h, t)| (*h, t)),
+                    &extra,
+                    mode,
+                    coef,
+                    smoothing,
+                    buf,
+                );
+                for ((_, d), (_, s)) in total.params_mut().into_iter().zip(buf.params()) {
+                    d.iter_mut().zip(s.iter()).for_each(|(a, b)| *a += b);
+                }
+                loss += (coef * l) as f64;
+                tokens += t;
+            }
+            self.t.finish(total);
+            (loss, tokens)
+        }
+        #[cfg(not(feature = "gpu"))]
+        {
+            let _ = (net, data, items, smoothing, total);
+            match *self {}
+        }
+    }
+}
+
+/// one token at a time through a generative net: `model::Decoder` on the CPU,
+/// `gpu::net::GpuDecoder` on the device
+pub trait Decode {
+    /// the logits for the next token
+    fn logits(&self) -> &[f32];
+    fn push_token(&mut self, t: u32);
+}
+
+impl Decode for super::model::Decoder<'_> {
+    fn logits(&self) -> &[f32] {
+        super::model::Decoder::logits(self)
+    }
+
+    fn push_token(&mut self, t: u32) {
+        super::model::Decoder::push_token(self, t)
+    }
+}
+
+#[cfg(feature = "gpu")]
+impl Decode for super::gpu::net::GpuDecoder<'_> {
+    fn logits(&self) -> &[f32] {
+        super::gpu::net::GpuDecoder::logits(self)
+    }
+
+    fn push_token(&mut self, t: u32) {
+        super::gpu::net::GpuDecoder::push_token(self, t)
+    }
+}
+
+/// a net uploaded for inference on the device (uninhabited without the GPU)
+#[cfg(feature = "gpu")]
+pub struct Runner {
+    pub gn: super::gpu::net::GpuNet,
+}
+
+#[cfg(not(feature = "gpu"))]
+pub enum Runner {}
+
+impl Runner {
+    /// the net on `device`, None on the CPU
+    pub fn open(device: Device, net: &Net) -> Result, String> {
+        device.check()?;
+        if !device.is_gpu() {
+            return Ok(None);
+        }
+        #[cfg(feature = "gpu")]
+        {
+            let g = super::gpu::shared()?;
+            Ok(Some(Runner {
+                gn: super::gpu::net::GpuNet::new(g, net, device.precision())?,
+            }))
+        }
+        #[cfg(not(feature = "gpu"))]
+        {
+            let _ = net;
+            unreachable!("checked")
+        }
+    }
+
+    /// every head's logits averaged over the windows of `data` (`train::forward_text`'s
+    /// mean), the trunk on the device
+    pub fn text_logits(&self, net: &Net, data: &[u8], extra: &[f32], gains: &super::model::Gains) -> Vec> {
+        #[cfg(feature = "gpu")]
+        {
+            self.gn.text_logits(net, data, extra, gains)
+        }
+        #[cfg(not(feature = "gpu"))]
+        {
+            let _ = (net, data, extra, gains);
+            match *self {}
+        }
+    }
+
+    /// many texts at once, their windows packed on the device: per text, each head's
+    /// logits and the pooled vector averaged over its windows (`Classifier::run_bytes`)
+    pub fn text_runs(
+        &self,
+        net: &Net,
+        texts: &[&[u8]],
+        extras: &[&[f32]],
+        gains: &super::model::Gains,
+    ) -> Vec<(Vec>, Vec)> {
+        #[cfg(feature = "gpu")]
+        {
+            self.gn
+                .text_runs(net, texts, extras, gains)
+                .into_iter()
+                .map(|r| (r.logits, r.pooled))
+                .collect()
+        }
+        #[cfg(not(feature = "gpu"))]
+        {
+            let _ = (net, texts, extras, gains);
+            match *self {}
+        }
+    }
+
+    /// a decoder on the device that has read the start token and `prompt`
+    pub fn decoder<'a>(&'a self, net: &'a Net, gains: super::model::Gains, prompt: &[u8]) -> Box {
+        #[cfg(feature = "gpu")]
+        {
+            Box::new(super::gpu::net::GpuDecoder::new(&self.gn, net, gains, prompt))
+        }
+        #[cfg(not(feature = "gpu"))]
+        {
+            let _ = (net, gains, prompt);
+            match *self {}
+        }
+    }
+}
+
+// ---------------------------------------------------------------- reading texts
+
+/// where classifiers read texts (predict, search, indexing, buckets, tints): the user's
+/// choice, for this process (`classify.device`)
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum Choice {
+    /// the GPU in exact precision when there is one that isn't a software renderer, the
+    /// probe finds it bit-exact on every kernel (so the results are the CPU's), and it
+    /// reads faster than the CPU with a model of the size at hand (measured on first use
+    /// of each size, `speed`); else the CPU
+    #[default]
+    Auto,
+    Cpu,
+    /// the GPU in exact precision, whatever the probe found
+    Gpu,
+    /// the GPU with plain operators
+    GpuFast,
+}
+
+impl Choice {
+    pub fn parse(s: &str) -> Option {
+        Some(match s.trim() {
+            "auto" | "" => Choice::Auto,
+            "cpu" => Choice::Cpu,
+            "gpu" => Choice::Gpu,
+            "gpu_fast" | "gpu fast" => Choice::GpuFast,
+            _ => return None,
+        })
+    }
+
+    pub fn name(self) -> &'static str {
+        match self {
+            Choice::Auto => "auto",
+            Choice::Cpu => "cpu",
+            Choice::Gpu => "gpu",
+            Choice::GpuFast => "gpu_fast",
+        }
+    }
+}
+
+static CHOICE: std::sync::Mutex> = std::sync::Mutex::new(None);
+
+/// the process's choice: as set, else `ANEND_CLASSIFY_DEVICE`, else auto
+pub fn choice() -> Choice {
+    if let Some(c) = *CHOICE.lock().unwrap_or_else(|e| e.into_inner()) {
+        return c;
+    }
+    std::env::var("ANEND_CLASSIFY_DEVICE")
+        .ok()
+        .and_then(|v| Choice::parse(&v))
+        .unwrap_or_default()
+}
+
+pub fn set_choice(c: Choice) {
+    *CHOICE.lock().unwrap_or_else(|e| e.into_inner()) = Some(c);
+}
+
+/// where reading runs, and why when it isn't where it was asked to
+#[derive(Clone, Debug, PartialEq, Serialize)]
+pub struct Reading {
+    pub choice: Choice,
+    pub device: Device,
+    /// the results are the CPU's bits (the CPU, or exact precision on a device the
+    /// probe finds exact)
+    pub exact: bool,
+    /// the GPU it runs on
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub gpu: Option,
+    /// why it runs somewhere else than asked, or why auto chose the CPU
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub note: Option,
+    /// the measured rates auto chose by (`speed`), for the model it reads with
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub speed: Option>,
+}
+
+impl Reading {
+    pub fn cpu(choice: Choice, note: Option) -> Reading {
+        Reading {
+            choice,
+            device: Device::Cpu,
+            exact: true,
+            gpu: None,
+            note,
+            speed: None,
+        }
+    }
+}
+
+/// whether the shared GPU is bit-exact on every kernel in exact precision (the probe,
+/// run once a process); Err when there's no GPU
+#[cfg(feature = "gpu")]
+pub fn probe_exact() -> Result {
+    static EXACT: std::sync::OnceLock = std::sync::OnceLock::new();
+    let g = super::gpu::shared()?;
+    Ok(*EXACT.get_or_init(|| super::gpu::probe::probe(g, super::gpu::Precision::Exact).exact()))
+}
+
+/// where a stack of nets reads for `choice`: `reading`, and for auto on a GPU, the rates
+/// measured for the stack's largest net decide (the GPU only where it's faster)
+pub fn reading_for(choice: Choice, allowed: bool, nets: &[&super::Classifier]) -> Reading {
+    let r = reading(choice, allowed);
+    if choice != Choice::Auto || !r.device.is_gpu() {
+        return r;
+    }
+    #[cfg(feature = "gpu")]
+    {
+        let Some(big) = nets
+            .iter()
+            .max_by_key(|c| c.net.params().iter().map(|(_, p)| p.len()).sum::())
+        else {
+            return r;
+        };
+        match super::speed::of(big, r.device) {
+            Ok(s) if s.gpu_faster() => Reading {
+                speed: Some(Box::new(s)),
+                ..r
+            },
+            Ok(s) => Reading {
+                note: Some(s.words()),
+                speed: Some(Box::new(s)),
+                ..Reading::cpu(choice, None)
+            },
+            Err(e) => Reading::cpu(
+                choice,
+                Some(format!("measuring the GPU failed ({e}), so the CPU reads")),
+            ),
+        }
+    }
+    #[cfg(not(feature = "gpu"))]
+    {
+        let _ = nets;
+        r
+    }
+}
+
+/// where reading runs for `choice`; `allowed` is false where the GPU isn't to be used (a
+/// shared hub without `--gpu`)
+pub fn reading(choice: Choice, allowed: bool) -> Reading {
+    if choice == Choice::Cpu {
+        return Reading::cpu(choice, None);
+    }
+    if !allowed {
+        return Reading::cpu(choice, Some("this hub reads on its CPU".into()));
+    }
+    let want = if choice == Choice::GpuFast {
+        Device::GpuFast
+    } else {
+        Device::Gpu
+    };
+    if let Err(e) = want.check() {
+        let note = match choice {
+            Choice::Auto => format!("no GPU: {e}; so the CPU reads"),
+            _ => format!("no GPU here: {e}; read on the CPU"),
+        };
+        return Reading::cpu(choice, Some(note));
+    }
+    #[cfg(feature = "gpu")]
+    {
+        let g = match super::gpu::shared() {
+            Ok(g) => g,
+            Err(e) => return Reading::cpu(choice, Some(format!("no GPU here: {e}; read on the CPU"))),
+        };
+        let name = g.describe();
+        let exact = want == Device::Gpu && probe_exact().unwrap_or(false);
+        if choice == Choice::Auto {
+            // a software renderer runs on the CPU and is always the slower; measuring it
+            // would only cost time (`ANEND_AUTO_SOFTWARE_GPU=1` measures it anyway)
+            let software_ok = std::env::var("ANEND_AUTO_SOFTWARE_GPU").is_ok_and(|v| v == "1");
+            if g.info.device_type == wgpu::DeviceType::Cpu && !software_ok {
+                return Reading::cpu(
+                    choice,
+                    Some(format!("the only GPU is a software renderer, {name}, so the CPU reads")),
+                );
+            }
+            if !exact {
+                return Reading::cpu(
+                    choice,
+                    Some(format!(
+                        "{name} isn't bit-exact on every kernel, so the CPU reads (choose the GPU to use it anyway)"
+                    )),
+                );
+            }
+        }
+        Reading {
+            choice,
+            device: want,
+            exact,
+            gpu: Some(name),
+            note: None,
+            speed: None,
+        }
+    }
+    #[cfg(not(feature = "gpu"))]
+    {
+        unreachable!("checked")
+    }
+}
+
+/// nets on the device for reading, kept between calls: uploading a net's weights costs
+/// more than reading a few texts with it. Keyed by the caller's name for the net and a
+/// fingerprint of its weights, so a retrained net is uploaded again.
+pub fn runner(key: &str, device: Device, net: &Net) -> Result>, String> {
+    if !device.is_gpu() {
+        return Ok(None);
+    }
+    #[cfg(feature = "gpu")]
+    {
+        use std::collections::HashMap;
+        use std::sync::{Arc, Mutex};
+        type Kept = Mutex>>;
+        static KEPT: std::sync::OnceLock = std::sync::OnceLock::new();
+        let kept = KEPT.get_or_init(Default::default);
+        let k = (key.to_string(), fingerprint(net), device);
+        if let Some(r) = kept.lock().unwrap_or_else(|e| e.into_inner()).get(&k) {
+            return Ok(Some(r.clone()));
+        }
+        let r = Arc::new(Runner::open(device, net)?.expect("a GPU device"));
+        let mut all = kept.lock().unwrap_or_else(|e| e.into_inner());
+        // a few nets at a time: the rest are uploaded again when next used
+        if all.len() >= 16 {
+            all.clear();
+        }
+        all.insert(k, r.clone());
+        Ok(Some(r))
+    }
+    #[cfg(not(feature = "gpu"))]
+    {
+        let _ = (key, net);
+        unreachable!("checked")
+    }
+}
+
+/// a cheap hash of a net's shapes and a sample of its weights (every 61st value of each
+/// tensor, and its last)
+#[cfg(feature = "gpu")]
+fn fingerprint(net: &Net) -> u64 {
+    let mut h: u64 = 0xcbf2_9ce4_8422_2325;
+    let mut eat = |v: u64| {
+        h ^= v;
+        h = h.wrapping_mul(0x0100_0000_01b3);
+    };
+    for (_, p) in net.params() {
+        eat(p.len() as u64);
+        for v in p.iter().step_by(61).chain(p.last()) {
+            eat(v.to_bits() as u64);
+        }
+    }
+    h
+}
+
+/// a decoder for `net` on the runner's device, or on the CPU without one
+pub fn decoder<'a>(
+    runner: Option<&'a Runner>,
+    net: &'a Net,
+    gains: super::model::Gains,
+    prompt: &[u8],
+) -> Box {
+    match runner {
+        Some(r) => r.decoder(net, gains, prompt),
+        None => Box::new(super::model::Decoder::new(net, gains, prompt)),
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn devices_parse_and_the_gpu_needs_the_feature() {
+        let d: Device = serde_json::from_str("\"gpu_fast\"").unwrap();
+        assert_eq!(d, Device::GpuFast);
+        assert_eq!(Device::default(), Device::Cpu);
+        assert!(Device::Cpu.check().is_ok());
+        #[cfg(not(feature = "gpu"))]
+        assert!(Device::Gpu.check().unwrap_err().contains("feature"));
+    }
+}
diff --git a/core/src/classify/generate.rs b/core/src/classify/generate.rs
new file mode 100644
index 00000000..abae2d67
--- /dev/null
+++ b/core/src/classify/generate.rs
@@ -0,0 +1,950 @@
+//! Generation, and generation shaped by classifiers ("the skinner box").
+//!
+//! A model with a generative head (`Net::generator`, causal) writes bytes one at a time
+//! through `Decoder`. `sample` picks each byte greedily or by temperature, top-k and
+//! top-p from a random stream keyed by (seed, candidate index), so the same seed gives
+//! the same bytes on any thread count and CPU.
+//!
+//! Critics are other models (any `Judge`: a classifier, a node of a `Graph`, a stored
+//! stack) each with what is wanted of one of its heads and a weight. `generate` draws
+//! candidates, scores each by every critic, drops those breaking the `Constraints`
+//! (must / must-not classes, sum ranges, length, bytes that must or mustn't appear) and
+//! ranks the rest. `Guidance` reweights the top next bytes during sampling by the
+//! critics' scores of the prefix extended by each. `reinforce` closes the loop: the
+//! generator is fine-tuned on samples weighted by reward (critic scores relative to
+//! their mean, or a person's yes/no): likelihood for good ones, unlikelihood for bad.
+
+use serde::{Deserialize, Serialize};
+
+use super::Classifier;
+use super::compose::Graph;
+use super::device::{self, Device, Runner};
+use super::kernels::softmax_rows;
+use super::math::{self, Rng, key};
+use super::pool::{self, Pool};
+use super::steer::Output;
+use super::train::{self, Example, FeedbackOpts, Target};
+
+// ---------------------------------------------------------------- sampling
+
+/// how each next byte is picked
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(default)]
+#[serde(deny_unknown_fields)]
+pub struct Sampling {
+    /// 0 picks the most likely byte (greedy); otherwise logits are divided by it
+    pub temperature: f32,
+    /// keep only the k most likely bytes (0: all)
+    pub top_k: usize,
+    /// keep the fewest most likely bytes whose probabilities reach p (1: all)
+    pub top_p: f32,
+    /// bytes to write at most (the prompt not counted)
+    pub max_len: usize,
+    /// a byte that ends the output (kept in it); END always ends it
+    pub stop: Option,
+    pub seed: u64,
+}
+
+impl Default for Sampling {
+    fn default() -> Sampling {
+        Sampling {
+            temperature: 0.8,
+            top_k: 0,
+            top_p: 0.95,
+            max_len: 200,
+            stop: None,
+            seed: 0,
+        }
+    }
+}
+
+impl Sampling {
+    pub fn greedy(max_len: usize) -> Sampling {
+        Sampling {
+            temperature: 0.0,
+            max_len,
+            ..Sampling::default()
+        }
+    }
+
+    pub fn check(&self) -> Result<(), String> {
+        if !(self.temperature >= 0.0 && self.temperature.is_finite()) {
+            return Err("temperature must be 0 or more".into());
+        }
+        if !(self.top_p > 0.0 && self.top_p <= 1.0) {
+            return Err("top_p must be in (0, 1]".into());
+        }
+        Ok(())
+    }
+}
+
+/// picks a next token (an index into the logits) from them; `adjust` (if any) is added to the
+/// scaled logits of the candidates it names. Ties go to the lower token.
+pub fn pick(logits: &[f32], s: &Sampling, r: &mut Rng) -> usize {
+    if s.temperature == 0.0 {
+        return argmax(logits);
+    }
+    let z: Vec = logits.iter().map(|l| l / s.temperature).collect();
+    let mut order: Vec = (0..z.len()).collect();
+    order.sort_by(|&a, &b| z[b].total_cmp(&z[a]).then(a.cmp(&b)));
+    if s.top_k > 0 {
+        order.truncate(s.top_k);
+    }
+    let mut p: Vec = order.iter().map(|&i| z[i]).collect();
+    let w = p.len();
+    softmax_rows(&mut p, w);
+    if s.top_p < 1.0 {
+        let mut acc = 0f32;
+        let mut keep = p.len();
+        for (i, &v) in p.iter().enumerate() {
+            acc += v;
+            if acc >= s.top_p {
+                keep = i + 1;
+                break;
+            }
+        }
+        order.truncate(keep);
+        p.truncate(keep);
+        let t: f32 = p.iter().sum();
+        p.iter_mut().for_each(|v| *v /= t);
+    }
+    let u = r.unit();
+    let mut acc = 0f32;
+    for (i, &v) in p.iter().enumerate() {
+        acc += v;
+        if u < acc {
+            return order[i];
+        }
+    }
+    *order.last().expect("at least one")
+}
+
+fn argmax(v: &[f32]) -> usize {
+    let mut best = 0;
+    for (i, &x) in v.iter().enumerate() {
+        if x > v[best] {
+            best = i;
+        }
+    }
+    best
+}
+
+/// ln softmax(logits)[i]
+fn log_prob(logits: &[f32], i: usize) -> f32 {
+    let m = logits.iter().fold(f32::NEG_INFINITY, |a, &b| a.max(b));
+    let e: Vec = logits.iter().map(|&l| math::exp(l - m)).collect();
+    (logits[i] - m) - math::ln(super::kernels::sum(&e))
+}
+
+/// one sample: the written bytes (prompt excluded) and their log-probability under the
+/// generator (unguided, temperature 1). `index` keys the random stream.
+pub fn sample(generator: &Classifier, prompt: &[u8], s: &Sampling, index: u64) -> (Vec, f32) {
+    sample_guided(generator, prompt, s, index, None, None)
+}
+
+/// `sample` decoding on the runner's device (the CPU without one)
+pub fn sample_on(
+    generator: &Classifier,
+    prompt: &[u8],
+    s: &Sampling,
+    index: u64,
+    runner: Option<&Runner>,
+) -> (Vec, f32) {
+    sample_guided(generator, prompt, s, index, None, runner)
+}
+
+/// reweights scaled next-byte logits in place, given the bytes written so far
+type Guide<'a> = &'a dyn Fn(&[u8], &mut [f32]);
+
+fn sample_guided(
+    generator: &Classifier,
+    prompt: &[u8],
+    s: &Sampling,
+    index: u64,
+    guide: Option,
+    runner: Option<&Runner>,
+) -> (Vec, f32) {
+    let mut r = Rng::new(key(&[s.seed, index, 0x5a3e]));
+    let net = &generator.net;
+    let mut dec = device::decoder(runner, net, generator.gains(), prompt);
+    let mut out = Vec::new();
+    let mut logp = 0f32;
+    while out.len() < s.max_len {
+        let mut l = dec.logits().to_vec();
+        let base = l.clone();
+        if let Some(g) = guide {
+            g(&out, &mut l);
+        }
+        let t = pick(&l, s, &mut r);
+        logp += log_prob(&base, t);
+        if net.ends(t) {
+            break;
+        }
+        let piece = net.index_bytes(t);
+        if let Some(i) = s.stop.and_then(|stop| piece.iter().position(|&b| b == stop)) {
+            out.extend_from_slice(&piece[..=i]);
+            break;
+        }
+        out.extend(piece);
+        dec.push_token(t as u32);
+    }
+    // a vocabulary token can end past the limit
+    out.truncate(s.max_len);
+    (out, logp)
+}
+
+// ---------------------------------------------------------------- critics
+
+/// anything that reads bytes into steered head outputs
+pub trait Judge: Sync {
+    fn judge(&self, data: &[u8]) -> Vec;
+}
+
+impl Judge for Classifier {
+    fn judge(&self, data: &[u8]) -> Vec {
+        self.predict_bytes(data, &vec![0.0; self.net.cfg.extra], None)
+    }
+}
+
+/// one node of a graph of classifiers, its upstream run first
+pub struct Node<'a> {
+    pub graph: &'a Graph,
+    pub node: usize,
+}
+
+impl Judge for Node<'_> {
+    fn judge(&self, data: &[u8]) -> Vec {
+        self.graph.predict(self.node, &String::from_utf8_lossy(data))
+    }
+}
+
+impl Judge for crate::classifiers::Stack {
+    fn judge(&self, data: &[u8]) -> Vec {
+        self.graph.predict(self.node, &String::from_utf8_lossy(data))
+    }
+}
+
+/// what a critic wants of its head, as a score in [0, 1]
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub enum Want {
+    /// the class's (or label's) probability
+    Class(usize),
+    /// one minus it
+    Not(usize),
+    /// a regression value near `value`: exp(−|v − value| / scale)
+    Near { index: usize, value: f32, scale: f32 },
+    /// a regression value in [lo, hi]: 1 inside, exp(−distance / scale) outside
+    Range { index: usize, lo: f32, hi: f32, scale: f32 },
+}
+
+impl Want {
+    pub fn score(&self, o: &Output) -> f32 {
+        let get = |i: usize| o.probs.get(i).copied().unwrap_or(0.0);
+        match *self {
+            Want::Class(c) => get(c),
+            Want::Not(c) => 1.0 - get(c),
+            Want::Near { index, value, scale } => math::exp(-(get(index) - value).abs() / scale.max(1e-6)),
+            Want::Range { index, lo, hi, scale } => {
+                let v = get(index);
+                let d = if v < lo {
+                    lo - v
+                } else if v > hi {
+                    v - hi
+                } else {
+                    0.0
+                };
+                math::exp(-d / scale.max(1e-6))
+            }
+        }
+    }
+}
+
+/// a model judging candidates
+pub struct Critic<'a> {
+    pub judge: &'a dyn Judge,
+    pub head: usize,
+    pub want: Want,
+    pub weight: f32,
+}
+
+impl<'a> Critic<'a> {
+    pub fn new(judge: &'a dyn Judge, head: usize, want: Want, weight: f32) -> Critic<'a> {
+        Critic {
+            judge,
+            head,
+            want,
+            weight,
+        }
+    }
+}
+
+/// a running sum a constraint can bound; written as docs/models.md has it (`bytes`,
+/// `bytes_reversed`, ...), and read in the names specs had before too (`Bytes`, ...)
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum Measure {
+    /// Σ (byte + 1), `crate::measure`
+    #[serde(alias = "Bytes")]
+    Bytes,
+    /// Σ (256 − byte)
+    #[serde(alias = "BytesReversed")]
+    BytesReversed,
+    /// letter sums a = 1 .. z = 26 and reversed, `crate::simd`
+    #[serde(alias = "Ordinal")]
+    Ordinal,
+    #[serde(alias = "Reversed")]
+    Reversed,
+    /// the number of bytes
+    #[serde(alias = "Length")]
+    Length,
+}
+
+impl Measure {
+    pub fn of(self, data: &[u8]) -> u64 {
+        match self {
+            Measure::Bytes => crate::measure::byte_sums(data).bytes,
+            Measure::BytesReversed => crate::measure::byte_sums(data).reversed,
+            Measure::Ordinal => crate::simd::sums(data).ordinal,
+            Measure::Reversed => crate::simd::sums(data).reversed,
+            Measure::Length => data.len() as u64,
+        }
+    }
+}
+
+/// a critic's verdict that must (or must not) hold: `class` among its head's members
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(deny_unknown_fields)]
+pub struct Gate {
+    pub critic: usize,
+    pub class: usize,
+    pub member: bool,
+}
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(deny_unknown_fields)]
+pub struct SumRange {
+    pub measure: Measure,
+    pub lo: u64,
+    pub hi: u64,
+    /// compare the sum modulo this (0: the sum itself)
+    #[serde(default)]
+    pub modulo: u64,
+}
+
+/// what a kept candidate must satisfy
+#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
+#[serde(default)]
+#[serde(deny_unknown_fields)]
+pub struct Constraints {
+    pub min_len: usize,
+    /// 0: no limit
+    pub max_len: usize,
+    pub gates: Vec,
+    pub sums: Vec,
+    pub contains: Vec>,
+    pub excludes: Vec>,
+}
+
+fn has(data: &[u8], pat: &[u8]) -> bool {
+    pat.is_empty() || data.windows(pat.len()).any(|w| w == pat)
+}
+
+impl Constraints {
+    /// the constraints a candidate breaks, in words (empty: it passes)
+    pub fn broken(&self, data: &[u8], outs: &[Vec]) -> Vec {
+        let mut v = Vec::new();
+        if data.len() < self.min_len {
+            v.push(format!("shorter than {}", self.min_len));
+        }
+        if self.max_len > 0 && data.len() > self.max_len {
+            v.push(format!("longer than {}", self.max_len));
+        }
+        for g in &self.gates {
+            let member = outs
+                .get(g.critic)
+                .is_some_and(|o| o.first().is_some_and(|o| o.members.contains(&g.class)));
+            if member != g.member {
+                v.push(format!(
+                    "critic {} {} class {}",
+                    g.critic,
+                    if g.member { "lacks" } else { "has" },
+                    g.class
+                ));
+            }
+        }
+        for s in &self.sums {
+            let mut x = s.measure.of(data);
+            if s.modulo > 0 {
+                x %= s.modulo;
+            }
+            if x < s.lo || x > s.hi {
+                v.push(format!("{:?} {x} outside {}..={}", s.measure, s.lo, s.hi));
+            }
+        }
+        for p in &self.contains {
+            if !has(data, p) {
+                v.push(format!("lacks {:?}", String::from_utf8_lossy(p)));
+            }
+        }
+        for p in &self.excludes {
+            if !p.is_empty() && has(data, p) {
+                v.push(format!("has {:?}", String::from_utf8_lossy(p)));
+            }
+        }
+        v
+    }
+}
+
+/// sampling-time steering by the critics
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(default)]
+pub struct Guidance {
+    /// how many of the generator's most likely next bytes the critics weigh; the rest
+    /// are dropped on guided steps
+    pub top_k: usize,
+    /// added to each weighed byte's scaled logit: strength × Σ weight·ln(score)
+    pub strength: f32,
+    /// guide every n-th byte (1: every byte); critics cost a pass each per weighed byte
+    pub every: usize,
+}
+
+impl Default for Guidance {
+    fn default() -> Guidance {
+        Guidance {
+            top_k: 4,
+            strength: 2.0,
+            every: 1,
+        }
+    }
+}
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(default)]
+pub struct GenOpts {
+    pub prompt: Vec,
+    pub sampling: Sampling,
+    /// candidates drawn
+    pub candidates: usize,
+    /// candidates returned at most (0: all that pass)
+    pub keep: usize,
+    pub guidance: Option,
+    /// critics see the prompt too (for continuations); otherwise only the written bytes
+    pub judge_prompt: bool,
+    /// 0 for every core
+    pub threads: usize,
+    /// where the generator decodes (the CPU unless asked; critics stay on the CPU)
+    pub device: Device,
+}
+
+impl Default for GenOpts {
+    fn default() -> GenOpts {
+        GenOpts {
+            prompt: Vec::new(),
+            sampling: Sampling::default(),
+            candidates: 8,
+            keep: 0,
+            guidance: None,
+            judge_prompt: false,
+            threads: 0,
+            device: Device::Cpu,
+        }
+    }
+}
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct Candidate {
+    /// the draw's index (its random stream)
+    pub index: u64,
+    /// the written bytes (no prompt)
+    pub bytes: Vec,
+    /// per critic, its score in [0, 1]
+    pub scores: Vec,
+    /// Σ weight·ln(score) over Σ weight (0 without critics)
+    pub score: f32,
+    /// the generator's log-probability of the bytes
+    pub logp: f32,
+    /// constraints broken (empty: kept)
+    pub broken: Vec,
+}
+
+impl Candidate {
+    pub fn text(&self) -> String {
+        String::from_utf8_lossy(&self.bytes).into_owned()
+    }
+
+    pub fn passed(&self) -> bool {
+        self.broken.is_empty()
+    }
+}
+
+fn combine(critics: &[Critic], scores: &[f32]) -> f32 {
+    let wsum: f32 = critics.iter().map(|c| c.weight).sum();
+    if wsum <= 0.0 {
+        return 0.0;
+    }
+    let s: f32 = critics
+        .iter()
+        .zip(scores)
+        .map(|(c, &v)| c.weight * math::ln(v.max(1e-6)))
+        .sum();
+    s / wsum
+}
+
+/// every critic's outputs and score on some bytes
+fn judge_all(critics: &[Critic], data: &[u8]) -> (Vec>, Vec) {
+    let outs: Vec> = critics.iter().map(|c| c.judge.judge(data)).collect();
+    let scores = critics
+        .iter()
+        .zip(&outs)
+        .map(|(c, o)| o.get(c.head).map_or(0.0, |o| c.want.score(o)))
+        .collect();
+    (outs, scores)
+}
+
+/// draws `opts.candidates` candidates in parallel and judges them all; each candidate
+/// is a function of (generator, critics, opts, its index) only, so the thread count
+/// changes nothing
+pub fn draw(
+    generator: &Classifier,
+    critics: &[Critic],
+    c: &Constraints,
+    opts: &GenOpts,
+) -> Result, String> {
+    opts.sampling.check()?;
+    if generator.net.generator.is_none() {
+        return Err("the model has no generative head".into());
+    }
+    let pool = Pool::new(if opts.threads == 0 {
+        pool::available()
+    } else {
+        opts.threads
+    });
+    // the generator on the device, when asked (one upload shared by every candidate)
+    let runner = Runner::open(opts.device, &generator.net)?;
+    let one = |i: u64| -> Candidate {
+        let shown = |out: &[u8]| -> Vec {
+            if opts.judge_prompt {
+                [&opts.prompt[..], out].concat()
+            } else {
+                out.to_vec()
+            }
+        };
+        let guide = |out: &[u8], l: &mut [f32]| {
+            let Some(g) = &opts.guidance else { return };
+            if critics.is_empty() || !out.len().is_multiple_of(g.every.max(1)) {
+                return;
+            }
+            let net = &generator.net;
+            let mut order: Vec = (0..l.len()).collect();
+            order.sort_by(|&a, &b| l[b].total_cmp(&l[a]).then(a.cmp(&b)));
+            order.truncate(g.top_k.max(1));
+            let mut adj = vec![f32::NEG_INFINITY; l.len()];
+            for &t in &order {
+                let ext = if net.ends(t) {
+                    out.to_vec()
+                } else {
+                    [out, &net.index_bytes(t)[..]].concat()
+                };
+                let (_, sc) = judge_all(critics, &shown(&ext));
+                // the scaled logit is raised by strength·score, so temperature still applies
+                adj[t] = l[t] + g.strength * combine(critics, &sc) * opts.sampling.temperature.max(1e-3);
+            }
+            l.copy_from_slice(&adj);
+        };
+        let (bytes, logp) = sample_guided(
+            generator,
+            &opts.prompt,
+            &opts.sampling,
+            i,
+            if opts.guidance.is_some() { Some(&guide) } else { None },
+            runner.as_ref(),
+        );
+        let seen = shown(&bytes);
+        let (outs, scores) = judge_all(critics, &seen);
+        Candidate {
+            index: i,
+            score: combine(critics, &scores),
+            broken: c.broken(&seen, &outs),
+            bytes,
+            scores,
+            logp,
+        }
+    };
+    let slots: Vec>> = (0..opts.candidates).map(|_| Default::default()).collect();
+    pool.run(opts.candidates, &|i| *slots[i].lock().unwrap() = Some(one(i as u64)));
+    Ok(slots.into_iter().map(|s| s.into_inner().unwrap().unwrap()).collect())
+}
+
+/// the candidates that pass the constraints, best score first (ties: lower index)
+pub fn generate(
+    generator: &Classifier,
+    critics: &[Critic],
+    c: &Constraints,
+    opts: &GenOpts,
+) -> Result, String> {
+    let mut v: Vec = draw(generator, critics, c, opts)?
+        .into_iter()
+        .filter(|c| c.passed())
+        .collect();
+    v.sort_by(|a, b| b.score.total_cmp(&a.score).then(a.index.cmp(&b.index)));
+    if opts.keep > 0 {
+        v.truncate(opts.keep);
+    }
+    Ok(v)
+}
+
+// ---------------------------------------------------------------- reinforcement
+
+/// a sample with how good it was: above 0 is learned toward (likelihood, weighted by
+/// the reward), below 0 away from (unlikelihood, weighted by −reward)
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct Rewarded {
+    pub prompt: Vec,
+    pub bytes: Vec,
+    pub reward: f32,
+}
+
+impl Rewarded {
+    /// a person's yes on a sample
+    pub fn yes(bytes: &[u8]) -> Rewarded {
+        Rewarded {
+            prompt: Vec::new(),
+            bytes: bytes.to_vec(),
+            reward: 1.0,
+        }
+    }
+
+    pub fn no(bytes: &[u8]) -> Rewarded {
+        Rewarded {
+            reward: -1.0,
+            ..Rewarded::yes(bytes)
+        }
+    }
+}
+
+/// rewards from critic scores: each candidate's score minus the mean score (so the
+/// better half is learned toward, the worse half away from), times `scale`; candidates
+/// that broke constraints get −scale
+pub fn rewards(cands: &[Candidate], prompt: &[u8], scale: f32) -> Vec {
+    let ok: Vec<&Candidate> = cands.iter().filter(|c| c.passed()).collect();
+    let mean = if ok.is_empty() {
+        0.0
+    } else {
+        ok.iter().map(|c| c.score).sum::() / ok.len() as f32
+    };
+    cands
+        .iter()
+        .map(|c| Rewarded {
+            prompt: prompt.to_vec(),
+            bytes: c.bytes.clone(),
+            reward: if c.passed() { (c.score - mean) * scale } else { -scale },
+        })
+        .collect()
+}
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(default)]
+pub struct ReinforceOpts {
+    pub steps: usize,
+    pub lr: f32,
+    /// rewards with a smaller magnitude are skipped
+    pub min_reward: f32,
+    /// weight of the replayed examples (the generator's own training texts, which keep
+    /// it from drifting off its data)
+    pub replay_weight: f32,
+    /// replayed examples per step
+    pub replay: usize,
+    pub freeze_trunk: bool,
+    pub clip: f32,
+    pub seed: u64,
+    pub threads: usize,
+}
+
+impl Default for ReinforceOpts {
+    fn default() -> ReinforceOpts {
+        ReinforceOpts {
+            steps: 8,
+            lr: 3e-4,
+            min_reward: 1e-3,
+            replay_weight: 0.5,
+            replay: 8,
+            freeze_trunk: false,
+            clip: 1.0,
+            seed: 0,
+            threads: 0,
+        }
+    }
+}
+
+#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
+pub struct ReinforceReport {
+    /// mean nats per byte of the rewarded (>0) samples, before and after
+    pub good_before: f64,
+    pub good_after: f64,
+    /// the same for the penalised (<0) samples
+    pub bad_before: f64,
+    pub bad_after: f64,
+    pub losses: Vec,
+    pub used: usize,
+}
+
+fn mean_nll(generator: &Classifier, s: &[&Rewarded]) -> f64 {
+    let (mut n, mut c) = (0f64, 0usize);
+    for r in s {
+        let data = [&r.prompt[..], &r.bytes[..]].concat();
+        let (a, b) = train::nll(generator, &data, r.prompt.len());
+        n += a;
+        c += b;
+    }
+    if c == 0 { 0.0 } else { n / c as f64 }
+}
+
+/// fine-tunes the generator on rewarded samples (reward-weighted likelihood, and
+/// unlikelihood for negative rewards), with `replay` texts mixed in
+pub fn reinforce(
+    generator: &mut Classifier,
+    samples: &[Rewarded],
+    replay: &[Example],
+    o: &ReinforceOpts,
+) -> Result {
+    let used: Vec<&Rewarded> = samples.iter().filter(|s| s.reward.abs() >= o.min_reward).collect();
+    let good: Vec<&Rewarded> = used.iter().copied().filter(|s| s.reward > 0.0).collect();
+    let bad: Vec<&Rewarded> = used.iter().copied().filter(|s| s.reward < 0.0).collect();
+    let mut data: Vec = used
+        .iter()
+        .map(|s| {
+            let from = s.prompt.len();
+            let t = if s.reward > 0.0 {
+                Target::Next { from }
+            } else {
+                Target::Avoid { from }
+            };
+            Example::bytes(&[&s.prompt[..], &s.bytes[..]].concat(), 0, t).weighted(s.reward.abs())
+        })
+        .collect();
+    let fresh = data.len();
+    data.extend(replay.iter().map(|e| e.clone().weighted(e.weight * o.replay_weight)));
+    let mut rep = ReinforceReport {
+        good_before: mean_nll(generator, &good),
+        bad_before: mean_nll(generator, &bad),
+        used: fresh,
+        ..ReinforceReport::default()
+    };
+    if fresh > 0 {
+        let fo = FeedbackOpts {
+            steps: o.steps,
+            lr: o.lr,
+            replay: o.replay,
+            freeze_trunk: o.freeze_trunk,
+            clip: o.clip,
+            seed: o.seed,
+            threads: o.threads,
+        };
+        rep.losses = train::tune(generator, &data, fresh, &fo)?;
+    }
+    rep.good_after = mean_nll(generator, &good);
+    rep.bad_after = mean_nll(generator, &bad);
+    Ok(rep)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::classify::model::{Config, GenSpec, HeadSpec, Pooling};
+    use crate::classify::{Flow, TrainOpts};
+
+    /// a tiny generator (tests only: sizes chosen for debug-build speed)
+    pub fn tiny_generator(seed: u64) -> Classifier {
+        let cfg = Config {
+            causal: true,
+            pooling: Pooling::Mean,
+            max_len: 40,
+            stride: 19,
+            dropout: 0.0,
+            ..Config::tiny().gematria(false)
+        };
+        Classifier::with_gen(cfg, &[], Some(GenSpec::new("next")), seed).unwrap()
+    }
+
+    fn corpus() -> Vec {
+        let words = ["ab", "abc", "abcd"];
+        (0..24)
+            .map(|i| Example::generate(&format!("{}.", words[i % 3])))
+            .collect()
+    }
+
+    fn trained(threads: usize) -> Classifier {
+        let mut g = tiny_generator(3);
+        let o = TrainOpts {
+            epochs: 40,
+            batch: 8,
+            lr: 1e-2,
+            val_fraction: 0.0,
+            threads,
+            seed: 1,
+            label_smoothing: 0.0,
+            ..TrainOpts::default()
+        };
+        train::train(&mut g, &corpus(), &o, |_| Flow::Go).unwrap();
+        g
+    }
+
+    #[test]
+    fn learns_sequences_and_samples_deterministically() {
+        let g = trained(2);
+        assert_eq!(g.to_bytes(), trained(3).to_bytes(), "thread count changed the weights");
+        let (out, _) = sample(&g, b"", &Sampling::greedy(10), 0);
+        assert!(out.starts_with(b"ab"), "greedy {:?}", String::from_utf8_lossy(&out));
+        let s = Sampling {
+            temperature: 1.0,
+            top_k: 5,
+            top_p: 0.9,
+            max_len: 12,
+            stop: Some(b'.'),
+            seed: 9,
+        };
+        let a: Vec<_> = (0..6).map(|i| sample(&g, b"", &s, i)).collect();
+        let b: Vec<_> = (0..6).map(|i| sample(&g, b"", &s, i)).collect();
+        assert_eq!(a, b);
+        assert!(a.iter().all(|(o, _)| o.len() <= 12));
+        assert!(a.iter().filter(|(o, _)| o.starts_with(b"ab")).count() >= 4, "{a:?}");
+        // the sampling seed matters
+        let other: Vec<_> = (0..6)
+            .map(|i| sample(&g, b"", &Sampling { seed: 10, ..s.clone() }, i))
+            .collect();
+        assert!(a.iter().zip(&other).all(|(x, y)| x.0.len() <= 12 && y.0.len() <= 12));
+        let p = train::evaluate(&g, &corpus(), &(0..24).collect::>(), &Pool::new(1));
+        assert!(p.bits_per_byte.unwrap() < 1.5, "{:?}", p.bits_per_byte);
+    }
+
+    #[test]
+    fn critics_rank_constrain_guide_and_reinforce() {
+        let mut g = trained(1);
+        // a "critic" that likes texts containing 'd': a classifier trained on it
+        let mut critic = Classifier::new(
+            Config::tiny().gematria(false),
+            &[HeadSpec::single("d", &["no", "yes"])],
+            2,
+        )
+        .unwrap();
+        let data: Vec = (0..32)
+            .map(|i| {
+                let t = ["ab.", "abc.", "abcd.", "abd.", "cd.", "ba."][i % 6];
+                Example::class(t, t.contains('d') as usize)
+            })
+            .collect();
+        let o = TrainOpts {
+            epochs: 30,
+            batch: 8,
+            lr: 1e-2,
+            val_fraction: 0.0,
+            threads: 1,
+            ..TrainOpts::default()
+        };
+        train::train(&mut critic, &data, &o, |_| Flow::Go).unwrap();
+        assert!(critic.judge(b"abcd.")[0].probs[1] > 0.7);
+        let critics = [Critic::new(&critic, 0, Want::Class(1), 1.0)];
+        let opts = GenOpts {
+            sampling: Sampling {
+                temperature: 1.2,
+                max_len: 8,
+                stop: Some(b'.'),
+                seed: 4,
+                ..Sampling::default()
+            },
+            candidates: 12,
+            threads: 2,
+            ..GenOpts::default()
+        };
+        let all = draw(&g, &critics, &Constraints::default(), &opts).unwrap();
+        assert_eq!(
+            all,
+            draw(
+                &g,
+                &critics,
+                &Constraints::default(),
+                &GenOpts {
+                    threads: 1,
+                    ..opts.clone()
+                }
+            )
+            .unwrap()
+        );
+        let ranked = generate(&g, &critics, &Constraints::default(), &opts).unwrap();
+        assert!(ranked.windows(2).all(|w| w[0].score >= w[1].score));
+        // constraints: must contain 'd' and be at most 6 bytes
+        let c = Constraints {
+            max_len: 6,
+            contains: vec![b"d".to_vec()],
+            ..Constraints::default()
+        };
+        let kept = generate(&g, &critics, &c, &opts).unwrap();
+        assert!(kept.iter().all(|k| k.bytes.contains(&b'd') && k.bytes.len() <= 6));
+        let sums = Constraints {
+            sums: vec![SumRange {
+                measure: Measure::Length,
+                lo: 3,
+                hi: 4,
+                modulo: 0,
+            }],
+            ..Constraints::default()
+        };
+        assert!(
+            generate(&g, &critics, &sums, &opts)
+                .unwrap()
+                .iter()
+                .all(|k| (3..=4).contains(&k.bytes.len()))
+        );
+        // guidance raises the mean critic score
+        let mean = |v: &[Candidate]| v.iter().map(|c| c.scores[0]).sum::() / v.len() as f32;
+        let guided = draw(
+            &g,
+            &critics,
+            &Constraints::default(),
+            &GenOpts {
+                guidance: Some(Guidance {
+                    top_k: 4,
+                    strength: 4.0,
+                    every: 1,
+                }),
+                ..opts.clone()
+            },
+        )
+        .unwrap();
+        assert!(
+            mean(&guided) > mean(&all),
+            "guided {} plain {}",
+            mean(&guided),
+            mean(&all)
+        );
+        // reinforcement: the rewarded samples get likelier, the penalised less likely
+        let rw = rewards(&all, b"", 1.0);
+        let rep = reinforce(
+            &mut g,
+            &rw,
+            &corpus(),
+            &ReinforceOpts {
+                steps: 6,
+                lr: 3e-3,
+                threads: 1,
+                ..ReinforceOpts::default()
+            },
+        )
+        .unwrap();
+        assert!(rep.used > 0 && rep.good_after < rep.good_before, "{rep:?}");
+        assert!(rep.bad_after > rep.bad_before, "{rep:?}");
+        // a person's yes and no
+        let ro = ReinforceOpts {
+            threads: 1,
+            lr: 3e-3,
+            steps: 4,
+            ..ReinforceOpts::default()
+        };
+        let before = train::nll(&g, b"abcd.", 0);
+        reinforce(&mut g, &[Rewarded::yes(b"abcd.")], &[], &ro).unwrap();
+        assert!(train::nll(&g, b"abcd.", 0).0 < before.0);
+        let before = train::nll(&g, b"ba.", 0);
+        reinforce(&mut g, &[Rewarded::no(b"ba.")], &[], &ro).unwrap();
+        assert!(train::nll(&g, b"ba.", 0).0 > before.0);
+    }
+}
diff --git a/core/src/classify/gpu/kernels.wgsl b/core/src/classify/gpu/kernels.wgsl
new file mode 100644
index 00000000..378f0713
--- /dev/null
+++ b/core/src/classify/gpu/kernels.wgsl
@@ -0,0 +1,837 @@
+// The engine's kernels as WGSL compute shaders (native through wgpu; the same source is
+// valid WebGPU). Each mirrors a function of `kernels.rs` / `model.rs` operation for
+// operation, so that on a device that rounds every + − × ÷ √ once (IEEE, no fused
+// multiply-add) the results are the CPU's bits:
+//
+// - products: each output element is one chain in ascending contraction index, from 0
+//   (or from y for accumulating products); threads split outputs, never a chain;
+// - vector reductions: 8 lanes, element i to lane i mod 8 in order, folded as
+//   ((l0+l4)+(l1+l5)) + ((l2+l6)+(l3+l7));
+// - exp and the logistic function are `math::exp` / `math::sigmoid`, never built-ins.
+//
+// The prelude Rust puts before this file defines `mul`, `div` and `sqrtf` and the
+// constants (as hex literals, so no decimal rounding happens in the shader compiler).
+// Exact prelude: `mul` launders each product through an integer XOR with a uniform
+// zero (`p.u3.w`), so the compiler cannot fuse it into the following add, and `div` /
+// `sqrtf` are correctly rounded in integer arithmetic. Fast prelude: plain operators.
+//
+// Bindings: 0 the parameters (dynamic offset), 1..6 storage buffers of f32; a kernel
+// uses the ones it names, the rest are bound to a dummy.
+
+struct P {
+    u0: vec4,
+    u1: vec4,
+    u2: vec4,
+    u3: vec4,
+    u4: vec4,
+    f0: vec4,
+}
+
+@group(0) @binding(0) var p: P;
+@group(0) @binding(1) var b1: array;
+@group(0) @binding(2) var b2: array;
+@group(0) @binding(3) var b3: array;
+@group(0) @binding(4) var b4: array;
+@group(0) @binding(5) var b5: array;
+@group(0) @binding(6) var b6: array;
+
+// ---------------------------------------------------------------- exact arithmetic
+
+/// a / b correctly rounded (to nearest, ties to even) for normal operands and results,
+/// by long division of the significands; anything else goes to the hardware divide
+fn div_sw(a: f32, b: f32) -> f32 {
+    let ua = bitcast(a);
+    let ub = bitcast(b);
+    let ea = (ua >> 23u) & 0xffu;
+    let eb = (ub >> 23u) & 0xffu;
+    if (ea == 0u || ea == 255u || eb == 0u || eb == 255u) {
+        return a / b;
+    }
+    let sign = (ua ^ ub) & 0x80000000u;
+    let ma = (ua & 0x7fffffu) | 0x800000u;
+    let mb = (ub & 0x7fffffu) | 0x800000u;
+    var e = i32(ea) - i32(eb) + 127;
+    var rem = ma;
+    if (rem < mb) {
+        rem = rem << 1u;
+        e = e - 1;
+    }
+    var q = 0u;
+    for (var i = 0u; i < 25u; i = i + 1u) {
+        q = q << 1u;
+        if (rem >= mb) {
+            rem = rem - mb;
+            q = q | 1u;
+        }
+        rem = rem << 1u;
+    }
+    var m = q >> 1u;
+    if ((q & 1u) == 1u && (rem != 0u || (m & 1u) == 1u)) {
+        m = m + 1u;
+    }
+    if (m == 0x1000000u) {
+        m = m >> 1u;
+        e = e + 1;
+    }
+    if (e <= 0 || e >= 255) {
+        return a / b;
+    }
+    return bitcast(sign | (u32(e) << 23u) | (m & 0x7fffffu));
+}
+
+/// √x correctly rounded for positive normal x, digit by digit; anything else goes to
+/// the hardware square root
+fn sqrt_sw(x: f32) -> f32 {
+    let u = bitcast(x);
+    let ex = (u >> 23u) & 0xffu;
+    if (ex == 0u || ex == 255u || (u >> 31u) == 1u) {
+        return sqrt(x);
+    }
+    var m = (u & 0x7fffffu) | 0x800000u;
+    var e = i32(ex) - 127;
+    if ((e & 1) != 0) {
+        m = m << 1u;
+        e = e - 1;
+    }
+    // r = ⌊√(m·2^25)⌋, 25 bits, from the 50-bit radicand two bits at a time
+    var r = 0u;
+    var rem = 0u;
+    for (var i = 0u; i < 25u; i = i + 1u) {
+        let j = 49u - 2u * i;
+        var two = 0u;
+        if (j >= 25u) {
+            two = ((m >> (j - 25u)) & 1u) << 1u;
+        }
+        if (j - 1u >= 25u) {
+            two = two | ((m >> (j - 26u)) & 1u);
+        }
+        rem = (rem << 2u) | two;
+        let trial = (r << 2u) | 1u;
+        if (rem >= trial) {
+            rem = rem - trial;
+            r = (r << 1u) | 1u;
+        } else {
+            r = r << 1u;
+        }
+    }
+    var mm = r >> 1u;
+    if ((r & 1u) == 1u && (rem != 0u || (mm & 1u) == 1u)) {
+        mm = mm + 1u;
+    }
+    var be = e / 2 + 127;
+    if (mm == 0x1000000u) {
+        mm = mm >> 1u;
+        be = be + 1;
+    }
+    return bitcast((u32(be) << 23u) | (mm & 0x7fffffu));
+}
+
+// ---------------------------------------------------------------- math.rs
+
+/// x, opaque to the optimiser (an XOR with the uniform zero): stops it simplifying
+/// `(x + C) − C` to x, which the rounding trick in `expf` depends on in either precision
+fn keep(x: f32) -> f32 {
+    return bitcast(bitcast(x) ^ p.u3.w);
+}
+
+fn pow2(k: i32) -> f32 {
+    return bitcast(u32(k + 127) << 23u);
+}
+
+/// `math::exp`, operation for operation
+fn expf(x: f32) -> f32 {
+    let c = clamp(x, EXP_LO, EXP_HI);
+    let k = keep(mul(c, LOG2E) + ROUND) - ROUND;
+    let r = (c - mul(k, LN2_HI)) - mul(k, LN2_LO);
+    let q = 1.0 + mul(r, 1.0 + mul(r, 0.5 + mul(r, C6 + mul(r, C24 + mul(r, C120 + mul(r, C720 + mul(r, C5040)))))));
+    let ki = i32(k);
+    let h = ki >> 1u;
+    let v = q * pow2(h) * pow2(ki - h);
+    if (x < EXP_LO) {
+        return 0.0;
+    }
+    if (x > EXP_HI) {
+        return bitcast(0x7f800000u);
+    }
+    return v;
+}
+
+/// `math::sigmoid`
+fn sigm(x: f32) -> f32 {
+    let e = expf(-abs(x));
+    let d = 1.0 + e;
+    if (x >= 0.0) {
+        return div(1.0, d);
+    }
+    return div(e, d);
+}
+
+fn fold8(l: array) -> f32 {
+    return ((l[0] + l[4]) + (l[1] + l[5])) + ((l[2] + l[6]) + (l[3] + l[7]));
+}
+
+fn flat(wid: vec3, nw: vec3, li: u32, size: u32) -> u32 {
+    return (wid.x + wid.y * nw.x) * size + li;
+}
+
+fn neg_inf() -> f32 {
+    return bitcast(0xff800000u);
+}
+
+// ---------------------------------------------------------------- products
+
+var ta: array;
+var tb: array;
+
+// y[z][r][c] (+)= Σ_p A[z][r][p]·B[z][p][c], each element one chain in ascending p.
+// u0 (n, k, m, flags: 1 accumulate, 2 causal: p ≤ t0 + r only)
+// u1 (a_off, a_rs, a_ps, a_zs)  u2 (b_off, b_ps, b_cs, b_zs)  u3 (y_off, y_rs, y_zs, ·)
+// u4 (t0, batch, per, ·): B's batch index is z / per (grouped keys and values); b1 A, b2 B, b3 y. Tiles of 64×64 outputs, 4×4 per thread, p in
+// steps of 16 through workgroup memory (which keeps every chain in order).
+@compute @workgroup_size(16, 16)
+fn gemm(@builtin(workgroup_id) wid: vec3, @builtin(local_invocation_id) lid: vec3, @builtin(local_invocation_index) li: u32) {
+    let n = p.u0.x;
+    let k = p.u0.y;
+    let m = p.u0.z;
+    let acc_in = (p.u0.w & 1u) == 1u;
+    let causal = (p.u0.w & 2u) == 2u;
+    let t0 = p.u4.x;
+    let z = wid.z;
+    let ab = p.u1.x + z * p.u1.w;
+    let bb = p.u2.x + (z / max(p.u4.z, 1u)) * p.u2.w;
+    let yb = p.u3.x + z * p.u3.z;
+    let r0 = wid.y * 64u;
+    let c0 = wid.x * 64u;
+    var acc: array, 4>;
+    for (var i = 0u; i < 4u; i = i + 1u) {
+        for (var j = 0u; j < 4u; j = j + 1u) {
+            let r = r0 + lid.y + 16u * i;
+            let c = c0 + lid.x + 16u * j;
+            var v = 0.0;
+            if (acc_in && r < n && c < m) {
+                v = b3[yb + r * p.u3.y + c];
+            }
+            acc[i][j] = v;
+        }
+    }
+    for (var p0 = 0u; p0 < k; p0 = p0 + 16u) {
+        for (var l = 0u; l < 4u; l = l + 1u) {
+            let e = li + l * 256u;
+            let rr = e / 16u;
+            let pp = e % 16u;
+            var va = 0.0;
+            if (r0 + rr < n && p0 + pp < k) {
+                va = b1[ab + (r0 + rr) * p.u1.y + (p0 + pp) * p.u1.z];
+            }
+            ta[e] = va;
+            let pb = e / 64u;
+            let cc = e % 64u;
+            var vb = 0.0;
+            if (p0 + pb < k && c0 + cc < m) {
+                vb = b2[bb + (p0 + pb) * p.u2.y + (c0 + cc) * p.u2.z];
+            }
+            tb[e] = vb;
+        }
+        workgroupBarrier();
+        let pend = min(16u, k - p0);
+        for (var pp = 0u; pp < pend; pp = pp + 1u) {
+            var bv: array;
+            for (var j = 0u; j < 4u; j = j + 1u) {
+                bv[j] = tb[pp * 64u + lid.x + 16u * j];
+            }
+            for (var i = 0u; i < 4u; i = i + 1u) {
+                let av = ta[(lid.y + 16u * i) * 16u + pp];
+                if (!causal || p0 + pp <= t0 + r0 + lid.y + 16u * i) {
+                    for (var j = 0u; j < 4u; j = j + 1u) {
+                        acc[i][j] = acc[i][j] + mul(av, bv[j]);
+                    }
+                }
+            }
+        }
+        workgroupBarrier();
+    }
+    for (var i = 0u; i < 4u; i = i + 1u) {
+        for (var j = 0u; j < 4u; j = j + 1u) {
+            let r = r0 + lid.y + 16u * i;
+            let c = c0 + lid.x + 16u * j;
+            if (r < n && c < m) {
+                b3[yb + r * p.u3.y + c] = acc[i][j];
+            }
+        }
+    }
+}
+
+// the same product, one thread per output (few rows: decoding, the heads)
+@compute @workgroup_size(64)
+fn gemm_small(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let n = p.u0.x;
+    let k = p.u0.y;
+    let m = p.u0.z;
+    let i = flat(wid, nw, li, 64u);
+    let zc = p.u4.y;
+    if (i >= zc * n * m) {
+        return;
+    }
+    let z = i / (n * m);
+    let r = (i / m) % n;
+    let c = i % m;
+    let ab = p.u1.x + z * p.u1.w + r * p.u1.y;
+    let bb = p.u2.x + (z / max(p.u4.z, 1u)) * p.u2.w + c * p.u2.z;
+    let yi = p.u3.x + z * p.u3.z + r * p.u3.y + c;
+    var v = 0.0;
+    if ((p.u0.w & 1u) == 1u) {
+        v = b3[yi];
+    }
+    var kk = k;
+    if ((p.u0.w & 2u) == 2u) {
+        kk = min(k, p.u4.x + r + 1u);
+    }
+    for (var q = 0u; q < kk; q = q + 1u) {
+        v = v + mul(b1[ab + q * p.u1.z], b2[bb + q * p.u2.y]);
+    }
+    b3[yi] = v;
+}
+
+// causal attention scores: S[h][t][s] = dot8(q[h][t], k[h][s])·scale for s ≤ t0 + t,
+// else 0; head h reads key head h / per. u0 (n_q, width, dh, heads) u1 (q_off, q_hs, k_off, k_hs)
+// u2 (s_off, t0, per, ·)
+// f0.x scale; b1 q, b2 k, b3 S
+@compute @workgroup_size(64)
+fn scores(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let nq = p.u0.x;
+    let w = p.u0.y;
+    let dh = p.u0.z;
+    let i = flat(wid, nw, li, 64u);
+    if (i >= p.u0.w * nq * w) {
+        return;
+    }
+    let h = i / (nq * w);
+    let t = (i / w) % nq;
+    let s = i % w;
+    var v = 0.0;
+    if (s <= p.u2.y + t) {
+        let qb = p.u1.x + h * p.u1.y + t * dh;
+        let kb = p.u1.z + (h / max(p.u2.z, 1u)) * p.u1.w + s * dh;
+        var l: array;
+        for (var j = 0u; j < 8u; j = j + 1u) {
+            l[j] = 0.0;
+        }
+        for (var c = 0u; c < dh; c = c + 1u) {
+            l[c % 8u] = l[c % 8u] + mul(b1[qb + c], b2[kb + c]);
+        }
+        v = fold8(l) * p.f0.x;
+    }
+    b3[p.u2.x + i] = v;
+}
+
+// ---------------------------------------------------------------- rows of 8 lanes
+
+var red: array;
+
+fn fold_red(li: u32) -> f32 {
+    let r = (li / 8u) * 8u;
+    return ((red[r] + red[r + 4u]) + (red[r + 1u] + red[r + 5u])) + ((red[r + 2u] + red[r + 6u]) + (red[r + 3u] + red[r + 7u]));
+}
+
+// RMSNorm forward, 8 rows per workgroup, a lane per thread.
+// u0 (rows, d, x_off, y_off) u1 (trace, rstd_off, xhat_off, ·) f0.x eps;
+// b1 x, b2 g, b3 y, b4 x̂, b5 rstd
+@compute @workgroup_size(64)
+fn norm_fwd(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let rows = p.u0.x;
+    let d = p.u0.y;
+    let row = (wid.x + wid.y * nw.x) * 8u + li / 8u;
+    let lane = li % 8u;
+    let ok = row < rows;
+    let xb = p.u0.z + row * d;
+    var a = 0.0;
+    if (ok) {
+        for (var i = lane; i < d; i = i + 8u) {
+            let v = b1[xb + i];
+            a = a + mul(v, v);
+        }
+    }
+    red[li] = a;
+    workgroupBarrier();
+    let s = fold_red(li);
+    if (ok) {
+        let rs = div(1.0, sqrtf(div(s, f32(d)) + p.f0.x));
+        let tr = p.u1.x == 1u;
+        if (tr && lane == 0u) {
+            b5[p.u1.y + row] = rs;
+        }
+        for (var i = lane; i < d; i = i + 8u) {
+            let h = mul(b1[xb + i], rs);
+            if (tr) {
+                b4[p.u1.z + row * d + i] = h;
+            }
+            b3[p.u0.w + row * d + i] = mul(h, b2[i]);
+        }
+    }
+}
+
+// RMSNorm backward into dx: dx̂ = dy·g, c = dot(dx̂, x̂)/d, dx += rstd·(dx̂ − x̂·c).
+// u0 (rows, d, dy_off, xhat_off) u1 (rstd_off, dx_off, ·, ·);
+// b1 dy, b2 x̂, b3 g, b4 rstd, b5 dx
+@compute @workgroup_size(64)
+fn norm_back(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let rows = p.u0.x;
+    let d = p.u0.y;
+    let row = (wid.x + wid.y * nw.x) * 8u + li / 8u;
+    let lane = li % 8u;
+    let ok = row < rows;
+    let yb = p.u0.z + row * d;
+    let hb = p.u0.w + row * d;
+    var a = 0.0;
+    if (ok) {
+        for (var i = lane; i < d; i = i + 8u) {
+            a = a + mul(mul(b1[yb + i], b3[i]), b2[hb + i]);
+        }
+    }
+    red[li] = a;
+    workgroupBarrier();
+    let c = div(fold_red(li), f32(d));
+    if (ok) {
+        let s = b4[p.u1.x + row];
+        let xb = p.u1.y + row * d;
+        for (var i = lane; i < d; i = i + 8u) {
+            let dh = mul(b1[yb + i], b3[i]);
+            b5[xb + i] = b5[xb + i] + mul(s, dh - mul(b2[hb + i], c));
+        }
+    }
+}
+
+// dg[i] += Σ_r dy[r][i]·x̂[r][i] in row order (a column per thread); with flag 1 in
+// u1.x, dg[i] += Σ_r dy[r][i] (a bias gradient). u0 (rows, d, dy_off, xhat_off)
+// u1 (plain, dg_off, ·, ·); b1 dy, b2 x̂, b3 dg
+@compute @workgroup_size(64)
+fn col_acc(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let rows = p.u0.x;
+    let d = p.u0.y;
+    let i = flat(wid, nw, li, 64u);
+    if (i >= d) {
+        return;
+    }
+    var v = b3[p.u1.y + i];
+    if (p.u1.x == 1u) {
+        for (var r = 0u; r < rows; r = r + 1u) {
+            v = v + b1[p.u0.z + r * d + i];
+        }
+    } else {
+        for (var r = 0u; r < rows; r = r + 1u) {
+            v = v + mul(b1[p.u0.z + r * d + i], b2[p.u0.w + r * d + i]);
+        }
+    }
+    b3[p.u1.y + i] = v;
+}
+
+// softmax of rows in place: e = exp(x − max), x = e / Σe. A row's length is the width,
+// or for causal rows (u1.x = 1) min(t0 + (row mod n_q) + 1, width); the rest is left.
+// u0 (rows, width, off, ·) u1 (causal, n_q, t0, ·); b1 x
+@compute @workgroup_size(64)
+fn softmax(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let rows = p.u0.x;
+    let w = p.u0.y;
+    let row = (wid.x + wid.y * nw.x) * 8u + li / 8u;
+    let lane = li % 8u;
+    let ok = row < rows;
+    var len = w;
+    if (p.u1.x == 1u) {
+        len = min(p.u1.z + row % p.u1.y + 1u, w);
+    }
+    let base = p.u0.z + row * w;
+    var mx = neg_inf();
+    if (ok) {
+        for (var i = lane; i < len; i = i + 8u) {
+            mx = max(mx, b1[base + i]);
+        }
+    }
+    red[li] = mx;
+    workgroupBarrier();
+    let r8 = (li / 8u) * 8u;
+    var m = red[r8];
+    for (var j = 1u; j < 8u; j = j + 1u) {
+        m = max(m, red[r8 + j]);
+    }
+    workgroupBarrier();
+    var a = 0.0;
+    if (ok) {
+        for (var i = lane; i < len; i = i + 8u) {
+            let e = expf(b1[base + i] - m);
+            b1[base + i] = e;
+            a = a + e;
+        }
+    }
+    red[li] = a;
+    workgroupBarrier();
+    let s = fold_red(li);
+    if (ok) {
+        for (var i = lane; i < len; i = i + 8u) {
+            b1[base + i] = div(b1[base + i], s);
+        }
+    }
+}
+
+// softmax backward per row over the full width: dp = p·(dp − dot(p, dp)).
+// u0 (rows, width, p_off, dp_off); b1 p, b2 dp
+@compute @workgroup_size(64)
+fn softmax_back(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let rows = p.u0.x;
+    let w = p.u0.y;
+    let row = (wid.x + wid.y * nw.x) * 8u + li / 8u;
+    let lane = li % 8u;
+    let ok = row < rows;
+    let pb = p.u0.z + row * w;
+    let db = p.u0.w + row * w;
+    var a = 0.0;
+    if (ok) {
+        for (var i = lane; i < w; i = i + 8u) {
+            a = a + mul(b1[pb + i], b2[db + i]);
+        }
+    }
+    red[li] = a;
+    workgroupBarrier();
+    let c = fold_red(li);
+    if (ok) {
+        for (var i = lane; i < w; i = i + 8u) {
+            b2[db + i] = mul(b1[pb + i], b2[db + i] - c);
+        }
+    }
+}
+
+// out[r] = dot8(a[r], b[r]) over rows of length len. u0 (rows, len, ·, ·); b1 a, b2 b, b3 out
+@compute @workgroup_size(64)
+fn dot_rows(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let rows = p.u0.x;
+    let len = p.u0.y;
+    let r = flat(wid, nw, li, 64u);
+    if (r >= rows) {
+        return;
+    }
+    var l: array;
+    for (var j = 0u; j < 8u; j = j + 1u) {
+        l[j] = 0.0;
+    }
+    for (var c = 0u; c < len; c = c + 1u) {
+        l[c % 8u] = l[c % 8u] + mul(b1[r * len + c], b2[r * len + c]);
+    }
+    b3[r] = fold8(l);
+}
+
+// ---------------------------------------------------------------- elementwise
+
+// u0 (count, op, a_off, b_off) u1 (y_off, ·, ·, ·) f0.x a scalar;
+// ops: 0 y = a + b, 1 a += b, 2 a *= b, 3 a *= f, 4 a = f, 5 a = exp(a),
+// 6 y = sigmoid(a), 7 y = a / b, 8 y = √a, 9 a[i] += b[i mod width] (u1.y = width)
+@compute @workgroup_size(64)
+fn ew(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let i = flat(wid, nw, li, 64u);
+    if (i >= p.u0.x) {
+        return;
+    }
+    let ai = p.u0.z + i;
+    let bi = p.u0.w + i;
+    let yi = p.u1.x + i;
+    switch p.u0.y {
+        case 0u: { b3[yi] = b1[ai] + b2[bi]; }
+        case 1u: { b1[ai] = b1[ai] + b2[bi]; }
+        case 2u: { b1[ai] = b1[ai] * b2[bi]; }
+        case 3u: { b1[ai] = b1[ai] * p.f0.x; }
+        case 4u: { b1[ai] = p.f0.x; }
+        case 5u: { b1[ai] = expf(b1[ai]); }
+        case 6u: { b3[yi] = sigm(b1[ai]); }
+        case 7u: { b3[yi] = div(b1[ai], b2[bi]); }
+        case 8u: { b3[yi] = sqrtf(b1[ai]); }
+        case 9u: { b1[ai] = b1[ai] + b2[p.u0.w + i % p.u1.y]; }
+        default: {}
+    }
+}
+
+// SwiGLU forward: s = σ(g), act = (g·s)·u. u0 (count, ·, ·, ·); b1 g, b2 u, b3 s, b4 act
+@compute @workgroup_size(64)
+fn swiglu(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let i = flat(wid, nw, li, 64u);
+    if (i >= p.u0.x) {
+        return;
+    }
+    let g = b1[i];
+    let s = sigm(g);
+    b3[i] = s;
+    b4[i] = (g * s) * b2[i];
+}
+
+// SwiGLU backward: du = dact·(g·s), dg = (dact·u)·(s·(1 + g·(1 − s))).
+// u0 (count, ·, ·, ·); b1 dact, b2 g, b3 s, b4 u, b5 dg, b6 du
+@compute @workgroup_size(64)
+fn swiglu_back(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let i = flat(wid, nw, li, 64u);
+    if (i >= p.u0.x) {
+        return;
+    }
+    let da = b1[i];
+    let g = b2[i];
+    let s = b3[i];
+    b6[i] = da * (g * s);
+    b5[i] = (da * b4[i]) * (s * (1.0 + mul(g, 1.0 - s)));
+}
+
+// rotary positions on rows of 2·half: (a, b) → (a·c − b·s, a·s + b·c), backward the
+// transpose. Row r is position t0 + (r mod per). u0 (rows, half, off, per) u1 (t0, back, ·, ·);
+// b1 x, b2 cos, b3 sin ([positions × half])
+@compute @workgroup_size(64)
+fn rope(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let half = p.u0.y;
+    let i = flat(wid, nw, li, 64u);
+    if (i >= p.u0.x * half) {
+        return;
+    }
+    let r = i / half;
+    let j = i % half;
+    let t = p.u1.x + r % p.u0.w;
+    let xb = p.u0.z + r * 2u * half;
+    let c = b2[t * half + j];
+    let s = b3[t * half + j];
+    let a = b1[xb + j];
+    let b = b1[xb + j + half];
+    if (p.u1.y == 0u) {
+        b1[xb + j] = mul(a, c) - mul(b, s);
+        b1[xb + j + half] = mul(a, s) + mul(b, c);
+    } else {
+        b1[xb + j] = mul(a, c) + mul(b, s);
+        b1[xb + j + half] = mul(b, c) - mul(a, s);
+    }
+}
+
+// strided copy: dst[d_off + z·d_zs + r·d_rs + c] = src[s_off + z·s_zs + r·s_rs + c].
+// u0 (width, rows, zs, ·) u1 (s_off, s_zs, s_rs, ·) u2 (d_off, d_zs, d_rs, ·); b1 src, b2 dst
+@compute @workgroup_size(64)
+fn copy(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let w = p.u0.x;
+    let rows = p.u0.y;
+    let i = flat(wid, nw, li, 64u);
+    if (i >= w * rows * p.u0.z) {
+        return;
+    }
+    let c = i % w;
+    let r = (i / w) % rows;
+    let z = i / (w * rows);
+    b2[p.u2.x + z * p.u2.y + r * p.u2.z + c] = b1[p.u1.x + z * p.u1.y + r * p.u1.z + c];
+}
+
+// ---------------------------------------------------------------- packed windows of any length
+//
+// Attention over many windows of different lengths, packed one after another, in one
+// dispatch per step. b6 is the pack's table, integers held as f32 (all below 2^24): at
+// [row] the window a packed row is in, and at [u4.x + 3w] window w's first row, length
+// and the sum of the squared lengths before it. A window's queries are [head][pos][dh]
+// from H·dh·start, its keys and values [kv head][pos][dh] from KV·dh·start, its scores
+// [head][t][s] from H·(that sum); the same places the per-window dispatches use. Every
+// value is computed by the same chain as the per-window kernels (`copy`, `rope`, `gemm`
+// then `ew` scale or `scores`, `softmax`, `gemm`), so packing changes no bits.
+// u4 (table offset, H, KV, ·) everywhere below.
+
+fn w_of(row: u32) -> u32 {
+    return u32(b6[row]);
+}
+
+fn w_start(w: u32) -> u32 {
+    return u32(b6[p.u4.x + 3u * w]);
+}
+
+fn w_len(w: u32) -> u32 {
+    return u32(b6[p.u4.x + 3u * w + 1u]);
+}
+
+fn w_sq(w: u32) -> u32 {
+    return u32(b6[p.u4.x + 3u * w + 2u]);
+}
+
+// queries, keys and values out of the projected rows [n][(H + 2KV)·dh].
+// u0 (n, w3, dh, ·); b1 qkv, b2 q, b3 k, b4 v
+@compute @workgroup_size(64)
+fn split_v(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let w3 = p.u0.y;
+    let dh = p.u0.z;
+    let i = flat(wid, nw, li, 64u);
+    if (i >= p.u0.x * w3) {
+        return;
+    }
+    let hh = p.u4.y;
+    let kv = p.u4.z;
+    let r = i / w3;
+    let c = i % w3;
+    let w = w_of(r);
+    let s = w_start(w);
+    let m = w_len(w);
+    let t = r - s;
+    if (c < hh * dh) {
+        b2[hh * dh * s + (c / dh) * m * dh + t * dh + c % dh] = b1[i];
+    } else if (c < (hh + kv) * dh) {
+        let c2 = c - hh * dh;
+        b3[kv * dh * s + (c2 / dh) * m * dh + t * dh + c2 % dh] = b1[i];
+    } else {
+        let c2 = c - (hh + kv) * dh;
+        b4[kv * dh * s + (c2 / dh) * m * dh + t * dh + c2 % dh] = b1[i];
+    }
+}
+
+// rotary positions on [heads][pos][dh] rows of every window (heads = u0.z: H for queries,
+// KV for keys); a row's position is its place in its window. u0 (n, half, heads, ·);
+// b1 x, b2 cos, b3 sin
+@compute @workgroup_size(64)
+fn rope_v(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let half = p.u0.y;
+    let heads = p.u0.z;
+    let i = flat(wid, nw, li, 64u);
+    if (i >= p.u0.x * heads * half) {
+        return;
+    }
+    let r = i / half;
+    let j = i % half;
+    let w = w_of(r / heads);
+    let t = (r - heads * w_start(w)) % w_len(w);
+    let xb = r * 2u * half;
+    let c = b2[t * half + j];
+    let s = b3[t * half + j];
+    let a = b1[xb + j];
+    let b = b1[xb + j + half];
+    b1[xb + j] = mul(a, c) - mul(b, s);
+    b1[xb + j + half] = mul(a, s) + mul(b, c);
+}
+
+// scores of every window: S[h][t][s] for s < its length (u0.w = L, the longest). Not
+// causal (u0.y = 0): the product chain in ascending c, then × scale, as `gemm` then `ew`
+// 3; causal (u0.y = 1): dot8 × scale for s ≤ t, else 0, as `scores`.
+// u0 (n, causal, dh, L) u1 (per, ·, ·, ·) f0.x scale; b1 q, b2 k, b3 S
+@compute @workgroup_size(64)
+fn qk_v(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let dh = p.u0.z;
+    let ll = p.u0.w;
+    let hh = p.u4.y;
+    let kv = p.u4.z;
+    let i = flat(wid, nw, li, 64u);
+    if (i >= p.u0.x * hh * ll) {
+        return;
+    }
+    let r = i / ll;
+    let u = i % ll;
+    let w = w_of(r / hh);
+    let m = w_len(w);
+    if (u >= m) {
+        return;
+    }
+    let s0 = w_start(w);
+    let local = r - hh * s0;
+    let head = local / m;
+    let t = local % m;
+    let qb = r * dh;
+    let kb = kv * dh * s0 + (head / max(p.u1.x, 1u)) * m * dh + u * dh;
+    let out = hh * w_sq(w) + local * m + u;
+    if (p.u0.y == 0u) {
+        var v = 0.0;
+        for (var c = 0u; c < dh; c = c + 1u) {
+            v = v + mul(b1[qb + c], b2[kb + c]);
+        }
+        b3[out] = v * p.f0.x;
+    } else {
+        var v = 0.0;
+        if (u <= t) {
+            var l: array;
+            for (var j = 0u; j < 8u; j = j + 1u) {
+                l[j] = 0.0;
+            }
+            for (var c = 0u; c < dh; c = c + 1u) {
+                l[c % 8u] = l[c % 8u] + mul(b1[qb + c], b2[kb + c]);
+            }
+            v = fold8(l) * p.f0.x;
+        }
+        b3[out] = v;
+    }
+}
+
+// softmax of every window's score rows (H·n rows), as `softmax`; causal (u0.y = 1) rows
+// stop at t + 1. u0 (n, causal, ·, ·); b1 S
+@compute @workgroup_size(64)
+fn softmax_v(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let hh = p.u4.y;
+    let rows = p.u0.x * hh;
+    let row = (wid.x + wid.y * nw.x) * 8u + li / 8u;
+    let lane = li % 8u;
+    let ok = row < rows;
+    var len = 0u;
+    var base = 0u;
+    if (ok) {
+        let w = w_of(row / hh);
+        let m = w_len(w);
+        let local = row - hh * w_start(w);
+        len = m;
+        if (p.u0.y == 1u) {
+            len = min(local % m + 1u, m);
+        }
+        base = hh * w_sq(w) + local * m;
+    }
+    var mx = neg_inf();
+    if (ok) {
+        for (var i = lane; i < len; i = i + 8u) {
+            mx = max(mx, b1[base + i]);
+        }
+    }
+    red[li] = mx;
+    workgroupBarrier();
+    let r8 = (li / 8u) * 8u;
+    var m = red[r8];
+    for (var j = 1u; j < 8u; j = j + 1u) {
+        m = max(m, red[r8 + j]);
+    }
+    workgroupBarrier();
+    var a = 0.0;
+    if (ok) {
+        for (var i = lane; i < len; i = i + 8u) {
+            let e = expf(b1[base + i] - m);
+            b1[base + i] = e;
+            a = a + e;
+        }
+    }
+    red[li] = a;
+    workgroupBarrier();
+    let s = fold_red(li);
+    if (ok) {
+        for (var i = lane; i < len; i = i + 8u) {
+            b1[base + i] = div(b1[base + i], s);
+        }
+    }
+}
+
+// every window's probabilities times its values, into the packed rows of ctx [n][H·dh]:
+// one chain per output in ascending s (causal: s ≤ t), as `gemm`.
+// u0 (n, causal, dh, ·) u1 (per, ·, ·, ·); b1 S, b2 v, b3 ctx
+@compute @workgroup_size(64)
+fn pv_v(@builtin(workgroup_id) wid: vec3, @builtin(num_workgroups) nw: vec3, @builtin(local_invocation_index) li: u32) {
+    let dh = p.u0.z;
+    let hh = p.u4.y;
+    let kv = p.u4.z;
+    let aw = hh * dh;
+    let i = flat(wid, nw, li, 64u);
+    if (i >= p.u0.x * aw) {
+        return;
+    }
+    let r = i / aw;
+    let col = i % aw;
+    let head = col / dh;
+    let j = col % dh;
+    let w = w_of(r);
+    let s0 = w_start(w);
+    let m = w_len(w);
+    let t = r - s0;
+    let pb = hh * w_sq(w) + head * m * m + t * m;
+    let vb = kv * dh * s0 + (head / max(p.u1.x, 1u)) * m * dh + j;
+    var kk = m;
+    if (p.u0.y == 1u) {
+        kk = min(m, t + 1u);
+    }
+    var v = 0.0;
+    for (var u = 0u; u < kk; u = u + 1u) {
+        v = v + mul(b1[pb + u], b2[vb + u * dh]);
+    }
+    b3[i] = v;
+}
diff --git a/core/src/classify/gpu/mod.rs b/core/src/classify/gpu/mod.rs
new file mode 100644
index 00000000..5b0a22f2
--- /dev/null
+++ b/core/src/classify/gpu/mod.rs
@@ -0,0 +1,1125 @@
+//! The GPU compute backend (cargo feature `gpu`): the engine's kernels as WGSL compute
+//! shaders run through wgpu (Vulkan, Metal, DX12, GL natively; the same WGSL is valid
+//! WebGPU, so a browser build can use it later).
+//!
+//! - [`Gpu`]: a device and queue, the shader module in two precisions, buffers, and
+//!   [`Run`], which records a list of kernel dispatches and submits them at once.
+//! - [`net::GpuNet`]: a [`Net`](super::Net)'s trunk resident on the device — forward
+//!   (inference and training), the generative head, a KV-cache decoder, and backward.
+//! - [`probe`]: runs every kernel on random data on the device and on the CPU and reports
+//!   whether the device matched bit for bit.
+//!
+//! The CPU path stays the reference. Shaders follow its operation order exactly (see
+//! `kernels.wgsl`), so on a device that rounds each operation once the results are the
+//! CPU's bits; whether a device does is a measured fact ([`probe`]), not an assumption.
+//! [`Precision::Exact`] guards against the usual differences (fused multiply-adds,
+//! approximate division and square root) at some cost; [`Precision::Fast`] uses the
+//! plain operators and stays within a small tolerance of the CPU.
+
+pub mod net;
+pub mod probe;
+#[cfg(test)]
+pub(crate) mod tests;
+pub mod train;
+
+use std::collections::HashMap;
+use std::sync::{Mutex, OnceLock};
+
+use wgpu::util::DeviceExt;
+
+/// how the shaders do their arithmetic
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default, serde::Serialize, serde::Deserialize)]
+#[serde(rename_all = "lowercase")]
+pub enum Precision {
+    /// every product laundered so it cannot fuse into an add, division and square root
+    /// correctly rounded in integer arithmetic: the CPU's bits on an IEEE device
+    #[default]
+    Exact,
+    /// plain operators: the driver may fuse multiply-adds and approximate ÷ and √
+    Fast,
+}
+
+/// counters of what the device was asked to do, for profiling (`gpu_profile`): read
+/// with [`Profile::take`]
+#[derive(Default)]
+pub struct Profile {
+    pub buffers: std::sync::atomic::AtomicU64,
+    pub buffer_bytes: std::sync::atomic::AtomicU64,
+    pub uploads: std::sync::atomic::AtomicU64,
+    pub dispatches: std::sync::atomic::AtomicU64,
+    pub bind_groups: std::sync::atomic::AtomicU64,
+    pub submits: std::sync::atomic::AtomicU64,
+    pub reads: std::sync::atomic::AtomicU64,
+    /// nanoseconds building command buffers (bind groups, passes), waiting for the
+    /// device, and copying results out of mapped memory
+    pub ns_encode: std::sync::atomic::AtomicU64,
+    /// nanoseconds making buffers and writing into them
+    pub ns_upload: std::sync::atomic::AtomicU64,
+    pub ns_wait: std::sync::atomic::AtomicU64,
+    pub ns_readback: std::sync::atomic::AtomicU64,
+}
+
+pub static PROFILE: Profile = Profile {
+    buffers: std::sync::atomic::AtomicU64::new(0),
+    buffer_bytes: std::sync::atomic::AtomicU64::new(0),
+    uploads: std::sync::atomic::AtomicU64::new(0),
+    dispatches: std::sync::atomic::AtomicU64::new(0),
+    bind_groups: std::sync::atomic::AtomicU64::new(0),
+    submits: std::sync::atomic::AtomicU64::new(0),
+    reads: std::sync::atomic::AtomicU64::new(0),
+    ns_encode: std::sync::atomic::AtomicU64::new(0),
+    ns_upload: std::sync::atomic::AtomicU64::new(0),
+    ns_wait: std::sync::atomic::AtomicU64::new(0),
+    ns_readback: std::sync::atomic::AtomicU64::new(0),
+};
+
+fn count(c: &std::sync::atomic::AtomicU64, n: u64) {
+    c.fetch_add(n, std::sync::atomic::Ordering::Relaxed);
+}
+
+impl Profile {
+    /// the counts since the last take, as (name, value) pairs; zeroes them
+    pub fn take(&self) -> Vec<(&'static str, u64)> {
+        use std::sync::atomic::Ordering::Relaxed;
+        [
+            ("buffers", &self.buffers),
+            ("buffer_bytes", &self.buffer_bytes),
+            ("uploads", &self.uploads),
+            ("dispatches", &self.dispatches),
+            ("bind_groups", &self.bind_groups),
+            ("submits", &self.submits),
+            ("reads", &self.reads),
+            ("ns_encode", &self.ns_encode),
+            ("ns_upload", &self.ns_upload),
+            ("ns_wait", &self.ns_wait),
+            ("ns_readback", &self.ns_readback),
+        ]
+        .into_iter()
+        .map(|(n, c)| (n, c.swap(0, Relaxed)))
+        .collect()
+    }
+}
+
+/// per kernel: dispatches and nanoseconds, gathered when `ANEND_GPU_PROFILE_OPS=1` (each
+/// dispatch then runs alone and is waited for, so the totals are slower than a real run
+/// and only their proportions mean anything)
+pub static OP_NS: Mutex> =
+    Mutex::new(std::collections::BTreeMap::new());
+
+fn profiling_ops() -> bool {
+    static ON: OnceLock = OnceLock::new();
+    *ON.get_or_init(|| std::env::var("ANEND_GPU_PROFILE_OPS").is_ok_and(|v| v == "1"))
+}
+
+/// a place in a buffer: the buffer and an offset in floats
+pub type At<'a> = (&'a Buf, usize);
+
+/// a device buffer of f32
+pub struct Buf {
+    pub(crate) b: wgpu::Buffer,
+    pub len: usize,
+}
+
+impl Buf {
+    pub fn bytes(&self) -> u64 {
+        self.b.size()
+    }
+}
+
+/// the parameters every kernel reads (`struct P` in the shader): 20 u32 then 4 f32
+#[derive(Clone, Copy, Default)]
+pub(crate) struct Params {
+    pub u: [u32; 20],
+    pub f: [f32; 4],
+}
+
+const PARAM_BYTES: u64 = 96;
+
+impl Params {
+    pub fn new(u: &[u32]) -> Params {
+        let mut p = Params::default();
+        p.u[..u.len()].copy_from_slice(u);
+        p
+    }
+
+    pub fn f(mut self, f: &[f32]) -> Params {
+        self.f[..f.len()].copy_from_slice(f);
+        self
+    }
+
+    fn bytes(&self) -> [u8; PARAM_BYTES as usize] {
+        let mut out = [0u8; PARAM_BYTES as usize];
+        for (i, v) in self.u.iter().enumerate() {
+            // u3.w is the exact path's zero; never anything else
+            let v = if i == 15 { 0 } else { *v };
+            out[i * 4..i * 4 + 4].copy_from_slice(&v.to_le_bytes());
+        }
+        for (i, v) in self.f.iter().enumerate() {
+            out[80 + i * 4..84 + i * 4].copy_from_slice(&v.to_le_bytes());
+        }
+        out
+    }
+}
+
+/// an f32 as a WGSL hexadecimal literal holding exactly its value
+fn hex(v: f32) -> String {
+    let b = v.to_bits();
+    let sign = if b >> 31 == 1 { "-" } else { "" };
+    let e = ((b >> 23) & 0xff) as i32;
+    let m = b & 0x7f_ffff;
+    if e == 0 && m == 0 {
+        return format!("{sign}0.0f");
+    }
+    assert!(e != 0 && e != 255, "normal constants only");
+    format!("{sign}0x1.{:06x}p{}f", m << 1, e - 127)
+}
+
+/// the shader source for a precision: constants, the arithmetic, then the kernels
+pub fn source(prec: Precision) -> String {
+    let consts = [
+        ("EXP_LO", -87.0f32),
+        ("EXP_HI", 88.72f32),
+        ("LOG2E", std::f32::consts::LOG2_E),
+        ("ROUND", 12_582_912.0f32),
+        ("LN2_HI", 0.693_359_4f32),
+        ("LN2_LO", -2.121_944_4e-4f32),
+        ("C6", 1.0f32 / 6.0),
+        ("C24", 1.0f32 / 24.0),
+        ("C120", 1.0f32 / 120.0),
+        ("C720", 1.0f32 / 720.0),
+        ("C5040", 1.0f32 / 5040.0),
+    ];
+    let mut s = String::new();
+    for (n, v) in consts {
+        s += &format!("const {n}: f32 = {};\n", hex(v));
+    }
+    s += match prec {
+        Precision::Exact => {
+            "fn mul(a: f32, b: f32) -> f32 { return bitcast(bitcast(a * b) ^ p.u3.w); }\n\
+             fn div(a: f32, b: f32) -> f32 { return div_sw(a, b); }\n\
+             fn sqrtf(x: f32) -> f32 { return sqrt_sw(x); }\n"
+        }
+        Precision::Fast => {
+            "fn mul(a: f32, b: f32) -> f32 { return a * b; }\n\
+             fn div(a: f32, b: f32) -> f32 { return a / b; }\n\
+             fn sqrtf(x: f32) -> f32 { return sqrt(x); }\n"
+        }
+    };
+    s + include_str!("kernels.wgsl")
+}
+
+pub struct Gpu {
+    pub device: wgpu::Device,
+    pub queue: wgpu::Queue,
+    pub info: wgpu::AdapterInfo,
+    pub limits: wgpu::Limits,
+    layout: wgpu::BindGroupLayout,
+    playout: wgpu::PipelineLayout,
+    modules: [OnceLock; 2],
+    pipes: Mutex>,
+    dummy: wgpu::Buffer,
+    align: u64,
+}
+
+// Proving `Gpu: Send + Sync` structurally walks wgpu's types deep enough on some
+// backends to hit the compiler's recursion limit (the future-incompatible
+// `recursion_depth_exceeding_limit` warning on `SHARED`). Every field is Send + Sync on
+// native targets (wgpu's handles are, the rest is std); the test below checks each field's
+// type on its own, so the static needs no structural proof.
+// SAFETY: see above. On wasm wgpu's handles are not Send, so there the structural
+// proof stays (and fails, as it should: the browser build has no shared GPU).
+#[cfg(not(target_arch = "wasm32"))]
+unsafe impl Send for Gpu {}
+#[cfg(not(target_arch = "wasm32"))]
+unsafe impl Sync for Gpu {}
+
+static SHARED: OnceLock> = OnceLock::new();
+
+#[cfg(test)]
+#[allow(dead_code)]
+fn fields_are_send_and_sync() {
+    fn both() {}
+    both::();
+    both::();
+    both::();
+    both::();
+    both::();
+    both::();
+    both::>();
+    both::>>();
+    both::();
+}
+
+/// the process's GPU, opened on first use; `Err` says why there is none (no adapter, or
+/// `ANEND_GPU=off`). `WGPU_BACKEND` (vulkan, metal, dx12, gl) and `WGPU_ADAPTER_NAME`
+/// pick among several.
+pub fn shared() -> Result<&'static Gpu, String> {
+    SHARED.get_or_init(Gpu::new).as_ref().map_err(|e| e.clone())
+}
+
+impl Gpu {
+    pub fn new() -> Result {
+        if std::env::var("ANEND_GPU").is_ok_and(|v| v == "off" || v == "0") {
+            return Err("the GPU is turned off (ANEND_GPU=off)".into());
+        }
+        let instance = wgpu::Instance::new(wgpu::InstanceDescriptor::new_without_display_handle_from_env());
+        let adapter = match std::env::var("WGPU_ADAPTER_NAME") {
+            Ok(name) => {
+                let all = pollster::block_on(instance.enumerate_adapters(wgpu::Backends::all()));
+                let name = name.to_lowercase();
+                all.into_iter()
+                    .find(|a| a.get_info().name.to_lowercase().contains(&name))
+                    .ok_or(format!("no GPU adapter named like {name:?}"))?
+            }
+            Err(_) => pollster::block_on(instance.request_adapter(&wgpu::RequestAdapterOptions {
+                power_preference: wgpu::PowerPreference::HighPerformance,
+                force_fallback_adapter: false,
+                compatible_surface: None,
+                apply_limit_buckets: false,
+            }))
+            .map_err(|e| format!("no GPU adapter: {e}"))?,
+        };
+        let info = adapter.get_info();
+        // everything the adapter offers: model sizes are bounded by the device, not by us
+        let limits = adapter.limits();
+        let (device, queue) = pollster::block_on(adapter.request_device(&wgpu::DeviceDescriptor {
+            label: Some("anend classify"),
+            required_features: wgpu::Features::empty(),
+            required_limits: limits.clone(),
+            experimental_features: wgpu::ExperimentalFeatures::disabled(),
+            memory_hints: wgpu::MemoryHints::Performance,
+            trace: wgpu::Trace::Off,
+        }))
+        .map_err(|e| format!("GPU device {}: {e}", info.name))?;
+        let storage = |binding| wgpu::BindGroupLayoutEntry {
+            binding,
+            visibility: wgpu::ShaderStages::COMPUTE,
+            ty: wgpu::BindingType::Buffer {
+                ty: wgpu::BufferBindingType::Storage { read_only: false },
+                has_dynamic_offset: false,
+                min_binding_size: None,
+            },
+            count: None,
+        };
+        let mut entries = vec![wgpu::BindGroupLayoutEntry {
+            binding: 0,
+            visibility: wgpu::ShaderStages::COMPUTE,
+            ty: wgpu::BindingType::Buffer {
+                ty: wgpu::BufferBindingType::Uniform,
+                has_dynamic_offset: true,
+                min_binding_size: wgpu::BufferSize::new(PARAM_BYTES),
+            },
+            count: None,
+        }];
+        entries.extend((1..=6).map(storage));
+        let layout = device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
+            label: Some("kernels"),
+            entries: &entries,
+        });
+        let playout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
+            label: Some("kernels"),
+            bind_group_layouts: &[Some(&layout)],
+            immediate_size: 0,
+        });
+        let dummy = device.create_buffer(&wgpu::BufferDescriptor {
+            label: Some("unused binding"),
+            size: 16,
+            usage: wgpu::BufferUsages::STORAGE,
+            mapped_at_creation: false,
+        });
+        let align = (limits.min_uniform_buffer_offset_alignment as u64).max(PARAM_BYTES);
+        Ok(Gpu {
+            device,
+            queue,
+            info,
+            limits,
+            layout,
+            playout,
+            modules: [OnceLock::new(), OnceLock::new()],
+            pipes: Mutex::new(HashMap::new()),
+            dummy,
+            align,
+        })
+    }
+
+    /// "name (backend, device type)"
+    pub fn describe(&self) -> String {
+        format!(
+            "{} ({:?}, {:?})",
+            self.info.name, self.info.backend, self.info.device_type
+        )
+    }
+
+    /// the largest buffer the device takes, in f32s
+    pub fn max_floats(&self) -> usize {
+        self.limits
+            .max_storage_buffer_binding_size
+            .min(self.limits.max_buffer_size) as usize
+            / 4
+    }
+
+    fn module(&self, prec: Precision) -> &wgpu::ShaderModule {
+        self.modules[prec as usize].get_or_init(|| {
+            self.device.create_shader_module(wgpu::ShaderModuleDescriptor {
+                label: Some("kernels.wgsl"),
+                source: wgpu::ShaderSource::Wgsl(source(prec).into()),
+            })
+        })
+    }
+
+    fn pipeline(&self, entry: &'static str, prec: Precision) -> wgpu::ComputePipeline {
+        let mut pipes = self.pipes.lock().unwrap();
+        pipes
+            .entry((entry, prec))
+            .or_insert_with(|| {
+                self.device.create_compute_pipeline(&wgpu::ComputePipelineDescriptor {
+                    label: Some(entry),
+                    layout: Some(&self.playout),
+                    module: self.module(prec),
+                    entry_point: Some(entry),
+                    compilation_options: wgpu::PipelineCompilationOptions::default(),
+                    cache: None,
+                })
+            })
+            .clone()
+    }
+
+    /// a buffer holding `data`
+    pub fn upload(&self, data: &[f32]) -> Buf {
+        if data.is_empty() {
+            return self.zeros(0);
+        }
+        let t = std::time::Instant::now();
+        count(&PROFILE.buffers, 1);
+        count(&PROFILE.uploads, 1);
+        count(&PROFILE.buffer_bytes, (data.len() * 4) as u64);
+        let b = self.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
+            label: None,
+            contents: f32_bytes(data),
+            usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC | wgpu::BufferUsages::COPY_DST,
+        });
+        count(&PROFILE.ns_upload, t.elapsed().as_nanos() as u64);
+        Buf { b, len: data.len() }
+    }
+
+    /// a zeroed buffer of n floats (at least one, as bindings cannot be empty)
+    pub fn zeros(&self, n: usize) -> Buf {
+        let t = std::time::Instant::now();
+        count(&PROFILE.buffers, 1);
+        count(&PROFILE.buffer_bytes, (n.max(1) * 4) as u64);
+        let b = self.device.create_buffer(&wgpu::BufferDescriptor {
+            label: None,
+            size: (n.max(1) * 4) as u64,
+            usage: wgpu::BufferUsages::STORAGE | wgpu::BufferUsages::COPY_SRC | wgpu::BufferUsages::COPY_DST,
+            mapped_at_creation: false,
+        });
+        count(&PROFILE.ns_upload, t.elapsed().as_nanos() as u64);
+        Buf { b, len: n }
+    }
+
+    /// overwrites floats from `off` (lands before the next submitted run)
+    pub fn write(&self, buf: &Buf, off: usize, data: &[f32]) {
+        if !data.is_empty() {
+            let t = std::time::Instant::now();
+            debug_assert!(off + data.len() <= buf.len.max(1));
+            count(&PROFILE.uploads, 1);
+            self.queue.write_buffer(&buf.b, (off * 4) as u64, f32_bytes(data));
+            count(&PROFILE.ns_upload, t.elapsed().as_nanos() as u64);
+        }
+    }
+
+    /// a buffer's contents
+    pub fn read(&self, buf: &Buf) -> Vec {
+        let mut r = self.run(Precision::Exact);
+        let t = r.read(buf, 0, buf.len);
+        r.submit().swap_remove(t)
+    }
+
+    pub fn run(&self, prec: Precision) -> Run<'_> {
+        Run {
+            g: self,
+            prec,
+            params: Vec::new(),
+            recs: Vec::new(),
+            reads: 0,
+        }
+    }
+}
+
+fn f32_bytes(v: &[f32]) -> &[u8] {
+    // SAFETY: f32 has no padding and any bytes are valid u8s
+    unsafe { std::slice::from_raw_parts(v.as_ptr() as *const u8, std::mem::size_of_val(v)) }
+}
+
+enum Rec {
+    Dispatch {
+        entry: &'static str,
+        pipe: wgpu::ComputePipeline,
+        bufs: [Option; 6],
+        slot: u64,
+        groups: [u32; 3],
+    },
+    Copy {
+        src: wgpu::Buffer,
+        so: u64,
+        dst: wgpu::Buffer,
+        doff: u64,
+        size: u64,
+    },
+    Read {
+        src: wgpu::Buffer,
+        off: u64,
+        len: usize,
+    },
+}
+
+/// a list of kernel dispatches (and buffer copies and reads) submitted together, in
+/// order; each dispatch sees the writes of the ones before it
+pub struct Run<'g> {
+    pub(crate) g: &'g Gpu,
+    pub prec: Precision,
+    params: Vec,
+    recs: Vec,
+    reads: usize,
+}
+
+/// workgroups for `n` items of `per` each, as an (x, y) grid within the 65535 limit
+pub(crate) fn grid(n: usize, per: usize) -> [u32; 3] {
+    let g = n.div_ceil(per).max(1);
+    let x = g.min(65_535);
+    [x as u32, g.div_ceil(x) as u32, 1]
+}
+
+impl<'g> Run<'g> {
+    pub fn gpu(&self) -> &'g Gpu {
+        self.g
+    }
+
+    pub(crate) fn op(&mut self, entry: &'static str, bufs: &[&Buf], p: Params, groups: [u32; 3]) {
+        if groups.contains(&0) {
+            return;
+        }
+        let slot = self.params.len() as u64;
+        self.params.extend_from_slice(&p.bytes());
+        self.params.resize((slot + self.g.align) as usize, 0);
+        let mut bs: [Option; 6] = Default::default();
+        for (i, b) in bufs.iter().enumerate() {
+            bs[i] = Some(b.b.clone());
+        }
+        let pipe = self.g.pipeline(entry, self.prec);
+        self.recs.push(Rec::Dispatch {
+            entry,
+            pipe,
+            bufs: bs,
+            slot,
+            groups,
+        });
+    }
+
+    /// copies `len` floats between buffers
+    pub fn copy(&mut self, src: &Buf, so: usize, dst: &Buf, doff: usize, len: usize) {
+        if len > 0 {
+            self.recs.push(Rec::Copy {
+                src: src.b.clone(),
+                so: (so * 4) as u64,
+                dst: dst.b.clone(),
+                doff: (doff * 4) as u64,
+                size: (len * 4) as u64,
+            });
+        }
+    }
+
+    /// reads `len` floats from `off` once the run has executed; returns the index of the
+    /// result in `submit`'s list
+    pub fn read(&mut self, buf: &Buf, off: usize, len: usize) -> usize {
+        self.recs.push(Rec::Read {
+            src: buf.b.clone(),
+            off: (off * 4) as u64,
+            len,
+        });
+        self.reads += 1;
+        self.reads - 1
+    }
+
+    /// submits everything and waits for the reads (and only then returns)
+    pub fn submit(self) -> Vec> {
+        let g = self.g;
+        let started = std::time::Instant::now();
+        count(&PROFILE.submits, 1);
+        count(&PROFILE.reads, self.reads as u64);
+        count(
+            &PROFILE.dispatches,
+            self.recs.iter().filter(|r| matches!(r, Rec::Dispatch { .. })).count() as u64,
+        );
+        let ub = (!self.params.is_empty()).then(|| {
+            g.device.create_buffer_init(&wgpu::util::BufferInitDescriptor {
+                label: Some("params"),
+                contents: &self.params,
+                usage: wgpu::BufferUsages::UNIFORM,
+            })
+        });
+        let mut enc = g
+            .device
+            .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None });
+        let mut staging = Vec::new();
+        let by_op = profiling_ops();
+        let mut i = 0;
+        while i < self.recs.len() {
+            if let Rec::Dispatch { .. } = self.recs[i] {
+                let ub = ub.as_ref().expect("params");
+                let mut groups = Vec::new();
+                while let Some(Rec::Dispatch { bufs, .. }) = self.recs.get(i) {
+                    if by_op && !groups.is_empty() {
+                        break;
+                    }
+                    let mut entries = vec![wgpu::BindGroupEntry {
+                        binding: 0,
+                        resource: wgpu::BindingResource::Buffer(wgpu::BufferBinding {
+                            buffer: ub,
+                            offset: 0,
+                            size: wgpu::BufferSize::new(PARAM_BYTES),
+                        }),
+                    }];
+                    for (j, b) in bufs.iter().enumerate() {
+                        entries.push(wgpu::BindGroupEntry {
+                            binding: j as u32 + 1,
+                            resource: b.as_ref().unwrap_or(&g.dummy).as_entire_binding(),
+                        });
+                    }
+                    count(&PROFILE.bind_groups, 1);
+                    groups.push(g.device.create_bind_group(&wgpu::BindGroupDescriptor {
+                        label: None,
+                        layout: &g.layout,
+                        entries: &entries,
+                    }));
+                    i += 1;
+                }
+                let start = i - groups.len();
+                let mut pass = enc.begin_compute_pass(&wgpu::ComputePassDescriptor {
+                    label: None,
+                    timestamp_writes: None,
+                });
+                for (bg, rec) in groups.iter().zip(&self.recs[start..i]) {
+                    if let Rec::Dispatch { pipe, slot, groups, .. } = rec {
+                        pass.set_pipeline(pipe);
+                        pass.set_bind_group(0, bg, &[*slot as u32]);
+                        pass.dispatch_workgroups(groups[0], groups[1], groups[2]);
+                    }
+                }
+                drop(pass);
+                if by_op && let Rec::Dispatch { entry, .. } = &self.recs[start] {
+                    // this dispatch alone, waited for, its time added to its kernel's
+                    let done = std::mem::replace(
+                        &mut enc,
+                        g.device
+                            .create_command_encoder(&wgpu::CommandEncoderDescriptor { label: None }),
+                    );
+                    let t = std::time::Instant::now();
+                    g.queue.submit([done.finish()]);
+                    g.device.poll(wgpu::PollType::wait_indefinitely()).expect("GPU poll");
+                    let mut m = OP_NS.lock().unwrap_or_else(|e| e.into_inner());
+                    let e = m.entry(entry).or_default();
+                    e.0 += 1;
+                    e.1 += t.elapsed().as_nanos() as u64;
+                }
+                continue;
+            }
+            match &self.recs[i] {
+                Rec::Copy {
+                    src,
+                    so,
+                    dst,
+                    doff,
+                    size,
+                } => enc.copy_buffer_to_buffer(src, *so, dst, *doff, *size),
+                Rec::Read { src, off, len } => {
+                    let size = (*len as u64 * 4).max(4);
+                    let st = g.device.create_buffer(&wgpu::BufferDescriptor {
+                        label: Some("read"),
+                        size,
+                        usage: wgpu::BufferUsages::MAP_READ | wgpu::BufferUsages::COPY_DST,
+                        mapped_at_creation: false,
+                    });
+                    if *len > 0 {
+                        enc.copy_buffer_to_buffer(src, *off, &st, 0, size);
+                    }
+                    staging.push((st, *len));
+                }
+                Rec::Dispatch { .. } => unreachable!(),
+            }
+            i += 1;
+        }
+        g.queue.submit([enc.finish()]);
+        count(&PROFILE.ns_encode, started.elapsed().as_nanos() as u64);
+        if staging.is_empty() {
+            return Vec::new();
+        }
+        let waited = std::time::Instant::now();
+        for (st, _) in &staging {
+            st.map_async(wgpu::MapMode::Read, .., |r| r.expect("GPU read"));
+        }
+        g.device.poll(wgpu::PollType::wait_indefinitely()).expect("GPU poll");
+        count(&PROFILE.ns_wait, waited.elapsed().as_nanos() as u64);
+        let copied = std::time::Instant::now();
+        let out = staging
+            .into_iter()
+            .map(|(st, len)| {
+                let v = {
+                    let view = st.get_mapped_range(..).expect("mapped");
+                    view[..len * 4]
+                        .as_chunks::<4>()
+                        .0
+                        .iter()
+                        .map(|c| f32::from_le_bytes(*c))
+                        .collect()
+                };
+                st.unmap();
+                v
+            })
+            .collect();
+        count(&PROFILE.ns_readback, copied.elapsed().as_nanos() as u64);
+        out
+    }
+
+    // ------------------------------------------------------------ kernels
+
+    /// y (+)= A·B for `z` products, each output one chain in ascending p; causal limits
+    /// row r's chain to p ≤ t0 + r (attention over the positions so far)
+    #[allow(clippy::too_many_arguments)]
+    pub fn gemm(
+        &mut self,
+        a: View,
+        b: View,
+        y: View,
+        n: usize,
+        k: usize,
+        m: usize,
+        z: usize,
+        acc: bool,
+        causal: Option,
+    ) {
+        if n == 0 || m == 0 || z == 0 {
+            return;
+        }
+        let flags = acc as u32 | if causal.is_some() { 2 } else { 0 };
+        let u = [
+            n as u32,
+            k as u32,
+            m as u32,
+            flags,
+            a.off as u32,
+            a.s0 as u32,
+            a.s1 as u32,
+            a.zs as u32,
+            b.off as u32,
+            b.s0 as u32,
+            b.s1 as u32,
+            b.zs as u32,
+            y.off as u32,
+            y.s0 as u32,
+            y.zs as u32,
+            0,
+            causal.unwrap_or(0) as u32,
+            z as u32,
+            b.per as u32,
+        ];
+        let p = Params::new(&u);
+        if n < 16 {
+            self.op("gemm_small", &[a.buf, b.buf, y.buf], p, grid(n * m * z, 64));
+        } else {
+            self.op(
+                "gemm",
+                &[a.buf, b.buf, y.buf],
+                p,
+                [m.div_ceil(64) as u32, n.div_ceil(64) as u32, z as u32],
+            );
+        }
+    }
+
+    /// RMSNorm of `rows` rows of d from x[x_off..] into y[y_off..]; with a trace, x̂ and
+    /// rstd too
+    #[allow(clippy::too_many_arguments)]
+    pub fn norm_fwd(
+        &mut self,
+        x: (&Buf, usize),
+        g: &Buf,
+        y: (&Buf, usize),
+        trace: Option<(At, At)>,
+        rows: usize,
+        d: usize,
+        eps: f32,
+    ) {
+        let (xh, rs) = trace.unwrap_or(((y.0, 0), (y.0, 0)));
+        let tr = trace.is_some();
+        let p = Params::new(&[
+            rows as u32,
+            d as u32,
+            x.1 as u32,
+            y.1 as u32,
+            tr as u32,
+            rs.1 as u32,
+            xh.1 as u32,
+        ])
+        .f(&[eps]);
+        if tr {
+            self.op("norm_fwd", &[x.0, g, y.0, xh.0, rs.0], p, grid(rows, 8));
+        } else {
+            self.op("norm_fwd", &[x.0, g, y.0], p, grid(rows, 8));
+        }
+    }
+
+    /// RMSNorm backward: dx += …; dg += Σ dy·x̂ (rows in order)
+    #[allow(clippy::too_many_arguments)]
+    pub fn norm_back(
+        &mut self,
+        dy: (&Buf, usize),
+        xhat: (&Buf, usize),
+        rstd: (&Buf, usize),
+        g: &Buf,
+        dx: (&Buf, usize),
+        dg: (&Buf, usize),
+        rows: usize,
+        d: usize,
+    ) {
+        let p = Params::new(&[
+            rows as u32,
+            d as u32,
+            dy.1 as u32,
+            xhat.1 as u32,
+            rstd.1 as u32,
+            dx.1 as u32,
+        ]);
+        self.op("norm_back", &[dy.0, xhat.0, g, rstd.0, dx.0], p, grid(rows, 8));
+        self.col_acc(dy, Some(xhat), dg, rows, d);
+    }
+
+    /// dst[i] += Σ_r a[r][i]·b[r][i] (or Σ_r a[r][i] without b), rows in order
+    pub fn col_acc(&mut self, a: (&Buf, usize), b: Option<(&Buf, usize)>, dst: (&Buf, usize), rows: usize, d: usize) {
+        let (bb, plain) = match b {
+            Some(b) => (b, 0),
+            None => ((a.0, 0), 1),
+        };
+        let p = Params::new(&[rows as u32, d as u32, a.1 as u32, bb.1 as u32, plain, dst.1 as u32]);
+        if plain == 1 {
+            self.op("col_acc", &[a.0, &self.g.dummy_buf(), dst.0], p, grid(d, 64));
+        } else {
+            self.op("col_acc", &[a.0, bb.0, dst.0], p, grid(d, 64));
+        }
+    }
+
+    /// softmax of rows in place; causal rows (n_q per group, first at position t0) stop
+    /// at their position
+    pub fn softmax(&mut self, x: (&Buf, usize), rows: usize, width: usize, causal: Option<(usize, usize)>) {
+        let (c, nq, t0) = match causal {
+            Some((nq, t0)) => (1, nq, t0),
+            None => (0, 1, 0),
+        };
+        let p = Params::new(&[rows as u32, width as u32, x.1 as u32, 0, c, nq as u32, t0 as u32]);
+        self.op("softmax", &[x.0], p, grid(rows, 8));
+    }
+
+    pub fn softmax_back(&mut self, pr: (&Buf, usize), dp: (&Buf, usize), rows: usize, width: usize) {
+        let p = Params::new(&[rows as u32, width as u32, pr.1 as u32, dp.1 as u32]);
+        self.op("softmax_back", &[pr.0, dp.0], p, grid(rows, 8));
+    }
+
+    /// causal scores S[h][t][s] = dot(q, k)·scale for s ≤ t0 + t, else 0
+    #[allow(clippy::too_many_arguments)]
+    pub fn scores(
+        &mut self,
+        q: (&Buf, usize, usize),
+        k: (&Buf, usize, usize),
+        s: (&Buf, usize),
+        nq: usize,
+        width: usize,
+        dh: usize,
+        heads: usize,
+        t0: usize,
+        scale: f32,
+        per: usize,
+    ) {
+        let p = Params::new(&[
+            nq as u32,
+            width as u32,
+            dh as u32,
+            heads as u32,
+            q.1 as u32,
+            q.2 as u32,
+            k.1 as u32,
+            k.2 as u32,
+            s.1 as u32,
+            t0 as u32,
+            per as u32,
+        ])
+        .f(&[scale]);
+        self.op("scores", &[q.0, k.0, s.0], p, grid(heads * nq * width, 64));
+    }
+
+    /// elementwise op (see `ew` in the shader) over `count` items
+    #[allow(clippy::too_many_arguments)]
+    pub(crate) fn ew(
+        &mut self,
+        op: u32,
+        count: usize,
+        a: (&Buf, usize),
+        b: Option<(&Buf, usize)>,
+        y: Option<(&Buf, usize)>,
+        f: f32,
+        width: usize,
+    ) {
+        let d = self.g.dummy_buf();
+        let (bb, yy) = (b.unwrap_or((&d, 0)), y.unwrap_or((&d, 0)));
+        let p = Params::new(&[count as u32, op, a.1 as u32, bb.1 as u32, yy.1 as u32, width as u32]).f(&[f]);
+        self.op("ew", &[a.0, bb.0, yy.0], p, grid(count, 64));
+    }
+
+    /// y = a + b
+    pub fn add(&mut self, a: &Buf, b: &Buf, y: &Buf, count: usize) {
+        self.ew(0, count, (a, 0), Some((b, 0)), Some((y, 0)), 0.0, 0);
+    }
+
+    /// a += b
+    pub fn add_into(&mut self, a: (&Buf, usize), b: (&Buf, usize), count: usize) {
+        self.ew(1, count, a, Some(b), None, 0.0, 0);
+    }
+
+    /// a *= b elementwise
+    pub fn mul_into(&mut self, a: &Buf, b: &Buf, count: usize) {
+        self.ew(2, count, (a, 0), Some((b, 0)), None, 0.0, 0);
+    }
+
+    /// a *= f
+    pub fn scale(&mut self, a: (&Buf, usize), f: f32, count: usize) {
+        self.ew(3, count, a, None, None, f, 0);
+    }
+
+    /// a = f
+    pub fn fill(&mut self, a: (&Buf, usize), f: f32, count: usize) {
+        self.ew(4, count, a, None, None, f, 0);
+    }
+
+    /// rows of a (count in all) += b, b one row of `width`
+    pub fn add_rows(&mut self, a: &Buf, b: &Buf, count: usize, width: usize) {
+        self.ew(9, count, (a, 0), Some((b, 0)), None, 0.0, width);
+    }
+
+    pub fn swiglu(&mut self, g: &Buf, u: &Buf, s: &Buf, act: &Buf, count: usize) {
+        self.op("swiglu", &[g, u, s, act], Params::new(&[count as u32]), grid(count, 64));
+    }
+
+    #[allow(clippy::too_many_arguments)]
+    pub fn swiglu_back(&mut self, dact: &Buf, g: &Buf, s: &Buf, u: &Buf, dg: &Buf, du: &Buf, count: usize) {
+        self.op(
+            "swiglu_back",
+            &[dact, g, s, u, dg, du],
+            Params::new(&[count as u32]),
+            grid(count, 64),
+        );
+    }
+
+    /// rotates rows of 2·half in place; row r is position t0 + (r mod per)
+    #[allow(clippy::too_many_arguments)]
+    pub fn rope(
+        &mut self,
+        x: (&Buf, usize),
+        cos: &Buf,
+        sin: &Buf,
+        rows: usize,
+        half: usize,
+        per: usize,
+        t0: usize,
+        back: bool,
+    ) {
+        let p = Params::new(&[rows as u32, half as u32, x.1 as u32, per as u32, t0 as u32, back as u32]);
+        self.op("rope", &[x.0, cos, sin], p, grid(rows * half, 64));
+    }
+
+    /// dst[d + z·dzs + r·drs + c] = src[s + z·szs + r·srs + c] for c < width
+    #[allow(clippy::too_many_arguments)]
+    pub fn copy_strided(
+        &mut self,
+        src: (&Buf, usize, usize, usize),
+        dst: (&Buf, usize, usize, usize),
+        width: usize,
+        rows: usize,
+        zs: usize,
+    ) {
+        let p = Params::new(&[
+            width as u32,
+            rows as u32,
+            zs as u32,
+            0,
+            src.1 as u32,
+            src.2 as u32,
+            src.3 as u32,
+            0,
+            dst.1 as u32,
+            dst.2 as u32,
+            dst.3 as u32,
+        ]);
+        self.op("copy", &[src.0, dst.0], p, grid(width * rows * zs, 64));
+    }
+
+    // ------------------------------------------------------------ packed windows
+
+    /// a kernel over packed windows: its buffers, then the pack's table at binding 6
+    fn op_packed(&mut self, entry: &'static str, bufs: &[&Buf], pk: &Packed, mut p: Params, groups: [u32; 3]) {
+        let dummy = self.g.dummy_buf();
+        let mut all: Vec<&Buf> = bufs.to_vec();
+        while all.len() < 5 {
+            all.push(&dummy);
+        }
+        all.push(pk.table);
+        p.u[16] = pk.at as u32;
+        p.u[17] = pk.heads as u32;
+        p.u[18] = pk.kv as u32;
+        self.op(entry, &all, p, groups);
+    }
+
+    /// queries, keys and values of every window out of the projected rows `qkv`
+    /// [n][(H + 2KV)·dh], each window's heads apart (`copy_strided` per window)
+    pub fn split_packed(&mut self, pk: &Packed, qkv: &Buf, q: &Buf, k: &Buf, v: &Buf) {
+        let w3 = (pk.heads + 2 * pk.kv) * pk.dh;
+        let p = Params::new(&[pk.n as u32, w3 as u32, pk.dh as u32]);
+        self.op_packed("split_v", &[qkv, q, k, v], pk, p, grid(pk.n * w3, 64));
+    }
+
+    /// rotary positions on every window's [heads][pos][dh] rows (`rope` per window)
+    pub fn rope_packed(&mut self, pk: &Packed, x: &Buf, cos: &Buf, sin: &Buf, heads: usize) {
+        let half = pk.dh / 2;
+        let p = Params::new(&[pk.n as u32, half as u32, heads as u32]);
+        self.op_packed("rope_v", &[x, cos, sin], pk, p, grid(pk.n * heads * half, 64));
+    }
+
+    /// every window's scaled scores (`gemm` then `scale`, or causal `scores`)
+    pub fn qk_packed(&mut self, pk: &Packed, q: &Buf, k: &Buf, s: &Buf, causal: bool, scale: f32) {
+        let p = Params::new(&[
+            pk.n as u32,
+            causal as u32,
+            pk.dh as u32,
+            pk.longest as u32,
+            (pk.heads / pk.kv) as u32,
+        ])
+        .f(&[scale]);
+        self.op_packed("qk_v", &[q, k, s], pk, p, grid(pk.n * pk.heads * pk.longest, 64));
+    }
+
+    /// softmax of every window's score rows (`softmax` per window)
+    pub fn softmax_packed(&mut self, pk: &Packed, s: &Buf, causal: bool) {
+        let p = Params::new(&[pk.n as u32, causal as u32]);
+        self.op_packed("softmax_v", &[s], pk, p, grid(pk.n * pk.heads, 8));
+    }
+
+    /// every window's probabilities times its values into the packed rows of `ctx`
+    /// [n][H·dh] (`gemm` per window)
+    pub fn pv_packed(&mut self, pk: &Packed, s: &Buf, v: &Buf, ctx: &Buf, causal: bool) {
+        let p = Params::new(&[pk.n as u32, causal as u32, pk.dh as u32, 0, (pk.heads / pk.kv) as u32]);
+        self.op_packed("pv_v", &[s, v, ctx], pk, p, grid(pk.n * pk.heads * pk.dh, 64));
+    }
+}
+
+/// windows packed one after another, as the packed attention kernels see them: `n` rows
+/// in all, the longest window `longest` rows, and the table (at [row] the row's window;
+/// from `at`, per window its first row, length and the sum of the squared lengths
+/// before it, all as f32 integers)
+pub struct Packed<'a> {
+    pub table: &'a Buf,
+    pub at: usize,
+    pub n: usize,
+    pub longest: usize,
+    pub heads: usize,
+    pub kv: usize,
+    pub dh: usize,
+}
+
+/// the table of `Packed` for windows of these lengths
+pub fn packed_table(lens: &[usize]) -> Vec {
+    let n: usize = lens.iter().sum();
+    let mut t = Vec::with_capacity(n + 3 * lens.len());
+    for (w, &m) in lens.iter().enumerate() {
+        t.extend(std::iter::repeat_n(w as f32, m));
+    }
+    let (mut s, mut sq) = (0usize, 0usize);
+    for &m in lens {
+        assert!(s < 1 << 24 && sq < 1 << 24, "a pack's table holds integers below 2^24");
+        t.extend([s as f32, m as f32, sq as f32]);
+        s += m;
+        sq += m * m;
+    }
+    t
+}
+
+impl Gpu {
+    fn dummy_buf(&self) -> Buf {
+        Buf {
+            b: self.dummy.clone(),
+            len: 4,
+        }
+    }
+}
+
+/// an operand of `Run::gemm`: offset, two strides (A: row and p; B: p and column; y: row)
+/// and the stride between batched products
+#[derive(Clone, Copy)]
+pub struct View<'a> {
+    pub buf: &'a Buf,
+    pub off: usize,
+    pub s0: usize,
+    pub s1: usize,
+    pub zs: usize,
+    /// batched products: product z reads this operand's slice z / per (B only)
+    pub per: usize,
+}
+
+impl<'a> View<'a> {
+    /// a row-major matrix with rows of `cols`
+    pub fn rows(buf: &'a Buf, cols: usize) -> View<'a> {
+        View {
+            buf,
+            off: 0,
+            s0: cols,
+            s1: 1,
+            zs: 0,
+            per: 1,
+        }
+    }
+
+    /// the transpose of a row-major matrix with rows of `cols`
+    pub fn t(buf: &'a Buf, cols: usize) -> View<'a> {
+        View {
+            buf,
+            off: 0,
+            s0: 1,
+            s1: cols,
+            zs: 0,
+            per: 1,
+        }
+    }
+
+    pub fn at(mut self, off: usize) -> View<'a> {
+        self.off = off;
+        self
+    }
+
+    pub fn batch(mut self, zs: usize) -> View<'a> {
+        self.zs = zs;
+        self
+    }
+
+    pub fn per(mut self, per: usize) -> View<'a> {
+        self.per = per;
+        self
+    }
+
+    /// a strided view: offset, two strides, batch stride
+    pub fn of(buf: &'a Buf, off: usize, s0: usize, s1: usize, zs: usize) -> View<'a> {
+        View {
+            buf,
+            off,
+            s0,
+            s1,
+            zs,
+            per: 1,
+        }
+    }
+}
diff --git a/core/src/classify/gpu/net.rs b/core/src/classify/gpu/net.rs
new file mode 100644
index 00000000..40199a9e
--- /dev/null
+++ b/core/src/classify/gpu/net.rs
@@ -0,0 +1,1115 @@
+//! A [`Net`]'s trunk resident on the device: the weights uploaded once, each window's
+//! embedded tokens uploaded, every block run as a list of kernel dispatches in one
+//! submission, and only what the CPU needs read back (the final normed rows, the
+//! generative logits). The embedding lookup, pooling and the small classification
+//! heads stay on the CPU (they are a sliver of the work); the decoder keeps its
+//! key/value cache on the device.
+//!
+//! Each dispatch mirrors the CPU's operations in `Net::forward` / `Decoder::step` in the
+//! same order, so on a device the probe finds exact the outputs are the CPU's bits
+//! (`tests` check that, and a tolerance everywhere else).
+
+use super::{Buf, Gpu, Packed, Precision, Run, View, packed_table};
+use crate::classify::kernels as k;
+use crate::classify::model::{Gains, Net, Pooling};
+use crate::classify::text::{self, Window};
+
+struct GBlock {
+    heads: usize,
+    kv: usize,
+    ff: usize,
+    n1: Buf,
+    wqkv: Buf,
+    bqkv: Option,
+    qn: Option,
+    kn: Option,
+    wo: Buf,
+    n2: Buf,
+    wg: Buf,
+    wu: Buf,
+    wd: Buf,
+}
+
+/// a block's weights on the device
+pub(crate) struct BlockBufs<'a> {
+    pub n1: &'a Buf,
+    pub wqkv: &'a Buf,
+    pub qn: Option<&'a Buf>,
+    pub kn: Option<&'a Buf>,
+    pub wo: &'a Buf,
+    pub n2: &'a Buf,
+    pub wg: &'a Buf,
+    pub wu: &'a Buf,
+    pub wd: &'a Buf,
+}
+
+/// a net's trunk (blocks, final norm, generative head) on the device
+pub struct GpuNet {
+    pub g: &'static Gpu,
+    pub prec: Precision,
+    d: usize,
+    dh: usize,
+    eps: f32,
+    causal: bool,
+    qk_norm: bool,
+    max_len: usize,
+    gen_out: usize,
+    blocks: Vec,
+    nf: Buf,
+    genh: Option<(Buf, Buf)>,
+    cos: Buf,
+    sin: Buf,
+    /// this upload's number, naming whose pack buffers are kept
+    id: u64,
+}
+
+/// the buffers of the last pack read, kept for the next one of the same net: one pack's
+/// worth for the process, so nets kept for reading don't each hold their own
+static KEPT: std::sync::Mutex> = std::sync::Mutex::new(None);
+
+static NEXT_ID: std::sync::atomic::AtomicU64 = std::sync::atomic::AtomicU64::new(1);
+
+impl Drop for GpuNet {
+    fn drop(&mut self) {
+        let mut kept = KEPT.lock().unwrap_or_else(|e| e.into_inner());
+        if kept.as_ref().is_some_and(|k| k.owner == self.id) {
+            *kept = None;
+        }
+    }
+}
+
+/// a pack's buffers: room for `n` rows whose attention squares add up to `sq`, in up to
+/// `windows` windows, for the net numbered `owner`
+struct PackBufs {
+    owner: u64,
+    n: usize,
+    sq: usize,
+    windows: usize,
+    /// activations per distinct block shape, and which one each block uses
+    acts: Vec,
+    of_block: Vec,
+    x0: Buf,
+    x1: Buf,
+    xf: Buf,
+    table: Buf,
+}
+
+/// one block's activations for a window of n (the training trace keeps one per block)
+pub(crate) struct Acts {
+    pub a: Buf,
+    pub xh1: Buf,
+    pub rs1: Buf,
+    pub qkv: Buf,
+    /// queries [heads × n × dh] and keys, values [kv × n × dh], after norm and rotation
+    pub q: Buf,
+    pub k: Buf,
+    pub v: Buf,
+    /// before QK-norm, and its x̂ and rstd
+    pub q0: Buf,
+    pub k0: Buf,
+    pub qxh: Buf,
+    pub qrs: Buf,
+    pub kxh: Buf,
+    pub krs: Buf,
+    /// attention probabilities [heads × n × n]
+    pub p: Buf,
+    pub ctx: Buf,
+    pub o: Buf,
+    pub hres: Buf,
+    pub xh2: Buf,
+    pub rs2: Buf,
+    pub bn: Buf,
+    pub gg: Buf,
+    pub u: Buf,
+    pub s: Buf,
+    pub act: Buf,
+    pub dn: Buf,
+    pub m1: Option,
+    pub m2: Option,
+}
+
+impl GpuNet {
+    /// uploads a net; errors when a tensor is larger than the device takes
+    pub fn new(g: &'static Gpu, net: &Net, prec: Precision) -> Result {
+        let cfg = &net.cfg;
+        let max = g.max_floats();
+        let biggest = net
+            .blocks
+            .iter()
+            .flat_map(|b| [b.wqkv.len(), b.wg.len(), b.wd.len()])
+            .chain([net.gen_w.len(), cfg.max_len * cfg.max_len * cfg.heads])
+            .max()
+            .unwrap_or(0);
+        if biggest > max {
+            return Err(format!(
+                "a tensor of {biggest} floats is larger than {} takes ({max})",
+                g.describe()
+            ));
+        }
+        let opt = |v: &Vec| (!v.is_empty()).then(|| g.upload(v));
+        let blocks = net
+            .blocks
+            .iter()
+            .map(|b| GBlock {
+                heads: b.heads,
+                kv: cfg.kv_of(b.heads),
+                ff: b.ff,
+                n1: g.upload(&b.n1),
+                wqkv: g.upload(&b.wqkv),
+                bqkv: opt(&b.bqkv),
+                qn: opt(&b.qn),
+                kn: opt(&b.kn),
+                wo: g.upload(&b.wo),
+                n2: g.upload(&b.n2),
+                wg: g.upload(&b.wg),
+                wu: g.upload(&b.wu),
+                wd: g.upload(&b.wd),
+            })
+            .collect();
+        let (cos, sin) = net.rope.tables();
+        Ok(GpuNet {
+            g,
+            prec,
+            d: cfg.d_model,
+            dh: cfg.head_dim,
+            eps: cfg.norm_eps,
+            causal: cfg.causal,
+            qk_norm: cfg.qk_norm,
+            max_len: cfg.max_len,
+            gen_out: cfg.gen_out(),
+            blocks,
+            nf: g.upload(&net.nf),
+            genh: net
+                .generator
+                .as_ref()
+                .map(|_| (g.upload(&net.gen_w), g.upload(&net.gen_b))),
+            cos: g.upload(cos),
+            sin: g.upload(sin),
+            id: NEXT_ID.fetch_add(1, std::sync::atomic::Ordering::Relaxed),
+        })
+    }
+
+    /// writes a net's weights (same shapes) over the uploaded ones, as after an
+    /// optimizer step
+    pub fn refresh(&self, net: &Net) {
+        let g = self.g;
+        for (gb, b) in self.blocks.iter().zip(&net.blocks) {
+            for (buf, v) in [
+                (&gb.n1, &b.n1),
+                (&gb.wqkv, &b.wqkv),
+                (&gb.wo, &b.wo),
+                (&gb.n2, &b.n2),
+                (&gb.wg, &b.wg),
+                (&gb.wu, &b.wu),
+                (&gb.wd, &b.wd),
+            ] {
+                g.write(buf, 0, v);
+            }
+            for (buf, v) in [(&gb.bqkv, &b.bqkv), (&gb.qn, &b.qn), (&gb.kn, &b.kn)] {
+                if let Some(buf) = buf {
+                    g.write(buf, 0, v);
+                }
+            }
+        }
+        g.write(&self.nf, 0, &net.nf);
+        if let Some((w, b)) = &self.genh {
+            g.write(w, 0, &net.gen_w);
+            g.write(b, 0, &net.gen_b);
+        }
+    }
+
+    /// whether this net matches a CPU net's shapes (blocks, heads, widths)
+    pub fn fits(&self, net: &Net) -> bool {
+        self.blocks.len() == net.blocks.len()
+            && self.d == net.cfg.d_model
+            && self
+                .blocks
+                .iter()
+                .zip(&net.blocks)
+                .all(|(a, b)| a.heads == b.heads && a.ff == b.ff && a.wqkv.len == b.wqkv.len())
+    }
+
+    pub(crate) fn acts(&self, b: usize, n: usize, masks: bool) -> Acts {
+        self.acts_for(b, n, n * n, masks)
+    }
+
+    /// activations for `n` rows in all whose windows' attention squares add up to `sq`
+    /// (one window: `sq = n²`; packed windows: the sum of each one's)
+    fn acts_for(&self, b: usize, n: usize, sq: usize, masks: bool) -> Acts {
+        let g = self.g;
+        let blk = &self.blocks[b];
+        let (d, dh) = (self.d, self.dh);
+        let (h, kv, ff) = (blk.heads, blk.kv, blk.ff);
+        let w3 = (h + 2 * kv) * dh;
+        let qk = |m: usize| if self.qk_norm { m } else { 0 };
+        Acts {
+            a: g.zeros(n * d),
+            xh1: g.zeros(n * d),
+            rs1: g.zeros(n),
+            qkv: g.zeros(n * w3),
+            q: g.zeros(h * n * dh),
+            k: g.zeros(kv * n * dh),
+            v: g.zeros(kv * n * dh),
+            q0: g.zeros(qk(h * n * dh)),
+            k0: g.zeros(qk(kv * n * dh)),
+            qxh: g.zeros(qk(h * n * dh)),
+            qrs: g.zeros(qk(h * n)),
+            kxh: g.zeros(qk(kv * n * dh)),
+            krs: g.zeros(qk(kv * n)),
+            p: g.zeros(h * sq),
+            ctx: g.zeros(n * h * dh),
+            o: g.zeros(n * d),
+            hres: g.zeros(n * d),
+            xh2: g.zeros(n * d),
+            rs2: g.zeros(n),
+            bn: g.zeros(n * d),
+            gg: g.zeros(n * ff),
+            u: g.zeros(n * ff),
+            s: g.zeros(n * ff),
+            act: g.zeros(n * ff),
+            dn: g.zeros(n * d),
+            m1: masks.then(|| g.zeros(n * d)),
+            m2: masks.then(|| g.zeros(n * d)),
+        }
+    }
+
+    /// records block `l` over a window of n rows: x → out, its activations into `t`
+    pub(crate) fn block_fwd(&self, r: &mut Run, l: usize, x: &Buf, out: &Buf, t: &Acts, n: usize) {
+        self.block_fwd_packed(r, l, x, out, t, &[n], None);
+    }
+
+    /// records block `l` over windows packed one after another (`lens` rows each): the
+    /// row-wise work (norms, projections, the feed-forward) runs over all the rows at
+    /// once; attention runs per window, or with the pack's table (`tab`: the table
+    /// buffer, where its window records start, the longest window) for all windows at
+    /// once, a handful of dispatches whatever their number. Each output element is
+    /// computed by the same chain as for its window alone, so packing changes no bits.
+    #[allow(clippy::too_many_arguments)]
+    pub(crate) fn block_fwd_packed(
+        &self,
+        r: &mut Run,
+        l: usize,
+        x: &Buf,
+        out: &Buf,
+        t: &Acts,
+        lens: &[usize],
+        tab: Option<(&Buf, usize, usize)>,
+    ) {
+        let n: usize = lens.iter().sum();
+        let b = &self.blocks[l];
+        let (d, dh, eps) = (self.d, self.dh, self.eps);
+        let (h, kv, ff) = (b.heads, b.kv, b.ff);
+        let (aw, w3, per) = (h * dh, (h + 2 * kv) * dh, h / kv);
+        let scale = 1.0 / (dh as f32).sqrt();
+        r.norm_fwd((x, 0), &b.n1, (&t.a, 0), Some(((&t.xh1, 0), (&t.rs1, 0))), n, d, eps);
+        r.gemm(
+            View::rows(&t.a, d),
+            View::rows(&b.wqkv, w3),
+            View::rows(&t.qkv, w3),
+            n,
+            d,
+            w3,
+            1,
+            false,
+            None,
+        );
+        if let Some(bq) = &b.bqkv {
+            r.add_rows(&t.qkv, bq, n * w3, w3);
+        }
+        let (qd, kd) = if self.qk_norm { (&t.q0, &t.k0) } else { (&t.q, &t.k) };
+        let pk = tab.map(|(table, at, longest)| Packed {
+            table,
+            at,
+            n,
+            longest,
+            heads: h,
+            kv,
+            dh,
+        });
+        // where each window starts: its first row, and its attention square
+        let mut at = Vec::with_capacity(lens.len());
+        let (mut s, mut sq) = (0, 0);
+        for &m in lens {
+            at.push((s, sq, m));
+            s += m;
+            sq += m * m;
+        }
+        if let Some(pk) = &pk {
+            r.split_packed(pk, &t.qkv, qd, kd, &t.v);
+            at.clear();
+        }
+        for &(s, _, m) in &at {
+            let (qo, ko) = (h * dh * s, kv * dh * s);
+            r.copy_strided((&t.qkv, s * w3, dh, w3), (qd, qo, m * dh, dh), dh, m, h);
+            r.copy_strided((&t.qkv, s * w3 + aw, dh, w3), (kd, ko, m * dh, dh), dh, m, kv);
+            r.copy_strided(
+                (&t.qkv, s * w3 + aw + kv * dh, dh, w3),
+                (&t.v, ko, m * dh, dh),
+                dh,
+                m,
+                kv,
+            );
+        }
+        if self.qk_norm {
+            let (qn, kn) = (b.qn.as_ref().expect("qn"), b.kn.as_ref().expect("kn"));
+            r.norm_fwd(
+                (&t.q0, 0),
+                qn,
+                (&t.q, 0),
+                Some(((&t.qxh, 0), (&t.qrs, 0))),
+                h * n,
+                dh,
+                eps,
+            );
+            r.norm_fwd(
+                (&t.k0, 0),
+                kn,
+                (&t.k, 0),
+                Some(((&t.kxh, 0), (&t.krs, 0))),
+                kv * n,
+                dh,
+                eps,
+            );
+        }
+        if let Some(pk) = &pk {
+            r.rope_packed(pk, &t.q, &self.cos, &self.sin, h);
+            r.rope_packed(pk, &t.k, &self.cos, &self.sin, kv);
+            r.qk_packed(pk, &t.q, &t.k, &t.p, self.causal, scale);
+            r.softmax_packed(pk, &t.p, self.causal);
+            r.pv_packed(pk, &t.p, &t.v, &t.ctx, self.causal);
+        }
+        for &(s, sq, m) in &at {
+            let (qo, ko, po) = (h * dh * s, kv * dh * s, h * sq);
+            r.rope((&t.q, qo), &self.cos, &self.sin, h * m, dh / 2, m, 0, false);
+            r.rope((&t.k, ko), &self.cos, &self.sin, kv * m, dh / 2, m, 0, false);
+            let pv_a = View::of(&t.p, po, m, 1, m * m);
+            let pv_b = View::of(&t.v, ko, dh, 1, m * dh).per(per);
+            let pv_y = View::of(&t.ctx, s * aw, aw, 1, dh);
+            if self.causal {
+                r.scores(
+                    (&t.q, qo, m * dh),
+                    (&t.k, ko, m * dh),
+                    (&t.p, po),
+                    m,
+                    m,
+                    dh,
+                    h,
+                    0,
+                    scale,
+                    per,
+                );
+                r.softmax((&t.p, po), h * m, m, Some((m, 0)));
+                r.gemm(pv_a, pv_b, pv_y, m, m, dh, h, false, Some(0));
+            } else {
+                let qa = View::of(&t.q, qo, dh, 1, m * dh);
+                let kb = View::of(&t.k, ko, 1, dh, m * dh).per(per);
+                r.gemm(qa, kb, View::of(&t.p, po, m, 1, m * m), m, dh, m, h, false, None);
+                r.scale((&t.p, po), scale, h * m * m);
+                r.softmax((&t.p, po), h * m, m, None);
+                r.gemm(pv_a, pv_b, pv_y, m, m, dh, h, false, None);
+            }
+        }
+        r.gemm(
+            View::rows(&t.ctx, aw),
+            View::rows(&b.wo, d),
+            View::rows(&t.o, d),
+            n,
+            aw,
+            d,
+            1,
+            false,
+            None,
+        );
+        if let Some(m) = &t.m1 {
+            r.mul_into(&t.o, m, n * d);
+        }
+        r.add(x, &t.o, &t.hres, n * d);
+        r.norm_fwd(
+            (&t.hres, 0),
+            &b.n2,
+            (&t.bn, 0),
+            Some(((&t.xh2, 0), (&t.rs2, 0))),
+            n,
+            d,
+            eps,
+        );
+        r.gemm(
+            View::rows(&t.bn, d),
+            View::rows(&b.wg, ff),
+            View::rows(&t.gg, ff),
+            n,
+            d,
+            ff,
+            1,
+            false,
+            None,
+        );
+        r.gemm(
+            View::rows(&t.bn, d),
+            View::rows(&b.wu, ff),
+            View::rows(&t.u, ff),
+            n,
+            d,
+            ff,
+            1,
+            false,
+            None,
+        );
+        r.swiglu(&t.gg, &t.u, &t.s, &t.act, n * ff);
+        r.gemm(
+            View::rows(&t.act, ff),
+            View::rows(&b.wd, d),
+            View::rows(&t.dn, d),
+            n,
+            ff,
+            d,
+            1,
+            false,
+            None,
+        );
+        if let Some(m) = &t.m2 {
+            r.mul_into(&t.dn, m, n * d);
+        }
+        r.add(&t.hres, &t.dn, out, n * d);
+    }
+
+    /// the final norm (with its x̂, rstd) and, with a generative head, its logits
+    pub(crate) fn top_fwd(
+        &self,
+        r: &mut Run,
+        x: &Buf,
+        xf: &Buf,
+        nf: Option<(&Buf, &Buf)>,
+        genh: Option<&Buf>,
+        n: usize,
+    ) {
+        r.norm_fwd(
+            (x, 0),
+            &self.nf,
+            (xf, 0),
+            nf.map(|(a, b)| ((a, 0), (b, 0))),
+            n,
+            self.d,
+            self.eps,
+        );
+        if let (Some(y), Some((w, b))) = (genh, &self.genh) {
+            let go = self.gen_out;
+            r.gemm(
+                View::rows(xf, self.d),
+                View::rows(w, go),
+                View::rows(y, go),
+                n,
+                self.d,
+                go,
+                1,
+                false,
+                None,
+            );
+            r.add_rows(y, b, n * go, go);
+        }
+    }
+
+    /// one window through the trunk: the final normed rows [n × d] and, when asked
+    /// and the net has one, the generative logits [n × gen_out]
+    pub fn forward(&self, net: &Net, w: &Window, gains: &Gains, want_gen: bool) -> (Vec, Option>) {
+        let n = w.len();
+        assert!(n <= self.max_len, "window longer than max_len");
+        let g = self.g;
+        let d = self.d;
+        let x0 = g.upload(&net.embed(w, gains));
+        let x1 = g.zeros(n * d);
+        let mut r = g.run(self.prec);
+        let mut acts: Option = None;
+        let (mut xa, mut xb) = (&x0, &x1);
+        for l in 0..self.blocks.len() {
+            // blocks of the same shape share one set of activation buffers
+            let same = acts
+                .as_ref()
+                .is_some_and(|a| a.qkv.len == n * self.w3(l) && a.gg.len == n * self.blocks[l].ff);
+            if !same {
+                acts = Some(self.acts(l, n, false));
+            }
+            self.block_fwd(&mut r, l, xa, xb, acts.as_ref().unwrap(), n);
+            std::mem::swap(&mut xa, &mut xb);
+        }
+        let xf = g.zeros(n * d);
+        let genh = (want_gen && self.genh.is_some()).then(|| g.zeros(n * self.gen_out));
+        self.top_fwd(&mut r, xa, &xf, None, genh.as_ref(), n);
+        let t0 = r.read(&xf, 0, n * d);
+        let t1 = genh.as_ref().map(|y| r.read(y, 0, y.len));
+        let mut out = r.submit();
+        let yv = t1.map(|i| std::mem::take(&mut out[i]));
+        (std::mem::take(&mut out[t0]), yv)
+    }
+
+    pub(crate) fn gen_bufs(&self) -> Option<(&Buf, &Buf)> {
+        self.genh.as_ref().map(|(w, b)| (w, b))
+    }
+
+    pub(crate) fn nf_buf(&self) -> &Buf {
+        &self.nf
+    }
+
+    pub(crate) fn cos_buf(&self) -> &Buf {
+        &self.cos
+    }
+
+    pub(crate) fn sin_buf(&self) -> &Buf {
+        &self.sin
+    }
+
+    pub(crate) fn block_bufs(&self, l: usize) -> BlockBufs<'_> {
+        let b = &self.blocks[l];
+        BlockBufs {
+            n1: &b.n1,
+            wqkv: &b.wqkv,
+            qn: b.qn.as_ref(),
+            kn: b.kn.as_ref(),
+            wo: &b.wo,
+            n2: &b.n2,
+            wg: &b.wg,
+            wu: &b.wu,
+            wd: &b.wd,
+        }
+    }
+
+    fn w3(&self, l: usize) -> usize {
+        let b = &self.blocks[l];
+        (b.heads + 2 * b.kv) * self.dh
+    }
+
+    /// every head's logits for a window, computed on the CPU from the device's rows
+    /// as `Net::forward` and `Net::logits` do
+    pub fn head_logits(&self, net: &Net, w: &Window, extra: &[f32], gains: &Gains) -> Vec> {
+        let (xf, _) = self.forward(net, w, gains, false);
+        let z = head_input(net, w, &xf, extra, gains);
+        (0..net.heads.len()).map(|h| head_logits(net, &z, h)).collect()
+    }
+
+    /// the mean of the heads' logits over every window of some data
+    /// (`train::forward_text` on the device)
+    pub fn text_logits(&self, net: &Net, data: &[u8], extra: &[f32], gains: &Gains) -> Vec> {
+        self.text_runs(net, &[data], &[extra], gains).swap_remove(0).logits
+    }
+
+    /// whether `n` packed rows whose attention squares add up to `sq` fit one submission
+    fn fits_pack(&self, n: usize, sq: usize) -> bool {
+        // the pack's table holds rows and squares as f32 integers
+        if n >= 1 << 24 || sq >= 1 << 24 {
+            return false;
+        }
+        let max = self.g.max_floats();
+        let mut total = 3 * n * self.d;
+        for b in &self.blocks {
+            let w3 = (b.heads + 2 * b.kv) * self.dh;
+            let widest = [b.heads * sq, n * w3, n * b.ff, n * self.d]
+                .into_iter()
+                .max()
+                .unwrap_or(0);
+            if widest > max {
+                return false;
+            }
+            let qk = if self.qk_norm { 3 } else { 1 };
+            let block = n * (9 * self.d + w3 + 2 + qk * (b.heads + 2 * b.kv) * self.dh + 4 * b.ff) + b.heads * sq;
+            total = total.max(3 * n * self.d + block);
+        }
+        total <= PACK_FLOATS
+    }
+
+    /// many windows through the trunk, packed into as few submissions as fit
+    /// ([`PACK_FLOATS`] of activations, at most [`PACK_WINDOWS`] windows each): every
+    /// window's final normed rows [n × d], the same values `forward` gives one by one
+    pub fn forward_many(&self, net: &Net, ws: &[&Window], gains: &Gains) -> Vec> {
+        // by length, so a pack's windows are of similar lengths (the packed scores
+        // kernel spans the longest); the results go back to the windows' own order
+        let mut order: Vec = (0..ws.len()).collect();
+        order.sort_by_key(|&i| ws[i].len());
+        let sorted: Vec<&Window> = order.iter().map(|&i| ws[i]).collect();
+        let mut rows: Vec> = Vec::with_capacity(ws.len());
+        let mut i = 0;
+        while i < sorted.len() {
+            let (mut n, mut sq, mut j) = (0, 0, i);
+            while j < sorted.len() && j - i < PACK_WINDOWS {
+                let m = sorted[j].len();
+                if j > i && !self.fits_pack(n + m, sq + m * m) {
+                    break;
+                }
+                n += m;
+                sq += m * m;
+                j += 1;
+            }
+            rows.extend(self.forward_pack(net, &sorted[i..j], gains, n, sq));
+            i = j;
+        }
+        let mut out: Vec> = vec![Vec::new(); ws.len()];
+        for (k, r) in order.into_iter().zip(rows) {
+            out[k] = r;
+        }
+        out
+    }
+
+    fn forward_pack(&self, net: &Net, ws: &[&Window], gains: &Gains, n: usize, sq: usize) -> Vec> {
+        let g = self.g;
+        let d = self.d;
+        let lens: Vec = ws.iter().map(|w| w.len()).collect();
+        let mut emb = Vec::with_capacity(n * d);
+        for w in ws {
+            assert!(w.len() <= self.max_len, "window longer than max_len");
+            emb.extend(net.embed(w, gains));
+        }
+        let table = packed_table(&lens);
+        let longest = lens.iter().copied().max().unwrap_or(0);
+        // the pack's buffers are kept between calls and made again only when a pack
+        // needs more room, so a call neither allocates nor clears its activations
+        let mut kept = KEPT.lock().unwrap_or_else(|e| e.into_inner());
+        if !kept
+            .as_ref()
+            .is_some_and(|k| k.owner == self.id && k.n >= n && k.sq >= sq && k.windows >= ws.len())
+        {
+            // a little room to spare, so packs of about this size reuse them
+            let (cn, csq) = (n + n / 4, sq + sq / 4);
+            let (cn, csq) = if self.fits_pack(cn, csq) { (cn, csq) } else { (n, sq) };
+            let cw = (ws.len() + ws.len() / 4).max(1);
+            let mut shapes: Vec<(usize, usize)> = Vec::new();
+            let mut acts = Vec::new();
+            let mut of_block = Vec::new();
+            for l in 0..self.blocks.len() {
+                let shape = (self.w3(l), self.blocks[l].ff);
+                let i = match shapes.iter().position(|s| *s == shape) {
+                    Some(i) => i,
+                    None => {
+                        shapes.push(shape);
+                        acts.push(self.acts_for(l, cn, csq, false));
+                        acts.len() - 1
+                    }
+                };
+                of_block.push(i);
+            }
+            *kept = None;
+            *kept = Some(PackBufs {
+                owner: self.id,
+                n: cn,
+                sq: csq,
+                windows: cw,
+                acts,
+                of_block,
+                x0: g.zeros(cn * d),
+                x1: g.zeros(cn * d),
+                xf: g.zeros(cn * d),
+                table: g.zeros(cn + 3 * cw),
+            });
+        }
+        let k = kept.as_ref().expect("made above");
+        g.write(&k.x0, 0, &emb);
+        g.write(&k.table, 0, &table);
+        let mut r = g.run(self.prec);
+        let (mut xa, mut xb) = (&k.x0, &k.x1);
+        for l in 0..self.blocks.len() {
+            let tab = Some((&k.table, n, longest));
+            self.block_fwd_packed(&mut r, l, xa, xb, &k.acts[k.of_block[l]], &lens, tab);
+            std::mem::swap(&mut xa, &mut xb);
+        }
+        self.top_fwd(&mut r, xa, &k.xf, None, None, n);
+        let t0 = r.read(&k.xf, 0, n * d);
+        let all = r.submit().swap_remove(t0);
+        drop(kept);
+        let mut out = Vec::with_capacity(ws.len());
+        let mut at = 0;
+        for m in lens {
+            out.push(all[at..at + m * d].to_vec());
+            at += m * d;
+        }
+        out
+    }
+
+    /// many texts at once, every window of all of them packed through the trunk: per
+    /// text, each head's logits and the pooled vector averaged over its windows in
+    /// window order, as `Classifier::run_bytes` computes them on the CPU. `extras` is one
+    /// per text.
+    pub fn text_runs(&self, net: &Net, texts: &[&[u8]], extras: &[&[f32]], gains: &Gains) -> Vec {
+        assert_eq!(texts.len(), extras.len(), "one extra input per text");
+        let per: Vec> = texts.iter().map(|t| net.windows_of(t).0).collect();
+        let flat: Vec<&Window> = per.iter().flatten().collect();
+        let rows = self.forward_many(net, &flat, gains);
+        let mut rows = rows.into_iter();
+        per.iter()
+            .zip(extras)
+            .map(|(ws, extra)| {
+                let mut logits: Vec> = net.heads.iter().map(|h| vec![0.0; h.width()]).collect();
+                let mut pool_sum = vec![0f32; net.cfg.pooled()];
+                for w in ws {
+                    let xf = rows.next().expect("a window's rows");
+                    let (_, pv) = pooled(net, &xf, w.len());
+                    let z = head_input(net, w, &xf, extra, gains);
+                    for (h, acc) in logits.iter_mut().enumerate() {
+                        acc.iter_mut().zip(head_logits(net, &z, h)).for_each(|(a, b)| *a += b);
+                    }
+                    pool_sum.iter_mut().zip(&pv).for_each(|(a, b)| *a += b);
+                }
+                let nw = ws.len() as f32;
+                logits.iter_mut().flatten().for_each(|v| *v /= nw);
+                pool_sum.iter_mut().for_each(|v| *v /= nw);
+                TextRun {
+                    logits,
+                    pooled: pool_sum,
+                    windows: ws.len(),
+                }
+            })
+            .collect()
+    }
+}
+
+/// most activation floats one packed submission holds (512 MiB); each buffer also stays
+/// within the device's own limit (`fits_pack`)
+pub const PACK_FLOATS: usize = 128 << 20;
+/// most windows one packed submission holds
+pub const PACK_WINDOWS: usize = 4096;
+
+/// a text's run on the device: what `Classifier::run_bytes` gives on the CPU
+#[derive(Clone, Debug)]
+pub struct TextRun {
+    /// per head, the mean of the windows' logits
+    pub logits: Vec>,
+    /// the mean of the windows' pooled vectors
+    pub pooled: Vec,
+    pub windows: usize,
+}
+
+/// pooled rows, the side vector and the extra inputs: the heads' input, as the tail of
+/// `Net::forward` builds it (inference: no dropout)
+pub(crate) fn pooled(net: &Net, xf: &[f32], n: usize) -> (Vec, Vec) {
+    let d = net.cfg.d_model;
+    let mean = || {
+        let mut m = vec![0f32; d];
+        for row in xf.chunks_exact(d) {
+            m.iter_mut().zip(row).for_each(|(a, b)| *a += b);
+        }
+        m.iter_mut().for_each(|a| *a /= n as f32);
+        m
+    };
+    let mut pool_p = Vec::new();
+    let pooled = match net.cfg.pooling {
+        Pooling::Cls => xf[..d].to_vec(),
+        Pooling::Mean => mean(),
+        Pooling::ClsMean => [&xf[..d], &mean()[..]].concat(),
+        Pooling::Attention => {
+            pool_p = xf.chunks_exact(d).map(|r| k::dot(r, &net.pool_q)).collect();
+            k::softmax_rows(&mut pool_p, n);
+            let mut m = vec![0f32; d];
+            for (row, &p) in xf.chunks_exact(d).zip(&pool_p) {
+                k::axpy(&mut m, p, row);
+            }
+            m
+        }
+    };
+    (pool_p, pooled)
+}
+
+fn head_input(net: &Net, w: &Window, xf: &[f32], extra: &[f32], gains: &Gains) -> Vec {
+    let (_, mut z) = pooled(net, xf, w.len());
+    if net.cfg.side {
+        z.extend(w.side.iter().map(|v| v * gains.side));
+    }
+    assert_eq!(extra.len(), net.cfg.extra, "extra inputs");
+    z.extend(extra.iter().map(|v| v * gains.extra));
+    z
+}
+
+fn head_logits(net: &Net, z: &[f32], h: usize) -> Vec {
+    let hd = &net.heads[h];
+    let mut y = k::matmul(k::rows(z, z.len()), &hd.w, 1, z.len(), hd.width(), None);
+    y.iter_mut().zip(&hd.b).for_each(|(a, b)| *a += b);
+    y
+}
+
+/// the embedding of the token a decoder reads at position `seq.len()`, with the feature
+/// channels a causal window gives it there (as `Decoder::step` computes them)
+fn step_embedding(net: &Net, seq: &[u32], token: u32, gains: &Gains) -> Vec {
+    let cfg = &net.cfg;
+    let pos = seq.len();
+    let mut w1 = Window {
+        tokens: vec![token],
+        letter: vec![0],
+        ordinal: vec![0],
+        reversed: vec![0],
+        atbash: vec![0],
+        root: vec![0],
+        ..Window::default()
+    };
+    if pos > 0 && (cfg.letters || cfg.words) {
+        let bytes: Vec = seq.iter().map(|&t| t as u8).collect();
+        let w = text::window_with(&bytes, true, false);
+        w1.letter[0] = w.letter[pos];
+        w1.ordinal[0] = w.ordinal[pos];
+        w1.reversed[0] = w.reversed[pos];
+        w1.atbash[0] = w.atbash[pos];
+        w1.root[0] = w.root[pos];
+    }
+    net.embed(&w1, gains)
+}
+
+/// `model::Decoder` on the device: one token at a time with the keys and values of
+/// every block cached on the device, the same restarts when the window fills. Each
+/// step is one submission and one read of the logits.
+pub struct GpuDecoder<'a> {
+    gn: &'a GpuNet,
+    net: &'a Net,
+    gains: Gains,
+    seq: Vec,
+    /// per block: keys and values [kv × max_len × dh]
+    kc: Vec,
+    vc: Vec,
+    logits: Vec,
+    st: Step,
+}
+
+/// one step's buffers (a single row)
+struct Step {
+    x: Buf,
+    x2: Buf,
+    a: Buf,
+    qkv: Buf,
+    q0: Buf,
+    q: Buf,
+    k0: Buf,
+    k: Buf,
+    p: Buf,
+    ctx: Buf,
+    o: Buf,
+    hres: Buf,
+    bn: Buf,
+    gg: Buf,
+    u: Buf,
+    s: Buf,
+    act: Buf,
+    dn: Buf,
+    xf: Buf,
+    y: Buf,
+}
+
+impl<'a> GpuDecoder<'a> {
+    /// a decoder that has read the start token and then `prompt` (bytes, or through
+    /// the net's tokenizer), as `Decoder::new`
+    pub fn new(gn: &'a GpuNet, net: &'a Net, gains: Gains, prompt: &[u8]) -> GpuDecoder<'a> {
+        let mut dec = GpuDecoder::empty(gn, net, gains);
+        let (ts, _) = net.sequence(prompt, 0);
+        for t in ts {
+            dec.push_token(t);
+        }
+        dec
+    }
+
+    /// a decoder that has read the start token and these token ids
+    pub fn from_tokens(gn: &'a GpuNet, net: &'a Net, gains: Gains, prompt: &[u32]) -> GpuDecoder<'a> {
+        let mut dec = GpuDecoder::empty(gn, net, gains);
+        for &t in prompt {
+            dec.push_token(t);
+        }
+        dec
+    }
+
+    fn empty(gn: &'a GpuNet, net: &'a Net, gains: Gains) -> GpuDecoder<'a> {
+        assert!(
+            net.cfg.causal && net.generator.is_some(),
+            "decoding needs a causal model with a generative head"
+        );
+        let g = gn.g;
+        let (d, dh, ml) = (gn.d, gn.dh, gn.max_len);
+        let hmax = gn.blocks.iter().map(|b| b.heads).max().unwrap_or(1);
+        let kvmax = gn.blocks.iter().map(|b| b.kv).max().unwrap_or(1);
+        let ffmax = gn.blocks.iter().map(|b| b.ff).max().unwrap_or(1);
+        let w3max = (0..gn.blocks.len()).map(|l| gn.w3(l)).max().unwrap_or(1);
+        let st = Step {
+            x: g.zeros(d),
+            x2: g.zeros(d),
+            a: g.zeros(d),
+            qkv: g.zeros(w3max),
+            q0: g.zeros(hmax * dh),
+            q: g.zeros(hmax * dh),
+            k0: g.zeros(kvmax * dh),
+            k: g.zeros(kvmax * dh),
+            p: g.zeros(hmax * ml),
+            ctx: g.zeros(hmax * dh),
+            o: g.zeros(d),
+            hres: g.zeros(d),
+            bn: g.zeros(d),
+            gg: g.zeros(ffmax),
+            u: g.zeros(ffmax),
+            s: g.zeros(ffmax),
+            act: g.zeros(ffmax),
+            dn: g.zeros(d),
+            xf: g.zeros(d),
+            y: g.zeros(gn.gen_out),
+        };
+        let mut dec = GpuDecoder {
+            gn,
+            net,
+            gains,
+            seq: Vec::new(),
+            kc: gn.blocks.iter().map(|b| g.zeros(b.kv * ml * dh)).collect(),
+            vc: gn.blocks.iter().map(|b| g.zeros(b.kv * ml * dh)).collect(),
+            logits: Vec::new(),
+            st,
+        };
+        dec.restart(&[]);
+        dec
+    }
+
+    pub fn logits(&self) -> &[f32] {
+        &self.logits
+    }
+
+    pub fn tokens(&self) -> &[u32] {
+        &self.seq
+    }
+
+    pub fn window(&self) -> Vec {
+        self.net.token_bytes(&self.seq)
+    }
+
+    fn restart(&mut self, keep: &[u32]) {
+        // the cache rows past the position are never read, so nothing to clear
+        self.seq.clear();
+        self.step(self.net.start_token());
+        for &t in keep {
+            self.seq.push(t);
+            self.step(t);
+        }
+    }
+
+    pub fn push(&mut self, b: u8) {
+        self.push_token(b as u32);
+    }
+
+    pub fn push_token(&mut self, t: u32) {
+        let cfg = &self.net.cfg;
+        if self.seq.len() + 1 >= cfg.max_len {
+            let keep = self.seq[self.seq.len() - cfg.room() / 2..].to_vec();
+            self.restart(&keep);
+        }
+        self.seq.push(t);
+        self.step(t);
+    }
+
+    fn step(&mut self, token: u32) {
+        let (gn, net, st) = (self.gn, self.net, &self.st);
+        let cfg = &net.cfg;
+        let (d, dh, eps, ml) = (gn.d, gn.dh, gn.eps, gn.max_len);
+        let pos = self.seq.len();
+        let x = step_embedding(net, &self.seq, token, &self.gains);
+        let g = gn.g;
+        g.write(&st.x, 0, &x);
+        let mut r = g.run(gn.prec);
+        let scale = 1.0 / (dh as f32).sqrt();
+        let (mut xa, mut xb) = (&st.x, &st.x2);
+        for (l, b) in gn.blocks.iter().enumerate() {
+            let (h, kv, ff) = (b.heads, b.kv, b.ff);
+            let (aw, w3, per) = (h * dh, gn.w3(l), h / kv);
+            let (kc, vc) = (&self.kc[l], &self.vc[l]);
+            r.norm_fwd((xa, 0), &b.n1, (&st.a, 0), None, 1, d, eps);
+            r.gemm(
+                View::rows(&st.a, d),
+                View::rows(&b.wqkv, w3),
+                View::rows(&st.qkv, w3),
+                1,
+                d,
+                w3,
+                1,
+                false,
+                None,
+            );
+            if let Some(bq) = &b.bqkv {
+                r.add_rows(&st.qkv, bq, w3, w3);
+            }
+            let (qd, kd) = if cfg.qk_norm { (&st.q0, &st.k0) } else { (&st.q, &st.k) };
+            r.copy_strided((&st.qkv, 0, dh, w3), (qd, 0, dh, dh), dh, 1, h);
+            r.copy_strided((&st.qkv, aw, dh, w3), (kd, 0, dh, dh), dh, 1, kv);
+            r.copy_strided((&st.qkv, aw + kv * dh, dh, w3), (vc, pos * dh, ml * dh, dh), dh, 1, kv);
+            if cfg.qk_norm {
+                let (qn, kn) = (b.qn.as_ref().expect("qn"), b.kn.as_ref().expect("kn"));
+                r.norm_fwd((&st.q0, 0), qn, (&st.q, 0), None, h, dh, eps);
+                r.norm_fwd((&st.k0, 0), kn, (&st.k, 0), None, kv, dh, eps);
+            }
+            r.rope((&st.q, 0), &gn.cos, &gn.sin, h, dh / 2, 1, pos, false);
+            r.rope((&st.k, 0), &gn.cos, &gn.sin, kv, dh / 2, 1, pos, false);
+            r.copy_strided((&st.k, 0, dh, dh), (kc, pos * dh, ml * dh, dh), dh, 1, kv);
+            let w = pos + 1;
+            r.scores(
+                (&st.q, 0, dh),
+                (kc, 0, ml * dh),
+                (&st.p, 0),
+                1,
+                w,
+                dh,
+                h,
+                pos,
+                scale,
+                per,
+            );
+            r.softmax((&st.p, 0), h, w, None);
+            r.gemm(
+                View::of(&st.p, 0, w, 1, w),
+                View::of(vc, 0, dh, 1, ml * dh).per(per),
+                View::of(&st.ctx, 0, aw, 1, dh),
+                1,
+                w,
+                dh,
+                h,
+                false,
+                None,
+            );
+            r.gemm(
+                View::rows(&st.ctx, aw),
+                View::rows(&b.wo, d),
+                View::rows(&st.o, d),
+                1,
+                aw,
+                d,
+                1,
+                false,
+                None,
+            );
+            r.add(xa, &st.o, &st.hres, d);
+            r.norm_fwd((&st.hres, 0), &b.n2, (&st.bn, 0), None, 1, d, eps);
+            r.gemm(
+                View::rows(&st.bn, d),
+                View::rows(&b.wg, ff),
+                View::rows(&st.gg, ff),
+                1,
+                d,
+                ff,
+                1,
+                false,
+                None,
+            );
+            r.gemm(
+                View::rows(&st.bn, d),
+                View::rows(&b.wu, ff),
+                View::rows(&st.u, ff),
+                1,
+                d,
+                ff,
+                1,
+                false,
+                None,
+            );
+            r.swiglu(&st.gg, &st.u, &st.s, &st.act, ff);
+            r.gemm(
+                View::rows(&st.act, ff),
+                View::rows(&b.wd, d),
+                View::rows(&st.dn, d),
+                1,
+                ff,
+                d,
+                1,
+                false,
+                None,
+            );
+            r.add(&st.hres, &st.dn, xb, d);
+            std::mem::swap(&mut xa, &mut xb);
+        }
+        gn.top_fwd(&mut r, xa, &st.xf, None, Some(&st.y), 1);
+        let t = r.read(&st.y, 0, gn.gen_out);
+        self.logits = r.submit().swap_remove(t);
+    }
+}
diff --git a/core/src/classify/gpu/probe.rs b/core/src/classify/gpu/probe.rs
new file mode 100644
index 00000000..d091d48b
--- /dev/null
+++ b/core/src/classify/gpu/probe.rs
@@ -0,0 +1,331 @@
+//! The exactness probe: every kernel on random data, on the device and on the CPU
+//! reference (`kernels`, `math`, `model::Rope`), compared bit for bit. A device that
+//! matches everywhere in `Precision::Exact` gives the CPU's results for whole models
+//! too (the model code only chains these kernels); one that does not is still usable
+//! within the reported tolerance.
+
+use super::{Buf, Gpu, Precision, View};
+use crate::classify::kernels::{self as k, rows, transposed};
+use crate::classify::math::Rng;
+use crate::classify::model::Rope;
+
+/// one kernel's comparison
+#[derive(Clone, Debug)]
+pub struct Check {
+    pub kernel: &'static str,
+    pub values: usize,
+    /// values whose bits differ
+    pub differ: usize,
+    /// the largest difference in units in the last place
+    pub max_ulps: u64,
+    /// the largest |gpu − cpu| / max(|cpu|, 1e-6)
+    pub max_rel: f32,
+}
+
+#[derive(Clone, Debug)]
+pub struct Report {
+    pub device: String,
+    pub precision: Precision,
+    pub checks: Vec,
+}
+
+impl Report {
+    /// every kernel matched bit for bit
+    pub fn exact(&self) -> bool {
+        self.checks.iter().all(|c| c.differ == 0)
+    }
+
+    pub fn max_rel(&self) -> f32 {
+        self.checks.iter().map(|c| c.max_rel).fold(0.0, f32::max)
+    }
+
+    pub fn summary(&self) -> String {
+        let mut s = format!(
+            "{} {:?}: {}\n",
+            self.device,
+            self.precision,
+            if self.exact() {
+                "bit-exact on every kernel".to_string()
+            } else {
+                format!("not bit-exact (largest relative difference {:.2e})", self.max_rel())
+            }
+        );
+        for c in &self.checks {
+            s += &format!(
+                "  {:<14} {:>7} values  {:>6} differ  max {:>4} ulp  rel {:.1e}\n",
+                c.kernel, c.values, c.differ, c.max_ulps, c.max_rel
+            );
+        }
+        s
+    }
+}
+
+fn ulps(a: f32, b: f32) -> u64 {
+    if a.to_bits() == b.to_bits() || (a.is_nan() && b.is_nan()) {
+        return 0;
+    }
+    let key = |x: f32| {
+        let b = x.to_bits() as i64;
+        if b < 0x8000_0000 { b } else { 0x8000_0000 - b }
+    };
+    (key(a) - key(b)).unsigned_abs()
+}
+
+/// compares device values against the reference
+pub fn compare(kernel: &'static str, gpu: &[f32], cpu: &[f32]) -> Check {
+    assert_eq!(gpu.len(), cpu.len(), "{kernel}: lengths");
+    let mut c = Check {
+        kernel,
+        values: cpu.len(),
+        differ: 0,
+        max_ulps: 0,
+        max_rel: 0.0,
+    };
+    for (&g, &r) in gpu.iter().zip(cpu) {
+        if g.to_bits() != r.to_bits() {
+            c.differ += 1;
+            c.max_ulps = c.max_ulps.max(ulps(g, r));
+            let rel = (g - r).abs() / r.abs().max(1e-6);
+            c.max_rel = c.max_rel.max(if rel.is_nan() { f32::INFINITY } else { rel });
+        }
+    }
+    c
+}
+
+fn rand(n: usize, seed: u64, scale: f32) -> Vec {
+    let mut r = Rng::new(seed);
+    (0..n).map(|_| r.symmetric(scale)).collect()
+}
+
+/// runs the probe on a device in one precision
+pub fn probe(g: &Gpu, prec: Precision) -> Report {
+    let mut checks = Vec::new();
+    let up = |v: &[f32]| g.upload(v);
+    let read = |b: &Buf| g.read(b);
+
+    // products: tiled and per-output paths, A plain and transposed, fresh and accumulating
+    let (mut gy, mut cy) = (Vec::new(), Vec::new());
+    for (i, &(n, kk, m)) in [
+        (1, 64, 300),
+        (5, 7, 3),
+        (16, 64, 48),
+        (37, 19, 71),
+        (130, 129, 131),
+        (64, 256, 96),
+    ]
+    .iter()
+    .enumerate()
+    {
+        let a = rand(n * kk, 10 + i as u64, 1.0);
+        let b = rand(kk * m, 20 + i as u64, 1.0);
+        let y0 = rand(n * m, 30 + i as u64, 1.0);
+        let at = k::transpose(&a, n, kk);
+        let (ba, bat, bb) = (up(&a), up(&at), up(&b));
+        for (acc, trans) in [(false, false), (true, false), (true, true)] {
+            let by = up(&y0);
+            let mut r = g.run(prec);
+            let av = if trans { View::t(&bat, n) } else { View::rows(&ba, kk) };
+            r.gemm(av, View::rows(&bb, m), View::rows(&by, m), n, kk, m, 1, acc, None);
+            r.submit();
+            gy.extend(read(&by));
+            let mut want = if acc { y0.clone() } else { vec![0.0; n * m] };
+            let sa = if trans { transposed(&at, n) } else { rows(&a, kk) };
+            k::gemm(&mut want, sa, &b, n, kk, m, None);
+            cy.extend(want);
+        }
+    }
+    checks.push(compare("gemm", &gy, &cy));
+
+    // dot and sum (a dot with ones) by the 8-lane rule
+    let (nr, len) = (40, 203);
+    let a = rand(nr * len, 40, 1.0);
+    let b = rand(nr * len, 41, 1.0);
+    let ones = vec![1.0; nr * len];
+    let (ba, bb, bo, out) = (up(&a), up(&b), up(&ones), g.zeros(nr * 2));
+    let mut r = g.run(prec);
+    let p = super::Params::new(&[nr as u32, len as u32]);
+    r.op("dot_rows", &[&ba, &bb, &out], p, super::grid(nr, 64));
+    let out2 = g.zeros(nr);
+    r.op("dot_rows", &[&ba, &bo, &out2], p, super::grid(nr, 64));
+    r.submit();
+    let want: Vec = (0..nr)
+        .map(|i| k::dot(&a[i * len..(i + 1) * len], &b[i * len..(i + 1) * len]))
+        .collect();
+    checks.push(compare("dot", &read(&out)[..nr], &want));
+    let want: Vec = (0..nr).map(|i| k::sum(&a[i * len..(i + 1) * len])).collect();
+    checks.push(compare("sum", &read(&out2), &want));
+
+    // RMSNorm forward and backward
+    let (nr, d) = (37, 133);
+    let x = rand(nr * d, 50, 2.0);
+    let gn = rand(d, 51, 1.0);
+    let dy = rand(nr * d, 52, 1.0);
+    let dx0 = rand(nr * d, 53, 1.0);
+    let dg0 = rand(d, 54, 1.0);
+    let (bx, bg, by, bh, bs) = (up(&x), up(&gn), g.zeros(nr * d), g.zeros(nr * d), g.zeros(nr));
+    let (bdy, bdx, bdg) = (up(&dy), up(&dx0), up(&dg0));
+    let mut r = g.run(prec);
+    r.norm_fwd((&bx, 0), &bg, (&by, 0), Some(((&bh, 0), (&bs, 0))), nr, d, 1e-5);
+    r.norm_back((&bdy, 0), (&bh, 0), (&bs, 0), &bg, (&bdx, 0), (&bdg, 0), nr, d);
+    r.submit();
+    let (cy, nm) = k::norm_fwd(&x, &gn, d, 1e-5);
+    let mut gv = read(&by);
+    gv.extend(read(&bh));
+    gv.extend(read(&bs));
+    let mut cv = cy.clone();
+    cv.extend(&nm.xhat);
+    cv.extend(&nm.rstd);
+    checks.push(compare("norm", &gv, &cv));
+    let (mut cdx, mut cdg) = (dx0.clone(), dg0.clone());
+    // backward from the device's own forward, so the comparison isolates the backward
+    let gnm = k::Norm {
+        xhat: read(&bh),
+        rstd: read(&bs),
+    };
+    k::norm_back(&dy, &gnm, &gn, d, &mut cdx, &mut cdg);
+    let mut gv = read(&bdx);
+    gv.extend(read(&bdg));
+    cdx.extend(cdg);
+    checks.push(compare("norm_back", &gv, &cdx));
+
+    // softmax rows (full and causal) and its backward
+    let (nr, w) = (29, 77);
+    let x = rand(nr * w, 60, 6.0);
+    let dp = rand(nr * w, 61, 1.0);
+    let (bx, bc, bd) = (up(&x), up(&x), up(&dp));
+    let mut r = g.run(prec);
+    r.softmax((&bx, 0), nr, w, None);
+    r.softmax((&bc, 0), nr, w, Some((nr, 3)));
+    r.submit();
+    let mut cs = x.clone();
+    k::softmax_rows(&mut cs, w);
+    let mut cc = x.clone();
+    for (t, row) in cc.chunks_exact_mut(w).enumerate() {
+        let len = (t + 4).min(w);
+        k::softmax_rows(&mut row[..len], len);
+    }
+    let mut gv = read(&bx);
+    gv.extend(read(&bc));
+    let mut cv = cs.clone();
+    cv.extend(cc);
+    checks.push(compare("softmax", &gv, &cv));
+    let gp = read(&bx);
+    let mut r = g.run(prec);
+    let bp = up(&gp);
+    r.softmax_back((&bp, 0), (&bd, 0), nr, w);
+    r.submit();
+    let mut cd = dp.clone();
+    k::softmax_back_rows(&gp, &mut cd, w);
+    checks.push(compare("softmax_back", &read(&bd), &cd));
+
+    // elementwise: exp, sigmoid, ÷, √ over a wide range
+    let mut x = rand(4000, 70, 1.0);
+    x.iter_mut()
+        .enumerate()
+        .for_each(|(i, v)| *v *= [0.01, 1.0, 10.0, 90.0][i % 4]);
+    x.extend([0.0, -0.0, 88.7, -86.9, 1e-30, -1e-30]);
+    let y = rand(x.len(), 71, 3.0);
+    let pos: Vec = x.iter().map(|v| v.abs() + 1e-3).collect();
+    let n = x.len();
+    let (bx, by, bp) = (up(&x), up(&y), up(&pos));
+    let (be, bsg, bdv, bsq) = (up(&x), g.zeros(n), g.zeros(n), g.zeros(n));
+    let mut r = g.run(prec);
+    r.ew(5, n, (&be, 0), None, None, 0.0, 0);
+    r.ew(6, n, (&bx, 0), None, Some((&bsg, 0)), 0.0, 0);
+    r.ew(7, n, (&by, 0), Some((&bp, 0)), Some((&bdv, 0)), 0.0, 0);
+    r.ew(8, n, (&bp, 0), None, Some((&bsq, 0)), 0.0, 0);
+    r.submit();
+    let mut ce = x.clone();
+    k::exp_slice(&mut ce);
+    checks.push(compare("exp", &read(&be), &ce));
+    let mut cs = vec![0.0; n];
+    k::sigmoid_slice(&x, &mut cs);
+    checks.push(compare("sigmoid", &read(&bsg), &cs));
+    let cd: Vec = y.iter().zip(&pos).map(|(a, b)| a / b).collect();
+    checks.push(compare("divide", &read(&bdv), &cd));
+    let cq: Vec = pos.iter().map(|v| v.sqrt()).collect();
+    checks.push(compare("sqrt", &read(&bsq), &cq));
+
+    // SwiGLU forward and backward
+    let n = 1500;
+    let (gg, uu, da) = (rand(n, 80, 5.0), rand(n, 81, 2.0), rand(n, 82, 1.0));
+    let (bg, bu, bs, ba, bda, bdg, bdu) = (
+        up(&gg),
+        up(&uu),
+        g.zeros(n),
+        g.zeros(n),
+        up(&da),
+        g.zeros(n),
+        g.zeros(n),
+    );
+    let mut r = g.run(prec);
+    r.swiglu(&bg, &bu, &bs, &ba, n);
+    r.swiglu_back(&bda, &bg, &bs, &bu, &bdg, &bdu, n);
+    r.submit();
+    let mut s = vec![0.0; n];
+    k::sigmoid_slice(&gg, &mut s);
+    let gs = read(&bs);
+    let mut cv: Vec = (0..n).map(|i| (gg[i] * s[i]) * uu[i]).collect();
+    cv.extend((0..n).map(|i| (da[i] * uu[i]) * (gs[i] * (1.0 + gg[i] * (1.0 - gs[i])))));
+    cv.extend((0..n).map(|i| da[i] * (gg[i] * gs[i])));
+    let mut gv = read(&ba);
+    gv.extend(read(&bdg));
+    gv.extend(read(&bdu));
+    checks.push(compare("swiglu", &gv, &cv));
+
+    // rotary positions, forward and back
+    let (len, dh) = (50, 32);
+    let rope = Rope::new(len, dh, 10_000.0);
+    let x = rand(len * dh, 90, 1.0);
+    let (cos, sin) = rope.tables();
+    let (bc, bs, bx, bb) = (up(cos), up(sin), up(&x), up(&x));
+    let mut r = g.run(prec);
+    r.rope((&bx, 0), &bc, &bs, len, dh / 2, len, 0, false);
+    r.rope((&bb, 0), &bc, &bs, len, dh / 2, len, 0, true);
+    r.submit();
+    let (mut cf, mut cb) = (x.clone(), x.clone());
+    rope.apply(&mut cf, len);
+    rope.back(&mut cb, len);
+    let mut gv = read(&bx);
+    gv.extend(read(&bb));
+    cf.extend(cb);
+    checks.push(compare("rope", &gv, &cf));
+
+    // causal attention scores (8-lane dots)
+    let (nq, dh2) = (20, 24);
+    let q = rand(2 * nq * dh2, 100, 1.0);
+    let kk = rand(2 * nq * dh2, 101, 1.0);
+    let (bq, bk, bsc) = (up(&q), up(&kk), g.zeros(2 * nq * nq));
+    let scale = 1.0 / (dh2 as f32).sqrt();
+    let mut r = g.run(prec);
+    r.scores(
+        (&bq, 0, nq * dh2),
+        (&bk, 0, nq * dh2),
+        (&bsc, 0),
+        nq,
+        nq,
+        dh2,
+        2,
+        0,
+        scale,
+        1,
+    );
+    r.submit();
+    let mut cv = vec![0f32; 2 * nq * nq];
+    for h in 0..2 {
+        for t in 0..nq {
+            for s in 0..=t {
+                let qb = h * nq * dh2 + t * dh2;
+                let kb = h * nq * dh2 + s * dh2;
+                cv[(h * nq + t) * nq + s] = k::dot(&q[qb..qb + dh2], &kk[kb..kb + dh2]) * scale;
+            }
+        }
+    }
+    checks.push(compare("scores", &read(&bsc), &cv));
+
+    Report {
+        device: g.describe(),
+        precision: prec,
+        checks,
+    }
+}
diff --git a/core/src/classify/gpu/tests.rs b/core/src/classify/gpu/tests.rs
new file mode 100644
index 00000000..92e6e848
--- /dev/null
+++ b/core/src/classify/gpu/tests.rs
@@ -0,0 +1,346 @@
+use super::probe::probe;
+use super::*;
+
+/// the device, or None (and a note) where there is none: tests skip, they do not fail
+pub(crate) fn device() -> Option<&'static Gpu> {
+    match shared() {
+        Ok(g) => Some(g),
+        Err(e) => {
+            eprintln!("skipping GPU test: {e}");
+            None
+        }
+    }
+}
+
+#[test]
+fn kernels_match_the_cpu() {
+    let Some(g) = device() else { return };
+    for prec in [Precision::Exact, Precision::Fast] {
+        let rep = probe(g, prec);
+        eprintln!("{}", rep.summary());
+        assert!(rep.max_rel() < 1e-4, "{}", rep.summary());
+    }
+}
+
+use super::net::{GpuDecoder, GpuNet};
+use crate::classify::model::{Config, Decoder, Gains, GenSpec, HeadSpec, Mode, Net, Pooling};
+use crate::classify::text;
+
+/// equal bits where the probe found the device exact, else within `tol` relative
+fn close(what: &str, got: &[f32], want: &[f32], exact: bool) {
+    assert_eq!(got.len(), want.len(), "{what}: lengths");
+    let c = probe::compare("model", got, want);
+    if exact {
+        assert_eq!(c.differ, 0, "{what}: {c:?}");
+    } else {
+        let scale = want.iter().fold(1e-3f32, |a, b| a.max(b.abs()));
+        for (a, b) in got.iter().zip(want) {
+            assert!((a - b).abs() <= 1e-3 * scale, "{what}: {a} vs {b}");
+        }
+    }
+}
+
+fn configs() -> Vec<(&'static str, Config)> {
+    let base = Config {
+        d_model: 48,
+        head_dim: 12,
+        heads: 4,
+        layers: 2,
+        d_ff: 80,
+        max_len: 40,
+        stride: 19,
+        pooling: Pooling::Mean,
+        ..Config::tiny().gematria(false)
+    };
+    vec![
+        (
+            "causal",
+            Config {
+                causal: true,
+                ..base.clone()
+            },
+        ),
+        (
+            "causal gqa qk-norm bias",
+            Config {
+                causal: true,
+                kv_heads: 2,
+                qk_norm: true,
+                qkv_bias: true,
+                ..base.clone().gematria(true)
+            },
+        ),
+        (
+            "encoder",
+            Config {
+                causal: false,
+                pooling: Pooling::Attention,
+                qk_norm: true,
+                ..base.clone()
+            },
+        ),
+        (
+            "tiny",
+            Config {
+                causal: true,
+                pooling: Pooling::Mean,
+                ..Config::tiny()
+            },
+        ),
+    ]
+}
+
+fn exact_device(g: &Gpu, prec: Precision) -> bool {
+    probe(g, prec).exact()
+}
+
+#[test]
+fn trunk_and_heads_match_the_cpu() {
+    let Some(g) = device() else { return };
+    let text = b"The quick brown fox, 1234 jumps over the lazy dog again and again.";
+    for prec in [Precision::Exact, Precision::Fast] {
+        let exact = exact_device(g, prec);
+        for (name, cfg) in configs() {
+            let generator = cfg.causal.then(|| GenSpec::new("next"));
+            let heads = [HeadSpec::single("c", &["a", "b", "c"])];
+            let mut net = Net::with_gen(cfg.clone(), &heads, generator, 3).unwrap();
+            if cfg.qkv_bias {
+                for b in &mut net.blocks {
+                    b.bqkv
+                        .iter_mut()
+                        .enumerate()
+                        .for_each(|(i, v)| *v = (i % 7) as f32 * 0.01);
+                }
+            }
+            // zero-initialised output projections would hide the blocks
+            for b in &mut net.blocks {
+                b.wo.iter_mut()
+                    .enumerate()
+                    .for_each(|(i, v)| *v += ((i % 13) as f32 - 6.0) * 0.003);
+                b.wd.iter_mut()
+                    .enumerate()
+                    .for_each(|(i, v)| *v += ((i % 11) as f32 - 5.0) * 0.003);
+            }
+            let gn = GpuNet::new(g, &net, prec).unwrap();
+            let gains = Gains::default();
+            for len in [3, 20, text.len().min(cfg.room())] {
+                let w = text::window_with(&text[..len], cfg.causal, !cfg.causal);
+                let tr = net.forward(&w, &[], &gains, Mode::EVAL, None);
+                let (_, gl) = gn.forward(&net, &w, &gains, true);
+                if cfg.causal {
+                    close(
+                        &format!("{name} {prec:?} gen {len}"),
+                        &gl.unwrap(),
+                        &net.gen_logits(&tr),
+                        exact,
+                    );
+                }
+                let hl = gn.head_logits(&net, &w, &[], &gains);
+                close(
+                    &format!("{name} {prec:?} head {len}"),
+                    &hl[0],
+                    &net.logits(&tr, 0),
+                    exact,
+                );
+            }
+        }
+    }
+}
+
+#[test]
+fn decoder_matches_the_cpu() {
+    let Some(g) = device() else { return };
+    for prec in [Precision::Exact, Precision::Fast] {
+        let exact = exact_device(g, prec);
+        for (name, cfg) in configs().into_iter().filter(|c| c.1.causal) {
+            let net = Net::with_gen(cfg.clone(), &[], Some(GenSpec::new("next")), 5).unwrap();
+            let gn = GpuNet::new(g, &net, prec).unwrap();
+            let mut cpu = Decoder::new(&net, Gains::default(), b"ab");
+            let mut gpu = GpuDecoder::new(&gn, &net, Gains::default(), b"ab");
+            close(&format!("{name} prompt"), gpu.logits(), cpu.logits(), exact);
+            // past max_len both restart from the last half window
+            for i in 0..cfg.max_len + 5 {
+                let b = b"hello, world "[i % 13];
+                cpu.push(b);
+                gpu.push(b);
+                close(&format!("{name} {prec:?} step {i}"), gpu.logits(), cpu.logits(), exact);
+            }
+            assert_eq!(gpu.tokens(), cpu.tokens());
+        }
+    }
+}
+
+#[test]
+fn training_matches_the_cpu() {
+    use crate::classify::device::Device;
+    use crate::classify::train::{self, Example, Target, TrainOpts};
+    use crate::classify::{Classifier, Flow};
+    let Some(g) = device() else { return };
+    let exact = exact_device(g, Precision::Exact);
+    for (name, cfg) in configs() {
+        let generator = cfg.causal.then(|| GenSpec::new("next"));
+        let heads = [HeadSpec::single("c", &["a", "b"])];
+        let cfg = Config { dropout: 0.1, ..cfg };
+        let fresh = Classifier::with_gen(cfg.clone(), &heads, generator, 9).unwrap();
+        let words = [
+            "alpha beta",
+            "gamma, delta",
+            "epsilon zeta eta theta iota kappa lambda mu",
+        ];
+        let data: Vec = (0..12)
+            .map(|i| {
+                let ex = Example::class(&format!("{} {i}", words[i % 3]), i % 2);
+                if cfg.causal {
+                    ex.and(0, Target::Next { from: 0 })
+                } else {
+                    ex
+                }
+            })
+            .collect();
+        let all: Vec = (0..data.len()).collect();
+        let run = |device: Device| {
+            let mut c = fresh.clone();
+            let o = TrainOpts {
+                epochs: 2,
+                batch: 4,
+                lr: 3e-3,
+                val_fraction: 0.0,
+                threads: 2,
+                device,
+                ..TrainOpts::default()
+            };
+            train::fit(&mut c, &data, &all, &[], &o, |_| Flow::Go).unwrap();
+            c
+        };
+        let cpu = run(Device::Cpu);
+        let gpu = run(Device::Gpu);
+        let flat = |c: &Classifier| -> Vec { c.net.params().into_iter().flat_map(|(_, t)| t.clone()).collect() };
+        close(&format!("{name} trained weights"), &flat(&gpu), &flat(&cpu), exact);
+        assert_ne!(flat(&cpu), flat(&fresh), "{name}: training moved the weights");
+    }
+}
+
+#[test]
+fn classification_and_model_run_match_the_cpu() {
+    use crate::classify::Classifier;
+    use crate::classify::device::{Device, Runner};
+    use crate::classify::spec::{Model, Value};
+    let Some(g) = device() else { return };
+    let exact = exact_device(g, Precision::Exact);
+    let long: String = (0..12).map(|i| format!("sentence {i} of a longer text, ")).collect();
+    for (name, cfg) in configs() {
+        let generator = cfg.causal.then(|| GenSpec::new("next"));
+        let heads = [HeadSpec::single("c", &["a", "b", "c"])];
+        let clf = Classifier::with_gen(cfg.clone(), &heads, generator, 4).unwrap();
+        let runner = Runner::open(Device::Gpu, &clf.net).unwrap();
+        for text in ["short", long.as_str()] {
+            let extra = vec![0.0; cfg.extra];
+            let cpu = clf.predict_bytes(text.as_bytes(), &extra, None);
+            let gpu = clf.predict_bytes_with(text.as_bytes(), &extra, runner.as_ref());
+            for (c, d) in cpu.iter().zip(&gpu) {
+                close(&format!("{name} predict {}", text.len()), &d.probs, &c.probs, exact);
+                assert_eq!(c.top, d.top);
+            }
+        }
+        let model = Model::from_classifier(clf);
+        let input = Value::Text("abc def".into());
+        let cpu = model.run_on(&input, None).unwrap();
+        let gpu = model.run_on(&input, runner.as_ref()).unwrap();
+        if exact {
+            assert_eq!(cpu, gpu, "{name}: run");
+        }
+    }
+}
+
+#[test]
+fn packed_texts_match_the_cpu_one_by_one() {
+    use crate::classify::Classifier;
+    let Some(g) = device() else { return };
+    for prec in [Precision::Exact, Precision::Fast] {
+        let exact = exact_device(g, prec);
+        for (name, cfg) in configs() {
+            let heads = [HeadSpec::single("c", &["a", "b", "c"])];
+            let mut clf = Classifier::new(cfg.clone(), &heads, 5).unwrap();
+            for b in &mut clf.net.blocks {
+                b.wo.iter_mut()
+                    .enumerate()
+                    .for_each(|(i, v)| *v += ((i % 13) as f32 - 6.0) * 0.003);
+                b.wd.iter_mut()
+                    .enumerate()
+                    .for_each(|(i, v)| *v += ((i % 11) as f32 - 5.0) * 0.003);
+            }
+            let gn = GpuNet::new(g, &clf.net, prec).unwrap();
+            // lengths from one byte to several windows, so windows of every size pack
+            let texts: Vec = (0..23)
+                .map(|i| {
+                    (0..(i * i % 97) + 1)
+                        .map(|j| (b'a' + ((i * 7 + j * 3) % 26) as u8) as char)
+                        .collect()
+                })
+                .collect();
+            let bytes: Vec<&[u8]> = texts.iter().map(|t| t.as_bytes()).collect();
+            let extra = vec![0.25f32; cfg.extra];
+            let extras: Vec<&[f32]> = texts.iter().map(|_| extra.as_slice()).collect();
+            let gains = clf.gains();
+            let runs = gn.text_runs(&clf.net, &bytes, &extras, &gains);
+            for (t, r) in texts.iter().zip(&runs) {
+                let cpu = clf.run(t, &extra, &gains, None);
+                assert_eq!(r.windows, cpu.windows, "{name}: windows");
+                close(
+                    &format!("{name} {prec:?} packed logits {}", t.len()),
+                    &r.logits[0],
+                    &cpu.logits[0],
+                    exact,
+                );
+                close(
+                    &format!("{name} {prec:?} packed pooled {}", t.len()),
+                    &r.pooled,
+                    &cpu.pooled,
+                    exact,
+                );
+            }
+        }
+    }
+}
+
+#[test]
+fn kept_pack_buffers_give_the_same_answers_call_after_call() {
+    use crate::classify::Classifier;
+    let Some(g) = device() else { return };
+    let exact = exact_device(g, Precision::Exact);
+    for (name, cfg) in configs() {
+        let heads = [HeadSpec::single("c", &["a", "b"])];
+        let mut clf = Classifier::new(cfg.clone(), &heads, 9).unwrap();
+        for b in &mut clf.net.blocks {
+            b.wo.iter_mut()
+                .enumerate()
+                .for_each(|(i, v)| *v += ((i % 13) as f32 - 6.0) * 0.003);
+        }
+        let gn = GpuNet::new(g, &clf.net, Precision::Exact).unwrap();
+        let gains = clf.gains();
+        let extra = vec![0.0f32; cfg.extra];
+        // a big call, a small one (reusing the big one's buffers, with stale rows in
+        // them), then a bigger one (new buffers)
+        for count in [30usize, 3, 60] {
+            let texts: Vec = (0..count)
+                .map(|i| {
+                    (0..(i * 7 + count) % 90 + 1)
+                        .map(|j| (b'a' + ((i + j * 5) % 26) as u8) as char)
+                        .collect()
+                })
+                .collect();
+            let bytes: Vec<&[u8]> = texts.iter().map(|t| t.as_bytes()).collect();
+            let extras: Vec<&[f32]> = texts.iter().map(|_| extra.as_slice()).collect();
+            let runs = gn.text_runs(&clf.net, &bytes, &extras, &gains);
+            for (t, r) in texts.iter().zip(&runs) {
+                let cpu = clf.run(t, &extra, &gains, None);
+                close(
+                    &format!("{name} call of {count}, {} bytes", t.len()),
+                    &r.logits[0],
+                    &cpu.logits[0],
+                    exact,
+                );
+            }
+        }
+    }
+}
diff --git a/core/src/classify/gpu/train.rs b/core/src/classify/gpu/train.rs
new file mode 100644
index 00000000..fb37fce0
--- /dev/null
+++ b/core/src/classify/gpu/train.rs
@@ -0,0 +1,717 @@
+//! Training on the device: one example's forward with its dropout masks, the losses
+//! and the heads on the CPU, then backward through the trunk on the device, every
+//! operation in `Net::backward_gen`'s order. The trunk's gradients (blocks, final norm,
+//! generative head) stay on the device and are summed over a batch in example order,
+//! as `train::batch_grad` sums its per-example buffers; the embedding, pooling and head
+//! gradients are computed on the CPU into the caller's per-example buffer. After the
+//! batch, `finish` reads the trunk's sums into the CPU gradient, and the optimizer
+//! steps on the CPU (`GpuNet::refresh` uploads the new weights).
+
+use std::sync::Mutex;
+
+use super::net::{Acts, GpuNet, pooled};
+use super::{Buf, Gpu, Precision, Run, View};
+use crate::classify::kernels as k;
+use crate::classify::math::key;
+use crate::classify::model::{Mode, Net, Pooling, dropout_mask};
+use crate::classify::text::{NUM, Window};
+use crate::classify::train::{Target, gen_loss, head_loss};
+
+/// a block's gradient tensors on the device
+struct GradBlock {
+    n1: Buf,
+    wqkv: Buf,
+    bqkv: Buf,
+    qn: Buf,
+    kn: Buf,
+    wo: Buf,
+    n2: Buf,
+    wg: Buf,
+    wu: Buf,
+    wd: Buf,
+}
+
+struct Grads {
+    blocks: Vec,
+    nf: Buf,
+    gen_w: Buf,
+    gen_b: Buf,
+}
+
+impl Grads {
+    fn new(g: &Gpu, net: &Net) -> Grads {
+        let z = |v: &Vec| g.zeros(v.len());
+        Grads {
+            blocks: net
+                .blocks
+                .iter()
+                .map(|b| GradBlock {
+                    n1: z(&b.n1),
+                    wqkv: z(&b.wqkv),
+                    bqkv: z(&b.bqkv),
+                    qn: z(&b.qn),
+                    kn: z(&b.kn),
+                    wo: z(&b.wo),
+                    n2: z(&b.n2),
+                    wg: z(&b.wg),
+                    wu: z(&b.wu),
+                    wd: z(&b.wd),
+                })
+                .collect(),
+            nf: z(&net.nf),
+            gen_w: z(&net.gen_w),
+            gen_b: z(&net.gen_b),
+        }
+    }
+
+    fn all(&self) -> Vec<&Buf> {
+        let mut v = Vec::new();
+        for b in &self.blocks {
+            v.extend([&b.n1, &b.wqkv, &b.bqkv, &b.qn, &b.kn, &b.wo, &b.n2, &b.wg, &b.wu, &b.wd]);
+        }
+        v.extend([&self.nf, &self.gen_w, &self.gen_b]);
+        v
+    }
+
+    /// the CPU tensors these mirror, in the same order
+    fn of(net: &mut Net) -> Vec<&mut Vec> {
+        let mut v = Vec::new();
+        for b in &mut net.blocks {
+            v.extend([
+                &mut b.n1,
+                &mut b.wqkv,
+                &mut b.bqkv,
+                &mut b.qn,
+                &mut b.kn,
+                &mut b.wo,
+                &mut b.n2,
+                &mut b.wg,
+                &mut b.wu,
+                &mut b.wd,
+            ]);
+        }
+        v.extend([&mut net.nf, &mut net.gen_w, &mut net.gen_b]);
+        v
+    }
+}
+
+/// backward's scratch for one window of up to max_len rows
+struct Back {
+    dx: Buf,
+    dd: Buf,
+    dact: Buf,
+    dg: Buf,
+    du: Buf,
+    dbn: Buf,
+    dout: Buf,
+    dctx: Buf,
+    ds: Buf,
+    dq: Buf,
+    dq0: Buf,
+    dkh: Buf,
+    dvh: Buf,
+    dkg: Buf,
+    dk0: Buf,
+    dqkv: Buf,
+    da: Buf,
+}
+
+struct State {
+    acts: Vec,
+    x: [Buf; 2],
+    xf: Buf,
+    xhf: Buf,
+    rsf: Buf,
+    genl: Buf,
+    dxf: Buf,
+    dgen: Buf,
+    back: Back,
+    ex: Grads,
+    total: Grads,
+}
+
+/// a net's training state on the device
+pub struct Trainer {
+    pub gn: GpuNet,
+    st: Mutex,
+}
+
+impl Trainer {
+    pub fn new(g: &'static Gpu, net: &Net, prec: Precision) -> Result {
+        let gn = GpuNet::new(g, net, prec)?;
+        let cfg = &net.cfg;
+        let (n, d, dh) = (cfg.max_len, cfg.d_model, cfg.head_dim);
+        let hmax = net.blocks.iter().map(|b| b.heads).max().unwrap_or(1);
+        let kvmax = net.blocks.iter().map(|b| cfg.kv_of(b.heads)).max().unwrap_or(1);
+        let ffmax = net.blocks.iter().map(|b| b.ff).max().unwrap_or(1);
+        let w3max = net.blocks.iter().map(|b| b.qkv_width(cfg)).max().unwrap_or(1);
+        let go = cfg.gen_out();
+        let masks = cfg.dropout > 0.0;
+        let st = State {
+            acts: (0..net.blocks.len()).map(|l| gn.acts(l, n, masks)).collect(),
+            x: [g.zeros(n * d), g.zeros(n * d)],
+            xf: g.zeros(n * d),
+            xhf: g.zeros(n * d),
+            rsf: g.zeros(n),
+            genl: g.zeros(n * go),
+            dxf: g.zeros(n * d),
+            dgen: g.zeros(n * go),
+            back: Back {
+                dx: g.zeros(n * d),
+                dd: g.zeros(n * d),
+                dact: g.zeros(n * ffmax),
+                dg: g.zeros(n * ffmax),
+                du: g.zeros(n * ffmax),
+                dbn: g.zeros(n * d),
+                dout: g.zeros(n * d),
+                dctx: g.zeros(n * hmax * dh),
+                ds: g.zeros(hmax * n * n),
+                dq: g.zeros(hmax * n * dh),
+                dq0: g.zeros(hmax * n * dh),
+                dkh: g.zeros(hmax * n * dh),
+                dvh: g.zeros(hmax * n * dh),
+                dkg: g.zeros(2 * kvmax * n * dh),
+                dk0: g.zeros(kvmax * n * dh),
+                dqkv: g.zeros(n * w3max),
+                da: g.zeros(n * d),
+            },
+            ex: Grads::new(g, net),
+            total: Grads::new(g, net),
+        };
+        Ok(Trainer { gn, st: Mutex::new(st) })
+    }
+
+    /// a new batch: the net's current weights uploaded, the sums zeroed
+    pub fn begin(&self, net: &Net) {
+        self.gn.refresh(net);
+        let st = self.st.lock().unwrap();
+        let mut r = self.gn.g.run(self.gn.prec);
+        for b in st.total.all() {
+            r.fill((b, 0), 0.0, b.len);
+        }
+        r.submit();
+    }
+
+    /// reads the batch's trunk gradient sums into `total` (whose trunk tensors the CPU
+    /// left at zero)
+    pub fn finish(&self, total: &mut Net) {
+        let st = self.st.lock().unwrap();
+        let bufs = st.total.all();
+        let mut r = self.gn.g.run(self.gn.prec);
+        let ids: Vec = bufs.iter().map(|b| r.read(b, 0, b.len)).collect();
+        let mut got = r.submit();
+        for (dst, i) in Grads::of(total).into_iter().zip(ids) {
+            *dst = std::mem::take(&mut got[i]);
+        }
+    }
+
+    /// one example: adds coef·∇loss into the device's sums (trunk) and into `g` (the
+    /// rest); returns the weighted loss and tokens, as `train::example_grad`
+    #[allow(clippy::too_many_arguments)]
+    pub fn example<'t>(
+        &self,
+        net: &Net,
+        w: &Window,
+        start: usize,
+        targets: impl Iterator,
+        extra: &[f32],
+        mode: Mode,
+        coef: f32,
+        smoothing: f32,
+        g: &mut Net,
+    ) -> (f32, usize) {
+        let st = &mut *self.st.lock().unwrap();
+        let gn = &self.gn;
+        let gpu = gn.g;
+        let cfg = &net.cfg;
+        let (d, n) = (cfg.d_model, w.len());
+        let go = cfg.gen_out();
+        let mask = |site: u64, len: usize| {
+            (mode.dropout > 0.0).then(|| dropout_mask(key(&[mode.key, site]), len, mode.dropout))
+        };
+        // forward
+        let mut x = net.embed(w, &cfg.gains);
+        let m0 = mask(1, n * d);
+        if let Some(m) = &m0 {
+            x.iter_mut().zip(m).for_each(|(a, b)| *a *= b);
+        }
+        gpu.write(&st.x[0], 0, &x);
+        for (l, a) in st.acts.iter().enumerate() {
+            let l1 = l as u64 + 1;
+            for (site, buf) in [(l1 << 8 | 2, &a.m1), (l1 << 8 | 3, &a.m2)] {
+                if let (Some(buf), Some(m)) = (buf, mask(site, n * d)) {
+                    gpu.write(buf, 0, &m);
+                }
+            }
+        }
+        let mut r = gpu.run(gn.prec);
+        for (l, a) in st.acts.iter().enumerate() {
+            let (xi, xo) = (&st.x[l % 2], &st.x[(l + 1) % 2]);
+            gn.block_fwd(&mut r, l, xi, xo, a, n);
+        }
+        let xl = &st.x[st.acts.len() % 2];
+        let has_gen = net.generator.is_some();
+        gn.top_fwd(
+            &mut r,
+            xl,
+            &st.xf,
+            Some((&st.xhf, &st.rsf)),
+            has_gen.then_some(&st.genl),
+            n,
+        );
+        let t_xf = r.read(&st.xf, 0, n * d);
+        let t_gl = has_gen.then(|| r.read(&st.genl, 0, n * go));
+        let mut out = r.submit();
+        let xf = std::mem::take(&mut out[t_xf]);
+        let genl = t_gl.map(|i| std::mem::take(&mut out[i]));
+        // the heads' input as `Net::forward` builds it
+        let (pool_p, mut pooled_v) = pooled(net, &xf, n);
+        let mp = mask(0xff01, pooled_v.len());
+        if let Some(m) = &mp {
+            pooled_v.iter_mut().zip(m).for_each(|(a, b)| *a *= b);
+        }
+        let mut z = pooled_v.clone();
+        if cfg.side {
+            z.extend(w.side.iter().map(|v| v * cfg.gains.side));
+        }
+        z.extend(extra.iter().map(|v| v * cfg.gains.extra));
+        // losses
+        let mut dls = vec![Vec::new(); net.heads.len()];
+        let mut dgen: Vec = Vec::new();
+        let mut loss = 0f32;
+        let add_scaled = |into: &mut Vec, dv: &[f32], s: f32| {
+            if into.is_empty() {
+                *into = vec![0.0; dv.len()];
+            }
+            into.iter_mut().zip(dv).for_each(|(a, b)| *a += b * s);
+        };
+        for (h, t) in targets {
+            if t.generative() {
+                let hw = net.generator.as_ref().map_or(1.0, |g| g.weight);
+                let (l, dv, _) = gen_loss(net, genl.as_ref().expect("generative head"), &w.tokens, start, t);
+                loss += hw * l;
+                add_scaled(&mut dgen, &dv, hw * coef);
+            } else {
+                let hd = &net.heads[h];
+                let hw = hd.spec.weight;
+                let mut y = k::matmul(k::rows(&z, z.len()), &hd.w, 1, z.len(), hd.width(), None);
+                y.iter_mut().zip(&hd.b).for_each(|(a, b)| *a += b);
+                let (l, dv) = head_loss(hd.spec.kind, &y, t, smoothing).expect("checked target");
+                loss += hw * l;
+                add_scaled(&mut dls[h], &dv, hw * coef);
+            }
+        }
+        // heads and pooling backward (CPU), as `Net::backward_gen` begins
+        let zl = z.len();
+        let p = cfg.pooled();
+        let mut dz = vec![0f32; zl];
+        for (h, dl) in dls.iter().enumerate() {
+            if dl.is_empty() {
+                continue;
+            }
+            let (hd, gh) = (&net.heads[h], &mut g.heads[h]);
+            let kw = hd.width();
+            k::gemm(&mut gh.w, k::transposed(&z, 1), dl, zl, 1, kw, None);
+            gh.b.iter_mut().zip(dl).for_each(|(a, b)| *a += b);
+            for (j, v) in dz.iter_mut().enumerate() {
+                *v += k::dot(&hd.w[j * kw..(j + 1) * kw], dl);
+            }
+        }
+        let mut dpool = dz[..p].to_vec();
+        if let Some(m) = &mp {
+            dpool.iter_mut().zip(m).for_each(|(a, b)| *a *= b);
+        }
+        let mut dxf = vec![0f32; n * d];
+        let add_mean = |dxf: &mut [f32], dm: &[f32]| {
+            let dmn: Vec = dm.iter().map(|v| v / n as f32).collect();
+            for row in dxf.chunks_exact_mut(d) {
+                row.iter_mut().zip(&dmn).for_each(|(a, b)| *a += b);
+            }
+        };
+        match cfg.pooling {
+            Pooling::Cls => dxf[..d].copy_from_slice(&dpool),
+            Pooling::Mean => add_mean(&mut dxf, &dpool),
+            Pooling::ClsMean => {
+                dxf[..d].copy_from_slice(&dpool[..d]);
+                add_mean(&mut dxf, &dpool[d..]);
+            }
+            Pooling::Attention => {
+                let mut dp: Vec = xf.chunks_exact(d).map(|r| k::dot(r, &dpool)).collect();
+                for (row, &pp) in dxf.chunks_exact_mut(d).zip(&pool_p) {
+                    k::axpy(row, pp, &dpool);
+                }
+                k::softmax_back_rows(&pool_p, &mut dp, n);
+                for (t, &de) in dp.iter().enumerate() {
+                    k::axpy(&mut g.pool_q, de, &xf[t * d..(t + 1) * d]);
+                    k::axpy(&mut dxf[t * d..(t + 1) * d], de, &net.pool_q);
+                }
+            }
+        }
+        gpu.write(&st.dxf, 0, &dxf);
+        if !dgen.is_empty() {
+            gpu.write(&st.dgen, 0, &dgen);
+        }
+        // the trunk backward on the device
+        let mut r = gpu.run(gn.prec);
+        for b in st.ex.all() {
+            r.fill((b, 0), 0.0, b.len);
+        }
+        if !dgen.is_empty() {
+            let (gw, _) = gn.gen_bufs().expect("generative head");
+            r.gemm(
+                View::t(&st.xf, d),
+                View::rows(&st.dgen, go),
+                View::rows(&st.ex.gen_w, go),
+                d,
+                n,
+                go,
+                1,
+                true,
+                None,
+            );
+            r.col_acc((&st.dgen, 0), None, (&st.ex.gen_b, 0), n, go);
+            r.gemm(
+                View::rows(&st.dgen, go),
+                View::t(gw, go),
+                View::rows(&st.dxf, d),
+                n,
+                go,
+                d,
+                1,
+                true,
+                None,
+            );
+        }
+        let bk = &st.back;
+        r.fill((&bk.dx, 0), 0.0, n * d);
+        r.norm_back(
+            (&st.dxf, 0),
+            (&st.xhf, 0),
+            (&st.rsf, 0),
+            gn.nf_buf(),
+            (&bk.dx, 0),
+            (&st.ex.nf, 0),
+            n,
+            d,
+        );
+        for l in (0..st.acts.len()).rev() {
+            self.block_back(&mut r, net, l, &st.acts[l], bk, &st.ex.blocks[l], n);
+        }
+        for (dst, src) in st.total.all().into_iter().zip(st.ex.all()) {
+            r.add_into((dst, 0), (src, 0), src.len);
+        }
+        let t_dx = r.read(&bk.dx, 0, n * d);
+        let mut dx = r.submit().swap_remove(t_dx);
+        if let Some(m) = &m0 {
+            dx.iter_mut().zip(m).for_each(|(a, b)| *a *= b);
+        }
+        embed_back(net, w, &dx, g);
+        (loss, n)
+    }
+
+    #[allow(clippy::too_many_arguments)]
+    fn block_back(&self, r: &mut Run, net: &Net, l: usize, t: &Acts, bk: &Back, gb: &GradBlock, n: usize) {
+        let cfg = &net.cfg;
+        let b = &net.blocks[l];
+        let wb = self.gn.block_bufs(l);
+        let (d, dh, ff) = (cfg.d_model, cfg.head_dim, b.ff);
+        let (h, kv) = (b.heads, cfg.kv_of(b.heads));
+        let (aw, w3, per) = (h * dh, b.qkv_width(cfg), h / kv);
+        let scale = 1.0 / (dh as f32).sqrt();
+        // feed-forward
+        r.copy(&bk.dx, 0, &bk.dd, 0, n * d);
+        if let Some(m) = &t.m2 {
+            r.mul_into(&bk.dd, m, n * d);
+        }
+        r.gemm(
+            View::t(&t.act, ff),
+            View::rows(&bk.dd, d),
+            View::rows(&gb.wd, d),
+            ff,
+            n,
+            d,
+            1,
+            true,
+            None,
+        );
+        r.gemm(
+            View::rows(&bk.dd, d),
+            View::t(wb.wd, d),
+            View::rows(&bk.dact, ff),
+            n,
+            d,
+            ff,
+            1,
+            false,
+            None,
+        );
+        r.swiglu_back(&bk.dact, &t.gg, &t.s, &t.u, &bk.dg, &bk.du, n * ff);
+        r.gemm(
+            View::t(&t.bn, d),
+            View::rows(&bk.dg, ff),
+            View::rows(&gb.wg, ff),
+            d,
+            n,
+            ff,
+            1,
+            true,
+            None,
+        );
+        r.gemm(
+            View::t(&t.bn, d),
+            View::rows(&bk.du, ff),
+            View::rows(&gb.wu, ff),
+            d,
+            n,
+            ff,
+            1,
+            true,
+            None,
+        );
+        r.gemm(
+            View::rows(&bk.dg, ff),
+            View::t(wb.wg, ff),
+            View::rows(&bk.dbn, d),
+            n,
+            ff,
+            d,
+            1,
+            false,
+            None,
+        );
+        r.gemm(
+            View::rows(&bk.du, ff),
+            View::t(wb.wu, ff),
+            View::rows(&bk.dbn, d),
+            n,
+            ff,
+            d,
+            1,
+            true,
+            None,
+        );
+        r.norm_back(
+            (&bk.dbn, 0),
+            (&t.xh2, 0),
+            (&t.rs2, 0),
+            wb.n2,
+            (&bk.dx, 0),
+            (&gb.n2, 0),
+            n,
+            d,
+        );
+        // attention
+        r.copy(&bk.dx, 0, &bk.dout, 0, n * d);
+        if let Some(m) = &t.m1 {
+            r.mul_into(&bk.dout, m, n * d);
+        }
+        r.gemm(
+            View::t(&t.ctx, aw),
+            View::rows(&bk.dout, d),
+            View::rows(&gb.wo, d),
+            aw,
+            n,
+            d,
+            1,
+            true,
+            None,
+        );
+        r.gemm(
+            View::rows(&bk.dout, d),
+            View::t(wb.wo, d),
+            View::rows(&bk.dctx, aw),
+            n,
+            d,
+            aw,
+            1,
+            false,
+            None,
+        );
+        let dco = View::of(&bk.dctx, 0, aw, 1, dh);
+        let nn = n * n;
+        let hs = n * dh;
+        // ds = dco·vᵀ, dv = pᵀ·dco, per head
+        r.gemm(
+            dco,
+            View::of(&t.v, 0, 1, dh, hs).per(per),
+            View::of(&bk.ds, 0, n, 1, nn),
+            n,
+            dh,
+            n,
+            h,
+            false,
+            None,
+        );
+        r.gemm(
+            View::of(&t.p, 0, 1, n, nn),
+            View::of(&bk.dctx, 0, aw, 1, dh),
+            View::of(&bk.dvh, 0, dh, 1, hs),
+            n,
+            n,
+            dh,
+            h,
+            false,
+            None,
+        );
+        r.softmax_back((&t.p, 0), (&bk.ds, 0), h * n, n);
+        r.scale((&bk.ds, 0), scale, h * nn);
+        r.gemm(
+            View::of(&bk.ds, 0, n, 1, nn),
+            View::of(&t.k, 0, dh, 1, hs).per(per),
+            View::of(&bk.dq, 0, dh, 1, hs),
+            n,
+            n,
+            dh,
+            h,
+            false,
+            None,
+        );
+        r.gemm(
+            View::of(&bk.ds, 0, 1, n, nn),
+            View::of(&t.q, 0, dh, 1, hs),
+            View::of(&bk.dkh, 0, dh, 1, hs),
+            n,
+            n,
+            dh,
+            h,
+            false,
+            None,
+        );
+        r.rope(
+            (&bk.dq, 0),
+            self.gn.cos_buf(),
+            self.gn.sin_buf(),
+            h * n,
+            dh / 2,
+            n,
+            0,
+            true,
+        );
+        let dq = if cfg.qk_norm {
+            r.fill((&bk.dq0, 0), 0.0, h * hs);
+            r.norm_back(
+                (&bk.dq, 0),
+                (&t.qxh, 0),
+                (&t.qrs, 0),
+                wb.qn.expect("qn"),
+                (&bk.dq0, 0),
+                (&gb.qn, 0),
+                h * n,
+                dh,
+            );
+            &bk.dq0
+        } else {
+            &bk.dq
+        };
+        // a group's key and value gradients, its heads summed in head order
+        let (dkg, dvg_off) = (&bk.dkg, kv * hs);
+        if per == 1 {
+            r.copy(&bk.dkh, 0, dkg, 0, kv * hs);
+            r.copy(&bk.dvh, 0, dkg, dvg_off, kv * hs);
+        } else {
+            for gi in 0..kv {
+                r.copy(&bk.dkh, gi * per * hs, dkg, gi * hs, hs);
+                r.copy(&bk.dvh, gi * per * hs, dkg, dvg_off + gi * hs, hs);
+                for j in 1..per {
+                    r.add_into((dkg, gi * hs), (&bk.dkh, (gi * per + j) * hs), hs);
+                    r.add_into((dkg, dvg_off + gi * hs), (&bk.dvh, (gi * per + j) * hs), hs);
+                }
+            }
+        }
+        r.rope(
+            (dkg, 0),
+            self.gn.cos_buf(),
+            self.gn.sin_buf(),
+            kv * n,
+            dh / 2,
+            n,
+            0,
+            true,
+        );
+        let (dk, dk_off) = if cfg.qk_norm {
+            r.fill((&bk.dk0, 0), 0.0, kv * hs);
+            r.norm_back(
+                (dkg, 0),
+                (&t.kxh, 0),
+                (&t.krs, 0),
+                wb.kn.expect("kn"),
+                (&bk.dk0, 0),
+                (&gb.kn, 0),
+                kv * n,
+                dh,
+            );
+            (&bk.dk0, 0)
+        } else {
+            (dkg, 0)
+        };
+        r.copy_strided((dq, 0, hs, dh), (&bk.dqkv, 0, dh, w3), dh, n, h);
+        r.copy_strided((dk, dk_off, hs, dh), (&bk.dqkv, aw, dh, w3), dh, n, kv);
+        r.copy_strided((dkg, dvg_off, hs, dh), (&bk.dqkv, aw + kv * dh, dh, w3), dh, n, kv);
+        if !b.bqkv.is_empty() {
+            r.col_acc((&bk.dqkv, 0), None, (&gb.bqkv, 0), n, w3);
+        }
+        r.gemm(
+            View::t(&t.a, d),
+            View::rows(&bk.dqkv, w3),
+            View::rows(&gb.wqkv, w3),
+            d,
+            n,
+            w3,
+            1,
+            true,
+            None,
+        );
+        r.gemm(
+            View::rows(&bk.dqkv, w3),
+            View::t(wb.wqkv, w3),
+            View::rows(&bk.da, d),
+            n,
+            w3,
+            d,
+            1,
+            false,
+            None,
+        );
+        r.norm_back(
+            (&bk.da, 0),
+            (&t.xh1, 0),
+            (&t.rs1, 0),
+            wb.n1,
+            (&bk.dx, 0),
+            (&gb.n1, 0),
+            n,
+            d,
+        );
+    }
+}
+
+/// the embedding tables' gradients from d(loss)/d(embedded rows), token by token in
+/// order, as the end of `Net::backward_gen`
+fn embed_back(net: &Net, w: &Window, dx: &[f32], g: &mut Net) {
+    let d = net.cfg.d_model;
+    let gn = &net.cfg.gains;
+    let rows_of = |i: u8| i as usize * d..(i as usize + 1) * d;
+    for t in 0..w.len() {
+        let r = &dx[t * d..(t + 1) * d];
+        let tk = w.tokens[t] as usize;
+        g.tok[tk * d..(tk + 1) * d].iter_mut().zip(r).for_each(|(a, b)| *a += b);
+        if w.tokens[t] == NUM && !g.num.is_empty() {
+            let v = w.values.get(t).copied().unwrap_or(0.0);
+            g.num.iter_mut().zip(r).for_each(|(a, b)| *a += v * b);
+        }
+        let dl: Vec = r.iter().map(|v| gn.letter * v).collect();
+        let dw: Vec = r.iter().map(|v| gn.word * v).collect();
+        let add = |tab: &mut Vec, idx: u8, v: &[f32]| {
+            tab[rows_of(idx)].iter_mut().zip(v).for_each(|(a, b)| *a += b);
+        };
+        if net.cfg.letters {
+            add(&mut g.letter, w.letter[t], &dl);
+        }
+        if net.cfg.words {
+            add(&mut g.word_ord, w.ordinal[t], &dw);
+            add(&mut g.word_rev, w.reversed[t], &dw);
+            add(&mut g.word_atb, w.atbash[t], &dw);
+            add(&mut g.word_root, w.root[t], &dw);
+        }
+    }
+}
diff --git a/core/src/classify/grow.rs b/core/src/classify/grow.rs
index 7508cb05..eb85e4c2 100644
--- a/core/src/classify/grow.rs
+++ b/core/src/classify/grow.rs
@@ -69,8 +69,15 @@ pub fn widen_ff(net: &mut Net, b: usize, add: usize, seed: u64) {
     blk.ff = pick.len();
 }
 
+/// whether heads can be added or pruned: not when keys and values are grouped or the
+/// projections have biases (imported pretrained models)
+pub fn heads_change(net: &Net) -> bool {
+    net.cfg.kv_heads == 0 && !net.cfg.qkv_bias
+}
+
 /// adds `add` attention heads to block `b`; their output rows are zero
 pub fn add_heads(net: &mut Net, b: usize, add: usize, seed: u64) {
+    assert!(heads_change(net), "heads of grouped or biased attention don't change");
     let (d, dh) = (net.cfg.d_model, net.cfg.head_dim);
     let mut r = Rng::new(key(&[seed, 0x4ead, b as u64]));
     let blk = &mut net.blocks[b];
@@ -108,6 +115,7 @@ pub fn prune_ff(net: &mut Net, b: usize, keep: &[usize]) {
 
 /// keeps only the listed heads of block `b`
 pub fn prune_heads(net: &mut Net, b: usize, keep: &[usize]) {
+    assert!(heads_change(net), "heads of grouped or biased attention don't change");
     let (d, dh) = (net.cfg.d_model, net.cfg.head_dim);
     let blk = &mut net.blocks[b];
     let a = blk.heads * dh;
@@ -245,7 +253,7 @@ pub fn prune(clf: &mut Classifier, data: &[Example], val: &[usize], o: &PruneOpt
             rep.units += drop;
         }
         let hs = &imp.heads[l];
-        if o.heads && hs.len() > 1 {
+        if o.heads && hs.len() > 1 && heads_change(&clf.net) {
             let mean = hs.iter().sum::() / hs.len() as f64;
             let (worst, &w) = hs.iter().enumerate().min_by(|a, b| a.1.total_cmp(b.1)).unwrap();
             if w < 0.5 * mean {
@@ -336,7 +344,7 @@ impl Grower {
     fn allowed(&self, a: Action, net: &Net) -> bool {
         match a {
             Action::Widen => net.blocks.iter().any(|b| b.ff < self.max_ff),
-            Action::AddHead => net.blocks.iter().any(|b| b.heads < self.max_heads),
+            Action::AddHead => heads_change(net) && net.blocks.iter().any(|b| b.heads < self.max_heads),
             Action::Deepen => net.blocks.len() < self.max_layers,
             _ => true,
         }
diff --git a/core/src/classify/io.rs b/core/src/classify/io.rs
index 2bb2ee04..e32533d2 100644
--- a/core/src/classify/io.rs
+++ b/core/src/classify/io.rs
@@ -13,11 +13,13 @@
 use serde::{Deserialize, Serialize};
 
 use super::math::fnv;
-use super::model::{Config, HeadSpec, Net, Rope};
+use super::model::{Config, GenSpec, HeadSpec, Net, Rope};
 use super::{Classifier, Meta, Steer};
 
 pub const MAGIC: &[u8; 8] = b"ANENDCLS";
-pub const VERSION: u32 = 1;
+/// 2 adds optional feature channels, NUM tokens, causal models and the generative head;
+/// version 1 files read as version 2 files with the gematria channels on
+pub const VERSION: u32 = 2;
 
 /// the largest shapes a file may claim, so a damaged or hostile header can't make the
 /// reader allocate more than the file itself could hold
@@ -31,14 +33,41 @@ pub const MAX_OUT_HEADS: usize = 16;
 pub const MAX_CLASSES: usize = 1024;
 pub const MAX_EXTRA: usize = 1 << 16;
 
+/// the shape limits for models with their own vocabulary (imported pretrained models),
+/// set far past any open checkpoint: they only stop a hostile header from asking for
+/// absurd tables that the weights' size check can't see (the rotary table)
+pub const BIG_D_MODEL: usize = 1 << 16;
+pub const BIG_HEAD_DIM: usize = 1 << 12;
+pub const BIG_HEADS: usize = 1 << 12;
+pub const BIG_LAYERS: usize = 1 << 12;
+pub const BIG_FF: usize = 1 << 20;
+pub const BIG_LEN: usize = 1 << 21;
+pub const BIG_VOCAB: usize = 1 << 24;
+
+/// a model's tokenizer as saved: its `tokenizer.json` and the lexicon's tokens
+#[derive(Serialize, Deserialize)]
+struct SavedLexicon {
+    tokenizer: String,
+    start: u32,
+    end: u32,
+    #[serde(default)]
+    stops: Vec,
+}
+
 #[derive(Serialize, Deserialize)]
 struct Header {
     config: Config,
     /// (heads, ff) of each block, which growth and pruning change
     blocks: Vec<(usize, usize)>,
     heads: Vec,
+    /// the generative head (version 2)
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    generator: Option,
     steer: Steer,
     meta: Meta,
+    /// the tokenizer of a model with its own vocabulary
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    lexicon: Option,
 }
 
 impl Classifier {
@@ -47,8 +76,15 @@ impl Classifier {
             config: self.net.cfg.clone(),
             blocks: self.net.blocks.iter().map(|b| (b.heads, b.ff)).collect(),
             heads: self.net.heads.iter().map(|h| h.spec.clone()).collect(),
+            generator: self.net.generator.clone(),
             steer: self.steer.clone(),
             meta: self.meta.clone(),
+            lexicon: self.net.lexicon.as_ref().map(|l| SavedLexicon {
+                tokenizer: l.tokenizer.source().to_string(),
+                start: l.start,
+                end: l.end,
+                stops: l.stops.clone(),
+            }),
         };
         let json = serde_json::to_vec(&header).expect("header serialises");
         let n = self.net.weight_count();
@@ -80,7 +116,7 @@ impl Classifier {
             return Err("not a classifier file".into());
         }
         let version = u32::from_le_bytes(take(8, 4)?.try_into().unwrap());
-        if version != VERSION {
+        if version != 1 && version != VERSION {
             return Err(format!(
                 "classifier format version {version}, this build reads {VERSION}"
             ));
@@ -103,13 +139,17 @@ impl Classifier {
         }
         let mut cfg = h.config.clone();
         cfg.layers = h.blocks.len();
-        let mut net = Net::new(cfg, &h.heads, 0)?;
+        let mut net = Net::with_gen(cfg, &h.heads, h.generator.clone(), 0)?;
         // reshape the blocks to what was saved, then fill every tensor
         for (blk, &(heads, ff)) in net.blocks.iter_mut().zip(&h.blocks) {
             let (d, a) = (h.config.d_model, heads * h.config.head_dim);
             blk.heads = heads;
             blk.ff = ff;
-            blk.wqkv = vec![0.0; d * 3 * a];
+            let w3 = blk.qkv_width(&h.config);
+            blk.wqkv = vec![0.0; d * w3];
+            if h.config.qkv_bias {
+                blk.bqkv = vec![0.0; w3];
+            }
             blk.wo = vec![0.0; a * d];
             blk.wg = vec![0.0; d * ff];
             blk.wu = vec![0.0; d * ff];
@@ -126,7 +166,22 @@ impl Classifier {
                 at += 4;
             }
         }
-        net.rope = Rope::new(net.cfg.max_len, net.cfg.head_dim, net.cfg.rope_base);
+        net.rope = Rope::of(&net.cfg);
+        if let Some(l) = h.lexicon {
+            let tokenizer = super::bpe::Tokenizer::from_json(&l.tokenizer)?;
+            let ok = |t: u32| (t as usize) < net.cfg.vocab_size;
+            if !ok(l.start) || !ok(l.end) || !l.stops.iter().all(|&t| ok(t)) {
+                return Err("the classifier file's start or end token is out of range".into());
+            }
+            net.lexicon = Some(std::sync::Arc::new(super::bpe::Lexicon {
+                tokenizer,
+                start: l.start,
+                end: l.end,
+                stops: l.stops,
+            }));
+        } else if net.cfg.vocab_size > 0 {
+            return Err("the classifier file has a vocabulary but no tokenizer".into());
+        }
         Ok(Classifier {
             net,
             steer: h.steer,
@@ -170,21 +225,39 @@ fn expected_weights(h: &Header) -> Result {
     use super::text::{LETTERS, ROOT_BUCKETS, SIDE, SUM_BUCKETS, VOCAB};
     let c = &h.config;
     let bad = |what: &str| Err(format!("the classifier file's {what} is out of range"));
-    if c.d_model == 0 || c.d_model > MAX_D_MODEL {
+    let big = c.vocab_size > 0;
+    let pick = |small: usize, large: usize| if big { large } else { small };
+    let (max_d, max_hd, max_heads) = (
+        pick(MAX_D_MODEL, BIG_D_MODEL),
+        pick(MAX_HEAD_DIM, BIG_HEAD_DIM),
+        pick(MAX_HEADS, BIG_HEADS),
+    );
+    let (max_layers, max_ff, max_len) = (
+        pick(MAX_LAYERS, BIG_LAYERS),
+        pick(MAX_FF, BIG_FF),
+        pick(MAX_LEN, BIG_LEN),
+    );
+    if c.d_model == 0 || c.d_model > max_d {
         return bad("width");
     }
-    if c.head_dim == 0 || c.head_dim > MAX_HEAD_DIM || !c.head_dim.is_multiple_of(2) {
+    if c.head_dim == 0 || c.head_dim > max_hd || !c.head_dim.is_multiple_of(2) {
         return bad("head width");
     }
-    if c.heads == 0 || c.heads > MAX_HEADS || c.d_ff == 0 || c.d_ff > MAX_FF {
+    if c.heads == 0 || c.heads > max_heads || c.d_ff == 0 || c.d_ff > max_ff {
         return bad("block shape");
     }
-    if h.blocks.is_empty() || h.blocks.len() > MAX_LAYERS {
+    if c.vocab_size > BIG_VOCAB || (big && h.lexicon.is_none()) {
+        return bad("vocabulary");
+    }
+    if c.kv_heads > 0 && (!c.heads.is_multiple_of(c.kv_heads) || h.blocks.iter().any(|b| b.0 != c.heads)) {
+        return bad("key/value heads");
+    }
+    if h.blocks.is_empty() || h.blocks.len() > max_layers {
         return bad("depth");
     }
     // windows overlap by at most three quarters: a stride of 1 on long windows would make
     // every long text cost thousands of times its length to read
-    if c.max_len < 3 || c.max_len > MAX_LEN || c.stride == 0 || c.stride > MAX_LEN || c.stride * 4 < c.max_len - 2 {
+    if c.max_len < 3 || c.max_len > max_len || c.stride == 0 || c.stride > max_len || c.stride * 4 < c.max_len - 2 {
         return bad("window");
     }
     if c.extra > MAX_EXTRA {
@@ -200,7 +273,7 @@ fn expected_weights(h: &Header) -> Result {
     if ![g.letter, g.word, g.side, g.extra].iter().all(|x| x.is_finite()) {
         return bad("gains");
     }
-    if h.heads.is_empty()
+    if (h.heads.is_empty() && h.generator.is_none())
         || h.heads.len() > MAX_OUT_HEADS
         || h.heads
             .iter()
@@ -220,14 +293,30 @@ fn expected_weights(h: &Header) -> Result {
         return bad("steering");
     }
     let d = c.d_model;
-    let mut n: usize = (VOCAB + LETTERS + 3 * SUM_BUCKETS + ROOT_BUCKETS) * d;
+    let mut n: usize = if big { c.vocab_size } else { VOCAB + c.numbers as usize } * d;
+    n += if c.letters { LETTERS * d } else { 0 }
+        + if c.words {
+            (3 * SUM_BUCKETS + ROOT_BUCKETS) * d
+        } else {
+            0
+        };
+    if c.numbers {
+        n += d;
+    }
+    if h.generator.is_some() {
+        if !c.causal {
+            return bad("generative head (needs a causal model)");
+        }
+        n += (d + 1) * c.gen_out();
+    }
     for &(heads, ff) in &h.blocks {
-        if heads == 0 || heads > MAX_HEADS || ff == 0 || ff > MAX_FF {
+        if heads == 0 || heads > max_heads || ff == 0 || ff > max_ff {
             return bad("block shape");
         }
         let a = heads * c.head_dim;
+        let w3 = (heads + 2 * c.kv_of(heads)) * c.head_dim;
         let qk = if c.qk_norm { 2 * c.head_dim } else { 0 };
-        n += 2 * d + 4 * d * a + qk + 3 * d * ff;
+        n += 2 * d + d * w3 + a * d + qk + 3 * d * ff + if c.qkv_bias { w3 } else { 0 };
     }
     n += d + if c.pooling == Pooling::Attention { d } else { 0 };
     let pooled = if c.pooling == Pooling::ClsMean { 2 * d } else { d };
diff --git a/core/src/classify/kernels.rs b/core/src/classify/kernels.rs
index 4c981bf4..e0551953 100644
--- a/core/src/classify/kernels.rs
+++ b/core/src/classify/kernels.rs
@@ -359,6 +359,7 @@ const MR: usize = 6;
 
 /// A packed for the register tiles: tile t holds rows t·MR.., p-major, zero padded:
 /// `out[(t·k + p)·MR + i] = A[t·MR + i][p]`
+#[cfg_attr(target_arch = "wasm32", allow(dead_code))]
 fn pack(a: Strided, n: usize, k: usize) -> Vec {
     let tiles = n.div_ceil(MR);
     let mut out = vec![0f32; tiles * k * MR];
@@ -466,6 +467,7 @@ unsafe fn gemm_avx2(y: &mut [f32], a: Strided, b: &[f32], n: usize, k: usize, m:
 
 /// columns c0.. of row r, scalar chains
 #[inline(always)]
+#[cfg_attr(target_arch = "wasm32", allow(dead_code))]
 fn tail_cols(y: &mut [f32], a: Strided, b: &[f32], r: usize, c0: usize, k: usize, m: usize) {
     for c in c0..m {
         let mut v = y[r * m + c];
diff --git a/core/src/classify/mod.rs b/core/src/classify/mod.rs
index 264b0e78..d019d1d5 100644
--- a/core/src/classify/mod.rs
+++ b/core/src/classify/mod.rs
@@ -15,27 +15,44 @@
 //! | `metrics` | accuracy, F1, confusion, log-loss, calibration |
 //! | `steer` | the player's knobs (bias, temperature, threshold, gains) and the bias metric |
 //! | `grow` | widening, deepening and pruning, and the policy deciding when |
+//! | `codec` | numbers and pictures (patch codebooks) as bytes, a minimal PNG writer |
 //! | `compose` | classifiers feeding classifiers, outputs as lists, feedback through a stack |
+//! | `generate` | sampling from a generative head, critics, constraints, guidance, reinforcement |
 //! | `io` | the versioned binary file format |
+//! | `spec` | the declarative model spec: inputs, trunk, heads, data queries, critics; build, train, run |
+//! | `bench` | a one-time machine benchmark suggesting model sizes for this hardware |
 //!
 //! Every numeric operation goes through `kernels` and `math`: they are the backend
 //! boundary a GPU implementation would replace.
 
+pub mod bench;
+pub mod bpe;
+pub mod codec;
 pub mod compose;
+pub mod device;
+pub mod generate;
+#[cfg(feature = "gpu")]
+pub mod gpu;
 pub mod grow;
 pub mod io;
 pub mod kernels;
 pub mod math;
 pub mod metrics;
 pub mod model;
+pub mod pattern;
 pub mod pool;
+pub mod pretrained;
+pub mod report;
+pub mod safetensors;
+pub mod spec;
+pub mod speed;
 pub mod steer;
 pub mod text;
 pub mod train;
 
 use serde::{Deserialize, Serialize};
 
-pub use model::{Config, Gains, HeadKind, HeadSpec, Net, Pooling};
+pub use model::{Config, Gains, GenSpec, HeadKind, HeadSpec, Net, Pooling};
 pub use pool::Pool;
 pub use steer::{BiasReport, HeadSteer, Output, Steer};
 pub use train::{Example, Flow, Progress, Target, TrainOpts, TrainReport};
@@ -56,6 +73,10 @@ pub struct Meta {
     pub feedback: Vec,
     /// growth and pruning events, oldest first
     pub log: Vec,
+    /// the declarative spec the model was built from, and anything it learned besides
+    /// weights (a picture codebook); see `spec::Model`
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub spec: Option,
 }
 
 /// how many feedback examples a classifier keeps
@@ -82,7 +103,17 @@ pub struct Run {
 
 impl Classifier {
     pub fn new(cfg: Config, heads: &[HeadSpec], seed: u64) -> Result {
-        let net = Net::new(cfg, heads, seed)?;
+        Classifier::with_gen(cfg, heads, None, seed)
+    }
+
+    /// a model with pooled heads and optionally a generative head (causal configs only)
+    pub fn with_gen(
+        cfg: Config,
+        heads: &[HeadSpec],
+        generator: Option,
+        seed: u64,
+    ) -> Result {
+        let net = Net::with_gen(cfg, heads, generator, seed)?;
         let steer = Steer::neutral(&net.heads);
         Ok(Classifier {
             meta: Meta {
@@ -111,13 +142,23 @@ impl Classifier {
     }
 
     pub fn windows(&self, text: &str) -> Vec {
-        text::windows(text, self.net.cfg.max_len, self.net.cfg.stride)
+        self.windows_of(text.as_bytes())
+    }
+
+    /// the windows of any bytes (causal windows for a causal model)
+    pub fn windows_of(&self, data: &[u8]) -> Vec {
+        self.net.windows_of(data).0
     }
 
     /// every window of a text through the net with the given gains, averaged in window
     /// order; windows run in parallel on the pool, or a lone window's big products do
     pub fn run(&self, text: &str, extra: &[f32], gains: &Gains, pool: Option<&Pool>) -> Run {
-        let ws = self.windows(text);
+        self.run_bytes(text.as_bytes(), extra, gains, pool)
+    }
+
+    /// `run` over any bytes
+    pub fn run_bytes(&self, data: &[u8], extra: &[f32], gains: &Gains, pool: Option<&Pool>) -> Run {
+        let ws = self.windows_of(data);
         let heads = self.net.heads.len();
         let one = |w: &Window, p: Option<&Pool>| {
             let mut tr = self.net.forward(w, extra, gains, Mode::EVAL, p);
@@ -161,10 +202,24 @@ impl Classifier {
     }
 
     pub fn predict_on(&self, text: &str, extra: &[f32], pool: Option<&Pool>) -> Vec {
-        let r = self.run(text, extra, &self.gains(), pool);
+        self.predict_bytes(text.as_bytes(), extra, pool)
+    }
+
+    /// every head's steered output on any bytes
+    pub fn predict_bytes(&self, data: &[u8], extra: &[f32], pool: Option<&Pool>) -> Vec {
+        let r = self.run_bytes(data, extra, &self.gains(), pool);
         self.read(&r.logits)
     }
 
+    /// `predict_bytes` with the trunk on the runner's device (the CPU without one); the
+    /// same outputs, bit for bit on a device the probe finds exact
+    pub fn predict_bytes_with(&self, data: &[u8], extra: &[f32], runner: Option<&device::Runner>) -> Vec {
+        match runner {
+            Some(r) => self.read(&r.text_logits(&self.net, data, extra, &self.gains())),
+            None => self.predict_bytes(data, extra, None),
+        }
+    }
+
     /// steered outputs from window-averaged logits
     pub fn read(&self, logits: &[Vec]) -> Vec {
         logits
diff --git a/core/src/classify/model.rs b/core/src/classify/model.rs
index a5afc947..ae5d6f6f 100644
--- a/core/src/classify/model.rs
+++ b/core/src/classify/model.rs
@@ -1,20 +1,43 @@
-//! The network: an embedder (bytes plus the gematria channels), pre-norm encoder blocks
-//! (RMSNorm, multi-head self-attention with rotary positions and optional QK-norm, SwiGLU
-//! feed-forward, no biases), a final RMSNorm, a pooler, and one or more heads reading
-//! the pooled vector with the side vector and any inputs from other classifiers.
+//! The network: an embedder (bytes, optional NUM tokens, optional feature channels),
+//! pre-norm blocks (RMSNorm, multi-head self-attention with rotary positions and
+//! optional QK-norm, SwiGLU feed-forward, no biases), a final RMSNorm, a pooler, any
+//! number of heads reading the pooled vector (with the side vector and inputs from
+//! other models when configured), and optionally a generative head reading every
+//! position for the next byte.
+//!
+//! A causal model (`Config::causal`) masks attention so each position sees only itself
+//! and earlier ones; that is what lets the generative head be trained on every position
+//! at once and decoded one byte at a time with a cache (`Decoder`), bit for bit equal to
+//! the full pass.
 //!
 //! Weights are row-major `[in × out]`, so every layer is `y = x · W` (see `kernels` for
 //! the summation order). Forward passes keep a `Trace`; `backward` walks it in reverse
 //! and adds this window's gradients into a gradient `Net` of the same shape.
 
+use std::sync::Arc;
+
 use serde::{Deserialize, Serialize};
 
+use super::bpe::Lexicon;
 use super::kernels::{
     self as k, Norm, matmul, norm_back, norm_fwd, rows, softmax_back_rows, softmax_rows, transpose, transposed,
 };
 use super::math::{self, Rng, key, mix, unit};
 use super::pool::Pool;
-use super::text::{self, LETTERS, ROOT_BUCKETS, SIDE, SUM_BUCKETS, VOCAB, Window};
+use super::text::{self, LETTERS, NUM, ROOT_BUCKETS, SIDE, SUM_BUCKETS, VOCAB, Window};
+
+/// the generative head's outputs: the 256 byte values, then END
+pub const GEN_OUT: usize = 257;
+/// the generative head's "the data ends here" (SEP in the input)
+pub const END: usize = 256;
+
+fn yes() -> bool {
+    true
+}
+
+fn one() -> f32 {
+    1.0
+}
 
 /// how the encoder's token vectors become one vector
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
@@ -92,10 +115,64 @@ pub struct Config {
     pub gains: Gains,
     /// residual output projections start at zero (each block starts as the identity)
     pub zero_out: bool,
+    /// the letter value channel (a = 1 .. z = 26) added to each token; off for new
+    /// models, on in files saved before it was optional
+    #[serde(default = "yes")]
+    pub letters: bool,
+    /// the word sum channels (ordinal, reversed, Atbash, digit roots); same defaults
+    #[serde(default = "yes")]
+    pub words: bool,
+    /// causal attention: each position sees only itself and what came before
+    /// (needed by a generative head)
+    #[serde(default)]
+    pub causal: bool,
+    /// NUM tokens: a token row plus value × a learned direction
+    #[serde(default)]
+    pub numbers: bool,
+    /// key/value heads per block (grouped-query attention: each run of
+    /// `heads / kv_heads` query heads shares one); 0 means one per query head
+    #[serde(default, skip_serializing_if = "is_zero")]
+    pub kv_heads: usize,
+    /// a vocabulary of this many tokens (a pretrained model's, read through
+    /// `Net::lexicon`) in place of bytes; 0 means bytes
+    #[serde(default, skip_serializing_if = "is_zero")]
+    pub vocab_size: usize,
+    /// biases on the query, key and value projections (Qwen2)
+    #[serde(default, skip_serializing_if = "is_false")]
+    pub qkv_bias: bool,
+    /// how rotary frequencies are stretched for longer contexts
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub rope_scaling: Option,
+}
+
+fn is_zero(v: &usize) -> bool {
+    *v == 0
+}
+
+fn is_false(v: &bool) -> bool {
+    !*v
+}
+
+/// rotary frequency scaling, as pretrained checkpoints declare it
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(tag = "type", rename_all = "snake_case")]
+pub enum RopeScaling {
+    /// positions divided by `factor` (every frequency over `factor`)
+    Linear { factor: f64 },
+    /// Llama 3.1's: low frequencies over `factor`, high ones kept, a smooth blend between
+    Llama3 {
+        factor: f64,
+        low_freq_factor: f64,
+        high_freq_factor: f64,
+        original_max_position_embeddings: f64,
+    },
 }
 
 impl Config {
-    /// for tests: a few thousand weights
+    /// for tests and CI only: a few thousand weights, so the suite runs in seconds in a
+    /// debug build. Not a size to offer anyone; it is chosen for test speed, not for
+    /// what the hardware can do (see `bench::suggest` for that). Like every preset it
+    /// has no gematria channels; `gematria(true)` opts in.
     pub fn tiny() -> Config {
         Config {
             d_model: 16,
@@ -114,7 +191,43 @@ impl Config {
             extra: 0,
             gains: Gains::default(),
             zero_out: false,
+            letters: false,
+            words: false,
+            causal: false,
+            numbers: false,
+            kv_heads: 0,
+            vocab_size: 0,
+            qkv_bias: false,
+            rope_scaling: None,
         }
+        .gematria(false)
+    }
+
+    /// the gematria features (letter channel, word sum channels, side vector) on or off
+    pub fn gematria(mut self, on: bool) -> Config {
+        self.letters = on;
+        self.words = on;
+        self.side = on;
+        self
+    }
+
+    /// tokens in the embedding table
+    pub fn vocab(&self) -> usize {
+        if self.vocab_size > 0 {
+            self.vocab_size
+        } else {
+            VOCAB + self.numbers as usize
+        }
+    }
+
+    /// the generative head's width: bytes and END, or the vocabulary
+    pub fn gen_out(&self) -> usize {
+        if self.vocab_size > 0 { self.vocab_size } else { GEN_OUT }
+    }
+
+    /// key/value heads of a block with `heads` query heads
+    pub fn kv_of(&self, heads: usize) -> usize {
+        if self.kv_heads == 0 { heads } else { self.kv_heads }
     }
 
     /// about 0.6M weights; trains on a laptop in minutes
@@ -160,6 +273,39 @@ impl Config {
         if !(0.0..1.0).contains(&self.dropout) {
             return Err("dropout must be in [0, 1)".into());
         }
+        if self.causal && matches!(self.pooling, Pooling::Cls | Pooling::ClsMean) {
+            return Err("a causal model pools by mean or attention (CLS sees only itself)".into());
+        }
+        if self.kv_heads > 0 && !self.heads.is_multiple_of(self.kv_heads) {
+            return Err(format!(
+                "{} heads don't split into groups of {} key/value heads",
+                self.heads, self.kv_heads
+            ));
+        }
+        if self.vocab_size > 0 && (self.letters || self.words || self.side || self.numbers) {
+            return Err("a model with its own vocabulary reads tokens, not the byte feature channels".into());
+        }
+        match self.rope_scaling {
+            Some(RopeScaling::Linear { factor }) if !(factor.is_finite() && factor > 0.0) => {
+                return Err("rope scaling factor must be positive".into());
+            }
+            Some(RopeScaling::Llama3 {
+                factor,
+                low_freq_factor,
+                high_freq_factor,
+                original_max_position_embeddings,
+            }) if !(factor > 0.0
+                && low_freq_factor > 0.0
+                && high_freq_factor > low_freq_factor
+                && original_max_position_embeddings > 0.0
+                && factor.is_finite()
+                && high_freq_factor.is_finite()
+                && original_max_position_embeddings.is_finite()) =>
+            {
+                return Err("llama3 rope scaling needs factor > 0 and high_freq_factor > low_freq_factor > 0".into());
+            }
+            _ => {}
+        }
         Ok(())
     }
 
@@ -198,6 +344,27 @@ pub struct HeadSpec {
     pub kind: HeadKind,
     /// class, label or value names; their count is the head's width
     pub classes: Vec,
+    /// how much this head's loss counts when heads train together
+    #[serde(default = "one")]
+    pub weight: f32,
+}
+
+/// the generative head: next byte (or END) at every position of a causal model
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct GenSpec {
+    pub name: String,
+    /// how much its loss counts when heads train together
+    #[serde(default = "one")]
+    pub weight: f32,
+}
+
+impl GenSpec {
+    pub fn new(name: &str) -> GenSpec {
+        GenSpec {
+            name: name.into(),
+            weight: 1.0,
+        }
+    }
 }
 
 impl HeadSpec {
@@ -210,8 +377,14 @@ impl HeadSpec {
             name: name.into(),
             kind,
             classes: classes.iter().map(|c| c.to_string()).collect(),
+            weight: 1.0,
         }
     }
+
+    pub fn weighted(mut self, w: f32) -> HeadSpec {
+        self.weight = w;
+        self
+    }
 }
 
 #[derive(Clone, Debug, PartialEq)]
@@ -220,8 +393,11 @@ pub struct Block {
     pub ff: usize,
     /// RMSNorm gains before attention
     pub n1: Vec,
-    /// [d × 3·heads·head_dim]: queries, keys, values, each head after head
+    /// [d × (heads + 2·kv)·head_dim]: queries (heads), keys (kv), values (kv), each
+    /// head after head; kv = heads unless the config groups them (`Config::kv_heads`)
     pub wqkv: Vec,
+    /// biases of those projections (empty unless `Config::qkv_bias`)
+    pub bqkv: Vec,
     /// QK-norm gains, [head_dim] each (empty without QK-norm)
     pub qn: Vec,
     pub kn: Vec,
@@ -274,11 +450,42 @@ pub struct Rope {
 impl Rope {
     /// angle(t, i) = t · base^(−2i/head_dim), in f64 with `math`'s functions, then rounded
     pub fn new(max_len: usize, head_dim: usize, base: f32) -> Rope {
+        Rope::scaled(max_len, head_dim, base, None)
+    }
+
+    /// the rotation a configuration asks for
+    pub fn of(cfg: &Config) -> Rope {
+        Rope::scaled(cfg.max_len, cfg.head_dim, cfg.rope_base, cfg.rope_scaling.as_ref())
+    }
+
+    /// `new` with the frequencies stretched by `scaling`
+    pub fn scaled(max_len: usize, head_dim: usize, base: f32, scaling: Option<&RopeScaling>) -> Rope {
         let half = head_dim / 2;
         let lb = math::ln64(base as f64);
-        let freq: Vec = (0..half)
+        let mut freq: Vec = (0..half)
             .map(|i| math::exp64(-((2 * i) as f64) / head_dim as f64 * lb))
             .collect();
+        match scaling {
+            None => {}
+            Some(RopeScaling::Linear { factor }) => freq.iter_mut().for_each(|f| *f /= factor),
+            Some(&RopeScaling::Llama3 {
+                factor,
+                low_freq_factor: lo,
+                high_freq_factor: hi,
+                original_max_position_embeddings: old,
+            }) => {
+                let (lo_wave, hi_wave) = (old / lo, old / hi);
+                for f in freq.iter_mut() {
+                    let wave = 2.0 * std::f64::consts::PI / *f;
+                    if wave > lo_wave {
+                        *f /= factor;
+                    } else if wave >= hi_wave {
+                        let smooth = (old / wave - lo) / (hi - lo);
+                        *f = (1.0 - smooth) * *f / factor + smooth * *f;
+                    }
+                }
+            }
+        }
         let (mut cos, mut sin) = (Vec::with_capacity(max_len * half), Vec::with_capacity(max_len * half));
         for t in 0..max_len {
             for f in &freq {
@@ -290,22 +497,32 @@ impl Rope {
         Rope { half, cos, sin }
     }
 
+    /// the cosines and sines, [max_len × head_dim/2] each (for the GPU backend)
+    pub fn tables(&self) -> (&[f32], &[f32]) {
+        (&self.cos, &self.sin)
+    }
+
     /// rotates rows [n × 2·half] in place: (a, b) → (a·c − b·s, a·s + b·c), pairs (i, i+half)
-    fn apply(&self, x: &mut [f32], n: usize) {
-        let (h, d) = (self.half, 2 * self.half);
+    pub fn apply(&self, x: &mut [f32], n: usize) {
+        let d = 2 * self.half;
         for t in 0..n {
-            let row = &mut x[t * d..(t + 1) * d];
-            let (cs, sn) = (&self.cos[t * h..(t + 1) * h], &self.sin[t * h..(t + 1) * h]);
-            for i in 0..h {
-                let (a, b) = (row[i], row[i + h]);
-                row[i] = a * cs[i] - b * sn[i];
-                row[i + h] = a * sn[i] + b * cs[i];
-            }
+            self.apply_at(&mut x[t * d..(t + 1) * d], t);
+        }
+    }
+
+    /// rotates one row as position t
+    pub fn apply_at(&self, row: &mut [f32], t: usize) {
+        let h = self.half;
+        let (cs, sn) = (&self.cos[t * h..(t + 1) * h], &self.sin[t * h..(t + 1) * h]);
+        for i in 0..h {
+            let (a, b) = (row[i], row[i + h]);
+            row[i] = a * cs[i] - b * sn[i];
+            row[i + h] = a * sn[i] + b * cs[i];
         }
     }
 
     /// the transpose: (da, db) → (da·c + db·s, db·c − da·s)
-    fn back(&self, dx: &mut [f32], n: usize) {
+    pub fn back(&self, dx: &mut [f32], n: usize) {
         let (h, d) = (self.half, 2 * self.half);
         for t in 0..n {
             let row = &mut dx[t * d..(t + 1) * d];
@@ -322,11 +539,12 @@ impl Rope {
 #[derive(Clone, Debug, PartialEq)]
 pub struct Net {
     pub cfg: Config,
-    /// byte and special token embeddings [VOCAB × d]
+    /// byte and special token embeddings [vocab × d]
     pub tok: Vec,
-    /// letter value [27 × d]
+    /// letter value [27 × d] (empty without the letter channel)
     pub letter: Vec,
-    /// word sum buckets [97 × d] each, and digit roots [101 × d]
+    /// word sum buckets [97 × d] each, and digit roots [101 × d] (empty without the
+    /// word channels)
     pub word_ord: Vec,
     pub word_rev: Vec,
     pub word_atb: Vec,
@@ -337,7 +555,17 @@ pub struct Net {
     /// attention pooling query [d] (empty for other poolings)
     pub pool_q: Vec,
     pub heads: Vec,
+    /// the NUM value direction [d] (empty without numbers)
+    pub num: Vec,
+    /// the generative head, if any, and its weights [d × out] and [out], out being
+    /// `Config::gen_out` (empty without one)
+    pub generator: Option,
+    pub gen_w: Vec,
+    pub gen_b: Vec,
     pub rope: Rope,
+    /// the tokenizer of a model with its own vocabulary (`Config::vocab_size`), with
+    /// its start and end tokens; None for byte models
+    pub lexicon: Option>,
 }
 
 /// uniform in [−a, a) with a = std·√3, so the variance is std²
@@ -347,8 +575,14 @@ fn init(r: &mut Rng, n: usize, std: f32) -> Vec {
 }
 
 impl Block {
+    /// the width of the query, key and value projections together
+    pub fn qkv_width(&self, cfg: &Config) -> usize {
+        (self.heads + 2 * cfg.kv_of(self.heads)) * cfg.head_dim
+    }
+
     pub fn new(cfg: &Config, r: &mut Rng, zero_out: bool) -> Block {
         let (d, a, f) = (cfg.d_model, cfg.heads * cfg.head_dim, cfg.d_ff);
+        let w3 = (cfg.heads + 2 * cfg.kv_of(cfg.heads)) * cfg.head_dim;
         let din = 1.0 / (d as f32).sqrt();
         let out = |fan: usize| 1.0 / (fan as f32).sqrt() / (2.0 * cfg.layers as f32).sqrt();
         let qk = if cfg.qk_norm {
@@ -356,7 +590,7 @@ impl Block {
         } else {
             Vec::new()
         };
-        let wqkv = init(r, d * 3 * a, din);
+        let wqkv = init(r, d * w3, din);
         let wo = if zero_out {
             vec![0.0; a * d]
         } else {
@@ -374,6 +608,7 @@ impl Block {
             ff: f,
             n1: vec![1.0; d],
             wqkv,
+            bqkv: if cfg.qkv_bias { vec![0.0; w3] } else { Vec::new() },
             qn: qk.clone(),
             kn: qk,
             wo,
@@ -391,6 +626,7 @@ impl Block {
             ff: self.ff,
             n1: z(&self.n1),
             wqkv: z(&self.wqkv),
+            bqkv: z(&self.bqkv),
             qn: z(&self.qn),
             kn: z(&self.kn),
             wo: z(&self.wo),
@@ -404,18 +640,32 @@ impl Block {
 
 impl Net {
     pub fn new(cfg: Config, heads: &[HeadSpec], seed: u64) -> Result {
+        Net::with_gen(cfg, heads, None, seed)
+    }
+
+    /// a net with pooled heads and optionally a generative head (which needs `causal`)
+    pub fn with_gen(cfg: Config, heads: &[HeadSpec], generator: Option, seed: u64) -> Result {
         cfg.validate()?;
-        if heads.is_empty() || heads.iter().any(|h| h.classes.is_empty()) {
-            return Err("a classifier needs at least one head of at least one class".into());
+        if (heads.is_empty() && generator.is_none()) || heads.iter().any(|h| h.classes.is_empty()) {
+            return Err("a model needs at least one head, each of at least one class".into());
+        }
+        if generator.is_some() && !cfg.causal {
+            return Err("a generative head needs a causal model".into());
+        }
+        let fine = |w: f32| w >= 0.0 && w.is_finite();
+        if !heads.iter().all(|h| fine(h.weight)) || generator.as_ref().is_some_and(|g| !fine(g.weight)) {
+            return Err("head loss weights must be finite and not negative".into());
         }
         let mut r = Rng::new(key(&[seed, 0x1417]));
         let d = cfg.d_model;
-        let tok = init(&mut r, VOCAB * d, 0.5);
-        let letter = init(&mut r, LETTERS * d, 0.25);
-        let word_ord = init(&mut r, SUM_BUCKETS * d, 0.25);
-        let word_rev = init(&mut r, SUM_BUCKETS * d, 0.25);
-        let word_atb = init(&mut r, SUM_BUCKETS * d, 0.25);
-        let word_root = init(&mut r, ROOT_BUCKETS * d, 0.25);
+        let rows = if cfg.vocab_size > 0 { cfg.vocab_size } else { VOCAB };
+        let tok = init(&mut r, rows * d, 0.5);
+        let mut table = |on: bool, rows: usize| if on { init(&mut r, rows * d, 0.25) } else { Vec::new() };
+        let letter = table(cfg.letters, LETTERS);
+        let word_ord = table(cfg.words, SUM_BUCKETS);
+        let word_rev = table(cfg.words, SUM_BUCKETS);
+        let word_atb = table(cfg.words, SUM_BUCKETS);
+        let word_root = table(cfg.words, ROOT_BUCKETS);
         let blocks = (0..cfg.layers)
             .map(|_| Block::new(&cfg, &mut r, cfg.zero_out))
             .collect();
@@ -433,8 +683,26 @@ impl Net {
                 b: vec![0.0; s.classes.len()],
             })
             .collect();
-        let rope = Rope::new(cfg.max_len, cfg.head_dim, cfg.rope_base);
+        // tensors new since the first file version draw last, so older shapes start as before
+        let mut tok = tok;
+        let num = if cfg.numbers {
+            tok.extend(init(&mut r, d, 0.5));
+            init(&mut r, d, 0.5)
+        } else {
+            Vec::new()
+        };
+        let (gen_w, gen_b) = if generator.is_some() {
+            let out = cfg.gen_out();
+            (init(&mut r, d * out, 1.0 / (d as f32).sqrt()), vec![0.0; out])
+        } else {
+            (Vec::new(), Vec::new())
+        };
+        let rope = Rope::of(&cfg);
         Ok(Net {
+            num,
+            generator,
+            gen_w,
+            gen_b,
             tok,
             letter,
             word_ord,
@@ -447,6 +715,7 @@ impl Net {
             heads,
             rope,
             cfg,
+            lexicon: None,
         })
     }
 
@@ -473,10 +742,22 @@ impl Net {
                     b: z(&h.b),
                 })
                 .collect(),
+            num: z(&self.num),
+            generator: self.generator.clone(),
+            gen_w: z(&self.gen_w),
+            gen_b: z(&self.gen_b),
             rope: self.rope.clone(),
+            lexicon: self.lexicon.clone(),
         }
     }
 
+    /// what each output is called: the pooled heads, then the generative head
+    pub fn head_names(&self) -> Vec<&str> {
+        let mut v: Vec<&str> = self.heads.iter().map(|h| h.spec.name.as_str()).collect();
+        v.extend(self.generator.iter().map(|g| g.name.as_str()));
+        v
+    }
+
     /// every weight tensor in the fixed order the optimizer and the file format use
     pub fn params(&self) -> Vec<(Kind, &Vec)> {
         use Kind::*;
@@ -492,6 +773,7 @@ impl Net {
             v.extend([
                 (Gain, &b.n1),
                 (Matrix, &b.wqkv),
+                (Bias, &b.bqkv),
                 (Gain, &b.qn),
                 (Gain, &b.kn),
                 (Matrix, &b.wo),
@@ -505,6 +787,8 @@ impl Net {
         for h in &self.heads {
             v.extend([(Matrix, &h.w), (Bias, &h.b)]);
         }
+        // added in file version 2; empty when unused, so version 1 files read unchanged
+        v.extend([(Embedding, &self.num), (Matrix, &self.gen_w), (Bias, &self.gen_b)]);
         v
     }
 
@@ -522,6 +806,7 @@ impl Net {
             v.extend([
                 (Gain, &mut b.n1),
                 (Matrix, &mut b.wqkv),
+                (Bias, &mut b.bqkv),
                 (Gain, &mut b.qn),
                 (Gain, &mut b.kn),
                 (Matrix, &mut b.wo),
@@ -535,6 +820,11 @@ impl Net {
         for h in &mut self.heads {
             v.extend([(Matrix, &mut h.w), (Bias, &mut h.b)]);
         }
+        v.extend([
+            (Embedding, &mut self.num),
+            (Matrix, &mut self.gen_w),
+            (Bias, &mut self.gen_b),
+        ]);
         v
     }
 
@@ -565,7 +855,7 @@ impl Net {
             .map(|b| {
                 let a = b.heads * self.cfg.head_dim;
                 BlockT {
-                    wqkv: transpose(&b.wqkv, d, 3 * a),
+                    wqkv: transpose(&b.wqkv, d, b.qkv_width(&self.cfg)),
                     wo: transpose(&b.wo, a, d),
                     wg: transpose(&b.wg, d, b.ff),
                     wu: transpose(&b.wu, d, b.ff),
@@ -585,6 +875,21 @@ pub struct BlockT {
     pub wd: Vec,
 }
 
+/// causal attention for position t: scores q·k_s·scale for s ≤ t (8-lane dots),
+/// softmax over them into `p` (t + 1 long), out = Σ_s p_s·v_s in ascending s.
+/// `ks` and `vs` hold at least t + 1 rows of `dh`.
+#[allow(clippy::too_many_arguments)]
+pub fn attend_row(q: &[f32], ks: &[f32], vs: &[f32], t: usize, dh: usize, scale: f32, p: &mut [f32], out: &mut [f32]) {
+    for (s, ps) in p.iter_mut().enumerate().take(t + 1) {
+        *ps = k::dot(q, &ks[s * dh..(s + 1) * dh]) * scale;
+    }
+    softmax_rows(&mut p[..t + 1], t + 1);
+    out.iter_mut().for_each(|v| *v = 0.0);
+    for (s, &ps) in p.iter().enumerate().take(t + 1) {
+        k::axpy(out, ps, &vs[s * dh..(s + 1) * dh]);
+    }
+}
+
 /// a dropout mask: 0 or 1/(1 − p) per element, drawn from `mix(key ^ index)`
 pub fn dropout_mask(key: u64, n: usize, p: f32) -> Vec {
     let keep = 1.0 / (1.0 - p);
@@ -595,6 +900,15 @@ pub fn dropout_mask(key: u64, n: usize, p: f32) -> Vec {
     m
 }
 
+/// adds a bias to every row (nothing when it is empty)
+fn add_rows(x: &mut [f32], bias: &[f32]) {
+    if !bias.is_empty() {
+        for row in x.chunks_exact_mut(bias.len()) {
+            row.iter_mut().zip(bias).for_each(|(a, b)| *a += b);
+        }
+    }
+}
+
 fn mul_into(x: &mut [f32], m: &Option>) {
     if let Some(m) = m {
         x.iter_mut().zip(m).for_each(|(a, b)| *a *= b);
@@ -621,7 +935,8 @@ impl Mode {
 pub struct BlockTrace {
     n1: Norm,
     a: Vec,
-    /// per head [n × head_dim]: rotated queries and keys, values
+    /// [n × head_dim]: rotated queries per head; rotated keys and values per key/value
+    /// head (one per head unless grouped); the QK-norms likewise
     q: Vec>,
     kk: Vec>,
     v: Vec>,
@@ -642,7 +957,8 @@ pub struct BlockTrace {
 /// everything one window's forward pass leaves for backward
 pub struct Trace {
     pub n: usize,
-    tokens: Vec,
+    tokens: Vec,
+    values: Vec,
     chan: [Vec; 5],
     gains: Gains,
     m0: Option>,
@@ -699,6 +1015,11 @@ impl Drop for Trace {
 }
 
 impl Trace {
+    /// the window's tokens
+    pub fn tokens(&self) -> &[u32] {
+        &self.tokens
+    }
+
     /// block l's SwiGLU activations [n × ff]
     pub fn act(&self, l: usize) -> &[f32] {
         &self.blocks[l].act
@@ -712,7 +1033,7 @@ impl Trace {
 
 impl Net {
     /// the sum of the embeddings, per element `tok + gl·letter + gw·(((ord + rev) + atb) + root)`
-    fn embed(&self, w: &Window, gains: &Gains) -> Vec {
+    pub(crate) fn embed(&self, w: &Window, gains: &Gains) -> Vec {
         let d = self.cfg.d_model;
         let n = w.len();
         let mut x = vec![0f32; n * d];
@@ -721,15 +1042,26 @@ impl Net {
                 &tab[i as usize * d..(i as usize + 1) * d]
             }
             let tk = &self.tok[w.tokens[t] as usize * d..(w.tokens[t] as usize + 1) * d];
-            let le = row(&self.letter, w.letter[t], d);
-            let wo = row(&self.word_ord, w.ordinal[t], d);
-            let wr = row(&self.word_rev, w.reversed[t], d);
-            let wa = row(&self.word_atb, w.atbash[t], d);
-            let wq = row(&self.word_root, w.root[t], d);
             let xr = &mut x[t * d..(t + 1) * d];
-            for i in 0..d {
-                let word = ((wo[i] + wr[i]) + wa[i]) + wq[i];
-                xr[i] = (tk[i] + gains.letter * le[i]) + gains.word * word;
+            xr.copy_from_slice(tk);
+            if self.cfg.letters {
+                let le = row(&self.letter, w.letter[t], d);
+                for i in 0..d {
+                    xr[i] += gains.letter * le[i];
+                }
+            }
+            if self.cfg.words {
+                let wo = row(&self.word_ord, w.ordinal[t], d);
+                let wr = row(&self.word_rev, w.reversed[t], d);
+                let wa = row(&self.word_atb, w.atbash[t], d);
+                let wq = row(&self.word_root, w.root[t], d);
+                for i in 0..d {
+                    xr[i] += gains.word * (((wo[i] + wr[i]) + wa[i]) + wq[i]);
+                }
+            }
+            if w.tokens[t] == NUM && !self.num.is_empty() {
+                let v = w.value(t);
+                k::axpy(xr, v, &self.num);
             }
         }
         x
@@ -749,43 +1081,75 @@ impl Net {
         for (l, b) in self.blocks.iter().enumerate() {
             let l = l as u64 + 1;
             let a_w = b.heads * dh;
+            let kv = cfg.kv_of(b.heads);
+            let (w3, per) = (b.qkv_width(cfg), b.heads / kv);
             let (a, n1) = norm_fwd(&x, &b.n1, d, cfg.norm_eps);
-            let qkv = matmul(rows(&a, d), &b.wqkv, n, d, 3 * a_w, pool);
+            let mut qkv = matmul(rows(&a, d), &b.wqkv, n, d, w3, pool);
+            add_rows(&mut qkv, &b.bqkv);
             let mut ctx = k::zeros(n * a_w);
             let (mut qs, mut ks, mut vs, mut qns, mut kns, mut ps) = (vec![], vec![], vec![], vec![], vec![], vec![]);
+            let take = |off: usize| -> Vec {
+                let mut o = k::zeros(n * dh);
+                for t in 0..n {
+                    let s = t * w3 + off;
+                    o[t * dh..(t + 1) * dh].copy_from_slice(&qkv[s..s + dh]);
+                }
+                o
+            };
             for h in 0..b.heads {
-                let take = |off: usize| -> Vec {
-                    let mut o = k::zeros(n * dh);
-                    for t in 0..n {
-                        let s = t * 3 * a_w + off + h * dh;
-                        o[t * dh..(t + 1) * dh].copy_from_slice(&qkv[s..s + dh]);
+                let g = h / per;
+                if h % per == 0 {
+                    // this group's keys and values, normed and rotated once
+                    let (mut kh, v) = (take(a_w + g * dh), take(a_w + kv * dh + g * dh));
+                    if cfg.qk_norm {
+                        let (kq, kn) = norm_fwd(&kh, &b.kn, dh, cfg.norm_eps);
+                        k::recycle(std::mem::replace(&mut kh, kq));
+                        kns.push(kn);
                     }
-                    o
-                };
-                let (mut q, mut kh, v) = (take(0), take(a_w), take(2 * a_w));
+                    self.rope.apply(&mut kh, n);
+                    ks.push(kh);
+                    vs.push(v);
+                }
+                let mut q = take(h * dh);
                 if cfg.qk_norm {
                     let (qq, qn) = norm_fwd(&q, &b.qn, dh, cfg.norm_eps);
-                    let (kq, kn) = norm_fwd(&kh, &b.kn, dh, cfg.norm_eps);
                     k::recycle(std::mem::replace(&mut q, qq));
-                    k::recycle(std::mem::replace(&mut kh, kq));
                     qns.push(qn);
-                    kns.push(kn);
                 }
                 self.rope.apply(&mut q, n);
-                self.rope.apply(&mut kh, n);
-                let kt = transpose(&kh, n, dh);
-                let mut s = matmul(rows(&q, dh), &kt, n, dh, n, None);
-                s.iter_mut().for_each(|v| *v *= scale);
-                softmax_rows(&mut s, n);
-                let o = matmul(rows(&s, n), &v, n, n, dh, None);
-                for t in 0..n {
-                    ctx[t * a_w + h * dh..t * a_w + (h + 1) * dh].copy_from_slice(&o[t * dh..(t + 1) * dh]);
-                }
-                k::recycle(o);
-                k::recycle(kt);
+                let (kh, v) = (&ks[g], &vs[g]);
+                let s = if cfg.causal {
+                    // row by row over the positions so far, exactly as `Decoder` does;
+                    // the probabilities after t stay 0, which backward relies on
+                    let mut s = k::zeros(n * n);
+                    for t in 0..n {
+                        let c = &mut ctx[t * a_w + h * dh..t * a_w + (h + 1) * dh];
+                        attend_row(
+                            &q[t * dh..(t + 1) * dh],
+                            kh,
+                            v,
+                            t,
+                            dh,
+                            scale,
+                            &mut s[t * n..t * n + t + 1],
+                            c,
+                        );
+                    }
+                    s
+                } else {
+                    let kt = transpose(kh, n, dh);
+                    let mut s = matmul(rows(&q, dh), &kt, n, dh, n, None);
+                    s.iter_mut().for_each(|v| *v *= scale);
+                    softmax_rows(&mut s, n);
+                    let o = matmul(rows(&s, n), v, n, n, dh, None);
+                    for t in 0..n {
+                        ctx[t * a_w + h * dh..t * a_w + (h + 1) * dh].copy_from_slice(&o[t * dh..(t + 1) * dh]);
+                    }
+                    k::recycle(o);
+                    k::recycle(kt);
+                    s
+                };
                 qs.push(q);
-                ks.push(kh);
-                vs.push(v);
                 ps.push(s);
             }
             let mut o = matmul(rows(&ctx, a_w), &b.wo, n, a_w, d, pool);
@@ -871,6 +1235,7 @@ impl Net {
         Trace {
             n,
             tokens: w.tokens.clone(),
+            values: w.values.clone(),
             chan: [
                 w.letter.clone(),
                 w.ordinal.clone(),
@@ -899,9 +1264,24 @@ impl Net {
         y
     }
 
+    /// the generative head's logits at every position, [n × GEN_OUT]: row t predicts
+    /// the token after position t
+    pub fn gen_logits(&self, tr: &Trace) -> Vec {
+        assert!(self.generator.is_some(), "no generative head");
+        let d = self.cfg.d_model;
+        let mut y = matmul(rows(&tr.xf, d), &self.gen_w, tr.n, d, self.cfg.gen_out(), None);
+        add_rows(&mut y, &self.gen_b);
+        y
+    }
+
     /// adds one window's gradients into `g`, given d(loss)/d(logits) for each head
     /// (empty for heads without a loss). Returns d(loss)/d(extra inputs), for stacks.
     pub fn backward(&self, tr: &Trace, dlogits: &[Vec], tp: &[BlockT], g: &mut Net) -> Vec {
+        self.backward_gen(tr, dlogits, &[], tp, g)
+    }
+
+    /// `backward` with d(loss)/d(generative logits) too ([n × `Config::gen_out`], or empty)
+    pub fn backward_gen(&self, tr: &Trace, dlogits: &[Vec], dgen: &[f32], tp: &[BlockT], g: &mut Net) -> Vec {
         let cfg = &self.cfg;
         let (d, dh, n) = (cfg.d_model, cfg.head_dim, tr.n);
         let zl = tr.z.len();
@@ -948,6 +1328,15 @@ impl Net {
                 }
             }
         }
+        if !dgen.is_empty() {
+            let out = cfg.gen_out();
+            k::gemm(&mut g.gen_w, transposed(&tr.xf, d), dgen, d, n, out, None);
+            for row in dgen.chunks_exact(out) {
+                g.gen_b.iter_mut().zip(row).for_each(|(a, b)| *a += b);
+            }
+            let wt = transpose(&self.gen_w, d, out);
+            k::gemm(&mut dxf, rows(dgen, out), &wt, n, out, d, None);
+        }
         let mut dx = k::zeros(n * d);
         norm_back(&dxf, &tr.nf, &self.nf, d, &mut dx, &mut g.nf);
         let scale = 1.0 / (dh as f32).sqrt();
@@ -980,43 +1369,70 @@ impl Net {
             mul_into(&mut dout, &bt.m1);
             k::gemm(&mut gb.wo, transposed(&bt.ctx, a_w), &dout, a_w, n, d, None);
             let dctx = matmul(rows(&dout, d), &t.wo, n, d, a_w, None);
-            let mut dqkv = k::zeros(n * 3 * a_w);
+            let kv = cfg.kv_of(b.heads);
+            let (w3, per) = (b.qkv_width(cfg), b.heads / kv);
+            let mut dqkv = k::zeros(n * w3);
+            let put = |dqkv: &mut [f32], off: usize, src: &[f32]| {
+                for r in 0..n {
+                    dqkv[r * w3 + off..r * w3 + off + dh].copy_from_slice(&src[r * dh..(r + 1) * dh]);
+                }
+            };
+            // a group's key and value gradients, summed over its heads in head order
+            let (mut dkg, mut dvg): (Option>, Option>) = (None, None);
+            let add = |acc: &mut Option>, x: Vec| match acc {
+                Some(a) => {
+                    a.iter_mut().zip(&x).for_each(|(p, q)| *p += q);
+                    k::recycle(x);
+                }
+                None => *acc = Some(x),
+            };
             for h in 0..b.heads {
+                let g = h / per;
                 let mut dco = k::zeros(n * dh);
                 for r in 0..n {
                     dco[r * dh..(r + 1) * dh].copy_from_slice(&dctx[r * a_w + h * dh..r * a_w + (h + 1) * dh]);
                 }
-                let (q, kh, v, pr) = (&bt.q[h], &bt.kk[h], &bt.v[h], &bt.probs[h]);
+                let (q, kh, v, pr) = (&bt.q[h], &bt.kk[g], &bt.v[g], &bt.probs[h]);
                 let vt = transpose(v, n, dh);
                 let mut ds = matmul(rows(&dco, dh), &vt, n, dh, n, None);
                 let dv = matmul(transposed(pr, n), &dco, n, n, dh, None);
                 softmax_back_rows(pr, &mut ds, n);
                 ds.iter_mut().for_each(|v| *v *= scale);
                 let mut dq = matmul(rows(&ds, n), kh, n, n, dh, None);
-                let mut dk = matmul(transposed(&ds, n), q, n, n, dh, None);
+                let dk = matmul(transposed(&ds, n), q, n, n, dh, None);
                 self.rope.back(&mut dq, n);
-                self.rope.back(&mut dk, n);
                 if cfg.qk_norm {
                     let mut dq0 = k::zeros(n * dh);
                     norm_back(&dq, &bt.qn[h], &b.qn, dh, &mut dq0, &mut gb.qn);
-                    let mut dk0 = k::zeros(n * dh);
-                    norm_back(&dk, &bt.kn[h], &b.kn, dh, &mut dk0, &mut gb.kn);
                     k::recycle(std::mem::replace(&mut dq, dq0));
-                    k::recycle(std::mem::replace(&mut dk, dk0));
                 }
-                for r in 0..n {
-                    let row = &mut dqkv[r * 3 * a_w..(r + 1) * 3 * a_w];
-                    let src = r * dh..(r + 1) * dh;
-                    row[h * dh..(h + 1) * dh].copy_from_slice(&dq[src.clone()]);
-                    row[a_w + h * dh..a_w + (h + 1) * dh].copy_from_slice(&dk[src.clone()]);
-                    row[2 * a_w + h * dh..2 * a_w + (h + 1) * dh].copy_from_slice(&dv[src]);
+                put(&mut dqkv, h * dh, &dq);
+                add(&mut dkg, dk);
+                add(&mut dvg, dv);
+                if h % per == per - 1 {
+                    let (mut dk, dv) = (dkg.take().expect("summed"), dvg.take().expect("summed"));
+                    self.rope.back(&mut dk, n);
+                    if cfg.qk_norm {
+                        let mut dk0 = k::zeros(n * dh);
+                        norm_back(&dk, &bt.kn[g], &b.kn, dh, &mut dk0, &mut gb.kn);
+                        k::recycle(std::mem::replace(&mut dk, dk0));
+                    }
+                    put(&mut dqkv, a_w + g * dh, &dk);
+                    put(&mut dqkv, a_w + kv * dh + g * dh, &dv);
+                    k::recycle(dk);
+                    k::recycle(dv);
                 }
-                for v in [dco, vt, ds, dv, dq, dk] {
+                for v in [dco, vt, ds, dq] {
                     k::recycle(v);
                 }
             }
-            k::gemm(&mut gb.wqkv, transposed(&bt.a, d), &dqkv, d, n, 3 * a_w, None);
-            let da = matmul(rows(&dqkv, 3 * a_w), &t.wqkv, n, 3 * a_w, d, None);
+            if !gb.bqkv.is_empty() {
+                for row in dqkv.chunks_exact(w3) {
+                    gb.bqkv.iter_mut().zip(row).for_each(|(a, b)| *a += b);
+                }
+            }
+            k::gemm(&mut gb.wqkv, transposed(&bt.a, d), &dqkv, d, n, w3, None);
+            let da = matmul(rows(&dqkv, w3), &t.wqkv, n, w3, d, None);
             let mut dxin = dhres;
             norm_back(&da, &bt.n1, &b.n1, d, &mut dxin, &mut gb.n1);
             for v in [dout, dctx, dqkv, da] {
@@ -1032,22 +1448,320 @@ impl Net {
             let rows_of = |i: u8| i as usize * d..(i as usize + 1) * d;
             let tk = tr.tokens[t] as usize;
             g.tok[tk * d..(tk + 1) * d].iter_mut().zip(r).for_each(|(a, b)| *a += b);
+            if tr.tokens[t] == NUM && !g.num.is_empty() {
+                let v = tr.values.get(t).copied().unwrap_or(0.0);
+                g.num.iter_mut().zip(r).for_each(|(a, b)| *a += v * b);
+            }
             let dl: Vec = r.iter().map(|v| gn.letter * v).collect();
             let dw: Vec = r.iter().map(|v| gn.word * v).collect();
             let [cl, co, cr, ca, cq] = &tr.chan;
             let add = |tab: &mut Vec, idx: u8, v: &[f32]| {
                 tab[rows_of(idx)].iter_mut().zip(v).for_each(|(a, b)| *a += b);
             };
-            add(&mut g.letter, cl[t], &dl);
-            add(&mut g.word_ord, co[t], &dw);
-            add(&mut g.word_rev, cr[t], &dw);
-            add(&mut g.word_atb, ca[t], &dw);
-            add(&mut g.word_root, cq[t], &dw);
+            if self.cfg.letters {
+                add(&mut g.letter, cl[t], &dl);
+            }
+            if self.cfg.words {
+                add(&mut g.word_ord, co[t], &dw);
+                add(&mut g.word_rev, cr[t], &dw);
+                add(&mut g.word_atb, ca[t], &dw);
+                add(&mut g.word_root, cq[t], &dw);
+            }
         }
         dextra
     }
 }
 
+/// One token (a byte, or a vocabulary token for a pretrained model) at a time through a
+/// causal model with a key/value cache, giving the generative head's logits for the
+/// next one. Each step computes exactly what the full forward pass computes for that
+/// position (the same row operations in the same order), so decoding equals
+/// `gen_logits` bit for bit. When the window is full the decoder starts over from the
+/// start token (CLS, or the lexicon's) with the last half window.
+pub struct Decoder<'a> {
+    net: &'a Net,
+    gains: Gains,
+    /// the tokens in the current window (after its start token)
+    seq: Vec,
+    /// per block, per key/value head: rotated keys and values, rows of head_dim
+    keys: Vec>>,
+    vals: Vec>>,
+    logits: Vec,
+}
+
+impl<'a> Decoder<'a> {
+    /// a decoder that has read the start token and then `prompt` (bytes; a model with
+    /// a vocabulary encodes them with its tokenizer)
+    pub fn new(net: &'a Net, gains: Gains, prompt: &[u8]) -> Decoder<'a> {
+        let mut dec = Decoder::empty(net, gains);
+        match &net.lexicon {
+            Some(lx) => {
+                for t in lx.encode_split(prompt, 0).0 {
+                    dec.push_token(t);
+                }
+            }
+            None => {
+                for &b in prompt {
+                    dec.push(b);
+                }
+            }
+        }
+        dec
+    }
+
+    /// a decoder that has read the start token and then these token ids
+    pub fn from_tokens(net: &'a Net, gains: Gains, prompt: &[u32]) -> Decoder<'a> {
+        let mut dec = Decoder::empty(net, gains);
+        for &t in prompt {
+            dec.push_token(t);
+        }
+        dec
+    }
+
+    fn empty(net: &'a Net, gains: Gains) -> Decoder<'a> {
+        assert!(
+            net.cfg.causal && net.generator.is_some(),
+            "decoding needs a causal model with a generative head"
+        );
+        let mut dec = Decoder {
+            net,
+            gains,
+            seq: Vec::new(),
+            keys: Vec::new(),
+            vals: Vec::new(),
+            logits: Vec::new(),
+        };
+        dec.restart(&[]);
+        dec
+    }
+
+    /// the logits for the next token (`Config::gen_out` of them: bytes then END, or
+    /// the vocabulary)
+    pub fn logits(&self) -> &[f32] {
+        &self.logits
+    }
+
+    /// the bytes the current window holds
+    pub fn window(&self) -> Vec {
+        self.net.token_bytes(&self.seq)
+    }
+
+    /// the tokens the current window holds (after the start token)
+    pub fn tokens(&self) -> &[u32] {
+        &self.seq
+    }
+
+    fn restart(&mut self, keep: &[u32]) {
+        let net = self.net;
+        let kv = |b: &Block| vec![Vec::new(); net.cfg.kv_of(b.heads)];
+        self.keys = net.blocks.iter().map(kv).collect();
+        self.vals = net.blocks.iter().map(kv).collect();
+        self.seq.clear();
+        self.step(net.start_token());
+        for &t in keep {
+            self.seq.push(t);
+            self.step(t);
+        }
+    }
+
+    /// reads one more byte (byte models)
+    pub fn push(&mut self, b: u8) {
+        self.push_token(b as u32);
+    }
+
+    /// reads one more token
+    pub fn push_token(&mut self, t: u32) {
+        if self.seq.len() + 1 >= self.net.cfg.max_len {
+            let keep = self.seq[self.seq.len() - self.net.cfg.room() / 2..].to_vec();
+            self.restart(&keep);
+        }
+        self.seq.push(t);
+        self.step(t);
+    }
+
+    fn step(&mut self, token: u32) {
+        let net = self.net;
+        let cfg = &net.cfg;
+        let (d, dh) = (cfg.d_model, cfg.head_dim);
+        let pos = self.seq.len();
+        // the channels of this position, as a causal window computes them
+        let mut w1 = Window {
+            tokens: vec![token],
+            letter: vec![0],
+            ordinal: vec![0],
+            reversed: vec![0],
+            atbash: vec![0],
+            root: vec![0],
+            ..Window::default()
+        };
+        if pos > 0 && (cfg.letters || cfg.words) {
+            let bytes: Vec = self.seq.iter().map(|&t| t as u8).collect();
+            let w = text::window_with(&bytes, true, false);
+            w1.letter[0] = w.letter[pos];
+            w1.ordinal[0] = w.ordinal[pos];
+            w1.reversed[0] = w.reversed[pos];
+            w1.atbash[0] = w.atbash[pos];
+            w1.root[0] = w.root[pos];
+        }
+        let mut x = net.embed(&w1, &self.gains);
+        let scale = 1.0 / (dh as f32).sqrt();
+        for (l, b) in net.blocks.iter().enumerate() {
+            let a_w = b.heads * dh;
+            let kv = cfg.kv_of(b.heads);
+            let (w3, per) = (b.qkv_width(cfg), b.heads / kv);
+            let (a, _) = norm_fwd(&x, &b.n1, d, cfg.norm_eps);
+            let mut qkv = matmul(rows(&a, d), &b.wqkv, 1, d, w3, None);
+            add_rows(&mut qkv, &b.bqkv);
+            let mut ctx = vec![0f32; a_w];
+            let mut p = vec![0f32; pos + 1];
+            for h in 0..b.heads {
+                let g = h / per;
+                if h % per == 0 {
+                    let mut kh = qkv[a_w + g * dh..a_w + (g + 1) * dh].to_vec();
+                    let v = &qkv[a_w + (kv + g) * dh..a_w + (kv + g + 1) * dh];
+                    if cfg.qk_norm {
+                        kh = norm_fwd(&kh, &b.kn, dh, cfg.norm_eps).0;
+                    }
+                    net.rope.apply_at(&mut kh, pos);
+                    self.keys[l][g].extend_from_slice(&kh);
+                    self.vals[l][g].extend_from_slice(v);
+                }
+                let mut q = qkv[h * dh..(h + 1) * dh].to_vec();
+                if cfg.qk_norm {
+                    q = norm_fwd(&q, &b.qn, dh, cfg.norm_eps).0;
+                }
+                net.rope.apply_at(&mut q, pos);
+                attend_row(
+                    &q,
+                    &self.keys[l][g],
+                    &self.vals[l][g],
+                    pos,
+                    dh,
+                    scale,
+                    &mut p,
+                    &mut ctx[h * dh..(h + 1) * dh],
+                );
+            }
+            let o = matmul(rows(&ctx, a_w), &b.wo, 1, a_w, d, None);
+            let hres: Vec = x.iter().zip(&o).map(|(a, b)| a + b).collect();
+            let (bn, _) = norm_fwd(&hres, &b.n2, d, cfg.norm_eps);
+            let g = matmul(rows(&bn, d), &b.wg, 1, d, b.ff, None);
+            let u = matmul(rows(&bn, d), &b.wu, 1, d, b.ff, None);
+            let mut s = vec![0f32; g.len()];
+            k::sigmoid_slice(&g, &mut s);
+            let act: Vec = g.iter().zip(&s).zip(&u).map(|((g, s), u)| (g * s) * u).collect();
+            let dn = matmul(rows(&act, b.ff), &b.wd, 1, b.ff, d, None);
+            x = hres.iter().zip(&dn).map(|(a, b)| a + b).collect();
+        }
+        let (xf, _) = norm_fwd(&x, &net.nf, d, cfg.norm_eps);
+        let mut y = matmul(rows(&xf, d), &net.gen_w, 1, d, cfg.gen_out(), None);
+        y.iter_mut().zip(&net.gen_b).for_each(|(a, b)| *a += b);
+        self.logits = y;
+    }
+}
+
+impl Net {
+    /// the token every window starts with: CLS, or the lexicon's start
+    pub fn start_token(&self) -> u32 {
+        self.lexicon.as_ref().map_or(text::CLS, |l| l.start)
+    }
+
+    /// the generative head's "the data ends here": END, or the lexicon's end token
+    pub fn end_index(&self) -> usize {
+        self.lexicon.as_ref().map_or(END, |l| l.end as usize)
+    }
+
+    /// whether a generated index ends the output
+    pub fn ends(&self, t: usize) -> bool {
+        match &self.lexicon {
+            Some(l) => u32::try_from(t).is_ok_and(|t| l.stops(t)),
+            None => t == END,
+        }
+    }
+
+    /// the bytes a generated index (or window token) stands for
+    pub fn index_bytes(&self, t: usize) -> Vec {
+        match &self.lexicon {
+            Some(l) => l.tokenizer.token_bytes(t as u32),
+            None if t < 256 => vec![t as u8],
+            None => Vec::new(),
+        }
+    }
+
+    /// tokens back to bytes (special tokens of a lexicon left out)
+    pub fn token_bytes(&self, ts: &[u32]) -> Vec {
+        match &self.lexicon {
+            Some(l) => ts
+                .iter()
+                .filter(|&&t| !l.tokenizer.is_special(t))
+                .flat_map(|&t| l.tokenizer.token_bytes(t))
+                .collect(),
+            None => ts.iter().filter(|&&t| t < 256).map(|&t| t as u8).collect(),
+        }
+    }
+
+    /// the data as the token sequence this net reads, with the token index where
+    /// `data[from..]` starts: bytes as they are, or ids from the lexicon (prompt and
+    /// continuation encoded apart)
+    pub fn sequence(&self, data: &[u8], from: usize) -> (Vec, usize) {
+        match &self.lexicon {
+            Some(l) => l.encode_split(data, from),
+            None => (data.iter().map(|&b| b as u32).collect(), from),
+        }
+    }
+
+    /// one window over tokens `ts` (from `sequence`): the start token, the tokens and,
+    /// when `end`, the end token. Byte models get their feature channels as
+    /// `text::window_with` computes them (bit for bit the same window).
+    pub fn window_tokens(&self, ts: &[u32], end: bool) -> Window {
+        match &self.lexicon {
+            None => {
+                let bytes: Vec = ts.iter().map(|&t| t as u8).collect();
+                text::window_with(&bytes, self.cfg.causal, end)
+            }
+            Some(l) => {
+                let mut tokens = Vec::with_capacity(ts.len() + 2);
+                tokens.push(l.start);
+                tokens.extend_from_slice(ts);
+                if end {
+                    tokens.push(l.end);
+                }
+                Window {
+                    tokens,
+                    ..Window::default()
+                }
+            }
+        }
+    }
+
+    /// every window of some data, and where each starts in the token sequence
+    /// (`text::windows_of` for byte models)
+    pub fn windows_of(&self, data: &[u8]) -> (Vec, Vec) {
+        let c = &self.cfg;
+        if self.lexicon.is_none() {
+            let ws = text::windows_of(data, c.max_len, c.stride, c.causal);
+            return (ws, text::starts(data.len(), c.room(), c.stride));
+        }
+        let (ts, _) = self.sequence(data, 0);
+        self.windows_over(&ts)
+    }
+
+    /// every window of a token sequence, and their starts
+    pub fn windows_over(&self, ts: &[u32]) -> (Vec, Vec) {
+        let c = &self.cfg;
+        let room = c.room().max(1);
+        let starts = text::starts(ts.len(), room, c.stride);
+        let ws = starts
+            .iter()
+            .map(|&s| {
+                let e = (s + room).min(ts.len());
+                self.window_tokens(&ts[s..e], !c.causal || e == ts.len())
+            })
+            .collect();
+        (ws, starts)
+    }
+}
+
 /// a window for this net's sequence length
 pub fn window_of(cfg: &Config, bytes: &[u8]) -> Window {
     text::window(&bytes[..bytes.len().min(cfg.room())])
@@ -1145,10 +1859,125 @@ mod tests {
                     pooling,
                     qk_norm,
                     extra: 2,
-                    ..Config::tiny()
+                    ..Config::tiny().gematria(true)
                 });
             }
         }
+        // no gematria; grouped key/value heads with q/k/v biases (pretrained shapes)
+        check(Config {
+            extra: 2,
+            ..Config::tiny()
+        });
+        check(Config {
+            heads: 4,
+            kv_heads: 2,
+            qkv_bias: true,
+            extra: 2,
+            ..Config::tiny()
+        });
+    }
+
+    /// a causal model with a generative head, numbers and no gematria: finite
+    /// differences on every tensor through the generative logits and a pooled head
+    #[test]
+    fn generative_gradients_match_finite_differences() {
+        let cfg = Config {
+            causal: true,
+            numbers: true,
+            pooling: Pooling::Mean,
+            ..Config::tiny().gematria(false)
+        };
+        let heads = [HeadSpec::single("a", &["x", "y"])];
+        let mut net = Net::with_gen(cfg.clone(), &heads, Some(GenSpec::new("next")), 4).unwrap();
+        let mut r = Rng::new(10);
+        for (_, t) in net.params_mut() {
+            for v in t.iter_mut() {
+                *v += r.symmetric(0.05);
+            }
+        }
+        let mut w = text::window_with(b"owl and cat", true, true);
+        w.push_numbers(&[0.5, -1.25]);
+        let n = w.len();
+        let ch: Vec = (0..2).map(|_| r.symmetric(1.0)).collect();
+        let cg: Vec = (0..n * GEN_OUT).map(|_| r.symmetric(1.0)).collect();
+        let loss = |net: &Net| {
+            let tr = net.forward(&w, &[], &Gains::default(), Mode::EVAL, None);
+            k::dot(&net.logits(&tr, 0), &ch) + k::dot(&net.gen_logits(&tr), &cg)
+        };
+        let tr = net.forward(&w, &[], &Gains::default(), Mode::EVAL, None);
+        let mut g = net.zeros_like();
+        net.backward_gen(&tr, std::slice::from_ref(&ch), &cg, &net.transposes(), &mut g);
+        drop(tr);
+        let grads: Vec> = g.params().into_iter().map(|(_, t)| t.clone()).collect();
+        let eps = 4e-3f32;
+        let mut checked = 0;
+        for (ti, gt) in grads.iter().enumerate() {
+            for s in 0..4 {
+                if gt.is_empty() {
+                    break;
+                }
+                let i = (mix(ti as u64 * 31 + s) as usize) % gt.len();
+                if gt[i] == 0.0 && ti == 0 {
+                    continue;
+                }
+                let orig = net.params()[ti].1[i];
+                net.params_mut()[ti].1[i] = orig + eps;
+                let up = loss(&net);
+                net.params_mut()[ti].1[i] = orig - eps;
+                let dn = loss(&net);
+                net.params_mut()[ti].1[i] = orig;
+                let num = (up - dn) / (2.0 * eps);
+                // f32 differences of a sum over every logit: a little noise at this eps
+                let tol = 8e-3 + 3e-2 * num.abs().max(gt[i].abs());
+                assert!(
+                    (num - gt[i]).abs() <= tol,
+                    "tensor {ti} [{i}]: numeric {num} analytic {}",
+                    gt[i]
+                );
+                checked += 1;
+            }
+        }
+        assert!(checked > 40);
+    }
+
+    /// decoding with the cache equals the full causal pass, bit for bit, including
+    /// across a window restart
+    #[test]
+    fn decoder_equals_the_full_pass() {
+        for gematria in [false, true] {
+            let cfg = Config {
+                causal: true,
+                pooling: Pooling::Mean,
+                max_len: 12,
+                stride: 5,
+                ..Config::tiny().gematria(gematria)
+            };
+            let net = Net::with_gen(cfg, &[], Some(GenSpec::new("next")), 7).unwrap();
+            let text = b"Ab cd, efg";
+            let mut dec = Decoder::new(&net, Gains::default(), &[]);
+            let w = text::window_with(text, true, false);
+            let tr = net.forward(&w, &[], &Gains::default(), Mode::EVAL, None);
+            let full = net.gen_logits(&tr);
+            assert_eq!(dec.logits(), &full[..GEN_OUT]);
+            for (i, &b) in text.iter().enumerate() {
+                dec.push(b);
+                assert_eq!(
+                    dec.logits(),
+                    &full[(i + 1) * GEN_OUT..(i + 2) * GEN_OUT],
+                    "position {}",
+                    i + 1
+                );
+            }
+            // past max_len the decoder keeps the last half window
+            dec.push(b'!');
+            dec.push(b'?');
+            let kept = dec.window().to_vec();
+            assert_eq!(kept, b" efg!?");
+            let w = text::window_with(&kept, true, false);
+            let tr = net.forward(&w, &[], &Gains::default(), Mode::EVAL, None);
+            let full = net.gen_logits(&tr);
+            assert_eq!(dec.logits(), &full[kept.len() * GEN_OUT..]);
+        }
     }
 
     #[test]
diff --git a/core/src/classify/pattern.rs b/core/src/classify/pattern.rs
new file mode 100644
index 00000000..e4de68af
--- /dev/null
+++ b/core/src/classify/pattern.rs
@@ -0,0 +1,503 @@
+//! A small backtracking regular expression matcher, enough for the pre-tokenizer
+//! patterns tokenizers ship (GPT-2, Llama 3, Qwen2, StarCoder and their relatives):
+//! alternation, groups (`(…)`, `(?:…)`, `(?i:…)`), lookahead (`(?=…)`, `(?!…)`),
+//! greedy quantifiers (`? * + {n} {n,} {n,m}`), `.`, classes (`[…]`, `[^…]`, ranges)
+//! and the escapes `\s \S \d \D \w \W \r \n \t \p{…} \P{…}`.
+//!
+//! Matching is leftmost-first with backtracking, as in Oniguruma and `fancy-regex`
+//! (which the tokenizers library uses), so alternatives are tried in order. Unicode
+//! properties use std's tables: `\p{L}` is `char::is_alphabetic` (which also counts
+//! the combining marks of some scripts as letters), `\p{N}` is `char::is_numeric`,
+//! `\p{Lu}`/`\p{Ll}` are upper/lower case letters and `\p{Lt}`/`\p{Lm}`/`\p{Lo}` the
+//! other letters. Anything else (`\p{M}`, anchors, back references, lazy quantifiers)
+//! is refused with the construct named.
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+enum Prop {
+    Letter,
+    Upper,
+    Lower,
+    OtherLetter,
+    Number,
+    Digit,
+    Space,
+    Word,
+}
+
+impl Prop {
+    fn has(self, c: char) -> bool {
+        match self {
+            Prop::Letter => c.is_alphabetic(),
+            Prop::Upper => c.is_alphabetic() && c.is_uppercase(),
+            Prop::Lower => c.is_alphabetic() && c.is_lowercase(),
+            Prop::OtherLetter => c.is_alphabetic() && !c.is_uppercase() && !c.is_lowercase(),
+            Prop::Number => c.is_numeric(),
+            Prop::Digit => c.is_ascii_digit(),
+            Prop::Space => c.is_whitespace(),
+            Prop::Word => c.is_alphanumeric() || c == '_',
+        }
+    }
+}
+
+#[derive(Clone, Debug, PartialEq)]
+enum Item {
+    Range(char, char),
+    Prop(Prop, bool),
+}
+
+#[derive(Clone, Debug, PartialEq)]
+enum Node {
+    Char(char, bool),
+    Class(Vec, bool, bool),
+    Any,
+    Group(Vec>),
+    Look(Vec>, bool),
+    Repeat(Box, usize, usize),
+}
+
+/// a compiled pattern
+#[derive(Clone, Debug, PartialEq)]
+pub struct Regex {
+    source: String,
+    alt: Vec>,
+}
+
+struct Parser<'a> {
+    s: &'a [char],
+    i: usize,
+    src: &'a str,
+}
+
+impl Parser<'_> {
+    fn err(&self, what: &str) -> Result {
+        Err(format!("pattern {:?}: {what} (at {})", self.src, self.i))
+    }
+
+    fn peek(&self) -> Option {
+        self.s.get(self.i).copied()
+    }
+
+    fn eat(&mut self, c: char) -> bool {
+        if self.peek() == Some(c) {
+            self.i += 1;
+            true
+        } else {
+            false
+        }
+    }
+
+    fn alt(&mut self, ci: bool) -> Result>, String> {
+        let mut alts = vec![self.seq(ci)?];
+        while self.eat('|') {
+            alts.push(self.seq(ci)?);
+        }
+        Ok(alts)
+    }
+
+    fn seq(&mut self, ci: bool) -> Result, String> {
+        let mut v = Vec::new();
+        while let Some(c) = self.peek() {
+            if c == '|' || c == ')' {
+                break;
+            }
+            let atom = self.atom(ci)?;
+            let atom = self.quantified(atom)?;
+            v.push(atom);
+        }
+        Ok(v)
+    }
+
+    fn number(&mut self) -> Option {
+        let start = self.i;
+        while self.peek().is_some_and(|c| c.is_ascii_digit()) {
+            self.i += 1;
+        }
+        (self.i > start).then(|| self.s[start..self.i].iter().collect::().parse().ok())?
+    }
+
+    fn quantified(&mut self, atom: Node) -> Result {
+        let (min, max) = match self.peek() {
+            Some('?') => (0, 1),
+            Some('*') => (0, usize::MAX),
+            Some('+') => (1, usize::MAX),
+            Some('{') => {
+                let save = self.i;
+                self.i += 1;
+                let Some(a) = self.number() else {
+                    self.i = save;
+                    return Ok(atom);
+                };
+                let b = if self.eat(',') {
+                    self.number().unwrap_or(usize::MAX)
+                } else {
+                    a
+                };
+                if !self.eat('}') || b < a {
+                    return self.err("a malformed {n,m}");
+                }
+                self.i -= 1;
+                (a, b)
+            }
+            _ => return Ok(atom),
+        };
+        self.i += 1;
+        if matches!(self.peek(), Some('?' | '+')) {
+            return self.err("lazy or possessive quantifiers are not supported");
+        }
+        if matches!(atom, Node::Look(..)) {
+            return self.err("a quantified lookahead");
+        }
+        Ok(Node::Repeat(Box::new(atom), min, max))
+    }
+
+    fn atom(&mut self, ci: bool) -> Result {
+        let c = self.peek().expect("caller checked");
+        self.i += 1;
+        Ok(match c {
+            '(' => {
+                let node = if self.eat('?') {
+                    match self.peek() {
+                        Some(':') => {
+                            self.i += 1;
+                            Node::Group(self.alt(ci)?)
+                        }
+                        Some('i') if self.s.get(self.i + 1) == Some(&':') => {
+                            self.i += 2;
+                            Node::Group(self.alt(true)?)
+                        }
+                        Some('=') => {
+                            self.i += 1;
+                            Node::Look(self.alt(ci)?, false)
+                        }
+                        Some('!') => {
+                            self.i += 1;
+                            Node::Look(self.alt(ci)?, true)
+                        }
+                        _ => return self.err("this group kind is not supported"),
+                    }
+                } else {
+                    Node::Group(self.alt(ci)?)
+                };
+                if !self.eat(')') {
+                    return self.err("an unclosed group");
+                }
+                node
+            }
+            '[' => self.class(ci)?,
+            '.' => Node::Any,
+            '\\' => self.escape(ci, false)?,
+            '^' | '$' => return self.err("anchors are not supported"),
+            '*' | '+' | '?' => return self.err("a quantifier with nothing before it"),
+            c => Node::Char(c, ci),
+        })
+    }
+
+    fn prop(&mut self) -> Result {
+        let name: String = if self.eat('{') {
+            let start = self.i;
+            while self.peek().is_some_and(|c| c != '}') {
+                self.i += 1;
+            }
+            let n = self.s[start..self.i].iter().collect();
+            if !self.eat('}') {
+                return self.err("an unclosed \\p{");
+            }
+            n
+        } else {
+            match self.peek() {
+                Some(c) => {
+                    self.i += 1;
+                    c.to_string()
+                }
+                None => return self.err("\\p at the end"),
+            }
+        };
+        Ok(match name.as_str() {
+            "L" | "Letter" => Prop::Letter,
+            "Lu" => Prop::Upper,
+            "Ll" => Prop::Lower,
+            "Lt" | "Lm" | "Lo" => Prop::OtherLetter,
+            "N" | "Number" => Prop::Number,
+            "Nd" => Prop::Digit,
+            other => return self.err(&format!("unicode property {other} is not supported")),
+        })
+    }
+
+    /// an escape; in a class it must be a single item
+    fn escape(&mut self, ci: bool, in_class: bool) -> Result {
+        let Some(c) = self.peek() else {
+            return self.err("a backslash at the end");
+        };
+        self.i += 1;
+        let prop = |p: Prop, neg: bool| Node::Class(vec![Item::Prop(p, false)], neg, false);
+        Ok(match c {
+            's' => prop(Prop::Space, false),
+            'S' => prop(Prop::Space, true),
+            'd' => prop(Prop::Digit, false),
+            'D' => prop(Prop::Digit, true),
+            'w' => prop(Prop::Word, false),
+            'W' => prop(Prop::Word, true),
+            'p' => prop(self.prop()?, false),
+            'P' => prop(self.prop()?, true),
+            'r' => Node::Char('\r', ci),
+            'n' => Node::Char('\n', ci),
+            't' => Node::Char('\t', ci),
+            'f' => Node::Char('\x0c', ci),
+            'v' => Node::Char('\x0b', ci),
+            '0' => Node::Char('\0', ci),
+            c if c.is_ascii_alphanumeric() => {
+                return self.err(&format!(
+                    "escape \\{c} is not supported{}",
+                    if in_class { " in a class" } else { "" }
+                ));
+            }
+            c => Node::Char(c, ci),
+        })
+    }
+
+    fn class(&mut self, ci: bool) -> Result {
+        let neg = self.eat('^');
+        let mut items = Vec::new();
+        let mut first = true;
+        loop {
+            let Some(c) = self.peek() else {
+                return self.err("an unclosed class");
+            };
+            if c == ']' && !first {
+                self.i += 1;
+                break;
+            }
+            first = false;
+            self.i += 1;
+            let lo = if c == '\\' {
+                match self.escape(false, true)? {
+                    Node::Char(ch, _) => ch,
+                    Node::Class(it, n, _) => {
+                        // \s, \p{L}, \P{N} … inside a class
+                        for x in it {
+                            if let Item::Prop(p, _) = x {
+                                items.push(Item::Prop(p, n));
+                            }
+                        }
+                        continue;
+                    }
+                    _ => unreachable!(),
+                }
+            } else if c == '[' && self.peek() == Some(':') {
+                return self.err("POSIX classes are not supported");
+            } else {
+                c
+            };
+            if self.peek() == Some('-') && self.s.get(self.i + 1).is_some_and(|&n| n != ']') {
+                self.i += 1;
+                let hc = self.peek().expect("checked");
+                self.i += 1;
+                let hi = if hc == '\\' {
+                    match self.escape(false, true)? {
+                        Node::Char(ch, _) => ch,
+                        _ => return self.err("a range ending in a class"),
+                    }
+                } else {
+                    hc
+                };
+                if hi < lo {
+                    return self.err("a backwards range");
+                }
+                items.push(Item::Range(lo, hi));
+            } else {
+                items.push(Item::Range(lo, lo));
+            }
+        }
+        Ok(Node::Class(items, neg, ci))
+    }
+}
+
+fn fold(c: char) -> char {
+    let mut l = c.to_lowercase();
+    match (l.next(), l.next()) {
+        (Some(x), None) => x,
+        _ => c,
+    }
+}
+
+fn class_has(items: &[Item], neg: bool, ci: bool, c: char) -> bool {
+    let test = |c: char| {
+        items.iter().any(|it| match *it {
+            Item::Range(a, b) => (a..=b).contains(&c),
+            Item::Prop(p, n) => p.has(c) != n,
+        })
+    };
+    let hit = test(c) || (ci && (test(fold(c)) || c.to_uppercase().any(test)));
+    hit != neg
+}
+
+impl Node {
+    /// matches one character (for the iterative repeat)
+    fn single(&self, c: char) -> Option {
+        match self {
+            Node::Char(x, ci) => Some(*x == c || (*ci && fold(*x) == fold(c))),
+            Node::Class(items, neg, ci) => Some(class_has(items, *neg, *ci, c)),
+            Node::Any => Some(c != '\n'),
+            _ => None,
+        }
+    }
+}
+
+type Cont<'a> = &'a mut dyn FnMut(usize) -> bool;
+
+impl Regex {
+    pub fn new(src: &str) -> Result {
+        let chars: Vec = src.chars().collect();
+        let mut p = Parser { s: &chars, i: 0, src };
+        let alt = p.alt(false)?;
+        if p.i != chars.len() {
+            return p.err("an unmatched )");
+        }
+        Ok(Regex {
+            source: src.to_string(),
+            alt,
+        })
+    }
+
+    pub fn source(&self) -> &str {
+        &self.source
+    }
+
+    fn alt(&self, alt: &[Vec], s: &[char], pos: usize, k: Cont) -> bool {
+        alt.iter().any(|seq| self.seq(seq, s, pos, k))
+    }
+
+    fn seq(&self, seq: &[Node], s: &[char], pos: usize, k: Cont) -> bool {
+        match seq.split_first() {
+            None => k(pos),
+            Some((n, rest)) => self.node(n, s, pos, &mut |p| self.seq(rest, s, p, k)),
+        }
+    }
+
+    fn node(&self, n: &Node, s: &[char], pos: usize, k: Cont) -> bool {
+        match n {
+            Node::Group(alt) => self.alt(alt, s, pos, k),
+            Node::Look(alt, neg) => {
+                let found = self.alt(alt, s, pos, &mut |_| true);
+                found != *neg && k(pos)
+            }
+            Node::Repeat(inner, min, max) => {
+                if inner.single('a').is_some() {
+                    let mut count = 0;
+                    while count < *max && pos + count < s.len() && inner.single(s[pos + count]) == Some(true) {
+                        count += 1;
+                    }
+                    (*min..=count).rev().any(|c| k(pos + c))
+                } else {
+                    self.repeat(inner, *min, *max, 0, s, pos, k)
+                }
+            }
+            single => pos < s.len() && single.single(s[pos]) == Some(true) && k(pos + 1),
+        }
+    }
+
+    #[allow(clippy::too_many_arguments)]
+    fn repeat(&self, n: &Node, min: usize, max: usize, done: usize, s: &[char], pos: usize, k: Cont) -> bool {
+        if done < max
+            && self.node(n, s, pos, &mut |p| {
+                // an empty iteration can't make progress; stop repeating there
+                p != pos && self.repeat(n, min, max, done + 1, s, p, k)
+            })
+        {
+            return true;
+        }
+        done >= min && k(pos)
+    }
+
+    /// the end of the match starting at `pos`, if any
+    fn match_at(&self, s: &[char], pos: usize) -> Option {
+        let mut end = None;
+        self.alt(&self.alt, s, pos, &mut |p| {
+            end = Some(p);
+            true
+        });
+        end
+    }
+
+    /// every non-overlapping match, leftmost first, as char ranges
+    pub fn find_iter(&self, s: &[char]) -> Vec<(usize, usize)> {
+        let mut out = Vec::new();
+        let mut pos = 0;
+        while pos < s.len() {
+            match self.match_at(s, pos) {
+                Some(e) if e > pos => {
+                    out.push((pos, e));
+                    pos = e;
+                }
+                _ => pos += 1,
+            }
+        }
+        out
+    }
+
+    /// the matches of a string as substrings
+    pub fn find_all<'a>(&self, text: &'a str) -> Vec<&'a str> {
+        let chars: Vec = text.chars().collect();
+        let offs: Vec = text.char_indices().map(|(i, _)| i).chain([text.len()]).collect();
+        self.find_iter(&chars)
+            .into_iter()
+            .map(|(a, b)| &text[offs[a]..offs[b]])
+            .collect()
+    }
+}
+
+/// the GPT-2 pre-tokenizer pattern (`ByteLevel` with `use_regex`)
+pub const GPT2: &str = r"'s|'t|'re|'ve|'m|'ll|'d| ?\p{L}+| ?\p{N}+| ?[^\s\p{L}\p{N}]+|\s+(?!\S)|\s+";
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    const LLAMA3: &str = r"(?i:'s|'t|'re|'ve|'m|'ll|'d)|[^\r\n\p{L}\p{N}]?\p{L}+|\p{N}{1,3}| ?[^\s\p{L}\p{N}]+[\r\n]*|\s*[\r\n]+|\s+(?!\S)|\s+";
+
+    #[test]
+    fn gpt2_pattern_splits_like_the_reference() {
+        let r = Regex::new(GPT2).unwrap();
+        assert_eq!(
+            r.find_all("Hello world, it's 2024!  Ok"),
+            ["Hello", " world", ",", " it", "'s", " 2024", "!", " ", " Ok"]
+        );
+        assert_eq!(r.find_all("a   b\n\nc"), ["a", "  ", " b", "\n", "\n", "c"]);
+        assert_eq!(r.find_all("héllo wörld"), ["héllo", " wörld"]);
+        assert_eq!(r.find_all("tail   "), ["tail", "   "]);
+    }
+
+    #[test]
+    fn llama3_pattern_splits_like_the_reference() {
+        let r = Regex::new(LLAMA3).unwrap();
+        assert_eq!(
+            r.find_all("I'LL pay 12345 now"),
+            ["I", "'LL", " pay", " ", "123", "45", " now"]
+        );
+        assert_eq!(
+            r.find_all("x = (a+b);\n\ny"),
+            ["x", " =", " (", "a", "+b", ");\n\n", "y"]
+        );
+        assert_eq!(r.find_all("  \n hi"), ["  \n", " hi"]);
+        assert_eq!(r.find_all("$foo"), ["$foo"]);
+    }
+
+    #[test]
+    fn constructs() {
+        let r = Regex::new(r"a{2,3}|[x-z]+|(?:ab)+c|\d").unwrap();
+        assert_eq!(r.find_all("aaaa xyz ababc 7"), ["aaa", "xyz", "ababc", "7"]);
+        let r = Regex::new(r"foo(?=bar)|[^a-c\s]").unwrap();
+        assert_eq!(r.find_all("foobar foo"), ["foo", "r", "f", "o", "o"]);
+        for (bad, says) in [
+            (r"\p{M}", "property M"),
+            ("(a", "unclosed group"),
+            ("a)", "unmatched"),
+            ("a+?", "lazy"),
+            ("^a", "anchors"),
+            (r"\1", "escape \\1"),
+        ] {
+            let e = Regex::new(bad).unwrap_err();
+            assert!(e.contains(says), "{bad}: {e}");
+        }
+    }
+}
diff --git a/core/src/classify/pretrained.rs b/core/src/classify/pretrained.rs
new file mode 100644
index 00000000..b3f17a5a
--- /dev/null
+++ b/core/src/classify/pretrained.rs
@@ -0,0 +1,936 @@
+//! Pretrained open models in the engine: a HuggingFace model folder (`config.json`,
+//! `tokenizer.json`, safetensors weights, optionally `generation_config.json`) becomes a
+//! `Classifier` whose trunk and generative head are the checkpoint's, reading the
+//! checkpoint's own vocabulary (`bpe`). From there it is an ordinary engine model: it
+//! runs, generates through `generate` (critics, constraints, guidance, reinforcement),
+//! fine-tunes through `train`, takes extra classifier heads on its trunk, and saves as
+//! a classifier file (weights in f32 plus the tokenizer).
+//!
+//! Supported: the Llama family as `transformers` writes it, `model_type` `llama`
+//! (Llama 1–3, TinyLlama, SmolLM/SmolLM2, OpenLLaMA, …), `mistral`, `qwen2` (q/k/v
+//! biases) and `qwen3` (QK-norm). That is RMSNorm, SwiGLU (`silu`), rotary positions
+//! (`rope_theta`, `rope_scaling` `linear` or `llama3`), grouped key/value heads, an
+//! explicit `head_dim`, tied or separate input and output embeddings. Anything else in
+//! the config that would change the computation is refused with the field named.
+//!
+//! Numbers: the checkpoint's weights become f32 (F16/BF16 exactly), and the engine
+//! computes in f32 with its own deterministic kernels, so outputs match the reference
+//! implementation to rounding (not bit for bit), and match themselves bit for bit on
+//! any machine.
+
+use std::path::{Path, PathBuf};
+use std::sync::Arc;
+
+use serde_json::Value as Json;
+
+use super::bpe::{Lexicon, Tokenizer};
+use super::kernels::transpose;
+use super::model::{Config, Gains, GenSpec, HeadSpec, Net, Pooling, RopeScaling};
+use super::safetensors::Checkpoint;
+use super::{Classifier, Meta, Steer};
+
+/// the parts of `config.json` the engine uses, checked
+#[derive(Clone, Debug, PartialEq)]
+pub struct Arch {
+    pub model_type: String,
+    pub hidden: usize,
+    pub layers: usize,
+    pub heads: usize,
+    pub kv_heads: usize,
+    pub head_dim: usize,
+    pub ff: usize,
+    pub vocab: usize,
+    pub context: usize,
+    pub eps: f32,
+    pub theta: f32,
+    pub scaling: Option,
+    pub tied: bool,
+    pub bos: Option,
+    pub eos: Vec,
+}
+
+/// how a pretrained model is brought in
+#[derive(Clone, Debug, PartialEq)]
+pub struct Options {
+    /// tokens per window; default the model's context length (`max_position_embeddings`,
+    /// or its sliding window if shorter)
+    pub max_len: Option,
+    /// classifier heads to put on the trunk (new, untrained), besides the generator
+    pub heads: Vec,
+    /// the generative head's name
+    pub generator: String,
+    /// dropout when fine-tuning
+    pub dropout: f32,
+    /// seeds the new heads
+    pub seed: u64,
+}
+
+impl Default for Options {
+    fn default() -> Options {
+        Options {
+            max_len: None,
+            heads: Vec::new(),
+            generator: "next".into(),
+            dropout: 0.0,
+            seed: 0,
+        }
+    }
+}
+
+fn need_usize(v: &Json, f: &str) -> Result {
+    v[f].as_u64()
+        .map(|x| x as usize)
+        .ok_or(format!("config.json: {f} is missing or not a whole number"))
+}
+
+fn ids_of(v: &Json) -> Vec {
+    match v {
+        Json::Number(n) => n.as_u64().map(|x| vec![x as u32]).unwrap_or_default(),
+        Json::Array(a) => a.iter().filter_map(|x| x.as_u64().map(|x| x as u32)).collect(),
+        _ => Vec::new(),
+    }
+}
+
+impl Arch {
+    /// reads and checks a `config.json` (with `generation_config.json`'s end tokens,
+    /// when given)
+    pub fn from_json(text: &str, generation: Option<&str>) -> Result {
+        let v: Json = serde_json::from_str(text).map_err(|e| format!("config.json: {e}"))?;
+        let model_type = v["model_type"].as_str().unwrap_or("").to_string();
+        if !["llama", "mistral", "qwen2", "qwen3"].contains(&model_type.as_str()) {
+            return Err(format!(
+                "config.json: model_type {model_type:?} is not supported (llama, mistral, qwen2, qwen3)"
+            ));
+        }
+        let unsupported = |f: &str, why: &str| Err(format!("config.json: {f} {why} is not supported"));
+        let act = v["hidden_act"]
+            .as_str()
+            .or(v["hidden_activation"].as_str())
+            .unwrap_or("silu");
+        if act != "silu" {
+            return unsupported("hidden_act", &format!("{act:?} (silu is)"));
+        }
+        if v["attention_bias"].as_bool() == Some(true) {
+            return unsupported("attention_bias", "true (the output projection's bias)");
+        }
+        if v["mlp_bias"].as_bool() == Some(true) {
+            return unsupported("mlp_bias", "true");
+        }
+        if v["pretraining_tp"].as_u64().is_some_and(|t| t > 1) {
+            return unsupported("pretraining_tp", "above 1");
+        }
+        if v["num_experts"].as_u64().is_some_and(|n| n > 0) || v["num_local_experts"].as_u64().is_some_and(|n| n > 0) {
+            return unsupported("num_experts", "(mixture of experts)");
+        }
+        let hidden = need_usize(&v, "hidden_size")?;
+        let heads = need_usize(&v, "num_attention_heads")?;
+        let kv_heads = v["num_key_value_heads"].as_u64().map_or(heads, |x| x as usize);
+        let head_dim = match v["head_dim"].as_u64() {
+            Some(h) => h as usize,
+            None if heads > 0 && hidden.is_multiple_of(heads) => hidden / heads,
+            None => return Err("config.json: hidden_size is not a multiple of num_attention_heads".into()),
+        };
+        if heads == 0 || kv_heads == 0 || !heads.is_multiple_of(kv_heads) {
+            return Err(format!(
+                "config.json: num_attention_heads {heads} is not a multiple of num_key_value_heads {kv_heads}"
+            ));
+        }
+        if head_dim == 0 || !head_dim.is_multiple_of(2) {
+            return Err(format!("config.json: head_dim {head_dim} must be even"));
+        }
+        if v["partial_rotary_factor"].as_f64().is_some_and(|f| f != 1.0) {
+            return unsupported("partial_rotary_factor", "other than 1");
+        }
+        let mut context = v["max_position_embeddings"].as_u64().map_or(4096, |x| x as usize);
+        let sliding = match model_type.as_str() {
+            "qwen2" | "qwen3" => v["use_sliding_window"].as_bool() == Some(true),
+            _ => true,
+        };
+        if sliding && let Some(w) = v["sliding_window"].as_u64() {
+            // windows no longer than the sliding window see exactly what it lets through
+            context = context.min(w as usize);
+        }
+        let scaling = match &v["rope_scaling"] {
+            Json::Null => None,
+            s => {
+                let kind = s["rope_type"].as_str().or(s["type"].as_str()).unwrap_or("");
+                let f = |name: &str| {
+                    s[name]
+                        .as_f64()
+                        .ok_or(format!("config.json: rope_scaling.{name} is missing"))
+                };
+                match kind {
+                    "default" => None,
+                    "linear" => Some(RopeScaling::Linear { factor: f("factor")? }),
+                    "llama3" => Some(RopeScaling::Llama3 {
+                        factor: f("factor")?,
+                        low_freq_factor: f("low_freq_factor")?,
+                        high_freq_factor: f("high_freq_factor")?,
+                        original_max_position_embeddings: f("original_max_position_embeddings")?,
+                    }),
+                    other => return unsupported("rope_scaling", &format!("type {other:?} (linear and llama3 are)")),
+                }
+            }
+        };
+        let mut eos = ids_of(&v["eos_token_id"]);
+        if let Some(g) = generation {
+            let g: Json = serde_json::from_str(g).map_err(|e| format!("generation_config.json: {e}"))?;
+            for t in ids_of(&g["eos_token_id"]) {
+                if !eos.contains(&t) {
+                    eos.push(t);
+                }
+            }
+        }
+        Ok(Arch {
+            hidden,
+            layers: need_usize(&v, "num_hidden_layers")?,
+            heads,
+            kv_heads,
+            head_dim,
+            ff: need_usize(&v, "intermediate_size")?,
+            vocab: need_usize(&v, "vocab_size")?,
+            context,
+            eps: v["rms_norm_eps"].as_f64().unwrap_or(1e-6) as f32,
+            theta: v["rope_theta"].as_f64().unwrap_or(10000.0) as f32,
+            scaling,
+            tied: v["tie_word_embeddings"].as_bool().unwrap_or(false),
+            bos: v["bos_token_id"].as_u64().map(|x| x as u32),
+            eos,
+            model_type,
+        })
+    }
+
+    /// the engine configuration (biases and QK-norm as the checkpoint has them)
+    pub fn config(&self, o: &Options, qkv_bias: bool, qk_norm: bool) -> Result {
+        let max_len = o.max_len.unwrap_or(self.context).max(3);
+        let cfg = Config {
+            d_model: self.hidden,
+            head_dim: self.head_dim,
+            heads: self.heads,
+            layers: self.layers,
+            d_ff: self.ff,
+            max_len,
+            stride: ((max_len - 2) / 2).max(1),
+            dropout: o.dropout,
+            pooling: Pooling::Mean,
+            qk_norm,
+            rope_base: self.theta,
+            norm_eps: self.eps,
+            side: false,
+            extra: 0,
+            gains: Gains::default(),
+            zero_out: false,
+            letters: false,
+            words: false,
+            causal: true,
+            numbers: false,
+            kv_heads: if self.kv_heads == self.heads { 0 } else { self.kv_heads },
+            vocab_size: self.vocab,
+            qkv_bias,
+            rope_scaling: self.scaling.clone(),
+        };
+        cfg.validate()
+            .map_err(|e| format!("pretrained {}: {e}", self.model_type))?;
+        Ok(cfg)
+    }
+}
+
+/// a model folder's files
+pub struct Folder {
+    pub dir: PathBuf,
+    pub arch: Arch,
+    pub tokenizer: Tokenizer,
+    pub weights: Checkpoint,
+}
+
+impl Folder {
+    pub fn open(dir: &Path) -> Result {
+        let read = |name: &str| {
+            std::fs::read_to_string(dir.join(name)).map_err(|e| format!("{}: {e}", dir.join(name).display()))
+        };
+        let config = read("config.json")?;
+        let generation = read("generation_config.json").ok();
+        let arch = Arch::from_json(&config, generation.as_deref()).map_err(|e| format!("{}: {e}", dir.display()))?;
+        let tokenizer = Tokenizer::load(&dir.join("tokenizer.json"))?;
+        let weights = Checkpoint::open_dir(dir)?;
+        Ok(Folder {
+            dir: dir.to_path_buf(),
+            arch,
+            tokenizer,
+            weights,
+        })
+    }
+
+    /// the lexicon: BOS (or the first end token) to start, the end tokens to stop
+    pub fn lexicon(&self) -> Result {
+        let a = &self.arch;
+        if self.tokenizer.size() > a.vocab {
+            return Err(format!(
+                "tokenizer.json has {} tokens, more than the model's vocab_size {}",
+                self.tokenizer.size(),
+                a.vocab
+            ));
+        }
+        let end = *a.eos.first().ok_or("config.json: eos_token_id is missing")?;
+        let start = a.bos.unwrap_or(end);
+        if [start, end].iter().chain(&a.eos).any(|&t| t as usize >= a.vocab) {
+            return Err("config.json: bos/eos token ids are past vocab_size".into());
+        }
+        Ok(Lexicon {
+            tokenizer: self.tokenizer.clone(),
+            start,
+            end,
+            stops: a.eos[1..].to_vec(),
+        })
+    }
+
+    /// the engine model with the checkpoint's weights
+    pub fn model(&self, o: &Options) -> Result {
+        let a = &self.arch;
+        let w = &self.weights;
+        let qkv_bias = w.has("model.layers.0.self_attn.q_proj.bias");
+        let qk_norm = w.has("model.layers.0.self_attn.q_norm.weight");
+        if w.has("model.layers.0.self_attn.o_proj.bias") {
+            return Err("the checkpoint has an output projection bias (not supported)".into());
+        }
+        let cfg = a.config(o, qkv_bias, qk_norm)?;
+        let mut net = Net::with_gen(cfg, &o.heads, Some(GenSpec::new(&o.generator)), o.seed)?;
+        net.lexicon = Some(Arc::new(self.lexicon()?));
+        let (d, dh, v) = (a.hidden, a.head_dim, a.vocab);
+        let (qa, kva) = (a.heads * dh, a.kv_heads * dh);
+        net.tok = w.get("model.embed_tokens.weight", &[v, d])?;
+        // [V × d] → the head's [d × V]
+        let head = if w.has("lm_head.weight") {
+            w.get("lm_head.weight", &[v, d])?
+        } else if a.tied {
+            net.tok.clone()
+        } else {
+            return Err("the checkpoint has no lm_head.weight and tie_word_embeddings is false".into());
+        };
+        net.gen_w = transpose(&head, v, d);
+        drop(head);
+        net.gen_b = vec![0.0; v];
+        net.nf = w.get("model.norm.weight", &[d])?;
+        for (l, b) in net.blocks.iter_mut().enumerate() {
+            let p = |n: &str| format!("model.layers.{l}.{n}");
+            b.n1 = w.get(&p("input_layernorm.weight"), &[d])?;
+            b.n2 = w.get(&p("post_attention_layernorm.weight"), &[d])?;
+            // q, k, v [out × d] side by side as columns of [d × (q + 2·kv)]
+            let wq = w.get(&p("self_attn.q_proj.weight"), &[qa, d])?;
+            let wk = w.get(&p("self_attn.k_proj.weight"), &[kva, d])?;
+            let wv = w.get(&p("self_attn.v_proj.weight"), &[kva, d])?;
+            let mut rows = wq;
+            rows.extend(wk);
+            rows.extend(wv);
+            b.wqkv = transpose(&rows, qa + 2 * kva, d);
+            drop(rows);
+            if qkv_bias {
+                let mut bias = w.get(&p("self_attn.q_proj.bias"), &[qa])?;
+                bias.extend(w.get(&p("self_attn.k_proj.bias"), &[kva])?);
+                bias.extend(w.get(&p("self_attn.v_proj.bias"), &[kva])?);
+                b.bqkv = bias;
+            }
+            if qk_norm {
+                b.qn = w.get(&p("self_attn.q_norm.weight"), &[dh])?;
+                b.kn = w.get(&p("self_attn.k_norm.weight"), &[dh])?;
+            }
+            b.wo = transpose(&w.get(&p("self_attn.o_proj.weight"), &[d, qa])?, d, qa);
+            b.wg = transpose(&w.get(&p("mlp.gate_proj.weight"), &[a.ff, d])?, a.ff, d);
+            b.wu = transpose(&w.get(&p("mlp.up_proj.weight"), &[a.ff, d])?, a.ff, d);
+            b.wd = transpose(&w.get(&p("mlp.down_proj.weight"), &[d, a.ff])?, d, a.ff);
+        }
+        let steer = Steer::neutral(&net.heads);
+        let name = self
+            .dir
+            .file_name()
+            .map(|n| n.to_string_lossy().into_owned())
+            .unwrap_or_else(|| a.model_type.clone());
+        Ok(Classifier {
+            meta: Meta {
+                name,
+                seed: o.seed,
+                class_counts: net.heads.iter().map(|h| vec![0.0; h.width()]).collect(),
+                log: vec![format!(
+                    "imported pretrained {} from {}",
+                    a.model_type,
+                    self.dir.display()
+                )],
+                ..Meta::default()
+            },
+            net,
+            steer,
+            opt: None,
+        })
+    }
+}
+
+/// a pretrained model folder as an engine model
+pub fn load(dir: &Path, o: &Options) -> Result {
+    Folder::open(dir)?.model(o)
+}
+
+/// writes a tiny synthetic llama checkpoint into `dir` (tests elsewhere in the crate)
+#[cfg(test)]
+pub(crate) fn synthetic_checkpoint(dir: &Path, seed: u64) {
+    tests::synth(dir, &tests::Shape::llama(), seed);
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::classify::bpe::tests::{byte_level_json, sentencepiece_json};
+    use crate::classify::generate::{self, Constraints, Critic, GenOpts, Sampling, Want};
+    use crate::classify::math::Rng;
+    use crate::classify::model::{Decoder, Mode};
+    use crate::classify::safetensors::{Dtype, write};
+    use crate::classify::train::{self, Example, TrainOpts};
+    use crate::classify::{Flow, HeadSpec};
+    use std::collections::BTreeMap;
+
+    /// a synthetic checkpoint's shapes (tests only: tiny so the suite stays fast; the
+    /// loader itself has no size limits)
+    #[derive(Clone)]
+    pub(super) struct Shape {
+        model_type: &'static str,
+        d: usize,
+        layers: usize,
+        heads: usize,
+        kv: usize,
+        dh: usize,
+        ff: usize,
+        vocab: usize,
+        tied: bool,
+        bias: bool,
+        qk_norm: bool,
+        dtype: Dtype,
+        shards: bool,
+        sentencepiece: bool,
+        extra: serde_json::Value,
+    }
+
+    impl Shape {
+        pub(super) fn llama() -> Shape {
+            Shape {
+                model_type: "llama",
+                d: 24,
+                layers: 2,
+                heads: 4,
+                kv: 2,
+                dh: 8,
+                ff: 40,
+                vocab: 288,
+                tied: true,
+                bias: false,
+                qk_norm: false,
+                dtype: Dtype::F32,
+                shards: false,
+                sentencepiece: false,
+                extra: serde_json::json!({}),
+            }
+        }
+    }
+
+    pub(super) type Tensors = BTreeMap, Vec)>;
+
+    fn dir(name: &str) -> PathBuf {
+        let d = std::env::temp_dir().join(format!("anend-pre-{}-{name}", std::process::id()));
+        let _ = std::fs::remove_dir_all(&d);
+        std::fs::create_dir_all(&d).unwrap();
+        d
+    }
+
+    /// writes config.json, tokenizer.json and random weights; returns the weights
+    pub(super) fn synth(dir: &Path, s: &Shape, seed: u64) -> Tensors {
+        let mut r = Rng::new(seed);
+        let mut t: Tensors = BTreeMap::new();
+        let mut put = |name: String, shape: Vec, scale: f32, base: f32| {
+            let n = shape.iter().product();
+            let v: Vec = (0..n).map(|_| base + r.symmetric(scale)).collect();
+            t.insert(name, (shape, v));
+        };
+        let (d, qa, kva) = (s.d, s.heads * s.dh, s.kv * s.dh);
+        put("model.embed_tokens.weight".into(), vec![s.vocab, d], 1.0, 0.0);
+        if !s.tied {
+            put("lm_head.weight".into(), vec![s.vocab, d], 0.3, 0.0);
+        }
+        put("model.norm.weight".into(), vec![d], 0.2, 1.0);
+        for l in 0..s.layers {
+            let p = |n: &str| format!("model.layers.{l}.{n}");
+            put(p("input_layernorm.weight"), vec![d], 0.2, 1.0);
+            put(p("post_attention_layernorm.weight"), vec![d], 0.2, 1.0);
+            put(p("self_attn.q_proj.weight"), vec![qa, d], 0.4, 0.0);
+            put(p("self_attn.k_proj.weight"), vec![kva, d], 0.4, 0.0);
+            put(p("self_attn.v_proj.weight"), vec![kva, d], 0.4, 0.0);
+            put(p("self_attn.o_proj.weight"), vec![d, qa], 0.3, 0.0);
+            if s.bias {
+                put(p("self_attn.q_proj.bias"), vec![qa], 0.3, 0.0);
+                put(p("self_attn.k_proj.bias"), vec![kva], 0.3, 0.0);
+                put(p("self_attn.v_proj.bias"), vec![kva], 0.3, 0.0);
+            }
+            if s.qk_norm {
+                put(p("self_attn.q_norm.weight"), vec![s.dh], 0.2, 1.0);
+                put(p("self_attn.k_norm.weight"), vec![s.dh], 0.2, 1.0);
+            }
+            put(p("mlp.gate_proj.weight"), vec![s.ff, d], 0.3, 0.0);
+            put(p("mlp.up_proj.weight"), vec![s.ff, d], 0.3, 0.0);
+            put(p("mlp.down_proj.weight"), vec![d, s.ff], 0.3, 0.0);
+        }
+        // what the reader will see after the dtype round trip
+        for (_, v) in t.values_mut() {
+            *v = crate::classify::safetensors::to_f32(
+                s.dtype,
+                &match s.dtype {
+                    Dtype::F32 => v.iter().flat_map(|x| x.to_le_bytes()).collect::>(),
+                    Dtype::BF16 => v
+                        .iter()
+                        .flat_map(|x| crate::classify::safetensors::f32_to_bf16(*x).to_le_bytes())
+                        .collect(),
+                    Dtype::F16 => v
+                        .iter()
+                        .flat_map(|x| crate::classify::safetensors::f32_to_f16(*x).to_le_bytes())
+                        .collect(),
+                    Dtype::F64 => unreachable!(),
+                },
+            );
+        }
+        let list: Vec<(&str, Dtype, &[usize], &[f32])> = t
+            .iter()
+            .map(|(n, (sh, v))| (n.as_str(), s.dtype, &sh[..], &v[..]))
+            .collect();
+        if s.shards {
+            let (a, b) = list.split_at(list.len() / 2);
+            write(&dir.join("model-00001-of-00002.safetensors"), a).unwrap();
+            write(&dir.join("model-00002-of-00002.safetensors"), b).unwrap();
+            let mut map = serde_json::Map::new();
+            for (n, ..) in a {
+                map.insert(n.to_string(), "model-00001-of-00002.safetensors".into());
+            }
+            for (n, ..) in b {
+                map.insert(n.to_string(), "model-00002-of-00002.safetensors".into());
+            }
+            std::fs::write(
+                dir.join("model.safetensors.index.json"),
+                serde_json::json!({"metadata": {}, "weight_map": map}).to_string(),
+            )
+            .unwrap();
+        } else {
+            write(&dir.join("model.safetensors"), &list).unwrap();
+        }
+        let tok = if s.sentencepiece {
+            sentencepiece_json()
+        } else {
+            byte_level_json()
+        };
+        let tk = Tokenizer::from_json(&tok).unwrap();
+        let (bos, eos) = if s.sentencepiece {
+            (Some(1), 2)
+        } else {
+            (None, tk.id("<|endoftext|>").unwrap())
+        };
+        std::fs::write(dir.join("tokenizer.json"), tok).unwrap();
+        let mut cfg = serde_json::json!({
+            "architectures": ["X"], "model_type": s.model_type, "hidden_size": d,
+            "intermediate_size": s.ff, "num_hidden_layers": s.layers,
+            "num_attention_heads": s.heads, "num_key_value_heads": s.kv, "head_dim": s.dh,
+            "max_position_embeddings": 64, "rms_norm_eps": 1e-5, "rope_theta": 10000.0,
+            "tie_word_embeddings": s.tied, "vocab_size": s.vocab, "hidden_act": "silu",
+            "eos_token_id": eos, "torch_dtype": "bfloat16"
+        });
+        if let Some(b) = bos {
+            cfg["bos_token_id"] = b.into();
+        }
+        for (k, v) in s.extra.as_object().unwrap() {
+            cfg[k] = v.clone();
+        }
+        std::fs::write(dir.join("config.json"), cfg.to_string()).unwrap();
+        t
+    }
+
+    /// the reference computation, written straight from the transformers code (f64,
+    /// weights as [out × in]); logits at every position of `ids`
+    fn reference(t: &Tensors, s: &Shape, theta: f64, ids: &[u32]) -> Vec> {
+        let g = |n: &str| -> Vec { t[n].1.iter().map(|&x| x as f64).collect() };
+        let lin = |w: &[f64], x: &[f64], out: usize| -> Vec {
+            let i = x.len();
+            (0..out).map(|o| (0..i).map(|j| w[o * i + j] * x[j]).sum()).collect()
+        };
+        let norm = |x: &[f64], w: &[f64]| -> Vec {
+            let ms = x.iter().map(|v| v * v).sum::() / x.len() as f64;
+            let r = 1.0 / (ms + 1e-5).sqrt();
+            x.iter().zip(w).map(|(a, b)| a * r * b).collect()
+        };
+        let rope = |x: &mut [f64], pos: usize| {
+            let h = s.dh / 2;
+            for i in 0..h {
+                let f = theta.powf(-((2 * i) as f64) / s.dh as f64);
+                let (sn, c) = (pos as f64 * f).sin_cos();
+                let (a, b) = (x[i], x[i + h]);
+                x[i] = a * c - b * sn;
+                x[i + h] = b * c + a * sn;
+            }
+        };
+        let (d, dh) = (s.d, s.dh);
+        let emb = g("model.embed_tokens.weight");
+        let mut xs: Vec> = ids
+            .iter()
+            .map(|&i| emb[i as usize * d..(i as usize + 1) * d].to_vec())
+            .collect();
+        for l in 0..s.layers {
+            let p = |n: &str| format!("model.layers.{l}.{n}");
+            let (wq, wk, wv, wo) = (
+                g(&p("self_attn.q_proj.weight")),
+                g(&p("self_attn.k_proj.weight")),
+                g(&p("self_attn.v_proj.weight")),
+                g(&p("self_attn.o_proj.weight")),
+            );
+            let mut qs = Vec::new();
+            let mut ks = Vec::new();
+            let mut vs = Vec::new();
+            for (pos, x) in xs.iter().enumerate() {
+                let h = norm(x, &g(&p("input_layernorm.weight")));
+                let mut q = lin(&wq, &h, s.heads * dh);
+                let mut k = lin(&wk, &h, s.kv * dh);
+                let mut v = lin(&wv, &h, s.kv * dh);
+                if s.bias {
+                    for (a, b) in q.iter_mut().zip(g(&p("self_attn.q_proj.bias"))) {
+                        *a += b;
+                    }
+                    for (a, b) in k.iter_mut().zip(g(&p("self_attn.k_proj.bias"))) {
+                        *a += b;
+                    }
+                    for (a, b) in v.iter_mut().zip(g(&p("self_attn.v_proj.bias"))) {
+                        *a += b;
+                    }
+                }
+                for (hh, chunk) in q.chunks_mut(dh).enumerate() {
+                    if s.qk_norm {
+                        let n = norm(chunk, &g(&p("self_attn.q_norm.weight")));
+                        chunk.copy_from_slice(&n);
+                    }
+                    rope(chunk, pos);
+                    let _ = hh;
+                }
+                for chunk in k.chunks_mut(dh) {
+                    if s.qk_norm {
+                        let n = norm(chunk, &g(&p("self_attn.k_norm.weight")));
+                        chunk.copy_from_slice(&n);
+                    }
+                    rope(chunk, pos);
+                }
+                qs.push(q);
+                ks.push(k);
+                vs.push(v);
+            }
+            let per = s.heads / s.kv;
+            for t in 0..xs.len() {
+                let mut ctx = vec![0f64; s.heads * dh];
+                for h in 0..s.heads {
+                    let g_ = h / per;
+                    let q = &qs[t][h * dh..(h + 1) * dh];
+                    let sc: Vec = (0..=t)
+                        .map(|u| {
+                            q.iter()
+                                .zip(&ks[u][g_ * dh..(g_ + 1) * dh])
+                                .map(|(a, b)| a * b)
+                                .sum::()
+                                / (dh as f64).sqrt()
+                        })
+                        .collect();
+                    let m = sc.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
+                    let e: Vec = sc.iter().map(|v| (v - m).exp()).collect();
+                    let z: f64 = e.iter().sum();
+                    for (u, eu) in e.iter().enumerate() {
+                        for i in 0..dh {
+                            ctx[h * dh + i] += eu / z * vs[u][g_ * dh + i];
+                        }
+                    }
+                }
+                let o = lin(&wo, &ctx, d);
+                let x = &mut xs[t];
+                x.iter_mut().zip(&o).for_each(|(a, b)| *a += b);
+                let h2 = norm(x, &g(&p("post_attention_layernorm.weight")));
+                let gt = lin(&g(&p("mlp.gate_proj.weight")), &h2, s.ff);
+                let up = lin(&g(&p("mlp.up_proj.weight")), &h2, s.ff);
+                let act: Vec = gt.iter().zip(&up).map(|(a, b)| a / (1.0 + (-a).exp()) * b).collect();
+                let dn = lin(&g(&p("mlp.down_proj.weight")), &act, d);
+                x.iter_mut().zip(&dn).for_each(|(a, b)| *a += b);
+            }
+        }
+        let head = if s.tied {
+            g("model.embed_tokens.weight")
+        } else {
+            g("lm_head.weight")
+        };
+        xs.iter()
+            .map(|x| lin(&head, &norm(x, &g("model.norm.weight")), s.vocab))
+            .collect()
+    }
+
+    fn compare(s: &Shape, name: &str) -> Classifier {
+        let dd = dir(name);
+        let t = synth(&dd, s, 7);
+        let clf = load(&dd, &Options::default()).unwrap();
+        let net = &clf.net;
+        let ids: Vec = std::iter::once(net.start_token())
+            .chain(net.lexicon.as_ref().unwrap().tokenizer.encode("hello world, the 12"))
+            .collect();
+        let want = reference(&t, s, 10000.0, &ids);
+        let w = net.window_tokens(&ids[1..], false);
+        assert_eq!(w.tokens, ids);
+        let tr = net.forward(&w, &[], &net.cfg.gains, Mode::EVAL, None);
+        let got = net.gen_logits(&tr);
+        let v = s.vocab;
+        for (p, row) in want.iter().enumerate() {
+            for (i, &x) in row.iter().enumerate() {
+                let y = got[p * v + i] as f64;
+                assert!(
+                    (x - y).abs() < 2e-3 * (1.0 + x.abs()),
+                    "{name} position {p} token {i}: reference {x} engine {y}"
+                );
+            }
+        }
+        // the cached decoder gives the same bits as the full pass
+        let mut dec = Decoder::from_tokens(net, net.cfg.gains, &[]);
+        assert_eq!(dec.logits(), &got[..v]);
+        for (p, &id) in ids[1..].iter().enumerate() {
+            dec.push_token(id);
+            assert_eq!(
+                dec.logits(),
+                &got[(p + 1) * v..(p + 2) * v],
+                "{name} decoder at {}",
+                p + 1
+            );
+        }
+        clf
+    }
+
+    #[test]
+    fn llama_family_checkpoints_match_the_reference() {
+        compare(&Shape::llama(), "llama");
+        // Qwen2: q/k/v biases, separate output embedding, bfloat16, two shards
+        compare(
+            &Shape {
+                model_type: "qwen2",
+                bias: true,
+                tied: false,
+                dtype: Dtype::BF16,
+                shards: true,
+                ..Shape::llama()
+            },
+            "qwen2",
+        );
+        // Qwen3: QK-norm, head_dim apart from hidden/heads, half floats
+        compare(
+            &Shape {
+                model_type: "qwen3",
+                qk_norm: true,
+                dh: 10,
+                heads: 6,
+                kv: 3,
+                dtype: Dtype::F16,
+                ..Shape::llama()
+            },
+            "qwen3",
+        );
+        // Mistral / TinyLlama shaped: SentencePiece tokenizer with BOS, plain heads
+        compare(
+            &Shape {
+                model_type: "mistral",
+                heads: 4,
+                kv: 4,
+                tied: false,
+                sentencepiece: true,
+                ..Shape::llama()
+            },
+            "mistral",
+        );
+    }
+
+    #[test]
+    fn rope_scaling_and_errors_in_words() {
+        let ok = |extra: serde_json::Value| {
+            let mut c = serde_json::json!({"model_type": "llama", "hidden_size": 16, "intermediate_size": 8,
+                "num_hidden_layers": 1, "num_attention_heads": 2, "vocab_size": 300, "eos_token_id": [1, 2]});
+            for (k, v) in extra.as_object().unwrap() {
+                c[k] = v.clone();
+            }
+            Arch::from_json(&c.to_string(), Some(r#"{"eos_token_id": [2, 3]}"#))
+        };
+        let a = ok(serde_json::json!({})).unwrap();
+        assert_eq!((a.kv_heads, a.head_dim, a.eos.clone()), (2, 8, vec![1, 2, 3]));
+        let a = ok(
+            serde_json::json!({"rope_scaling": {"rope_type": "llama3", "factor": 8.0, "low_freq_factor": 1.0,
+            "high_freq_factor": 4.0, "original_max_position_embeddings": 8192}}),
+        )
+        .unwrap();
+        assert!(matches!(a.scaling, Some(RopeScaling::Llama3 { .. })));
+        let cfg = a.config(&Options::default(), false, false).unwrap();
+        let plain = crate::classify::model::Rope::new(cfg.max_len, 8, cfg.rope_base);
+        assert_ne!(crate::classify::model::Rope::of(&cfg), plain);
+        for (extra, says) in [
+            (serde_json::json!({"model_type": "gemma"}), "model_type \"gemma\""),
+            (serde_json::json!({"hidden_act": "gelu"}), "hidden_act \"gelu\""),
+            (
+                serde_json::json!({"rope_scaling": {"type": "yarn", "factor": 4.0}}),
+                "rope_scaling type \"yarn\"",
+            ),
+            (serde_json::json!({"attention_bias": true}), "attention_bias"),
+            (serde_json::json!({"num_key_value_heads": 3}), "num_key_value_heads 3"),
+            (serde_json::json!({"hidden_size": null}), "hidden_size"),
+        ] {
+            let e = ok(extra.clone()).unwrap_err();
+            assert!(e.contains(says), "{extra}: {e}");
+        }
+        // a missing or misshapen tensor names itself
+        let dd = dir("broken");
+        let mut t = synth(&dd, &Shape::llama(), 1);
+        t.remove("model.layers.1.mlp.up_proj.weight");
+        let list: Vec<(&str, Dtype, &[usize], &[f32])> = t
+            .iter()
+            .map(|(n, (sh, v))| (n.as_str(), Dtype::F32, &sh[..], &v[..]))
+            .collect();
+        write(&dd.join("model.safetensors"), &list).unwrap();
+        let e = load(&dd, &Options::default()).unwrap_err();
+        assert!(e.contains("model.layers.1.mlp.up_proj.weight"), "{e}");
+        let mut c: Json = serde_json::from_str(&std::fs::read_to_string(dd.join("config.json")).unwrap()).unwrap();
+        c["intermediate_size"] = 41.into();
+        std::fs::write(dd.join("config.json"), c.to_string()).unwrap();
+        let e = load(&dd, &Options::default()).unwrap_err();
+        assert!(e.contains("mlp.gate_proj.weight") && e.contains("[40, 24]"), "{e}");
+    }
+
+    /// generation with critics, fine-tuning, saving: the engine's paths on a pretrained model
+    #[test]
+    fn pretrained_models_generate_tune_and_save() {
+        let dd = dir("paths");
+        synth(&dd, &Shape::llama(), 3);
+        let o = Options {
+            heads: vec![HeadSpec::single("kind", &["a", "b"])],
+            max_len: Some(24),
+            ..Options::default()
+        };
+        let mut g = load(&dd, &o).unwrap();
+        assert_eq!(g.net.head_names(), ["kind", "next"]);
+        // a byte-model critic judges what the pretrained model writes
+        let critic = Classifier::new(
+            crate::classify::Config::tiny().gematria(false),
+            &[HeadSpec::single("d", &["no", "yes"])],
+            2,
+        )
+        .unwrap();
+        let critics = [Critic::new(&critic, 0, Want::Class(1), 1.0)];
+        let opts = GenOpts {
+            prompt: b"hello".to_vec(),
+            sampling: Sampling {
+                temperature: 1.0,
+                max_len: 16,
+                seed: 5,
+                ..Sampling::default()
+            },
+            candidates: 4,
+            threads: 2,
+            guidance: Some(generate::Guidance::default()),
+            ..GenOpts::default()
+        };
+        let a = generate::draw(&g, &critics, &Constraints::default(), &opts).unwrap();
+        let b = generate::draw(
+            &g,
+            &critics,
+            &Constraints::default(),
+            &GenOpts {
+                threads: 1,
+                ..opts.clone()
+            },
+        )
+        .unwrap();
+        assert_eq!(a, b);
+        assert!(a.iter().all(|c| c.bytes.len() <= 16 && c.scores.len() == 1));
+        // fine-tuning on a text makes it likelier; the classifier head trains alongside
+        let text = "the world, hello the world";
+        let before = train::nll(&g, text.as_bytes(), 0);
+        assert!(before.1 > 3, "{before:?}");
+        let data: Vec = (0..6)
+            .map(|i| {
+                if i % 2 == 0 {
+                    Example::generate(text)
+                } else {
+                    Example::class("hello", 1)
+                }
+            })
+            .collect();
+        let to = TrainOpts {
+            epochs: 4,
+            batch: 3,
+            lr: 3e-3,
+            val_fraction: 0.0,
+            threads: 2,
+            ..TrainOpts::default()
+        };
+        train::train(&mut g, &data, &to, |_| Flow::Go).unwrap();
+        let after = train::nll(&g, text.as_bytes(), 0);
+        assert!(after.0 < before.0, "{before:?} → {after:?}");
+        // the file keeps the vocabulary, the tokenizer and every weight
+        let back = Classifier::from_bytes(&g.to_bytes()).unwrap();
+        assert_eq!(back.net, g.net);
+        assert_eq!(train::nll(&back, text.as_bytes(), 0), after);
+        let (s1, _) = generate::sample(&g, b"hello", &Sampling::greedy(8), 0);
+        assert_eq!(generate::sample(&back, b"hello", &Sampling::greedy(8), 0).0, s1);
+    }
+
+    /// the declarative spec: `"from": {"pretrained": dir}`, trained, run, generating
+    /// with a critic model; checks name what a pretrained spec can't set
+    #[test]
+    fn a_pretrained_model_from_a_spec() {
+        use crate::classify::spec::{self, MemSource, Model, ModelSpec, Value};
+        let dd = dir("spec");
+        synth(&dd, &Shape::llama(), 4);
+        let json = r#"{
+          "name": "writer",
+          "from": {"pretrained": "DIR"},
+          "input": {"type": "text"},
+          "trunk": {"max_len": 32},
+          "heads": [{"name": "next", "kind": "generate"},
+                    {"name": "tone", "kind": "classify", "classes": ["calm", "loud"]}],
+          "data": [{"from": "list", "list": "texts", "head": "next"},
+                   {"from": "list", "list": "loud", "head": "tone", "class": "loud"},
+                   {"from": "list", "list": "calm", "head": "tone", "class": "calm"}],
+          "critics": [{"model": "judge", "head": "kind", "want": {"class": "yes"}}],
+          "sampling": {"temperature": 1.0, "max_len": 12, "seed": 2},
+          "train": {"epochs": 2, "batch": 2, "lr": 0.002, "val_fraction": 0.0, "threads": 2}
+        }"#
+        .replace("DIR", &dd.display().to_string().replace('\\', "/"));
+        let sp = ModelSpec::from_json(&json).unwrap();
+        let src = MemSource::default()
+            .with_texts("texts", &["hello the world", "the world, hello"])
+            .with_texts("loud", &["HELLO!", "WORLD!"])
+            .with_texts("calm", &["hello", "world"]);
+        let (m, rep) = spec::train(None, &sp, &src, None, |_| Flow::Go).unwrap();
+        assert!(rep.steps > 0);
+        let a = m.run(&Value::Text("hello".into())).unwrap();
+        assert!(a.contains_key("tone") && a.contains_key("next"), "{a:?}");
+        let judge = ModelSpec::from_json(
+            r#"{"name": "judge", "input": {"type": "text"}, "trunk": {"preset": "test"},
+                "heads": [{"name": "kind", "kind": "classify", "classes": ["no", "yes"]}]}"#,
+        )
+        .unwrap();
+        let jm = spec::build(&judge, None).unwrap();
+        let models: BTreeMap = [("judge".to_string(), &jm)].into();
+        let c = spec::generate(&m, &models, &Value::Text("the".into()), 3, None).unwrap();
+        assert!(!c.is_empty() && c.iter().all(|c| c.bytes.len() <= 12));
+        // saved and read back: the weights travel in the file, not the folder
+        let back = Model::from_bytes(&m.to_bytes()).unwrap();
+        assert_eq!(back.run(&Value::Text("hello".into())).unwrap(), a);
+        for (field, says) in [
+            (r#""trunk": {"preset": "small"}"#, "sizes come from its checkpoint"),
+            (r#""input": {"type": "text", "features": ["letters"]}"#, "plain text"),
+        ] {
+            let mut v: serde_json::Value = serde_json::from_str(&json).unwrap();
+            let f: serde_json::Value = serde_json::from_str(&format!("{{{field}}}")).unwrap();
+            for (k, x) in f.as_object().unwrap() {
+                v[k] = x.clone();
+            }
+            let e = ModelSpec::from_json(&v.to_string()).unwrap_err();
+            assert!(e.contains(says), "{e}");
+        }
+    }
+}
diff --git a/core/src/classify/report.rs b/core/src/classify/report.rs
new file mode 100644
index 00000000..353d4baf
--- /dev/null
+++ b/core/src/classify/report.rs
@@ -0,0 +1,354 @@
+//! `gpu.report`: what this machine's GPU is, whether it computes the CPU's bits, and how
+//! fast it trains and reads texts next to the CPU, as one JSON value the user writes to
+//! a file and pastes back. Everything in it is measured on the machine it runs on; a
+//! build without the `gpu` feature, or a machine without an adapter, still reports the
+//! CPU's side and says why the GPU's is missing.
+
+use std::time::Instant;
+
+use serde_json::{Value, json};
+
+use super::device::{self, Device, Runner};
+use super::pool::{self, Pool};
+use super::train::{self, Example, TrainOpts};
+use super::{Classifier, Flow, HeadSpec, kernels};
+
+/// how much the report measures
+#[derive(Clone, Debug)]
+pub struct Opts {
+    /// presets to time (see `classifiers::preset`)
+    pub sizes: Vec,
+    /// texts to predict on each device
+    pub texts: usize,
+    /// optimizer steps in the fixed training run
+    pub steps: usize,
+    /// seconds each device may spend predicting, per size: a slow device (a software
+    /// renderer) stops early and its rate is over the texts it got through
+    pub budget: f64,
+    /// texts predicted between looks at the time
+    pub chunk: usize,
+}
+
+impl Default for Opts {
+    fn default() -> Opts {
+        Opts {
+            sizes: vec!["compact".into(), "small".into()],
+            texts: 10_000,
+            steps: 40,
+            budget: 120.0,
+            chunk: 500,
+        }
+    }
+}
+
+/// a text for the fixed workloads: deterministic, 20 to about 400 bytes, words from one
+/// of two vocabularies so a classifier has something to learn
+fn text(i: usize) -> (String, usize) {
+    const A: [&str; 8] = ["river", "stone", "moss", "fern", "heron", "reed", "clay", "dusk"];
+    const B: [&str; 8] = ["copper", "gear", "valve", "rivet", "piston", "wire", "bolt", "lamp"];
+    let class = i % 2;
+    let words = if class == 0 { &A } else { &B };
+    let mut h = (i as u64).wrapping_mul(0x9e37_79b9_7f4a_7c15) | 1;
+    let len = 20 + (h % 380) as usize;
+    let mut s = String::new();
+    while s.len() < len {
+        h ^= h << 13;
+        h ^= h >> 7;
+        h ^= h << 17;
+        s.push_str(words[(h % 8) as usize]);
+        s.push(if h.is_multiple_of(11) { '\n' } else { ' ' });
+    }
+    (s, class)
+}
+
+fn data(n: usize) -> Vec {
+    (0..n)
+        .map(|i| {
+            let (t, c) = text(i);
+            Example::class(&t, c)
+        })
+        .collect()
+}
+
+fn opts(device: Device, steps: usize) -> TrainOpts {
+    TrainOpts {
+        epochs: 1000,
+        batch: 8,
+        lr: 2e-3,
+        val_fraction: 0.0,
+        patience: 0,
+        max_steps: steps,
+        seed: 7,
+        threads: 0,
+        device,
+        ..TrainOpts::default()
+    }
+}
+
+fn fresh(size: &str) -> Result {
+    let cfg = crate::classifiers::preset(size)
+        .ok_or_else(|| format!("no preset {size:?}"))?
+        .gematria(true);
+    Classifier::new(cfg, &[HeadSpec::single("report", &["a", "b"])], 11)
+}
+
+/// the GPU's side of the report: the adapter, its limits and the probe
+#[cfg(feature = "gpu")]
+fn adapter() -> Value {
+    use super::gpu::{self, Precision, probe};
+    let g = match gpu::shared() {
+        Ok(g) => g,
+        Err(e) => return json!({ "error": e }),
+    };
+    let i = &g.info;
+    let l = &g.limits;
+    let probes: Vec = [Precision::Exact, Precision::Fast]
+        .into_iter()
+        .map(|p| {
+            let t = Instant::now();
+            let r = probe::probe(g, p);
+            json!({
+                "precision": format!("{p:?}").to_lowercase(),
+                "exact": r.exact(),
+                "max_rel": r.max_rel(),
+                "seconds": t.elapsed().as_secs_f64(),
+                "kernels": r.checks.iter().map(|c| json!({
+                    "kernel": c.kernel, "values": c.values, "differ": c.differ,
+                    "max_ulps": c.max_ulps, "max_rel": c.max_rel,
+                })).collect::>(),
+            })
+        })
+        .collect();
+    json!({
+        "name": i.name,
+        "vendor": format!("{:#06x}", i.vendor),
+        "device": format!("{:#06x}", i.device),
+        "device_type": format!("{:?}", i.device_type),
+        "backend": format!("{:?}", i.backend),
+        "driver": i.driver,
+        "driver_info": i.driver_info,
+        "limits": {
+            "max_buffer_size": l.max_buffer_size,
+            "max_storage_buffer_binding_size": l.max_storage_buffer_binding_size,
+            "max_uniform_buffer_binding_size": l.max_uniform_buffer_binding_size,
+            "min_uniform_buffer_offset_alignment": l.min_uniform_buffer_offset_alignment,
+            "max_storage_buffers_per_shader_stage": l.max_storage_buffers_per_shader_stage,
+            "max_compute_workgroup_size": [l.max_compute_workgroup_size_x, l.max_compute_workgroup_size_y, l.max_compute_workgroup_size_z],
+            "max_compute_invocations_per_workgroup": l.max_compute_invocations_per_workgroup,
+            "max_compute_workgroup_storage_size": l.max_compute_workgroup_storage_size,
+            "max_compute_workgroups_per_dimension": l.max_compute_workgroups_per_dimension,
+            "all": format!("{l:?}"),
+        },
+        "probe": probes,
+    })
+}
+
+#[cfg(not(feature = "gpu"))]
+fn adapter() -> Value {
+    json!({ "error": "this build has no GPU backend (build with the cargo feature `gpu`)" })
+}
+
+/// the fixed training run on one device: seconds, and the trained weights
+fn train_on(size: &str, device: Device, steps: usize, data: &[Example]) -> Result<(f64, Vec, Value), String> {
+    let mut clf = fresh(size)?;
+    let t = Instant::now();
+    let r = train::train(&mut clf, data, &opts(device, steps), |_| Flow::Go)?;
+    let secs = t.elapsed().as_secs_f64();
+    let v = json!({
+        "seconds": secs,
+        "steps": r.steps,
+        "tokens_per_sec": r.tokens as f64 / secs.max(1e-9),
+    });
+    Ok((secs, clf.to_bytes(), v))
+}
+
+/// predicting `texts` on one device, `chunk` at a time, stopping once `budget` seconds
+/// have gone by: seconds and the probabilities of the texts it got through
+fn predict_on(
+    clf: &Classifier,
+    device: Device,
+    texts: &[&str],
+    pool: &Pool,
+    budget: f64,
+    chunk: usize,
+) -> Result<(f64, Vec>), String> {
+    let t = Instant::now();
+    let runner = match device {
+        Device::Cpu => None,
+        _ => Some(Runner::open(device, &clf.net)?.ok_or("no GPU")?),
+    };
+    let zero = vec![0f32; clf.net.cfg.extra];
+    let mut probs: Vec> = Vec::with_capacity(texts.len());
+    for chunk in texts.chunks(chunk.max(1)) {
+        if !probs.is_empty() && t.elapsed().as_secs_f64() > budget {
+            break;
+        }
+        match &runner {
+            None => probs.extend(
+                clf.predict_many(chunk, &[], pool)
+                    .into_iter()
+                    .map(|mut o| o.swap_remove(0).probs),
+            ),
+            Some(r) => {
+                let bytes: Vec<&[u8]> = chunk.iter().map(|t| t.as_bytes()).collect();
+                let extras: Vec<&[f32]> = chunk.iter().map(|_| zero.as_slice()).collect();
+                probs.extend(
+                    r.text_runs(&clf.net, &bytes, &extras, &clf.gains())
+                        .into_iter()
+                        .map(|(l, _)| clf.read(&l).swap_remove(0).probs),
+                );
+            }
+        }
+    }
+    Ok((t.elapsed().as_secs_f64(), probs))
+}
+
+/// a predicting run's figures
+fn rate(secs: f64, done: usize, all: usize) -> Value {
+    let mut v = json!({ "seconds": secs, "texts": done, "texts_per_sec": done as f64 / secs.max(1e-9) });
+    if done < all {
+        v["stopped"] = json!(format!("after {done} of {all} texts: the time budget ran out"));
+    }
+    v
+}
+
+/// how far a device's probabilities are from the CPU's
+fn compare(cpu: &[Vec], other: &[Vec]) -> Value {
+    let (mut differ, mut max) = (0usize, 0f32);
+    for (a, b) in cpu.iter().zip(other) {
+        if a.iter().zip(b).any(|(x, y)| x.to_bits() != y.to_bits()) {
+            differ += 1;
+        }
+        for (x, y) in a.iter().zip(b) {
+            max = max.max((x - y).abs());
+        }
+    }
+    json!({ "texts_differing": differ, "max_abs_difference": max })
+}
+
+/// the whole report
+pub fn report(o: &Opts) -> Value {
+    let started = Instant::now();
+    let threads = pool::available();
+    let gpu_ok = Device::Gpu.check();
+    let mut sizes = Vec::new();
+    let train_data = data(64);
+    let texts: Vec<(String, usize)> = (0..o.texts).map(|i| text(i + 1_000_000)).collect();
+    let texts: Vec<&str> = texts.iter().map(|(t, _)| t.as_str()).collect();
+    let cpu_pool = Pool::new(threads);
+    for size in &o.sizes {
+        let mut v = json!({ "preset": size });
+        let res: Result<(), String> = (|| {
+            let (_, cpu_bytes, cpu) = train_on(size, Device::Cpu, o.steps, &train_data)?;
+            let clf = Classifier::from_bytes(&cpu_bytes)?;
+            v["weights"] = json!(clf.net.params().iter().map(|(_, p)| p.len()).sum::());
+            v["train"] = json!({ "cpu": cpu });
+            let (cpu_secs, cpu_probs) = predict_on(&clf, Device::Cpu, &texts, &cpu_pool, o.budget, o.chunk)?;
+            let cpu_rate = cpu_probs.len() as f64 / cpu_secs.max(1e-9);
+            v["predict"] = json!({
+                "texts": texts.len(),
+                "cpu": rate(cpu_secs, cpu_probs.len(), texts.len()),
+            });
+            if gpu_ok.is_ok() {
+                for (name, dev) in [("gpu", Device::Gpu), ("gpu_fast", Device::GpuFast)] {
+                    match train_on(size, dev, o.steps, &train_data) {
+                        Ok((_, bytes, mut t)) => {
+                            t["same_weights_as_cpu"] = json!(bytes == cpu_bytes);
+                            v["train"][name] = t;
+                        }
+                        Err(e) => v["train"][name] = json!({ "error": e }),
+                    }
+                    match predict_on(&clf, dev, &texts, &cpu_pool, o.budget, o.chunk) {
+                        Ok((secs, probs)) => {
+                            let mut p = rate(secs, probs.len(), texts.len());
+                            p["speedup_over_cpu"] =
+                                json!(p["texts_per_sec"].as_f64().unwrap_or(0.0) / cpu_rate.max(1e-9));
+                            // the texts both got through
+                            p["against_cpu"] = compare(&cpu_probs, &probs);
+                            v["predict"][name] = p;
+                        }
+                        Err(e) => v["predict"][name] = json!({ "error": e }),
+                    }
+                }
+            }
+            Ok(())
+        })();
+        if let Err(e) = res {
+            v["error"] = json!(e);
+        }
+        sizes.push(v);
+    }
+    json!({
+        "report": "anend gpu.report",
+        "version": 1,
+        "anend": env!("CARGO_PKG_VERSION"),
+        "os": std::env::consts::OS,
+        "arch": std::env::consts::ARCH,
+        "debug_build": cfg!(debug_assertions),
+        "cpu": { "threads": threads, "kernels": kernels::simd_name() },
+        "gpu_build": cfg!(feature = "gpu"),
+        "gpu": adapter(),
+        "gpu_note": gpu_ok.err(),
+        "reading": device::reading(device::choice(), true),
+        "workload": {
+            "train": format!("{} steps of batch 8 on 64 two-class texts, seed 7", o.steps),
+            "predict": format!("{} texts of 20 to about 400 bytes, at most {} s on each device", o.texts, o.budget),
+        },
+        "sizes": sizes,
+        "seconds": started.elapsed().as_secs_f64(),
+    })
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn the_report_measures_and_compares() {
+        let r = report(&Opts {
+            sizes: vec!["tiny".into()],
+            texts: 12,
+            steps: 2,
+            budget: 600.0,
+            chunk: 500,
+        });
+        eprintln!("{r:#}");
+        let s = &r["sizes"][0];
+        assert!(s.get("error").is_none(), "{r}");
+        assert!(s["train"]["cpu"]["seconds"].as_f64().is_some(), "{r}");
+        assert_eq!(s["predict"]["texts"], 12, "{r}");
+        assert_eq!(s["predict"]["cpu"]["texts"], 12, "{r}");
+        // a budget of nothing stops after the first chunk
+        let short = report(&Opts {
+            sizes: vec!["tiny".into()],
+            texts: 12,
+            steps: 1,
+            budget: 0.0,
+            chunk: 5,
+        });
+        assert_eq!(short["sizes"][0]["predict"]["cpu"]["texts"], 5, "{short}");
+        assert!(short["sizes"][0]["predict"]["cpu"]["stopped"].is_string(), "{short}");
+        if Device::Gpu.check().is_ok() {
+            // the probe ran, and exact precision on an exact device gives the CPU's bits
+            assert!(
+                r["gpu"]["probe"][0]["kernels"]
+                    .as_array()
+                    .is_some_and(|k| !k.is_empty()),
+                "{r}"
+            );
+            if r["gpu"]["probe"][0]["exact"] == true {
+                assert_eq!(s["predict"]["gpu"]["against_cpu"]["texts_differing"], 0, "{r}");
+                assert_eq!(s["train"]["gpu"]["same_weights_as_cpu"], true, "{r}");
+            }
+            assert!(
+                s["predict"]["gpu_fast"]["against_cpu"]["max_abs_difference"]
+                    .as_f64()
+                    .unwrap()
+                    < 1e-3,
+                "{r}"
+            );
+        } else {
+            assert!(r["gpu_note"].is_string(), "{r}");
+        }
+    }
+}
diff --git a/core/src/classify/safetensors.rs b/core/src/classify/safetensors.rs
new file mode 100644
index 00000000..dea4aaf7
--- /dev/null
+++ b/core/src/classify/safetensors.rs
@@ -0,0 +1,558 @@
+//! The safetensors weight format (what open models ship in), read and written with std
+//! and `serde_json` only.
+//!
+//! A file is an 8-byte little-endian header length `N`, `N` bytes of JSON mapping each
+//! tensor name to `{"dtype", "shape", "data_offsets": [begin, end]}` (offsets into the
+//! data that follows the header; an optional `"__metadata__"` map of strings), then the
+//! raw little-endian data. Big checkpoints are split into shards listed by
+//! `model.safetensors.index.json` (`{"weight_map": {name: file}}`).
+//!
+//! Tensors are read on demand (seek + read), so a checkpoint never has to fit in memory
+//! twice; `F32`, `F16`, `BF16` and `F64` convert to f32 (F16 and BF16 exactly, F64
+//! rounded). Integer and quantised dtypes are refused by name.
+
+use std::collections::BTreeMap;
+use std::fs::File;
+use std::io::{Read, Seek, SeekFrom, Write};
+use std::path::{Path, PathBuf};
+use std::sync::Mutex;
+
+use serde_json::Value as Json;
+
+/// the element types read (and written)
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum Dtype {
+    F32,
+    F16,
+    BF16,
+    F64,
+}
+
+impl Dtype {
+    pub fn parse(s: &str) -> Result {
+        Ok(match s {
+            "F32" => Dtype::F32,
+            "F16" => Dtype::F16,
+            "BF16" => Dtype::BF16,
+            "F64" => Dtype::F64,
+            other => {
+                return Err(format!(
+                    "dtype {other} is not supported (F32, F16, BF16 and F64 are; quantised checkpoints need converting first)"
+                ));
+            }
+        })
+    }
+
+    pub fn name(self) -> &'static str {
+        match self {
+            Dtype::F32 => "F32",
+            Dtype::F16 => "F16",
+            Dtype::BF16 => "BF16",
+            Dtype::F64 => "F64",
+        }
+    }
+
+    pub fn size(self) -> usize {
+        match self {
+            Dtype::F32 => 4,
+            Dtype::F16 | Dtype::BF16 => 2,
+            Dtype::F64 => 8,
+        }
+    }
+}
+
+/// IEEE half to f32, exactly (subnormals, infinities and NaN included)
+pub fn f16_to_f32(h: u16) -> f32 {
+    let sign = ((h >> 15) as u32) << 31;
+    let exp = ((h >> 10) & 0x1f) as u32;
+    let man = (h & 0x3ff) as u32;
+    let bits = match (exp, man) {
+        (0, 0) => sign,
+        (0, m) => {
+            // subnormal: normalise the mantissa
+            let mut e = 127 - 15 + 1;
+            let mut m = m;
+            while m & 0x400 == 0 {
+                m <<= 1;
+                e -= 1;
+            }
+            sign | (e << 23) | ((m & 0x3ff) << 13)
+        }
+        (0x1f, 0) => sign | 0x7f80_0000,
+        (0x1f, m) => sign | 0x7fc0_0000 | (m << 13),
+        (e, m) => sign | ((e + 127 - 15) << 23) | (m << 13),
+    };
+    f32::from_bits(bits)
+}
+
+/// f32 to IEEE half, rounding to nearest even (overflow to infinity)
+pub fn f32_to_f16(x: f32) -> u16 {
+    let b = x.to_bits();
+    let sign = ((b >> 16) & 0x8000) as u16;
+    let exp = ((b >> 23) & 0xff) as i32;
+    let man = b & 0x7f_ffff;
+    if exp == 0xff {
+        return sign | 0x7c00 | if man != 0 { 0x200 } else { 0 };
+    }
+    let e = exp - 127 + 15;
+    if e >= 0x1f {
+        return sign | 0x7c00;
+    }
+    if e <= 0 {
+        if e < -10 {
+            return sign;
+        }
+        // subnormal half: shift the full mantissa (with its hidden bit) into place
+        let m = man | 0x80_0000;
+        let shift = (14 - e) as u32;
+        let half = 1u32 << (shift - 1);
+        let rest = m & ((1 << shift) - 1);
+        let mut v = m >> shift;
+        if rest > half || (rest == half && v & 1 == 1) {
+            v += 1;
+        }
+        return sign | v as u16;
+    }
+    let mut v = ((e as u32) << 10) | (man >> 13);
+    let rest = man & 0x1fff;
+    if rest > 0x1000 || (rest == 0x1000 && v & 1 == 1) {
+        v += 1; // may carry into the exponent, which is the right answer (up to infinity)
+    }
+    sign | v as u16
+}
+
+/// bfloat16 to f32, exactly
+pub fn bf16_to_f32(h: u16) -> f32 {
+    f32::from_bits((h as u32) << 16)
+}
+
+/// f32 to bfloat16, rounding to nearest even
+pub fn f32_to_bf16(x: f32) -> u16 {
+    let b = x.to_bits();
+    if x.is_nan() {
+        return ((b >> 16) | 0x40) as u16;
+    }
+    let rest = b & 0xffff;
+    let mut v = b >> 16;
+    if rest > 0x8000 || (rest == 0x8000 && v & 1 == 1) {
+        v += 1;
+    }
+    v as u16
+}
+
+/// little-endian raw data of `dtype` to f32
+pub fn to_f32(dtype: Dtype, raw: &[u8]) -> Vec {
+    match dtype {
+        Dtype::F32 => raw.as_chunks::<4>().0.iter().map(|c| f32::from_le_bytes(*c)).collect(),
+        Dtype::F16 => raw
+            .as_chunks::<2>()
+            .0
+            .iter()
+            .map(|c| f16_to_f32(u16::from_le_bytes(*c)))
+            .collect(),
+        Dtype::BF16 => raw
+            .as_chunks::<2>()
+            .0
+            .iter()
+            .map(|c| bf16_to_f32(u16::from_le_bytes(*c)))
+            .collect(),
+        Dtype::F64 => raw
+            .as_chunks::<8>()
+            .0
+            .iter()
+            .map(|c| f64::from_le_bytes(*c) as f32)
+            .collect(),
+    }
+}
+
+fn from_f32(dtype: Dtype, x: &[f32]) -> Vec {
+    let mut out = Vec::with_capacity(x.len() * dtype.size());
+    for &v in x {
+        match dtype {
+            Dtype::F32 => out.extend_from_slice(&v.to_le_bytes()),
+            Dtype::F16 => out.extend_from_slice(&f32_to_f16(v).to_le_bytes()),
+            Dtype::BF16 => out.extend_from_slice(&f32_to_bf16(v).to_le_bytes()),
+            Dtype::F64 => out.extend_from_slice(&(v as f64).to_le_bytes()),
+        }
+    }
+    out
+}
+
+/// one tensor's entry in a header
+#[derive(Clone, Debug, PartialEq)]
+pub struct Info {
+    pub dtype: Dtype,
+    pub shape: Vec,
+    /// byte range in the file (header included)
+    pub start: u64,
+    pub end: u64,
+}
+
+impl Info {
+    pub fn len(&self) -> usize {
+        self.shape.iter().product()
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.len() == 0
+    }
+}
+
+/// one safetensors file: its header read, tensors read on demand
+#[derive(Debug)]
+pub struct SafeTensors {
+    pub path: PathBuf,
+    pub tensors: BTreeMap,
+    pub metadata: BTreeMap,
+    file: Mutex,
+}
+
+/// tensors by name, and the metadata strings
+type Header = (BTreeMap, BTreeMap);
+
+/// parses a header (the JSON after the length) for a file of `file_len` bytes
+fn parse_header(json: &[u8], header_len: u64, file_len: u64) -> Result {
+    let v: Json = serde_json::from_slice(json).map_err(|e| format!("safetensors header: {e}"))?;
+    let obj = v.as_object().ok_or("safetensors header is not an object")?;
+    let base = 8 + header_len;
+    let mut tensors = BTreeMap::new();
+    let mut metadata = BTreeMap::new();
+    for (name, e) in obj {
+        if name == "__metadata__" {
+            if let Some(m) = e.as_object() {
+                for (k, v) in m {
+                    metadata.insert(k.clone(), v.as_str().unwrap_or_default().to_string());
+                }
+            }
+            continue;
+        }
+        let bad = |what: &str| format!("safetensors tensor {name:?}: {what}");
+        let dtype = Dtype::parse(e["dtype"].as_str().ok_or_else(|| bad("no dtype"))?).map_err(|m| bad(&m))?;
+        let shape: Vec = e["shape"]
+            .as_array()
+            .ok_or_else(|| bad("no shape"))?
+            .iter()
+            .map(|d| {
+                d.as_u64()
+                    .map(|d| d as usize)
+                    .ok_or_else(|| bad("shape is not whole numbers"))
+            })
+            .collect::>()?;
+        let off = e["data_offsets"].as_array().ok_or_else(|| bad("no data_offsets"))?;
+        let (b, en) = match (off.first().and_then(Json::as_u64), off.get(1).and_then(Json::as_u64)) {
+            (Some(b), Some(en)) if off.len() == 2 && b <= en => (b, en),
+            _ => return Err(bad("data_offsets is not [begin, end]")),
+        };
+        let count = shape
+            .iter()
+            .try_fold(1usize, |a, &d| a.checked_mul(d))
+            .ok_or_else(|| bad("shape too large"))?;
+        let bytes = count.checked_mul(dtype.size()).ok_or_else(|| bad("shape too large"))? as u64;
+        if en - b != bytes {
+            return Err(bad(&format!(
+                "{} bytes of data for shape {shape:?} of {}",
+                en - b,
+                dtype.name()
+            )));
+        }
+        let (start, end) = (
+            base.checked_add(b).ok_or_else(|| bad("offset"))?,
+            base.checked_add(en).ok_or_else(|| bad("offset"))?,
+        );
+        if end > file_len {
+            return Err(bad("data past the end of the file"));
+        }
+        tensors.insert(
+            name.clone(),
+            Info {
+                dtype,
+                shape,
+                start,
+                end,
+            },
+        );
+    }
+    Ok((tensors, metadata))
+}
+
+impl SafeTensors {
+    pub fn open(path: &Path) -> Result {
+        let err = |e: std::io::Error| format!("{}: {e}", path.display());
+        let mut f = File::open(path).map_err(err)?;
+        let file_len = f.metadata().map_err(err)?.len();
+        let mut n = [0u8; 8];
+        f.read_exact(&mut n)
+            .map_err(|_| format!("{}: not a safetensors file (too short)", path.display()))?;
+        let hl = u64::from_le_bytes(n);
+        if hl.checked_add(8).is_none_or(|e| e > file_len) {
+            return Err(format!(
+                "{}: not a safetensors file (header length {hl})",
+                path.display()
+            ));
+        }
+        let mut json = vec![0u8; hl as usize];
+        f.read_exact(&mut json).map_err(err)?;
+        let (tensors, metadata) = parse_header(&json, hl, file_len).map_err(|e| format!("{}: {e}", path.display()))?;
+        Ok(SafeTensors {
+            path: path.to_path_buf(),
+            tensors,
+            metadata,
+            file: Mutex::new(f),
+        })
+    }
+
+    /// a tensor's values as f32
+    pub fn read(&self, name: &str) -> Result, String> {
+        let info = self
+            .tensors
+            .get(name)
+            .ok_or_else(|| format!("{}: no tensor {name:?}", self.path.display()))?;
+        let mut raw = vec![0u8; (info.end - info.start) as usize];
+        let mut f = self.file.lock().unwrap();
+        f.seek(SeekFrom::Start(info.start))
+            .and_then(|_| f.read_exact(&mut raw))
+            .map_err(|e| format!("{}: {name}: {e}", self.path.display()))?;
+        Ok(to_f32(info.dtype, &raw))
+    }
+}
+
+/// a model's weights: one safetensors file or the shards of an index
+#[derive(Debug)]
+pub struct Checkpoint {
+    files: Vec,
+    /// tensor name → file
+    index: BTreeMap,
+}
+
+impl Checkpoint {
+    /// `model.safetensors.index.json` (sharded), else `model.safetensors`, else every
+    /// `*.safetensors` file in `dir`
+    pub fn open_dir(dir: &Path) -> Result {
+        let idx = dir.join("model.safetensors.index.json");
+        if idx.exists() {
+            return Checkpoint::open_index(&idx);
+        }
+        let one = dir.join("model.safetensors");
+        if one.exists() {
+            return Checkpoint::from_files(&[one]);
+        }
+        let mut all: Vec = std::fs::read_dir(dir)
+            .map_err(|e| format!("{}: {e}", dir.display()))?
+            .filter_map(|e| e.ok().map(|e| e.path()))
+            .filter(|p| p.extension().is_some_and(|x| x == "safetensors"))
+            .collect();
+        all.sort();
+        if all.is_empty() {
+            return Err(format!(
+                "{}: no safetensors weights (model.safetensors or an index)",
+                dir.display()
+            ));
+        }
+        Checkpoint::from_files(&all)
+    }
+
+    /// a sharded checkpoint from its index file
+    pub fn open_index(path: &Path) -> Result {
+        let text = std::fs::read_to_string(path).map_err(|e| format!("{}: {e}", path.display()))?;
+        let v: Json = serde_json::from_str(&text).map_err(|e| format!("{}: {e}", path.display()))?;
+        let map = v["weight_map"]
+            .as_object()
+            .ok_or(format!("{}: no weight_map", path.display()))?;
+        let dir = path.parent().unwrap_or(Path::new("."));
+        let mut names: Vec = map.values().filter_map(|f| f.as_str().map(String::from)).collect();
+        names.sort();
+        names.dedup();
+        for n in &names {
+            if n.contains("..") || Path::new(n).is_absolute() {
+                return Err(format!("{}: shard {n:?} is outside the model folder", path.display()));
+            }
+        }
+        let files: Vec = names.iter().map(|n| dir.join(n)).collect();
+        let cp = Checkpoint::from_files(&files)?;
+        // every tensor the index names must be in its shard
+        for (t, f) in map {
+            let f = f.as_str().unwrap_or_default();
+            let i = names.iter().position(|n| n == f).expect("listed");
+            if !cp.files[i].tensors.contains_key(t) {
+                return Err(format!("{}: tensor {t:?} is not in shard {f}", path.display()));
+            }
+        }
+        Ok(cp)
+    }
+
+    pub fn from_files(paths: &[PathBuf]) -> Result {
+        let files: Vec = paths.iter().map(|p| SafeTensors::open(p)).collect::>()?;
+        let mut index = BTreeMap::new();
+        for (i, f) in files.iter().enumerate() {
+            for name in f.tensors.keys() {
+                if index.insert(name.clone(), i).is_some() {
+                    return Err(format!("tensor {name:?} is in two shards"));
+                }
+            }
+        }
+        Ok(Checkpoint { files, index })
+    }
+
+    pub fn names(&self) -> impl Iterator {
+        self.index.keys().map(String::as_str)
+    }
+
+    pub fn has(&self, name: &str) -> bool {
+        self.index.contains_key(name)
+    }
+
+    pub fn info(&self, name: &str) -> Option<&Info> {
+        self.index.get(name).and_then(|&i| self.files[i].tensors.get(name))
+    }
+
+    /// a tensor as f32, checked against the shape the caller expects
+    pub fn get(&self, name: &str, shape: &[usize]) -> Result, String> {
+        let i = *self
+            .index
+            .get(name)
+            .ok_or_else(|| format!("the checkpoint has no tensor {name:?}"))?;
+        let info = &self.files[i].tensors[name];
+        if info.shape != shape {
+            return Err(format!(
+                "tensor {name:?} has shape {:?}, the config implies {shape:?}",
+                info.shape
+            ));
+        }
+        self.files[i].read(name)
+    }
+}
+
+/// writes a safetensors file (tensors in the order given, each as `dtype`)
+pub fn write(path: &Path, tensors: &[(&str, Dtype, &[usize], &[f32])]) -> Result<(), String> {
+    let mut header = serde_json::Map::new();
+    let mut data = Vec::new();
+    for (name, dtype, shape, values) in tensors {
+        if shape.iter().product::() != values.len() {
+            return Err(format!("tensor {name:?}: {} values for shape {shape:?}", values.len()));
+        }
+        let begin = data.len();
+        data.extend(from_f32(*dtype, values));
+        header.insert(
+            name.to_string(),
+            serde_json::json!({"dtype": dtype.name(), "shape": shape, "data_offsets": [begin, data.len()]}),
+        );
+    }
+    let mut json = serde_json::to_vec(&Json::Object(header)).expect("json");
+    // the format pads the header with spaces to a multiple of 8
+    while !json.len().is_multiple_of(8) {
+        json.push(b' ');
+    }
+    let mut f = File::create(path).map_err(|e| format!("{}: {e}", path.display()))?;
+    f.write_all(&(json.len() as u64).to_le_bytes())
+        .and_then(|_| f.write_all(&json))
+        .and_then(|_| f.write_all(&data))
+        .map_err(|e| format!("{}: {e}", path.display()))
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    fn dir(name: &str) -> PathBuf {
+        let d = std::env::temp_dir().join(format!("anend-st-{}-{name}", std::process::id()));
+        let _ = std::fs::remove_dir_all(&d);
+        std::fs::create_dir_all(&d).unwrap();
+        d
+    }
+
+    #[test]
+    fn half_floats_convert_exactly() {
+        for h in 0..=u16::MAX {
+            let f = f16_to_f32(h);
+            if f.is_nan() {
+                assert!(f32_to_f16(f) & 0x7c00 == 0x7c00);
+                continue;
+            }
+            assert_eq!(f32_to_f16(f), h, "half {h:#06x} → {f} back");
+            assert_eq!(f32_to_bf16(bf16_to_f32(h)), h);
+        }
+        assert_eq!(f16_to_f32(0x3c00), 1.0);
+        assert_eq!(f16_to_f32(0xc000), -2.0);
+        assert_eq!(f16_to_f32(0x0001), 2f32.powi(-24));
+        assert_eq!(f32_to_f16(65520.0), 0x7c00, "rounds up to infinity");
+        assert_eq!(f32_to_f16(1.0 + 2f32.powi(-11)), 0x3c00, "ties to even");
+        assert_eq!(bf16_to_f32(0x3f80), 1.0);
+        assert_eq!(f32_to_bf16(1.0 + 2f32.powi(-8)), 0x3f80, "ties to even");
+    }
+
+    #[test]
+    fn files_and_shards_read_back() {
+        let d = dir("shards");
+        let a: Vec = (0..6).map(|i| i as f32 * 0.5 - 1.0).collect();
+        let b = vec![1.5f32, -0.25, 3.0, 0.0];
+        write(
+            &d.join("one.safetensors"),
+            &[("a", Dtype::F32, &[2, 3], &a), ("b", Dtype::BF16, &[4], &b)],
+        )
+        .unwrap();
+        write(
+            &d.join("two.safetensors"),
+            &[("c", Dtype::F16, &[2, 2], &b), ("d", Dtype::F64, &[1], &[7.0])],
+        )
+        .unwrap();
+        std::fs::write(
+            d.join("model.safetensors.index.json"),
+            r#"{"metadata": {"total_size": 1}, "weight_map": {"a": "one.safetensors", "b": "one.safetensors",
+               "c": "two.safetensors", "d": "two.safetensors"}}"#,
+        )
+        .unwrap();
+        let cp = Checkpoint::open_dir(&d).unwrap();
+        assert_eq!(cp.names().collect::>(), ["a", "b", "c", "d"]);
+        assert_eq!(cp.get("a", &[2, 3]).unwrap(), a);
+        assert_eq!(cp.get("b", &[4]).unwrap(), b);
+        assert_eq!(cp.get("c", &[2, 2]).unwrap(), b);
+        assert_eq!(cp.get("d", &[1]).unwrap(), [7.0]);
+        assert!(cp.get("a", &[3, 2]).unwrap_err().contains("shape [2, 3]"));
+        assert!(cp.get("z", &[1]).unwrap_err().contains("no tensor"));
+        // a single file without an index
+        let d2 = dir("single");
+        write(
+            &d2.join("model.safetensors"),
+            &[("x", Dtype::F16, &[3], &[1.0, 2.0, -0.5])],
+        )
+        .unwrap();
+        assert_eq!(
+            Checkpoint::open_dir(&d2).unwrap().get("x", &[3]).unwrap(),
+            [1.0, 2.0, -0.5]
+        );
+    }
+
+    #[test]
+    fn bad_files_are_refused_in_words() {
+        let d = dir("bad");
+        let p = d.join("x.safetensors");
+        std::fs::write(&p, [1, 2, 3]).unwrap();
+        assert!(SafeTensors::open(&p).unwrap_err().contains("too short"));
+        let mk = |json: &str, data: usize| {
+            let mut v = (json.len() as u64).to_le_bytes().to_vec();
+            v.extend_from_slice(json.as_bytes());
+            v.extend(std::iter::repeat_n(0u8, data));
+            std::fs::write(&p, v).unwrap();
+            SafeTensors::open(&p).map(|_| ())
+        };
+        assert!(
+            mk(r#"{"w": {"dtype": "I8", "shape": [2], "data_offsets": [0, 2]}}"#, 2)
+                .unwrap_err()
+                .contains("dtype I8 is not supported")
+        );
+        assert!(
+            mk(r#"{"w": {"dtype": "F32", "shape": [2], "data_offsets": [0, 4]}}"#, 4)
+                .unwrap_err()
+                .contains("4 bytes of data for shape [2]")
+        );
+        assert!(
+            mk(r#"{"w": {"dtype": "F32", "shape": [2], "data_offsets": [0, 8]}}"#, 4)
+                .unwrap_err()
+                .contains("past the end")
+        );
+        let mut v = u64::MAX.to_le_bytes().to_vec();
+        v.extend([0; 8]);
+        std::fs::write(&p, v).unwrap();
+        assert!(SafeTensors::open(&p).unwrap_err().contains("header length"));
+    }
+}
diff --git a/core/src/classify/spec.rs b/core/src/classify/spec.rs
new file mode 100644
index 00000000..ab8d96ba
--- /dev/null
+++ b/core/src/classify/spec.rs
@@ -0,0 +1,1527 @@
+//! The declarative model spec: the primary way to make a model. A `ModelSpec` is plain
+//! data (JSON here; later the scripting language and the UI edit the same thing) that
+//! says what goes in, how big the trunk is, which outputs come out, what it learns from
+//! (queries over the save, through a `Source`), and, for generators, which other models
+//! judge what it writes. `build` makes the model, `train` resolves the data and trains
+//! every head together, `run` answers with named outputs, `generate` draws candidates
+//! judged by the spec's critics. An existing classifier is one instance of a spec
+//! (`Model::from_classifier`). The format is documented in `docs/models.md`.
+
+use std::collections::BTreeMap;
+
+use serde::{Deserialize, Serialize};
+
+use super::bench::{self, MachineProfile, Task};
+use super::codec::{Codebook, Image, NumberCodec};
+use super::device::{Device, Runner};
+use super::generate::{self, Candidate, Constraints, Critic, GenOpts, Judge, Sampling, Want};
+use super::model::{Config, GenSpec, HeadKind, HeadSpec, Pooling};
+use super::steer::Output;
+use super::train::{self, Example, Target, TrainOpts, TrainReport};
+use super::{Classifier, Flow, Progress};
+
+/// the newest spec version this build reads
+pub const SPEC_VERSION: u32 = 1;
+/// separates the input from the output of a pair in a sequence-to-sequence generator
+pub const PAIR: u8 = 0x1e;
+
+fn v1() -> u32 {
+    1
+}
+
+fn one() -> f32 {
+    1.0
+}
+
+/// an optional input feature channel (all off unless listed)
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum Feature {
+    /// a token's letter value, a = 1 .. z = 26
+    Letters,
+    /// the ordinal, reversed and Atbash sums of the word a token is in, and digit roots
+    WordSums,
+    /// whole-text measures (letter frequencies, sums, shape) at the heads
+    Side,
+}
+
+/// what a model reads
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(tag = "type", rename_all = "snake_case")]
+#[serde(deny_unknown_fields)]
+pub enum InputSpec {
+    /// UTF-8 text, as bytes, with any feature channels
+    Text {
+        #[serde(default)]
+        features: Vec,
+    },
+    /// any bytes
+    Bytes,
+    /// pictures cut into `patch`-pixel squares, each one of `codes` learned patch
+    /// prototypes (one token per patch)
+    Image {
+        width: usize,
+        height: usize,
+        #[serde(default = "patch8")]
+        patch: usize,
+        #[serde(default = "codes")]
+        codes: usize,
+    },
+    /// a vector of named numbers, written as fixed-width text for the trunk and also
+    /// given to the heads as they are
+    Numbers { names: Vec, codec: NumberCodec },
+}
+
+fn patch8() -> usize {
+    8
+}
+
+fn codes() -> usize {
+    128
+}
+
+/// the trunk; anything left out comes from the preset (or, with `preset: "auto"` and a
+/// machine profile, from the benchmark)
+#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
+#[serde(default)]
+#[serde(deny_unknown_fields)]
+pub struct TrunkSpec {
+    /// "test" (tests and CI only), "compact", "small", "base", or "auto"
+    pub preset: Option,
+    pub d_model: Option,
+    pub layers: Option,
+    pub heads: Option,
+    pub head_dim: Option,
+    pub d_ff: Option,
+    /// tokens per window, CLS and SEP included
+    pub max_len: Option,
+    /// default: on when there is a generate head
+    pub causal: Option,
+    pub pooling: Option,
+    pub dropout: Option,
+}
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum OutKind {
+    /// one class of several (softmax)
+    Classify,
+    /// any of several labels (a sigmoid each)
+    Multi,
+    /// numbers (squared error)
+    Regress,
+    /// the next byte (writes bytes, text, pictures, numbers)
+    Generate,
+}
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(deny_unknown_fields)]
+pub struct HeadDecl {
+    pub name: String,
+    pub kind: OutKind,
+    /// class, label or value names (none for generate)
+    #[serde(default)]
+    pub classes: Vec,
+    /// how much this head's loss counts when heads train together
+    #[serde(default = "one")]
+    pub weight: f32,
+}
+
+/// a value of the model's input type
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum Value {
+    Text(String),
+    Bytes(Vec),
+    Image(Image),
+    Numbers(Vec),
+}
+
+/// where training data comes from: queries over a `Source` (the save), or inline
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(tag = "from", rename_all = "snake_case")]
+#[serde(deny_unknown_fields)]
+pub enum DataQuery {
+    /// the members of list `list` as class `class` of head `head` (for a generate
+    /// head: texts to learn to write; for a regress head: `value`)
+    List {
+        list: String,
+        head: String,
+        #[serde(default)]
+        class: Option,
+        #[serde(default)]
+        value: Option>,
+    },
+    /// entries tagged `tag`, likewise
+    Tagged {
+        tag: String,
+        head: String,
+        #[serde(default)]
+        class: Option,
+        #[serde(default)]
+        value: Option>,
+    },
+    /// pairs (input from list `input`, output from list `output`) for a generate head:
+    /// it learns to write the output after the input
+    Pairs {
+        input: String,
+        output: String,
+        head: String,
+    },
+    /// the save's pictures (of list `list`, or all of them) for a picture model, likewise:
+    /// each scaled to the input's width and height
+    Pictures {
+        #[serde(default)]
+        list: Option,
+        head: String,
+        #[serde(default)]
+        class: Option,
+        #[serde(default)]
+        value: Option>,
+    },
+    /// examples written into the spec
+    Inline { items: Vec },
+}
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(deny_unknown_fields)]
+pub struct InlineItem {
+    pub input: Value,
+    pub head: String,
+    #[serde(default)]
+    pub class: Option,
+    #[serde(default)]
+    pub value: Option>,
+}
+
+/// what a critic wants of its head
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum WantDecl {
+    Class(String),
+    Not(String),
+    Near {
+        value: String,
+        target: f32,
+        scale: f32,
+    },
+    Range {
+        value: String,
+        lo: f32,
+        hi: f32,
+        scale: f32,
+    },
+}
+
+/// another model judging what a generator writes
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(deny_unknown_fields)]
+pub struct CriticSpec {
+    /// the model's name, resolved when generating
+    pub model: String,
+    pub head: String,
+    pub want: WantDecl,
+    #[serde(default = "one")]
+    pub weight: f32,
+}
+
+#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
+#[serde(default)]
+#[serde(deny_unknown_fields)]
+pub struct TrainSpec {
+    pub epochs: Option,
+    pub batch: Option,
+    pub lr: Option,
+    pub val_fraction: Option,
+    pub patience: Option,
+    pub max_steps: Option,
+    pub threads: Option,
+    /// seconds of training to size an "auto" trunk for
+    pub budget_seconds: Option,
+}
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(deny_unknown_fields)]
+pub struct ModelSpec {
+    #[serde(default = "v1")]
+    pub version: u32,
+    pub name: String,
+    pub input: InputSpec,
+    #[serde(default)]
+    pub trunk: TrunkSpec,
+    pub heads: Vec,
+    #[serde(default)]
+    pub data: Vec,
+    #[serde(default)]
+    pub critics: Vec,
+    #[serde(default)]
+    pub constraints: Constraints,
+    #[serde(default)]
+    pub sampling: Sampling,
+    #[serde(default)]
+    pub train: TrainSpec,
+    #[serde(default)]
+    pub seed: u64,
+    /// where the trunk comes from: a pretrained model folder instead of new weights
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub from: Option,
+    /// where training and generation run: "cpu" (the default and the reference),
+    /// "gpu" (exact precision) or "gpu_fast"; a GPU needs the `gpu` build feature
+    #[serde(default, skip_serializing_if = "is_cpu")]
+    pub device: Device,
+}
+
+fn is_cpu(d: &Device) -> bool {
+    *d == Device::Cpu
+}
+
+/// a model's starting point other than fresh weights
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum Origin {
+    /// a HuggingFace model folder (config.json, tokenizer.json, safetensors), see
+    /// `pretrained`: its trunk, vocabulary and language-model head (the spec's generate
+    /// head); the spec's classify/multi/regress heads go on its trunk, new
+    Pretrained(String),
+}
+
+/// the data behind queries: the save (the entry store implements this), or memory
+pub trait Source {
+    fn list(&self, name: &str) -> Result, String>;
+    fn tagged(&self, tag: &str) -> Result, String>;
+    /// the source's pictures: those of list `list`, or all of them
+    fn pictures(&self, list: Option<&str>) -> Result, String> {
+        let _ = list;
+        Err("this source holds no pictures".into())
+    }
+    /// by default the two lists side by side, in order
+    fn pairs(&self, input: &str, output: &str) -> Result, String> {
+        Ok(self.list(input)?.into_iter().zip(self.list(output)?).collect())
+    }
+}
+
+/// lists and tags in memory
+#[derive(Clone, Debug, Default)]
+pub struct MemSource {
+    pub lists: BTreeMap>,
+    pub tags: BTreeMap>,
+    /// pictures by list name ("" for all of them)
+    pub pictures: BTreeMap>,
+}
+
+impl MemSource {
+    pub fn with_list(mut self, name: &str, items: Vec) -> MemSource {
+        self.lists.insert(name.into(), items);
+        self
+    }
+
+    pub fn with_texts(self, name: &str, texts: &[&str]) -> MemSource {
+        self.with_list(name, texts.iter().map(|t| Value::Text(t.to_string())).collect())
+    }
+}
+
+impl Source for MemSource {
+    fn list(&self, name: &str) -> Result, String> {
+        self.lists.get(name).cloned().ok_or(format!("no list {name:?}"))
+    }
+
+    fn tagged(&self, tag: &str) -> Result, String> {
+        Ok(self.tags.get(tag).cloned().unwrap_or_default())
+    }
+
+    fn pictures(&self, list: Option<&str>) -> Result, String> {
+        let k = list.unwrap_or("");
+        self.pictures.get(k).cloned().ok_or(if k.is_empty() {
+            "no pictures".to_string()
+        } else {
+            format!("no pictures in list {k:?}")
+        })
+    }
+}
+
+/// one resolved data item: the value, its head, its class or values
+type Item = (Value, String, Option, Option>);
+
+/// a broken rule in a spec, and where: `path` is the field (`heads[1].classes`,
+/// `data[0].class`; empty for the whole spec)
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct SpecError {
+    pub model: String,
+    pub path: String,
+    pub message: String,
+}
+
+impl std::fmt::Display for SpecError {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        write!(f, "model spec {:?}: {}", self.model, self.message)
+    }
+}
+
+/// a head by name
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum Slot {
+    Pooled(usize),
+    Gen,
+}
+
+impl ModelSpec {
+    /// parses JSON and checks it
+    pub fn from_json(s: &str) -> Result {
+        let spec: ModelSpec = serde_json::from_str(s).map_err(|e| format!("model spec: {e}"))?;
+        spec.check()?;
+        Ok(spec)
+    }
+
+    pub fn to_json(&self) -> String {
+        serde_json::to_string_pretty(self).expect("specs serialise")
+    }
+
+    pub fn slot(&self, head: &str) -> Result {
+        let mut pooled = 0;
+        for h in &self.heads {
+            if h.name == head {
+                return Ok(if h.kind == OutKind::Generate {
+                    Slot::Gen
+                } else {
+                    Slot::Pooled(pooled)
+                });
+            }
+            if h.kind != OutKind::Generate {
+                pooled += 1;
+            }
+        }
+        Err(format!("{}: no head {head:?}", self.name))
+    }
+
+    fn decl(&self, head: &str) -> Result<&HeadDecl, String> {
+        self.heads
+            .iter()
+            .find(|h| h.name == head)
+            .ok_or(format!("{}: no head {head:?}", self.name))
+    }
+
+    fn generates(&self) -> bool {
+        self.heads.iter().any(|h| h.kind == OutKind::Generate)
+    }
+
+    /// every rule a spec must keep, with the first broken one in words
+    pub fn check(&self) -> Result<(), String> {
+        self.check_at().map_err(|e| e.to_string())
+    }
+
+    /// [`ModelSpec::check`] with where in the spec the broken rule is (`heads[1].classes`)
+    pub fn check_at(&self) -> Result<(), SpecError> {
+        let name = self.name.clone();
+        let at = |path: String, m: String| {
+            Err(SpecError {
+                model: name.clone(),
+                path,
+                message: m,
+            })
+        };
+        if self.version == 0 || self.version > SPEC_VERSION {
+            return at(
+                "version".into(),
+                format!("version {} (this build reads 1 to {SPEC_VERSION})", self.version),
+            );
+        }
+        if self.name.trim().is_empty() {
+            return at("name".into(), "a model needs a name".into());
+        }
+        if self.heads.is_empty() {
+            return at("heads".into(), "a model needs at least one head".into());
+        }
+        let mut names = std::collections::BTreeSet::new();
+        for (i, h) in self.heads.iter().enumerate() {
+            if !names.insert(&h.name) {
+                return at(format!("heads[{i}].name"), format!("two heads are called {:?}", h.name));
+            }
+            if !(h.weight >= 0.0 && h.weight.is_finite()) {
+                return at(
+                    format!("heads[{i}].weight"),
+                    format!("head {:?}: weight must be finite and not negative", h.name),
+                );
+            }
+            let classes = format!("heads[{i}].classes");
+            match h.kind {
+                OutKind::Generate if !h.classes.is_empty() => {
+                    return at(classes, format!("head {:?}: a generate head has no classes", h.name));
+                }
+                OutKind::Classify if h.classes.len() < 2 => {
+                    return at(
+                        classes,
+                        format!("head {:?}: classify needs at least two classes", h.name),
+                    );
+                }
+                OutKind::Multi | OutKind::Regress if h.classes.is_empty() => {
+                    return at(
+                        classes,
+                        format!("head {:?}: needs at least one label or value name", h.name),
+                    );
+                }
+                _ => {}
+            }
+        }
+        if let Some(i) = self
+            .heads
+            .iter()
+            .enumerate()
+            .filter(|(_, h)| h.kind == OutKind::Generate)
+            .nth(1)
+            .map(|(i, _)| i)
+        {
+            return at(format!("heads[{i}].kind"), "at most one generate head".into());
+        }
+        if self.generates() && self.trunk.causal == Some(false) {
+            return at("trunk.causal".into(), "a generate head needs a causal trunk".into());
+        }
+        if let InputSpec::Image {
+            width,
+            height,
+            patch,
+            codes,
+        } = self.input
+        {
+            if patch == 0 || width == 0 || height == 0 || width % patch != 0 || height % patch != 0 {
+                return at(
+                    "input".into(),
+                    format!("image {width}×{height} must be a positive multiple of the {patch} pixel patch"),
+                );
+            }
+            if codes == 0 || codes > super::codec::MAX_CODES {
+                return at(
+                    "input.codes".into(),
+                    format!("an image codebook holds 1 to {} codes", super::codec::MAX_CODES),
+                );
+            }
+        }
+        if let InputSpec::Numbers { names, .. } = &self.input
+            && names.is_empty()
+        {
+            return at("input.names".into(), "a numbers input names at least one number".into());
+        }
+        // a data item's head and target, the path's field that is wrong and why
+        let check_target =
+            |head: &str, class: &Option, value: &Option>| -> Result<(), (&'static str, String)> {
+                let h = self.decl(head).map_err(|e| ("head", e))?;
+                match h.kind {
+                    OutKind::Classify | OutKind::Multi => match class {
+                        Some(c) if h.classes.contains(c) => Ok(()),
+                        Some(c) => Err(("class", format!("head {head:?} has no class {c:?}"))),
+                        None => Err(("class", format!("data for head {head:?} names a class"))),
+                    },
+                    OutKind::Regress => match value {
+                        Some(v) if v.len() == h.classes.len() => Ok(()),
+                        _ => Err((
+                            "value",
+                            format!("data for head {head:?} gives {} values", h.classes.len()),
+                        )),
+                    },
+                    OutKind::Generate => Ok(()),
+                }
+            };
+        for (i, q) in self.data.iter().enumerate() {
+            let r = match q {
+                DataQuery::List { head, class, value, .. } | DataQuery::Tagged { head, class, value, .. } => {
+                    check_target(head, class, value).map_err(|(f, e)| (format!("data[{i}].{f}"), e))
+                }
+                DataQuery::Pictures { head, class, value, .. } => {
+                    if matches!(self.input, InputSpec::Image { .. }) {
+                        check_target(head, class, value).map_err(|(f, e)| (format!("data[{i}].{f}"), e))
+                    } else {
+                        Err((format!("data[{i}].from"), "pictures are data for an image input".into()))
+                    }
+                }
+                DataQuery::Pairs { head, .. } => match self.decl(head) {
+                    Err(e) => Err((format!("data[{i}].head"), e)),
+                    Ok(d) if d.kind == OutKind::Generate => Ok(()),
+                    Ok(_) => Err((
+                        format!("data[{i}].head"),
+                        format!("pairs train a generate head; {head:?} is not one"),
+                    )),
+                },
+                DataQuery::Inline { items } => items.iter().enumerate().try_for_each(|(j, it)| {
+                    check_target(&it.head, &it.class, &it.value)
+                        .map_err(|(f, e)| (format!("data[{i}].items[{j}].{f}"), e))
+                }),
+            };
+            if let Err((path, e)) = r {
+                return at(path, e);
+            }
+        }
+        if !self.critics.is_empty() && !self.generates() {
+            return at(
+                "critics".into(),
+                "critics judge what a generate head writes; this model has none".into(),
+            );
+        }
+        for (i, c) in self.critics.iter().enumerate() {
+            if c.model.trim().is_empty() {
+                return at(format!("critics[{i}].model"), "a critic names a model".into());
+            }
+            if !(c.weight >= 0.0 && c.weight.is_finite()) {
+                return at(
+                    format!("critics[{i}].weight"),
+                    format!("critic {:?}: weight must be finite and not negative", c.model),
+                );
+            }
+        }
+        if let Err(e) = self.sampling.check() {
+            let field = if e.contains("top_p") { "top_p" } else { "temperature" };
+            return at(format!("sampling.{field}"), e);
+        }
+        if let Some(Origin::Pretrained(dir)) = &self.from {
+            if !matches!(self.input, InputSpec::Text { ref features } if features.is_empty())
+                && self.input != InputSpec::Bytes
+            {
+                return at(
+                    "input".into(),
+                    format!("a pretrained model ({dir}) reads plain text, without feature channels"),
+                );
+            }
+            if !self.generates() {
+                return at(
+                    "heads".into(),
+                    "a pretrained model's language-model head is its generate head; declare one".into(),
+                );
+            }
+            let t = &self.trunk;
+            if t.preset.is_some()
+                || t.d_model.is_some()
+                || t.layers.is_some()
+                || t.heads.is_some()
+                || t.head_dim.is_some()
+                || t.d_ff.is_some()
+                || t.causal == Some(false)
+                || t.pooling.is_some()
+            {
+                return at(
+                    "trunk".into(),
+                    "a pretrained trunk's sizes come from its checkpoint (only max_len and dropout apply)".into(),
+                );
+            }
+        }
+        Ok(())
+    }
+
+    /// parses a spec's JSON and checks it, saying where a problem is: a field that doesn't
+    /// read (`heads[0].kind: unknown variant ...`), the first broken rule, or (with
+    /// `sizes`) a trunk the engine can't make (an unknown preset, sizes that don't fit)
+    pub fn parse(text: &str, sizes: bool) -> Result {
+        let model = || {
+            serde_json::from_str::(text)
+                .ok()
+                .and_then(|v| v.get("name").and_then(|n| n.as_str()).map(str::to_string))
+                .unwrap_or_default()
+        };
+        let de = &mut serde_json::Deserializer::from_str(text);
+        let spec: ModelSpec = serde_path_to_error::deserialize(de).map_err(|e| {
+            let path = e.path().to_string();
+            let inner = e.into_inner();
+            SpecError {
+                model: model(),
+                path: if path == "." { String::new() } else { path },
+                message: if inner.is_syntax() || inner.is_eof() {
+                    format!("the JSON doesn't read: {inner}")
+                } else {
+                    inner.to_string()
+                },
+            }
+        })?;
+        spec.check_at()?;
+        if sizes && spec.from.is_none() {
+            spec.config(None, 0).map_err(|e| SpecError {
+                model: spec.name.clone(),
+                path: if e.contains("preset") {
+                    "trunk.preset".into()
+                } else {
+                    "trunk".into()
+                },
+                message: e
+                    .strip_prefix(&format!("model spec {:?}: ", spec.name))
+                    .unwrap_or(&e)
+                    .to_string(),
+            })?;
+        }
+        Ok(spec)
+    }
+
+    /// the engine configuration this spec asks for
+    pub fn config(&self, profile: Option<&MachineProfile>, examples: usize) -> Result {
+        let t = &self.trunk;
+        let mut cfg = match t.preset.as_deref().unwrap_or("small") {
+            "test" | "tiny" => Config::tiny(),
+            "compact" => Config {
+                d_model: 48,
+                head_dim: 24,
+                heads: 2,
+                layers: 2,
+                d_ff: 128,
+                max_len: 96,
+                stride: 47,
+                dropout: 0.05,
+                ..Config::tiny()
+            },
+            "small" => Config::small(),
+            "base" => Config::base(),
+            "auto" => match profile {
+                Some(p) => bench::suggest(
+                    p,
+                    &Task {
+                        examples: examples.max(1),
+                        epochs: self.train.epochs.unwrap_or(20),
+                        max_len: t.max_len.unwrap_or(self.natural_len()),
+                        seconds: self.train.budget_seconds.unwrap_or(300.0),
+                    },
+                ),
+                None => Config::small(),
+            },
+            other => {
+                return Err(format!(
+                    "unknown trunk preset {other:?} (test, compact, small, base, auto)"
+                ));
+            }
+        };
+        cfg = cfg.gematria(false);
+        if let InputSpec::Text { features } = &self.input {
+            cfg.letters = features.contains(&Feature::Letters);
+            cfg.words = features.contains(&Feature::WordSums);
+            cfg.side = features.contains(&Feature::Side);
+        }
+        if let Some(v) = t.d_model {
+            cfg.d_model = v;
+        }
+        if let Some(v) = t.layers {
+            cfg.layers = v;
+        }
+        if let Some(v) = t.heads {
+            cfg.heads = v;
+        }
+        if let Some(v) = t.head_dim {
+            cfg.head_dim = v;
+        }
+        if let Some(v) = t.d_ff {
+            cfg.d_ff = v;
+        }
+        cfg.max_len = t.max_len.unwrap_or(match self.input {
+            InputSpec::Image { .. } | InputSpec::Numbers { .. } => self.natural_len(),
+            _ => cfg.max_len,
+        });
+        cfg.stride = (cfg.max_len.saturating_sub(2) / 2).max(1);
+        cfg.causal = t.causal.unwrap_or(self.generates());
+        cfg.pooling = t
+            .pooling
+            .unwrap_or(if cfg.causal { Pooling::Mean } else { cfg.pooling });
+        if let Some(v) = t.dropout {
+            cfg.dropout = v;
+        }
+        cfg.extra = match &self.input {
+            InputSpec::Numbers { names, .. } => names.len(),
+            _ => 0,
+        };
+        cfg.validate().map_err(|e| format!("model spec {:?}: {e}", self.name))?;
+        Ok(cfg)
+    }
+
+    /// the window an input needs whole (pictures and number vectors), else 128
+    fn natural_len(&self) -> usize {
+        match &self.input {
+            InputSpec::Image {
+                width, height, patch, ..
+            } => (width / patch + 1) * (height / patch) + 2,
+            InputSpec::Numbers { names, codec } => names.len() * (codec.width() + 1) + 2,
+            _ => 128,
+        }
+    }
+
+    fn train_opts(&self) -> TrainOpts {
+        let t = &self.train;
+        let d = TrainOpts::default();
+        TrainOpts {
+            epochs: t.epochs.unwrap_or(d.epochs),
+            batch: t.batch.unwrap_or(d.batch),
+            lr: t.lr.unwrap_or(d.lr),
+            val_fraction: t.val_fraction.unwrap_or(0.1),
+            patience: t.patience.unwrap_or(d.patience),
+            max_steps: t.max_steps.unwrap_or(0),
+            threads: t.threads.unwrap_or(0),
+            seed: self.seed,
+            device: self.device,
+            ..d
+        }
+    }
+}
+
+/// a model made from a spec: the engine's network, and what it learned besides weights
+#[derive(Clone, Debug)]
+pub struct Model {
+    pub spec: ModelSpec,
+    pub clf: Classifier,
+    /// the picture codebook (image inputs; learned by the first `train`)
+    pub codebook: Option,
+}
+
+/// one head's answer
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(rename_all = "snake_case")]
+pub enum Answer {
+    /// class (or label) probabilities by name, the top one, the members (steered)
+    Classes {
+        probs: BTreeMap,
+        top: String,
+        members: Vec,
+    },
+    Values(BTreeMap),
+    /// what the generate head wrote after the input, with the spec's sampling
+    Generated(Value),
+}
+
+#[derive(Serialize, Deserialize)]
+struct Saved {
+    spec: ModelSpec,
+    codebook: Option,
+}
+
+/// a fresh model for a spec; `profile` sizes an "auto" trunk
+pub fn build(spec: &ModelSpec, profile: Option<&MachineProfile>) -> Result {
+    build_for(spec, profile, 0)
+}
+
+fn build_for(spec: &ModelSpec, profile: Option<&MachineProfile>, examples: usize) -> Result {
+    spec.check()?;
+    let heads: Vec = spec
+        .heads
+        .iter()
+        .filter(|h| h.kind != OutKind::Generate)
+        .map(|h| {
+            let kind = match h.kind {
+                OutKind::Multi => HeadKind::Multi,
+                OutKind::Regress => HeadKind::Regress,
+                _ => HeadKind::Single,
+            };
+            let c: Vec<&str> = h.classes.iter().map(String::as_str).collect();
+            HeadSpec::new(&h.name, kind, &c).weighted(h.weight)
+        })
+        .collect();
+    let generator = spec
+        .heads
+        .iter()
+        .find(|h| h.kind == OutKind::Generate)
+        .map(|h| GenSpec {
+            name: h.name.clone(),
+            weight: h.weight,
+        });
+    let mut clf = match &spec.from {
+        Some(Origin::Pretrained(dir)) => {
+            let o = super::pretrained::Options {
+                max_len: spec.trunk.max_len,
+                heads,
+                generator: generator.map_or("next".into(), |g| g.name),
+                dropout: spec.trunk.dropout.unwrap_or(0.0),
+                seed: spec.seed,
+            };
+            super::pretrained::load(std::path::Path::new(dir), &o)
+        }
+        None => Classifier::with_gen(spec.config(profile, examples)?, &heads, generator, spec.seed),
+    }
+    .map_err(|e| format!("model spec {:?}: {e}", spec.name))?;
+    clf.meta.name = spec.name.clone();
+    Ok(Model {
+        spec: spec.clone(),
+        clf,
+        codebook: None,
+    })
+}
+
+impl Model {
+    /// an existing classifier as an instance of a spec (sizes and features from its
+    /// configuration, heads from its heads)
+    pub fn from_classifier(clf: Classifier) -> Model {
+        let c = &clf.net.cfg;
+        let mut features = Vec::new();
+        if c.letters {
+            features.push(Feature::Letters);
+        }
+        if c.words {
+            features.push(Feature::WordSums);
+        }
+        if c.side {
+            features.push(Feature::Side);
+        }
+        let mut heads: Vec = clf
+            .net
+            .heads
+            .iter()
+            .map(|h| HeadDecl {
+                name: h.spec.name.clone(),
+                kind: match h.spec.kind {
+                    HeadKind::Single => OutKind::Classify,
+                    HeadKind::Multi => OutKind::Multi,
+                    HeadKind::Regress => OutKind::Regress,
+                },
+                classes: h.spec.classes.clone(),
+                weight: h.spec.weight,
+            })
+            .collect();
+        if let Some(g) = &clf.net.generator {
+            heads.push(HeadDecl {
+                name: g.name.clone(),
+                kind: OutKind::Generate,
+                classes: Vec::new(),
+                weight: g.weight,
+            });
+        }
+        let spec = ModelSpec {
+            version: SPEC_VERSION,
+            name: if clf.meta.name.is_empty() {
+                "classifier".into()
+            } else {
+                clf.meta.name.clone()
+            },
+            input: InputSpec::Text { features },
+            trunk: TrunkSpec {
+                preset: Some("small".into()),
+                d_model: Some(c.d_model),
+                layers: Some(clf.net.blocks.len()),
+                heads: Some(c.heads),
+                head_dim: Some(c.head_dim),
+                d_ff: Some(c.d_ff),
+                max_len: Some(c.max_len),
+                causal: Some(c.causal),
+                pooling: Some(c.pooling),
+                dropout: Some(c.dropout),
+            },
+            heads,
+            data: Vec::new(),
+            critics: Vec::new(),
+            constraints: Constraints::default(),
+            sampling: Sampling::default(),
+            train: TrainSpec::default(),
+            seed: clf.meta.seed,
+            from: None,
+            device: Device::Cpu,
+        };
+        Model {
+            spec,
+            clf,
+            codebook: None,
+        }
+    }
+
+    pub fn to_bytes(&self) -> Vec {
+        let mut clf = self.clf.clone();
+        clf.meta.spec = Some(
+            serde_json::to_value(Saved {
+                spec: self.spec.clone(),
+                codebook: self.codebook.clone(),
+            })
+            .expect("specs serialise"),
+        );
+        clf.to_bytes()
+    }
+
+    /// a model file, or any classifier file (as `from_classifier`)
+    pub fn from_bytes(b: &[u8]) -> Result {
+        let clf = Classifier::from_bytes(b)?;
+        match clf.meta.spec.clone() {
+            Some(v) => {
+                let s: Saved = serde_json::from_value(v).map_err(|e| format!("model spec in file: {e}"))?;
+                Ok(Model {
+                    spec: s.spec,
+                    clf,
+                    codebook: s.codebook,
+                })
+            }
+            None => Ok(Model::from_classifier(clf)),
+        }
+    }
+
+    /// an input value as the bytes the trunk reads, and the heads' number inputs
+    pub fn encode(&self, v: &Value) -> Result<(Vec, Vec), String> {
+        match (&self.spec.input, v) {
+            (InputSpec::Text { .. } | InputSpec::Bytes, Value::Text(t)) => Ok((t.as_bytes().to_vec(), vec![])),
+            (InputSpec::Bytes | InputSpec::Text { .. }, Value::Bytes(b)) => Ok((b.clone(), vec![])),
+            (InputSpec::Image { width, height, .. }, Value::Image(im)) => {
+                if im.width != *width || im.height != *height {
+                    return Err(format!(
+                        "a {}×{} picture for a {width}×{height} model",
+                        im.width, im.height
+                    ));
+                }
+                let cb = self
+                    .codebook
+                    .as_ref()
+                    .ok_or("the picture codebook is learned by training first")?;
+                Ok((cb.encode(im), vec![]))
+            }
+            (InputSpec::Numbers { names, codec }, Value::Numbers(x)) => {
+                if x.len() != names.len() {
+                    return Err(format!("{} numbers for {} names", x.len(), names.len()));
+                }
+                let mut b = Vec::new();
+                for (i, &n) in x.iter().enumerate() {
+                    if i > 0 {
+                        b.push(b' ');
+                    }
+                    b.extend(codec.encode(n as f64));
+                }
+                Ok((b, x.clone()))
+            }
+            (i, v) => Err(format!("a {} value for a {} input", kind_of(v), input_kind(i))),
+        }
+    }
+
+    /// generated bytes back as a value of the input's type
+    pub fn decode(&self, b: &[u8]) -> Value {
+        match &self.spec.input {
+            InputSpec::Text { .. } => Value::Text(String::from_utf8_lossy(b).into_owned()),
+            InputSpec::Bytes => Value::Bytes(b.to_vec()),
+            InputSpec::Image { width, height, .. } => match &self.codebook {
+                Some(cb) => Value::Image(cb.decode(b, *width, *height)),
+                None => Value::Bytes(b.to_vec()),
+            },
+            InputSpec::Numbers { codec, .. } => Value::Numbers(
+                b.split(|&c| c == b' ')
+                    .map(|p| codec.decode(p).map_or(f32::NAN, |x| x as f32))
+                    .collect(),
+            ),
+        }
+    }
+
+    /// every head's answer on an input, by head name
+    pub fn run(&self, input: &Value) -> Result, String> {
+        self.run_on(input, self.runner()?.as_ref())
+    }
+
+    /// the model uploaded to the spec's `device` (None for the CPU); open it once and
+    /// pass it to `run_on` when running many inputs
+    pub fn runner(&self) -> Result, String> {
+        Runner::open(self.spec.device, &self.clf.net)
+    }
+
+    /// `run` with the trunk (and decoding) on the runner's device, the CPU without one
+    pub fn run_on(&self, input: &Value, runner: Option<&Runner>) -> Result, String> {
+        self.run_sampled(input, runner, &self.spec.sampling)
+    }
+
+    /// `run_on` with the generate head writing by `sampling` instead of the spec's
+    pub fn run_sampled(
+        &self,
+        input: &Value,
+        runner: Option<&Runner>,
+        sampling: &Sampling,
+    ) -> Result, String> {
+        let (bytes, extra) = self.encode(input)?;
+        let extra = if extra.is_empty() {
+            vec![0.0; self.clf.net.cfg.extra]
+        } else {
+            extra
+        };
+        let outs = if self.clf.net.heads.is_empty() {
+            Vec::new()
+        } else {
+            self.clf.predict_bytes_with(&bytes, &extra, runner)
+        };
+        let mut m = BTreeMap::new();
+        for (h, o) in self.clf.net.heads.iter().zip(&outs) {
+            let names = &h.spec.classes;
+            let a = match h.spec.kind {
+                HeadKind::Regress => Answer::Values(names.iter().cloned().zip(o.probs.iter().copied()).collect()),
+                _ => Answer::Classes {
+                    probs: names.iter().cloned().zip(o.probs.iter().copied()).collect(),
+                    top: names[o.top].clone(),
+                    members: o.members.iter().map(|&i| names[i].clone()).collect(),
+                },
+            };
+            m.insert(h.spec.name.clone(), a);
+        }
+        if let Some(g) = &self.clf.net.generator {
+            let prompt = self.prompt(&bytes);
+            sampling.check()?;
+            let (out, _) = generate::sample_on(&self.clf, &prompt, sampling, 0, runner);
+            m.insert(g.name.clone(), Answer::Generated(self.decode(&out)));
+        }
+        Ok(m)
+    }
+
+    /// what a generator continues from: a sequence-to-sequence model's input and PAIR
+    fn prompt(&self, input: &[u8]) -> Vec {
+        let pairs = self.spec.data.iter().any(|q| matches!(q, DataQuery::Pairs { .. }));
+        if pairs {
+            [input, &[PAIR]].concat()
+        } else {
+            input.to_vec()
+        }
+    }
+
+    /// the spec's data queries as training examples
+    pub fn examples(&mut self, src: &dyn Source) -> Result, String> {
+        let spec = self.spec.clone();
+        let mut items: Vec = Vec::new();
+        let mut pairs: Vec<(Value, Value, String)> = Vec::new();
+        for q in &spec.data {
+            match q {
+                DataQuery::List {
+                    list,
+                    head,
+                    class,
+                    value,
+                } => items.extend(
+                    src.list(list)?
+                        .into_iter()
+                        .map(|v| (v, head.clone(), class.clone(), value.clone())),
+                ),
+                DataQuery::Tagged {
+                    tag,
+                    head,
+                    class,
+                    value,
+                } => items.extend(
+                    src.tagged(tag)?
+                        .into_iter()
+                        .map(|v| (v, head.clone(), class.clone(), value.clone())),
+                ),
+                DataQuery::Pairs { input, output, head } => {
+                    pairs.extend(src.pairs(input, output)?.into_iter().map(|(a, b)| (a, b, head.clone())))
+                }
+                DataQuery::Pictures {
+                    list,
+                    head,
+                    class,
+                    value,
+                } => items.extend(
+                    src.pictures(list.as_deref())?
+                        .into_iter()
+                        .map(|v| (v, head.clone(), class.clone(), value.clone())),
+                ),
+                DataQuery::Inline { items: its } => items.extend(
+                    its.iter()
+                        .map(|i| (i.input.clone(), i.head.clone(), i.class.clone(), i.value.clone())),
+                ),
+            }
+        }
+        if let InputSpec::Image { patch, codes, .. } = spec.input
+            && self.codebook.is_none()
+        {
+            let ims: Vec = items
+                .iter()
+                .map(|i| &i.0)
+                .chain(pairs.iter().flat_map(|p| [&p.0, &p.1]))
+                .filter_map(|v| match v {
+                    Value::Image(im) => Some(im.clone()),
+                    _ => None,
+                })
+                .collect();
+            self.codebook = Some(Codebook::learn(&ims, patch, codes, 8, spec.seed)?);
+        }
+        let mut out = Vec::new();
+        for (v, head, class, value) in items {
+            let (bytes, extra) = self.encode(&v)?;
+            let d = spec.decl(&head)?;
+            let target = match (d.kind, spec.slot(&head)?) {
+                (OutKind::Generate, _) => Target::Next { from: 0 },
+                (OutKind::Classify, _) => Target::Class(index(d, class.as_deref())?),
+                (OutKind::Multi, _) => Target::Label(index(d, class.as_deref())?, true),
+                (OutKind::Regress, _) => Target::Values(value.unwrap_or_default()),
+            };
+            let h = match spec.slot(&head)? {
+                Slot::Pooled(i) => i,
+                Slot::Gen => 0,
+            };
+            out.push(Example::bytes(&bytes, h, target).with_extra(extra));
+        }
+        for (a, b, _) in pairs {
+            let (ia, _) = self.encode(&a)?;
+            let (ib, _) = self.encode(&b)?;
+            let prompt = self.prompt(&ia);
+            out.push(Example::bytes(
+                &[&prompt[..], &ib[..]].concat(),
+                0,
+                Target::Next { from: prompt.len() },
+            ));
+        }
+        Ok(out)
+    }
+}
+
+fn index(d: &HeadDecl, class: Option<&str>) -> Result {
+    let c = class.ok_or(format!("data for head {:?} names a class", d.name))?;
+    d.classes
+        .iter()
+        .position(|x| x == c)
+        .ok_or(format!("head {:?} has no class {c:?}", d.name))
+}
+
+fn kind_of(v: &Value) -> &'static str {
+    match v {
+        Value::Text(_) => "text",
+        Value::Bytes(_) => "bytes",
+        Value::Image(_) => "picture",
+        Value::Numbers(_) => "numbers",
+    }
+}
+
+fn input_kind(i: &InputSpec) -> &'static str {
+    match i {
+        InputSpec::Text { .. } => "text",
+        InputSpec::Bytes => "bytes",
+        InputSpec::Image { .. } => "picture",
+        InputSpec::Numbers { .. } => "numbers",
+    }
+}
+
+/// resolves the spec's data and trains every head together (a fresh model when `model`
+/// is None; an "auto" trunk is sized for the data found)
+pub fn train(
+    model: Option,
+    spec: &ModelSpec,
+    src: &dyn Source,
+    profile: Option<&MachineProfile>,
+    cb: impl FnMut(&Progress) -> Flow,
+) -> Result<(Model, TrainReport), String> {
+    let mut m = match model {
+        Some(m) => m,
+        None => build(spec, profile)?,
+    };
+    let data = m.examples(src)?;
+    if data.is_empty() {
+        return Err(format!("model spec {:?}: the data queries found nothing", spec.name));
+    }
+    if spec.trunk.preset.as_deref() == Some("auto") && m.clf.meta.steps == 0 {
+        let cb_saved = m.codebook.take();
+        m = build_for(spec, profile, data.len())?;
+        m.codebook = cb_saved;
+    }
+    let rep = train::train(&mut m.clf, &data, &spec.train_opts(), cb)?;
+    Ok((m, rep))
+}
+
+impl Judge for Model {
+    fn judge(&self, data: &[u8]) -> Vec {
+        self.clf.judge(data)
+    }
+}
+
+/// a critic's model as a generator's critics see it: what judges, and its heads (in the
+/// order its outputs come; generate heads left out)
+pub struct Critique<'a> {
+    pub judge: &'a dyn Judge,
+    pub heads: Vec,
+}
+
+impl Model {
+    /// this model as a critic
+    pub fn critique(&self) -> Critique<'_> {
+        Critique {
+            judge: self,
+            heads: self
+                .spec
+                .heads
+                .iter()
+                .filter(|h| h.kind != OutKind::Generate)
+                .cloned()
+                .collect(),
+        }
+    }
+}
+
+/// the spec's critics, resolved by model name, judge `opts.candidates` candidates;
+/// the kept ones come best first
+pub fn generate(
+    model: &Model,
+    models: &BTreeMap,
+    prompt: &Value,
+    candidates: usize,
+    guidance: Option,
+) -> Result, String> {
+    let critics: BTreeMap = models.iter().map(|(n, m)| (n.clone(), m.critique())).collect();
+    Ok(
+        generate_by(model, &critics, prompt, &model.spec.sampling, candidates, guidance)?
+            .into_iter()
+            .filter(Candidate::passed)
+            .collect(),
+    )
+}
+
+/// [`generate`] with the critics' models given as [`Critique`]s (any judge: a model, a
+/// stored classifier stack) and the sampling given; every candidate drawn comes back,
+/// the ones that keep the constraints first, each part best score first (ties: lower index)
+pub fn generate_by(
+    model: &Model,
+    models: &BTreeMap,
+    prompt: &Value,
+    sampling: &Sampling,
+    candidates: usize,
+    guidance: Option,
+) -> Result, String> {
+    let mut critics = Vec::new();
+    for c in &model.spec.critics {
+        let m = models
+            .get(&c.model)
+            .ok_or(format!("critic {:?} is not loaded", c.model))?;
+        let Some(h) = m.heads.iter().position(|d| d.name == c.head) else {
+            return Err(format!(
+                "critic {:?}: no head {:?} (a generate head can't judge)",
+                c.model, c.head
+            ));
+        };
+        let d = &m.heads[h];
+        let pos = |n: &str| {
+            d.classes
+                .iter()
+                .position(|x| x == n)
+                .ok_or(format!("critic {:?}: no class {n:?}", c.model))
+        };
+        let want = match &c.want {
+            WantDecl::Class(n) => Want::Class(pos(n)?),
+            WantDecl::Not(n) => Want::Not(pos(n)?),
+            WantDecl::Near { value, target, scale } => Want::Near {
+                index: pos(value)?,
+                value: *target,
+                scale: *scale,
+            },
+            WantDecl::Range { value, lo, hi, scale } => Want::Range {
+                index: pos(value)?,
+                lo: *lo,
+                hi: *hi,
+                scale: *scale,
+            },
+        };
+        critics.push(Critic::new(m.judge, h, want, c.weight));
+    }
+    let (bytes, _) = match prompt {
+        Value::Bytes(b) if b.is_empty() => (Vec::new(), Vec::new()),
+        v => model.encode(v)?,
+    };
+    // a continuation is judged whole (the start and what was written); a sequence to
+    // sequence model's output alone
+    let pairs = model.spec.data.iter().any(|q| matches!(q, DataQuery::Pairs { .. }));
+    let opts = GenOpts {
+        judge_prompt: !bytes.is_empty() && !pairs,
+        prompt: model.prompt(&bytes),
+        sampling: sampling.clone(),
+        candidates,
+        guidance,
+        device: model.spec.device,
+        ..GenOpts::default()
+    };
+    let mut v = generate::draw(&model.clf, &critics, &model.spec.constraints, &opts)?;
+    v.sort_by(|a, b| {
+        b.passed()
+            .cmp(&a.passed())
+            .then(b.score.total_cmp(&a.score))
+            .then(a.index.cmp(&b.index))
+    });
+    Ok(v)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    fn author_spec() -> ModelSpec {
+        ModelSpec::from_json(
+            r#"{
+              "name": "kind",
+              "input": {"type": "text"},
+              "trunk": {"preset": "test"},
+              "heads": [{"name": "kind", "kind": "classify", "classes": ["fruit", "rock"]}],
+              "data": [
+                {"from": "list", "list": "fruits", "head": "kind", "class": "fruit"},
+                {"from": "list", "list": "rocks", "head": "kind", "class": "rock"}
+              ],
+              "train": {"epochs": 12, "batch": 8, "lr": 0.003, "val_fraction": 0.0, "threads": 2}
+            }"#,
+        )
+        .unwrap()
+    }
+
+    fn source() -> MemSource {
+        MemSource::default()
+            .with_texts(
+                "fruits",
+                &[
+                    "apple plum",
+                    "peach melon",
+                    "grape apple",
+                    "mango plum",
+                    "cherry peach",
+                    "melon grape",
+                ],
+            )
+            .with_texts(
+                "rocks",
+                &[
+                    "granite slate",
+                    "flint shale",
+                    "quartz basalt",
+                    "stone rock",
+                    "slate flint",
+                    "basalt stone",
+                ],
+            )
+    }
+
+    #[test]
+    fn a_classifier_from_a_spec() {
+        let spec = author_spec();
+        let (m, rep) = train(None, &spec, &source(), None, |_| Flow::Go).unwrap();
+        assert!(rep.steps > 0);
+        let a = m.run(&Value::Text("slate granite flint".into())).unwrap();
+        match &a["kind"] {
+            Answer::Classes { top, .. } => assert_eq!(top, "rock"),
+            x => panic!("{x:?}"),
+        }
+        let back = Model::from_bytes(&m.to_bytes()).unwrap();
+        assert_eq!(back.spec, m.spec);
+        assert_eq!(
+            back.run(&Value::Text("apple".into())).unwrap(),
+            m.run(&Value::Text("apple".into())).unwrap()
+        );
+        // an old-style classifier converts
+        let c = Model::from_classifier(m.clf.clone());
+        assert_eq!(c.spec.heads, m.spec.heads);
+        assert!(c.spec.check().is_ok());
+        assert!(build(&c.spec, None).is_ok());
+    }
+
+    #[test]
+    fn specs_are_checked_with_clear_errors() {
+        let bad = |j: &str| ModelSpec::from_json(j).unwrap_err();
+        assert!(bad(r#"{"name":"x","input":{"type":"text"},"heads":[]}"#).contains("at least one head"));
+        assert!(
+            bad(r#"{"name":"x","version":9,"input":{"type":"text"},"heads":[{"name":"a","kind":"generate"}]}"#)
+                .contains("version 9")
+        );
+        assert!(
+            bad(r#"{"name":"x","input":{"type":"text"},"heads":[{"name":"a","kind":"classify","classes":["p"]}]}"#)
+                .contains("two classes")
+        );
+        assert!(bad(
+            r#"{"name":"x","input":{"type":"image","width":30,"height":32},"heads":[{"name":"a","kind":"generate"}]}"#
+        )
+        .contains("multiple"));
+        assert!(
+            bad(
+                r#"{"name":"x","input":{"type":"text"},"heads":[{"name":"a","kind":"classify","classes":["p","q"]}],
+              "data":[{"from":"list","list":"l","head":"a","class":"z"}]}"#
+            )
+            .contains("no class \"z\"")
+        );
+        assert!(bad(r#"{"name":"x","input":{"type":"text"},"heads":[{"name":"a","kind":"generate"}],"trunk":{"causal":false}}"#)
+            .contains("causal"));
+        assert!(
+            bad(
+                r#"{"name":"x","input":{"type":"text"},"heads":[{"name":"a","kind":"regress","classes":["v"]}],
+              "critics":[{"model":"m","head":"h","want":{"class":"c"}}]}"#
+            )
+            .contains("has none")
+        );
+        assert!(
+            build(&ModelSpec::from_json(r#"{"name":"x","input":{"type":"text"},"trunk":{"preset":"huge"},"heads":[{"name":"a","kind":"generate"}]}"#).unwrap(), None)
+                .unwrap_err()
+                .contains("unknown trunk preset")
+        );
+        // sizes left out: not the test preset
+        let s =
+            ModelSpec::from_json(r#"{"name":"x","input":{"type":"text"},"heads":[{"name":"a","kind":"generate"}]}"#)
+                .unwrap();
+        let c = s.config(None, 0).unwrap();
+        assert!(c.causal && c.d_model >= Config::small().d_model && !c.letters);
+    }
+
+    #[test]
+    fn a_steered_generator_and_a_number_regressor_from_specs() {
+        let (critic, _) = train(None, &author_spec(), &source(), None, |_| Flow::Go).unwrap();
+        let gspec = ModelSpec::from_json(
+            r#"{
+              "name": "writer",
+              "input": {"type": "text"},
+              "trunk": {"preset": "test", "max_len": 32},
+              "heads": [{"name": "next", "kind": "generate"}],
+              "data": [
+                {"from": "list", "list": "fruits", "head": "next"},
+                {"from": "list", "list": "rocks", "head": "next"}
+              ],
+              "critics": [{"model": "kind", "head": "kind", "want": {"class": "rock"}}],
+              "sampling": {"temperature": 1.0, "max_len": 16, "seed": 3},
+              "train": {"epochs": 10, "batch": 4, "lr": 0.01, "val_fraction": 0.0, "threads": 2}
+            }"#,
+        )
+        .unwrap();
+        let (g, _) = train(None, &gspec, &source(), None, |_| Flow::Go).unwrap();
+        let models: BTreeMap = [("kind".to_string(), &critic)].into();
+        let c = generate(&g, &models, &Value::Bytes(vec![]), 6, None).unwrap();
+        assert_eq!(c, generate(&g, &models, &Value::Bytes(vec![]), 6, None).unwrap());
+        assert!(c.windows(2).all(|w| w[0].score >= w[1].score));
+        assert!(matches!(
+            g.run(&Value::Text("gra".into())).unwrap()["next"],
+            Answer::Generated(Value::Text(_))
+        ));
+        assert!(
+            generate(&g, &BTreeMap::new(), &Value::Bytes(vec![]), 2, None)
+                .unwrap_err()
+                .contains("not loaded")
+        );
+
+        // numbers: y = a + b, read as fixed-width text plus the numbers themselves
+        let nspec = ModelSpec::from_json(
+            r#"{
+              "name": "sum",
+              "input": {"type": "numbers", "names": ["a", "b"], "codec": {"digits": 1, "decimals": 1, "signed": false}},
+              "trunk": {"preset": "test"},
+              "heads": [{"name": "y", "kind": "regress", "classes": ["sum"]}],
+              "train": {"epochs": 60, "batch": 8, "lr": 0.01, "val_fraction": 0.0, "threads": 1}
+            }"#,
+        )
+        .unwrap();
+        let items: Vec = (0..24)
+            .map(|i| {
+                let (a, b) = ((i % 5) as f32 * 0.5, (i % 7) as f32 * 0.3);
+                InlineItem {
+                    input: Value::Numbers(vec![a, b]),
+                    head: "y".into(),
+                    class: None,
+                    value: Some(vec![a + b]),
+                }
+            })
+            .collect();
+        let mut nspec = nspec;
+        nspec.data.push(DataQuery::Inline { items });
+        let (n, _) = train(None, &nspec, &MemSource::default(), None, |_| Flow::Go).unwrap();
+        let Answer::Values(v) = &n.run(&Value::Numbers(vec![1.0, 0.6])).unwrap()["y"] else {
+            panic!()
+        };
+        assert!((v["sum"] - 1.6).abs() < 0.4, "{v:?}");
+    }
+
+    #[test]
+    fn a_picture_generator_from_a_spec() {
+        let ims: Vec = (0..8)
+            .map(|i| Value::Image(super::super::codec::toy(16, i % 4, i as u64)))
+            .collect();
+        let spec = ModelSpec::from_json(
+            r#"{
+              "name": "pictures",
+              "input": {"type": "image", "width": 16, "height": 16, "patch": 4, "codes": 16},
+              "trunk": {"preset": "test"},
+              "heads": [{"name": "draw", "kind": "generate"}],
+              "data": [{"from": "list", "list": "toys", "head": "draw"}],
+              "sampling": {"temperature": 0.8, "max_len": 40, "seed": 1},
+              "train": {"epochs": 6, "batch": 4, "lr": 0.01, "val_fraction": 0.0, "threads": 1}
+            }"#,
+        )
+        .unwrap();
+        assert_eq!(spec.config(None, 0).unwrap().max_len, 5 * 4 + 2);
+        let (m, _) = train(None, &spec, &MemSource::default().with_list("toys", ims), None, |_| {
+            Flow::Go
+        })
+        .unwrap();
+        let Answer::Generated(Value::Image(im)) =
+            &m.run(&Value::Image(super::super::codec::toy(16, 0, 99))).unwrap()["draw"]
+        else {
+            panic!()
+        };
+        assert_eq!((im.width, im.height), (16, 16));
+    }
+}
diff --git a/core/src/classify/speed.rs b/core/src/classify/speed.rs
new file mode 100644
index 00000000..90fba1ed
--- /dev/null
+++ b/core/src/classify/speed.rs
@@ -0,0 +1,363 @@
+//! Auto's choice by measured speed. A GPU that gives the CPU's bits is only worth using
+//! where it is also faster, and that depends on the machine and the model's size: small
+//! models spend most of a GPU's time on overhead (submissions, waiting, reading back),
+//! which a fast CPU doesn't have. So on first use of a model size, auto reads a fixed set
+//! of texts on both, keeps the two rates, and reads where the rate is higher. The rates
+//! are kept per machine (the adapter and driver, the CPU's kernels and threads, and this
+//! build's version, since a new build may be faster) and per model size, in memory and in
+//! a small JSON file in the user's cache folder, so the measuring happens once.
+
+use std::collections::BTreeMap;
+use std::sync::Mutex;
+
+use serde::{Deserialize, Serialize};
+
+use super::model::Net;
+
+/// the two rates measured for one machine and model size
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct Speed {
+    /// the machine (see `machine`)
+    pub machine: String,
+    /// the model's size, in words (see `size_of`)
+    pub size: String,
+    pub gpu_texts_per_sec: f64,
+    pub cpu_texts_per_sec: f64,
+    /// texts each device read for the rate
+    pub texts: usize,
+}
+
+impl Speed {
+    pub fn gpu_faster(&self) -> bool {
+        self.gpu_texts_per_sec > self.cpu_texts_per_sec
+    }
+
+    /// the two rates and the choice, in words
+    pub fn words(&self) -> String {
+        format!(
+            "with a model of {}, the GPU reads {} texts a second and the CPU {}, so {} reads",
+            self.size,
+            rate(self.gpu_texts_per_sec),
+            rate(self.cpu_texts_per_sec),
+            if self.gpu_faster() { "the GPU" } else { "the CPU" }
+        )
+    }
+}
+
+fn rate(r: f64) -> String {
+    if r >= 100.0 {
+        format!("{r:.0}")
+    } else if r >= 10.0 {
+        format!("{r:.1}")
+    } else {
+        format!("{r:.2}")
+    }
+}
+
+/// a model's size in words: its width, blocks, window and weights (what its speed on
+/// each device depends on; the values of the weights don't matter)
+pub fn size_of(net: &Net) -> String {
+    let weights: usize = net.params().iter().map(|(_, p)| p.len()).sum();
+    let w = if weights >= 1_000_000 {
+        format!("{:.1}M", weights as f64 / 1e6)
+    } else {
+        format!("{}k", weights.div_ceil(1000))
+    };
+    format!(
+        "width {}, {} blocks, windows of {}, {w} weights{}",
+        net.cfg.d_model,
+        net.blocks.len(),
+        net.cfg.max_len,
+        if net.cfg.extra > 0 {
+            format!(", {} inputs from others", net.cfg.extra)
+        } else {
+            String::new()
+        }
+    )
+}
+
+#[derive(Default)]
+struct Kept {
+    loaded: bool,
+    all: BTreeMap<(String, String), Speed>,
+}
+
+static KEPT: Mutex = Mutex::new(Kept {
+    loaded: false,
+    all: BTreeMap::new(),
+});
+
+/// where the rates are kept on disk: `ANEND_SPEED_FILE`, else the user's cache folder;
+/// none in tests and in the browser (memory only)
+static FILE: Mutex>> = Mutex::new(None);
+
+/// sets where the rates are kept (None: memory only); for tests and embedders
+pub fn set_file(path: Option) {
+    *FILE.lock().unwrap_or_else(|e| e.into_inner()) = Some(path);
+    let mut k = KEPT.lock().unwrap_or_else(|e| e.into_inner());
+    k.loaded = false;
+    k.all.clear();
+}
+
+fn file() -> Option {
+    if let Some(f) = FILE.lock().unwrap_or_else(|e| e.into_inner()).clone() {
+        return f;
+    }
+    if cfg!(test) || cfg!(target_arch = "wasm32") {
+        return None;
+    }
+    if let Some(f) = std::env::var_os("ANEND_SPEED_FILE") {
+        return Some(f.into());
+    }
+    let home = std::env::var_os("HOME").map(std::path::PathBuf::from);
+    let base = if cfg!(target_os = "windows") {
+        std::env::var_os("LOCALAPPDATA").map(std::path::PathBuf::from)
+    } else if cfg!(target_os = "macos") {
+        home.map(|h| h.join("Library/Caches"))
+    } else {
+        std::env::var_os("XDG_CACHE_HOME")
+            .map(std::path::PathBuf::from)
+            .or_else(|| home.map(|h| h.join(".cache")))
+    };
+    base.map(|b| b.join("anend").join("gpu-speed.json"))
+}
+
+fn with_kept(f: impl FnOnce(&mut BTreeMap<(String, String), Speed>) -> T) -> T {
+    let mut k = KEPT.lock().unwrap_or_else(|e| e.into_inner());
+    if !k.loaded {
+        k.loaded = true;
+        if let Some(p) = file()
+            && let Ok(b) = std::fs::read(&p)
+            && let Ok(v) = serde_json::from_slice::>(&b)
+        {
+            for s in v {
+                k.all.insert((s.machine.clone(), s.size.clone()), s);
+            }
+        }
+    }
+    f(&mut k.all)
+}
+
+fn store(all: &BTreeMap<(String, String), Speed>) {
+    let Some(p) = file() else { return };
+    let mut v: Vec<&Speed> = all.values().collect();
+    v.sort_by(|a, b| (&a.machine, &a.size).cmp(&(&b.machine, &b.size)));
+    if let Some(d) = p.parent() {
+        let _ = std::fs::create_dir_all(d);
+    }
+    if let Ok(t) = serde_json::to_string_pretty(&v) {
+        let _ = std::fs::write(&p, t);
+    }
+}
+
+/// the rates kept for `machine`
+pub fn known(machine: &str) -> Vec {
+    with_kept(|all| {
+        let mut v: Vec = all.values().filter(|s| s.machine == machine).cloned().collect();
+        v.sort_by(|a, b| a.size.cmp(&b.size));
+        v
+    })
+}
+
+/// forgets the rates kept for `machine`, so each size is measured again on next use
+pub fn forget(machine: &str) {
+    with_kept(|all| {
+        all.retain(|(m, _), _| m != machine);
+        store(all);
+    })
+}
+
+/// the kept rates for this machine and size, or `measure`'s, kept for next time
+pub fn get_or_measure(
+    machine: &str,
+    size: &str,
+    measure: impl FnOnce() -> Result<(f64, f64, usize), String>,
+) -> Result {
+    let key = (machine.to_string(), size.to_string());
+    if let Some(s) = with_kept(|all| all.get(&key).cloned()) {
+        return Ok(s);
+    }
+    let (gpu, cpu, texts) = measure()?;
+    let s = Speed {
+        machine: machine.to_string(),
+        size: size.to_string(),
+        gpu_texts_per_sec: gpu,
+        cpu_texts_per_sec: cpu,
+        texts,
+    };
+    with_kept(|all| {
+        all.insert(key, s.clone());
+        store(all);
+    });
+    Ok(s)
+}
+
+/// the texts the measuring reads: deterministic, 20 to about 400 bytes
+pub fn texts(n: usize) -> Vec {
+    const W: [&str; 12] = [
+        "river", "stone", "copper", "gear", "heron", "valve", "moss", "lamp", "the", "of", "and", "light",
+    ];
+    (0..n)
+        .map(|i| {
+            let mut h = (i as u64 + 77).wrapping_mul(0x9e37_79b9_7f4a_7c15) | 1;
+            let len = 20 + (h % 380) as usize;
+            let mut s = String::new();
+            while s.len() < len {
+                h ^= h << 13;
+                h ^= h >> 7;
+                h ^= h << 17;
+                s.push_str(W[(h % 12) as usize]);
+                s.push(if h.is_multiple_of(9) { '.' } else { ' ' });
+            }
+            s
+        })
+        .collect()
+}
+
+#[cfg(feature = "gpu")]
+pub use on_gpu::*;
+
+#[cfg(feature = "gpu")]
+mod on_gpu {
+    use std::time::Instant;
+
+    use super::super::device::{Device, Runner};
+    use super::super::{Classifier, Pool, pool};
+    use super::*;
+
+    /// the GPU reading path's revision: raised when a change makes it faster or slower,
+    /// so rates kept from before are measured again
+    pub const READING_REVISION: u32 = 2;
+
+    /// this machine, as the rates are kept by: the adapter and driver, the CPU's kernels
+    /// and threads, this build's version and the reading path's revision
+    pub fn machine() -> Result {
+        let g = super::super::gpu::shared()?;
+        let i = &g.info;
+        Ok(format!(
+            "{} ({:?}, {} {}); CPU {} × {}; anend {} reading r{READING_REVISION}{}",
+            i.name,
+            i.backend,
+            i.driver,
+            i.driver_info,
+            super::super::kernels::simd_name(),
+            pool::available(),
+            env!("CARGO_PKG_VERSION"),
+            if cfg!(debug_assertions) { " debug" } else { "" }
+        ))
+    }
+
+    /// texts the CPU reads for its rate; the GPU reads `FIRST` first, and the rest only
+    /// when that rate is within a factor of 2 of the CPU's (a clearly slower GPU stops
+    /// early)
+    pub const TEXTS: usize = 192;
+    pub const FIRST: usize = 32;
+
+    /// reads the fixed texts with `clf` on the CPU and on `device`: (GPU rate, CPU rate,
+    /// texts), each a rate in texts a second, after a warm-up on each
+    pub fn measure(clf: &Classifier, device: Device) -> Result<(f64, f64, usize), String> {
+        let all = texts(TEXTS);
+        let refs: Vec<&str> = all.iter().map(String::as_str).collect();
+        let p = Pool::new(pool::available());
+        let extras: Vec> = if clf.net.cfg.extra > 0 {
+            refs.iter().map(|_| vec![0.0; clf.net.cfg.extra]).collect()
+        } else {
+            vec![]
+        };
+        let warm_x: Vec> = extras.iter().take(4).cloned().collect();
+        clf.predict_many(&refs[..4], &warm_x, &p);
+        let t = Instant::now();
+        clf.predict_many(&refs, &extras, &p);
+        let cpu = TEXTS as f64 / t.elapsed().as_secs_f64().max(1e-9);
+
+        let r = Runner::open(device, &clf.net)?.ok_or("no GPU")?;
+        let zero = vec![0f32; clf.net.cfg.extra];
+        let gains = clf.gains();
+        let read = |ts: &[&str]| {
+            let bytes: Vec<&[u8]> = ts.iter().map(|t| t.as_bytes()).collect();
+            let ex: Vec<&[f32]> = ts.iter().map(|_| zero.as_slice()).collect();
+            let t = Instant::now();
+            r.text_runs(&clf.net, &bytes, &ex, &gains);
+            t.elapsed().as_secs_f64().max(1e-9)
+        };
+        // the pipelines compile on the first call
+        read(&refs[..4]);
+        let first = FIRST as f64 / read(&refs[..FIRST]);
+        if first * 2.0 < cpu {
+            return Ok((first, cpu, FIRST));
+        }
+        let gpu = TEXTS as f64 / read(&refs);
+        Ok((gpu, cpu, TEXTS))
+    }
+
+    /// the rates for `clf`'s size on this machine, measured on first use
+    pub fn of(clf: &Classifier, device: Device) -> Result {
+        get_or_measure(&machine()?, &size_of(&clf.net), || measure(clf, device))
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn rates_are_kept_and_say_why() {
+        set_file(None);
+        let mut calls = 0;
+        let a = get_or_measure("test machine", "tiny", || {
+            calls += 1;
+            Ok((50.0, 400.0, 32))
+        })
+        .unwrap();
+        assert!(!a.gpu_faster());
+        assert!(
+            a.words().contains("the GPU reads 50.0 texts a second and the CPU 400"),
+            "{}",
+            a.words()
+        );
+        assert!(a.words().ends_with("so the CPU reads"));
+        let b = get_or_measure("test machine", "tiny", || {
+            calls += 1;
+            Ok((1.0, 1.0, 1))
+        })
+        .unwrap();
+        assert_eq!(a, b, "measured once");
+        assert_eq!(calls, 1);
+        assert_eq!(known("test machine").len(), 1);
+        forget("test machine");
+        assert!(known("test machine").is_empty());
+
+        // kept in the file (one test: the kept rates are the process's)
+        let dir = std::env::temp_dir().join(format!("anend-speed-{}", std::process::id()));
+        let f = dir.join("gpu-speed.json");
+        set_file(Some(f.clone()));
+        get_or_measure("file machine", "big", || Ok((900.0, 300.0, 192))).unwrap();
+        // as if a new process: the kept map is emptied and read back from the file
+        set_file(Some(f.clone()));
+        let k = known("file machine");
+        assert_eq!(k.len(), 1);
+        assert!(k[0].gpu_faster());
+        set_file(None);
+        let _ = std::fs::remove_dir_all(dir);
+    }
+}
+
+#[cfg(all(test, feature = "gpu"))]
+mod gpu_tests {
+    use super::*;
+    use crate::classify::device::Device;
+    use crate::classify::{Classifier, Config, HeadSpec};
+
+    #[test]
+    fn measuring_gives_both_rates() {
+        let Some(_) = crate::classify::gpu::tests::device() else {
+            return;
+        };
+        let clf = Classifier::new(Config::tiny(), &[HeadSpec::single("s", &["a", "b"])], 5).unwrap();
+        let (gpu, cpu, n) = measure(&clf, Device::Gpu).unwrap();
+        assert!(gpu > 0.0 && cpu > 0.0);
+        assert!(n == FIRST || n == TEXTS);
+        assert!(machine().unwrap().contains("anend"));
+        assert!(size_of(&clf.net).contains("blocks"));
+    }
+}
diff --git a/core/src/classify/testdata/v1_tiny.anendcls b/core/src/classify/testdata/v1_tiny.anendcls
new file mode 100644
index 00000000..cf85711e
Binary files /dev/null and b/core/src/classify/testdata/v1_tiny.anendcls differ
diff --git a/core/src/classify/testdata/v2_gematria.anendcls b/core/src/classify/testdata/v2_gematria.anendcls
new file mode 100644
index 00000000..f64e3857
Binary files /dev/null and b/core/src/classify/testdata/v2_gematria.anendcls differ
diff --git a/core/src/classify/tests.rs b/core/src/classify/tests.rs
index 28674109..b37a0ca0 100644
--- a/core/src/classify/tests.rs
+++ b/core/src/classify/tests.rs
@@ -143,7 +143,13 @@ fn long_texts_average_their_windows() {
 #[test]
 fn steering_and_its_bias_metric() {
     let data = synthetic(60, 6);
-    let mut clf = tiny_clf(6);
+    // with the gematria channels, so the side vector's gain has something to change
+    let mut clf = Classifier::new(
+        Config::tiny().gematria(true),
+        &[HeadSpec::single("kind", &["fruit", "rock"])],
+        6,
+    )
+    .unwrap();
     train::train(&mut clf, &data, &quick_opts(2), |_| Flow::Go).unwrap();
     let texts: Vec<&str> = data.iter().map(|e| e.text.as_str()).collect();
     let pool = Pool::new(2);
@@ -213,3 +219,72 @@ fn feedback_moves_the_judged_result() {
     .unwrap();
     assert_eq!(before, clf.net.blocks);
 }
+
+#[test]
+fn version_1_files_still_load_bit_exact() {
+    // saved by the engine before format version 2 (gematria channels then always on)
+    let clf = Classifier::from_bytes(include_bytes!("testdata/v1_tiny.anendcls")).unwrap();
+    assert!(clf.net.cfg.letters && clf.net.cfg.words && !clf.net.cfg.causal);
+    let l = clf.logits("granite and peach, 1234!", &[]);
+    let bits: Vec> = l.iter().map(|h| h.iter().map(|v| v.to_bits()).collect()).collect();
+    assert_eq!(bits, vec![vec![3190351502, 1041852471], vec![1049337253]]);
+    // and round-trips as version 2
+    let again = Classifier::from_bytes(&clf.to_bytes()).unwrap();
+    assert_eq!(again.logits("granite and peach, 1234!", &[]), l);
+}
+
+/// one trunk, two outputs trained together: a class head and a generative head, each
+/// example carrying both targets with per-head loss weights
+#[test]
+fn multi_output_models_train_heads_jointly() {
+    let cfg = Config {
+        causal: true,
+        pooling: Pooling::Mean,
+        ..Config::tiny().gematria(false)
+    };
+    let heads = [HeadSpec::single("kind", &["fruit", "rock"]).weighted(2.0)];
+    let mut m = Classifier::with_gen(cfg, &heads, Some(GenSpec::new("next")), 5).unwrap();
+    let data: Vec = synthetic(48, 4)
+        .into_iter()
+        .map(|e| e.and(0, Target::Next { from: 0 }))
+        .collect();
+    let o = TrainOpts {
+        epochs: 8,
+        val_fraction: 0.0,
+        ..quick_opts(2)
+    };
+    let all: Vec = (0..data.len()).collect();
+    let before = train::evaluate(&m, &data, &all, &Pool::new(1));
+    train::train(&mut m, &data, &o, |_| Flow::Go).unwrap();
+    let after = train::evaluate(&m, &data, &all, &Pool::new(1));
+    assert!(after.accuracy() >= 0.9, "{}", after.accuracy());
+    assert!(after.bits_per_byte.unwrap() < before.bits_per_byte.unwrap() - 1.0);
+    let back = Classifier::from_bytes(&m.to_bytes()).unwrap();
+    assert_eq!(back.net.generator, m.net.generator);
+    assert_eq!(back.net.heads[0].spec.weight, 2.0);
+    assert_eq!(back.predict("granite slate", &[]), m.predict("granite slate", &[]));
+}
+
+/// a version 2 file saved while the presets still had the gematria channels on (18 Oct):
+/// it keeps them, and answers with exactly the bits it gave then
+#[test]
+fn gematria_files_keep_their_channels_bit_exact() {
+    let clf = Classifier::from_bytes(include_bytes!("testdata/v2_gematria.anendcls")).unwrap();
+    assert!(clf.net.cfg.letters && clf.net.cfg.words && clf.net.cfg.side);
+    assert!(!Config::tiny().letters && !Config::small().words && !Config::base().side);
+    let l = clf.logits("granite and peach, 1234!", &[]);
+    let bits: Vec> = l.iter().map(|h| h.iter().map(|v| v.to_bits()).collect()).collect();
+    assert_eq!(bits, vec![vec![3199179086, 1054726511]]);
+    let p: Vec = clf.predict("slate and plum", &[])[0]
+        .probs
+        .iter()
+        .map(|v| v.to_bits())
+        .collect();
+    assert_eq!(p, [1057944601, 1055004622]);
+    assert_eq!(
+        Classifier::from_bytes(&clf.to_bytes())
+            .unwrap()
+            .logits("granite and peach, 1234!", &[]),
+        l
+    );
+}
diff --git a/core/src/classify/text.rs b/core/src/classify/text.rs
index 95239393..1f28c9f7 100644
--- a/core/src/classify/text.rs
+++ b/core/src/classify/text.rs
@@ -1,17 +1,27 @@
-//! From text to model input. Tokens are the UTF-8 bytes (0..=255) plus three specials;
-//! no vocabulary is learned or stored. Next to each token run the gematria channels:
-//! the letter's ordinal value, and the sums of the word the token sits in (ordinal,
-//! reversed and Atbash, each bucketed by modulo, and their digit roots), which the
-//! embedder adds onto the token. A whole window also gets a side vector of text level
-//! measures (letter frequencies, the sums, the prime factor chain, shape of the text).
+//! From data to model input. Tokens are bytes (0..=255) plus four specials (CLS, SEP,
+//! PAD, and NUM for a number whose value rides along); no vocabulary is learned or
+//! stored. Any data is bytes: text, binary, pictures through `codec`, numbers as text or
+//! as NUM tokens.
+//!
+//! Optional feature channels run next to each token. They are opt-in per model
+//! (`Config::letters`, `Config::words`, `Config::side`), off for new models and on for
+//! classifiers saved before they became optional: the letter's ordinal value, the sums
+//! of the word the token sits in (ordinal, reversed and Atbash, each bucketed by modulo,
+//! and their digit roots), and a whole-window side vector of text level measures (letter
+//! frequencies, the sums, the prime factor chain, shape of the text). In a causal model
+//! (one that generates) the word channels are the sums of the word so far, so no token
+//! sees a byte after it.
 
 use super::math::ln;
 use crate::simd;
 use crate::weum;
 
-pub const CLS: u16 = 256;
-pub const SEP: u16 = 257;
-pub const PAD: u16 = 258;
+pub const CLS: u32 = 256;
+pub const SEP: u32 = 257;
+pub const PAD: u32 = 258;
+/// a number: the token's embedding is its row plus value × a learned direction
+pub const NUM: u32 = 259;
+/// tokens without NUM (the table size of models without number inputs)
 pub const VOCAB: usize = 259;
 
 /// rows of the letter value table: 0 for "not a letter", then a = 1 .. z = 26
@@ -26,13 +36,15 @@ pub const SIDE: usize = 46;
 /// one window of a text, ready for the embedder
 #[derive(Clone, Debug, Default, PartialEq)]
 pub struct Window {
-    pub tokens: Vec,
+    pub tokens: Vec,
     pub letter: Vec,
     pub ordinal: Vec,
     pub reversed: Vec,
     pub atbash: Vec,
     pub root: Vec,
     pub side: Vec,
+    /// per token, the value of a NUM token (0 elsewhere); empty when there are none
+    pub values: Vec,
 }
 
 impl Window {
@@ -56,7 +68,13 @@ fn in_word(b: u8) -> bool {
 
 /// `[CLS] bytes [SEP]` with every channel filled in; `bytes` should fit the window
 pub fn window(bytes: &[u8]) -> Window {
-    let n = bytes.len() + 2;
+    window_with(bytes, false, true)
+}
+
+/// `[CLS] bytes`, then `[SEP]` when `end`. `causal`: each token's word channels are the
+/// sums of its word up to and including it (what a generator may see)
+pub fn window_with(bytes: &[u8], causal: bool, end: bool) -> Window {
+    let n = bytes.len() + 1 + end as usize;
     let mut w = Window {
         tokens: Vec::with_capacity(n),
         letter: vec![0; n],
@@ -65,10 +83,13 @@ pub fn window(bytes: &[u8]) -> Window {
         atbash: vec![0; n],
         root: vec![0; n],
         side: side(bytes),
+        values: Vec::new(),
     };
     w.tokens.push(CLS);
-    w.tokens.extend(bytes.iter().map(|&b| b as u16));
-    w.tokens.push(SEP);
+    w.tokens.extend(bytes.iter().map(|&b| b as u32));
+    if end {
+        w.tokens.push(SEP);
+    }
     for (i, &b) in bytes.iter().enumerate() {
         let lc = b | 0x20;
         if lc.is_ascii_lowercase() {
@@ -85,19 +106,54 @@ pub fn window(bytes: &[u8]) -> Window {
         while i < bytes.len() && in_word(bytes[i]) {
             i += 1;
         }
-        let s = simd::sums(&bytes[start..i]);
         let bucket = |v: u64| (1 + v % 96) as u8;
-        let root = (1 + 10 * digit_root(s.ordinal) + digit_root(s.reversed)) as u8;
-        for t in start + 1..i + 1 {
+        let mut fill = |t: usize, s: simd::Sums| {
             w.ordinal[t] = bucket(s.ordinal);
             w.reversed[t] = bucket(s.reversed);
             w.atbash[t] = bucket(s.atbash);
-            w.root[t] = root;
+            w.root[t] = (1 + 10 * digit_root(s.ordinal) + digit_root(s.reversed)) as u8;
+        };
+        if causal {
+            for t in start..i {
+                fill(t + 1, simd::sums(&bytes[start..t + 1]));
+            }
+        } else {
+            let s = simd::sums(&bytes[start..i]);
+            for t in start + 1..i + 1 {
+                fill(t, s);
+            }
         }
     }
     w
 }
 
+impl Window {
+    /// appends NUM tokens carrying `values` (no channels)
+    pub fn push_numbers(&mut self, values: &[f32]) {
+        if self.values.is_empty() {
+            self.values = vec![0.0; self.tokens.len()];
+        }
+        for &v in values {
+            self.tokens.push(NUM);
+            for c in [
+                &mut self.letter,
+                &mut self.ordinal,
+                &mut self.reversed,
+                &mut self.atbash,
+                &mut self.root,
+            ] {
+                c.push(0);
+            }
+            self.values.push(v);
+        }
+    }
+
+    /// the value at token t (0 when the window has no numbers)
+    pub fn value(&self, t: usize) -> f32 {
+        self.values.get(t).copied().unwrap_or(0.0)
+    }
+}
+
 /// where the windows of a `len` byte text start, for windows of `room` bytes advancing by
 /// `stride`: 0, stride, 2·stride, …, and the last one flush with the end
 pub fn starts(len: usize, room: usize, stride: usize) -> Vec {
@@ -113,11 +169,19 @@ pub fn starts(len: usize, room: usize, stride: usize) -> Vec {
 
 /// every window of a text for a model whose sequences are `max_len` tokens long
 pub fn windows(text: &str, max_len: usize, stride: usize) -> Vec {
+    windows_of(text.as_bytes(), max_len, stride, false)
+}
+
+/// every window of some bytes; `causal` windows have causal word channels and end in
+/// SEP only where the data ends
+pub fn windows_of(b: &[u8], max_len: usize, stride: usize, causal: bool) -> Vec {
     let room = max_len.saturating_sub(2).max(1);
-    let b = text.as_bytes();
     starts(b.len(), room, stride)
         .into_iter()
-        .map(|s| window(&b[s..(s + room).min(b.len())]))
+        .map(|s| {
+            let e = (s + room).min(b.len());
+            window_with(&b[s..e], causal, !causal || e == b.len())
+        })
         .collect()
 }
 
@@ -193,6 +257,24 @@ mod tests {
         assert_eq!(window(b"").tokens, vec![CLS, SEP]);
     }
 
+    #[test]
+    fn causal_channels_and_numbers() {
+        let c = window_with(b"Ab c", true, false);
+        assert_eq!(c.tokens, vec![CLS, 65, 98, 32, 99]);
+        // "A" so far sums to 1, "Ab" to 3
+        assert_eq!((c.ordinal[1], c.ordinal[2]), (2, 4));
+        let full = window(b"Ab c");
+        assert_eq!(full.ordinal[1], 4);
+        let mut n = window(b"x");
+        n.push_numbers(&[1.5, -2.0]);
+        assert_eq!(n.tokens, vec![CLS, 120, SEP, NUM, NUM]);
+        assert_eq!(n.values, vec![0.0, 0.0, 0.0, 1.5, -2.0]);
+        assert_eq!(n.root.len(), 5);
+        let ws = windows_of(&[b'a'; 100], 32, 15, true);
+        assert!(ws[..ws.len() - 1].iter().all(|w| *w.tokens.last().unwrap() != SEP));
+        assert_eq!(*ws.last().unwrap().tokens.last().unwrap(), SEP);
+    }
+
     #[test]
     fn window_starts() {
         assert_eq!(starts(10, 30, 15), vec![0]);
diff --git a/core/src/classify/train.rs b/core/src/classify/train.rs
index cef249b3..b2284f4b 100644
--- a/core/src/classify/train.rs
+++ b/core/src/classify/train.rs
@@ -14,10 +14,11 @@ use std::time::Instant;
 
 use serde::{Deserialize, Serialize};
 
+use super::device::{Device, Trainer};
 use super::kernels::{self as k, softmax_rows};
 use super::math::{self, Rng, key, mix};
 use super::metrics::{self, Metrics};
-use super::model::{BlockT, Gains, HeadKind, Mode, Net, Trace};
+use super::model::{BlockT, END, Gains, HeadKind, Mode, Net, Trace};
 use super::pool::{self, Pool};
 use super::text::{self, Window};
 use super::{Classifier, FEEDBACK_KEPT};
@@ -36,6 +37,12 @@ pub enum Target {
     Label(usize, bool),
     /// regression: the values
     Values(Vec),
+    /// generative head: predict each next byte (and the end) of the example's bytes,
+    /// counting only the bytes from index `from` on (a prompt before it is context)
+    Next { from: usize },
+    /// generative head: make each next byte from `from` on less likely
+    /// (unlikelihood, −ln(1 − p)), for samples judged bad
+    Avoid { from: usize },
 }
 
 impl Target {
@@ -46,6 +53,11 @@ impl Target {
             _ => None,
         }
     }
+
+    /// whether the target is for the generative head
+    pub fn generative(&self) -> bool {
+        matches!(self, Target::Next { .. } | Target::Avoid { .. })
+    }
 }
 
 #[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
@@ -57,6 +69,13 @@ pub struct Example {
     pub weight: f32,
     /// inputs from other classifiers; empty means zeros
     pub extra: Vec,
+    /// the data as bytes when it isn't text (pictures, binary); used instead of `text`
+    /// when not empty
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub raw: Vec,
+    /// more targets on other heads of the same model, trained in the same pass
+    #[serde(default, skip_serializing_if = "Vec::is_empty")]
+    pub also: Vec<(usize, Target)>,
 }
 
 impl Example {
@@ -72,9 +91,43 @@ impl Example {
             target,
             weight: 1.0,
             extra: Vec::new(),
+            raw: Vec::new(),
+            also: Vec::new(),
+        }
+    }
+
+    /// an example over bytes that need not be text
+    pub fn bytes(raw: &[u8], head: usize, target: Target) -> Example {
+        let mut e = Example::new("", head, target);
+        e.raw = raw.to_vec();
+        e
+    }
+
+    /// a text for the generative head to learn whole
+    pub fn generate(text: &str) -> Example {
+        Example::new(text, 0, Target::Next { from: 0 })
+    }
+
+    /// another head's target in the same pass
+    pub fn and(mut self, head: usize, target: Target) -> Example {
+        self.also.push((head, target));
+        self
+    }
+
+    /// the data: `raw` if set, else the text's bytes
+    pub fn data(&self) -> &[u8] {
+        if self.raw.is_empty() {
+            self.text.as_bytes()
+        } else {
+            &self.raw
         }
     }
 
+    /// every (head, target) of the example, the main one first
+    pub fn targets(&self) -> impl Iterator {
+        std::iter::once((self.head, &self.target)).chain(self.also.iter().map(|(h, t)| (*h, t)))
+    }
+
     pub fn weighted(mut self, w: f32) -> Example {
         self.weight = w;
         self
@@ -96,6 +149,9 @@ pub fn head_loss(kind: HeadKind, logits: &[f32], t: &Target, smoothing: f32) ->
     let kw = logits.len();
     let kf = kw as f32;
     let bad = || Err(format!("target {t:?} does not fit a {kind:?} head of {kw}"));
+    if t.generative() {
+        return bad();
+    }
     match kind {
         HeadKind::Single => {
             let m = logits.iter().fold(f32::NEG_INFINITY, |a, &b| a.max(b));
@@ -161,16 +217,71 @@ pub fn head_loss(kind: HeadKind, logits: &[f32], t: &Target, smoothing: f32) ->
     }
 }
 
+/// the generative loss of one window: at each position t whose next token is a byte
+/// (or SEP, read as END) at data index ≥ `from`, cross-entropy of the next token
+/// (`Next`) or −ln(1 − p) (`Avoid`), averaged over those positions. `offset` is the
+/// data index of the window's first byte. Returns (loss, d(loss)/d(logits) [n ×
+/// GEN_OUT], positions counted).
+pub fn gen_loss(net: &Net, logits: &[f32], tokens: &[u32], offset: usize, t: &Target) -> (f32, Vec, usize) {
+    let n = tokens.len();
+    let out = net.cfg.gen_out();
+    let mut g = vec![0f32; n * out];
+    let (from, avoid) = match t {
+        Target::Next { from } => (*from, false),
+        Target::Avoid { from } => (*from, true),
+        _ => return (0.0, g, 0),
+    };
+    let mut rows = Vec::new();
+    for p in 0..n.saturating_sub(1) {
+        let next = tokens[p + 1];
+        let class = match next {
+            // a vocabulary: every token is a class (the end token included)
+            t if net.lexicon.is_some() => t as usize,
+            b if b < 256 => b as usize,
+            text::SEP => END,
+            _ => continue,
+        };
+        if class >= out {
+            continue;
+        }
+        if offset + p >= from {
+            rows.push((p, class));
+        }
+    }
+    let count = rows.len();
+    let mut loss = 0f32;
+    for &(p, class) in &rows {
+        let row = &logits[p * out..(p + 1) * out];
+        let tg = if avoid {
+            Target::Not(class)
+        } else {
+            Target::Class(class)
+        };
+        let (l, d) = head_loss(HeadKind::Single, row, &tg, 0.0).expect("fits");
+        loss += l;
+        let inv = 1.0 / count as f32;
+        g[p * out..(p + 1) * out]
+            .iter_mut()
+            .zip(&d)
+            .for_each(|(a, b)| *a = b * inv);
+    }
+    (if count > 0 { loss / count as f32 } else { 0.0 }, g, count)
+}
+
 /// whether a text falls in the validation share: a seeded hash of its bytes, so the
 /// same text always lands on the same side
 pub fn is_validation(text: &str, fraction: f32, seed: u64) -> bool {
-    let h = mix(math::fnv(seed, text.as_bytes())) >> 40;
+    is_validation_bytes(text.as_bytes(), fraction, seed)
+}
+
+pub fn is_validation_bytes(data: &[u8], fraction: f32, seed: u64) -> bool {
+    let h = mix(math::fnv(seed, data)) >> 40;
     (h as f32) * (1.0 / 16_777_216.0) < fraction
 }
 
 /// indices of training and validation examples
 pub fn split(data: &[Example], fraction: f32, seed: u64) -> (Vec, Vec) {
-    (0..data.len()).partition(|&i| !is_validation(&data[i].text, fraction, seed))
+    (0..data.len()).partition(|&i| !is_validation_bytes(data[i].data(), fraction, seed))
 }
 
 // ---------------------------------------------------------------- optimizer
@@ -285,28 +396,87 @@ pub fn lr_at(step: usize, total: usize, warmup: usize, lr: f32, min_ratio: f32)
 }
 
 /// which tensors train: everything, or the heads only when the trunk is frozen
+/// (params end with the heads' pairs, then num, then the generative pair)
 pub fn trainable(net: &Net, freeze_trunk: bool) -> Vec {
     let n = net.params().len();
     let heads = 2 * net.heads.len();
-    (0..n).map(|i| !freeze_trunk || i >= n - heads).collect()
+    (0..n)
+        .map(|i| !freeze_trunk || (i >= n - 3 - heads && i < n - 3) || i >= n - 2)
+        .collect()
 }
 
 // ---------------------------------------------------------------- gradients
 
 /// one window of a training text: the whole text if it fits, else a crop placed by the key
 pub fn crop(net: &Net, text: &str, key: u64) -> Window {
+    crop_bytes(net, text.as_bytes(), key).0
+}
+
+/// `crop` over bytes, with the crop's start; a causal model's crop ends in SEP only
+/// where the data ends
+pub fn crop_bytes(net: &Net, b: &[u8], key: u64) -> (Window, usize) {
+    if net.lexicon.is_some() {
+        return crop_seq(net, &net.sequence(b, 0).0, key);
+    }
     let room = net.cfg.room();
-    let b = text.as_bytes();
+    let causal = net.cfg.causal;
     if b.len() <= room {
-        return text::window(b);
+        return (text::window_with(b, causal, true), 0);
     }
     let start = (mix(key) % (b.len() - room + 1) as u64) as usize;
-    text::window(&b[start..start + room])
+    let end = start + room == b.len();
+    (
+        text::window_with(&b[start..start + room], causal, !causal || end),
+        start,
+    )
+}
+
+/// `crop` over a token sequence (`Net::sequence`), the same windows as `crop_bytes`
+pub fn crop_seq(net: &Net, ts: &[u32], key: u64) -> (Window, usize) {
+    let room = net.cfg.room();
+    let causal = net.cfg.causal;
+    if ts.len() <= room {
+        return (net.window_tokens(ts, true), 0);
+    }
+    let start = (mix(key) % (ts.len() - room + 1) as u64) as usize;
+    let end = start + room == ts.len();
+    (net.window_tokens(&ts[start..start + room], !causal || end), start)
+}
+
+/// an example's data as the token sequence the net reads, and its targets with each
+/// generative target's `from` (a byte index) as a token index
+pub fn sequence_of(net: &Net, ex: &Example) -> (Vec, Vec<(usize, Target)>) {
+    let first = from_of(ex);
+    let (ts, at) = net.sequence(ex.data(), first.unwrap_or(0));
+    let moved = |f: usize| if Some(f) == first { at } else { f };
+    let targets = ex
+        .targets()
+        .map(|(h, t)| {
+            let t = match t {
+                Target::Next { from } => Target::Next { from: moved(*from) },
+                Target::Avoid { from } => Target::Avoid { from: moved(*from) },
+                t => t.clone(),
+            };
+            (h, t)
+        })
+        .collect();
+    (ts, targets)
+}
+
+fn from_of(ex: &Example) -> Option {
+    ex.targets().find_map(|(_, t)| match t {
+        Target::Next { from } | Target::Avoid { from } => Some(*from),
+        _ => None,
+    })
 }
 
 /// every window of a text forward, and the mean of their logits (in window order)
-pub fn forward_text(net: &Net, text: &str, extra: &[f32], gains: &Gains) -> (Vec, Vec>) {
-    let ws = text::windows(text, net.cfg.max_len, net.cfg.stride);
+pub fn forward_text(net: &Net, text: &[u8], extra: &[f32], gains: &Gains) -> (Vec, Vec>) {
+    forward_windows(net, &net.windows_of(text).0, extra, gains)
+}
+
+/// windows forward, and the mean of their logits (in window order)
+pub fn forward_windows(net: &Net, ws: &[Window], extra: &[f32], gains: &Gains) -> (Vec, Vec>) {
     let trs: Vec = ws
         .iter()
         .map(|w| net.forward(w, extra, gains, Mode::EVAL, None))
@@ -326,16 +496,38 @@ pub fn forward_text(net: &Net, text: &str, extra: &[f32], gains: &Gains) -> (Vec
 /// backward for `forward_text`: each window gets d(loss)/d(mean logits)/windows; returns
 /// d(loss)/d(extra) summed over the windows in order
 pub fn backward_text(net: &Net, trs: &[Trace], dlogits: &[Vec], tp: &[BlockT], g: &mut Net) -> Vec {
+    backward_text_gen(net, trs, dlogits, &[], tp, g)
+}
+
+/// `backward_text` with each window's d(loss)/d(generative logits) (empty for none)
+pub fn backward_text_gen(
+    net: &Net,
+    trs: &[Trace],
+    dlogits: &[Vec],
+    dgen: &[Vec],
+    tp: &[BlockT],
+    g: &mut Net,
+) -> Vec {
     let nw = trs.len() as f32;
     let dl: Vec> = dlogits.iter().map(|d| d.iter().map(|v| v / nw).collect()).collect();
     let mut dextra = vec![0f32; net.cfg.extra];
-    for tr in trs {
-        let de = net.backward(tr, &dl, tp, g);
+    for (i, tr) in trs.iter().enumerate() {
+        let dg = dgen.get(i).map_or(&[][..], |v| &v[..]);
+        let de = net.backward_gen(tr, &dl, dg, tp, g);
         dextra.iter_mut().zip(de).for_each(|(a, b)| *a += b);
     }
     dextra
 }
 
+/// the loss weight of the head a target is for
+fn head_weight(net: &Net, head: usize, t: &Target) -> f32 {
+    if t.generative() {
+        net.generator.as_ref().map_or(1.0, |g| g.weight)
+    } else {
+        net.heads[head].spec.weight
+    }
+}
+
 /// how an example's gradient is taken
 #[derive(Clone, Copy)]
 enum How {
@@ -359,31 +551,71 @@ fn zeros_for(net: &Net, e: &[f32]) -> Vec {
     }
 }
 
-/// adds coef·∇loss of one example into g; returns (loss, tokens)
+/// adds `into += scale·d`, creating it when empty
+fn add_scaled(into: &mut Vec, d: &[f32], scale: f32) {
+    if into.is_empty() {
+        *into = vec![0.0; d.len()];
+    }
+    into.iter_mut().zip(d).for_each(|(a, b)| *a += b * scale);
+}
+
+/// adds coef·∇loss of one example (every target, each times its head's weight) into g;
+/// returns (loss, tokens)
 fn example_grad(net: &Net, tp: &[BlockT], ex: &Example, it: &Item, smoothing: f32, g: &mut Net) -> (f32, usize) {
     let extra = zeros_for(net, &ex.extra);
-    let kind = net.heads[ex.head].spec.kind;
     let mut dls = vec![Vec::new(); net.heads.len()];
+    let mut loss = 0f32;
     match it.how {
         How::Crop(kk) => {
-            let w = crop(net, &ex.text, kk);
+            let (ts, targets) = sequence_of(net, ex);
+            let (w, start) = crop_seq(net, &ts, kk);
             let mode = Mode {
                 dropout: net.cfg.dropout,
                 key: kk,
             };
             let tr = net.forward(&w, &extra, &net.cfg.gains, mode, None);
-            let (l, d) = head_loss(kind, &net.logits(&tr, ex.head), &ex.target, smoothing).expect("checked target");
-            dls[ex.head] = d.iter().map(|v| v * it.coef).collect();
-            net.backward(&tr, &dls, tp, g);
-            (l, w.len())
+            let mut dgen = Vec::new();
+            for (h, t) in targets.iter().map(|(h, t)| (*h, t)) {
+                let hw = head_weight(net, h, t);
+                if t.generative() {
+                    let (l, d, _) = gen_loss(net, &net.gen_logits(&tr), &w.tokens, start, t);
+                    loss += hw * l;
+                    add_scaled(&mut dgen, &d, hw * it.coef);
+                } else {
+                    let kind = net.heads[h].spec.kind;
+                    let (l, d) = head_loss(kind, &net.logits(&tr, h), t, smoothing).expect("checked target");
+                    loss += hw * l;
+                    add_scaled(&mut dls[h], &d, hw * it.coef);
+                }
+            }
+            net.backward_gen(&tr, &dls, &dgen, tp, g);
+            (loss, w.len())
         }
         How::Whole => {
-            let (trs, avg) = forward_text(net, &ex.text, &extra, &net.cfg.gains);
-            let (l, d) = head_loss(kind, &avg[ex.head], &ex.target, smoothing).expect("checked target");
-            dls[ex.head] = d.iter().map(|v| v * it.coef).collect();
+            let (ts, targets) = sequence_of(net, ex);
+            let (ws, starts) = net.windows_over(&ts);
+            let (trs, avg) = forward_windows(net, &ws, &extra, &net.cfg.gains);
+            let nw = trs.len() as f32;
+            let mut dgen: Vec> = Vec::new();
+            for (h, t) in targets.iter().map(|(h, t)| (*h, t)) {
+                let hw = head_weight(net, h, t);
+                if t.generative() {
+                    dgen.resize(trs.len(), Vec::new());
+                    for (i, tr) in trs.iter().enumerate() {
+                        let (l, d, _) = gen_loss(net, &net.gen_logits(tr), tr.tokens(), starts[i], t);
+                        loss += hw * l / nw;
+                        add_scaled(&mut dgen[i], &d, hw * it.coef / nw);
+                    }
+                } else {
+                    let kind = net.heads[h].spec.kind;
+                    let (l, d) = head_loss(kind, &avg[h], t, smoothing).expect("checked target");
+                    loss += hw * l;
+                    add_scaled(&mut dls[h], &d, hw * it.coef);
+                }
+            }
             let tokens = trs.iter().map(|t| t.n).sum();
-            backward_text(net, &trs, &dls, tp, g);
-            (l, tokens)
+            backward_text_gen(net, &trs, &dls, &dgen, tp, g);
+            (loss, tokens)
         }
     }
 }
@@ -444,6 +676,9 @@ pub struct Evaluation {
     pub loss: f64,
     /// per head, when the data had examples for it
     pub heads: Vec>,
+    /// the generative head's mean cross-entropy in bits per predicted byte
+    #[serde(default)]
+    pub bits_per_byte: Option,
 }
 
 impl Evaluation {
@@ -458,15 +693,41 @@ pub fn evaluate(clf: &Classifier, data: &[Example], idx: &[usize], pool: &Pool)
     let net = &clf.net;
     type Slot = Mutex)>>;
     let slots: Vec = idx.iter().map(|_| Mutex::new(None)).collect();
+    let gen_nats: Vec> = idx.iter().map(|_| Mutex::new((0.0, 0))).collect();
     pool.run(idx.len(), &|i| {
         let ex = &data[idx[i]];
         let extra = zeros_for(net, &ex.extra);
-        let logits = clf
-            .run(&ex.text, &extra, &net.cfg.gains, None)
-            .logits
-            .swap_remove(ex.head);
-        let (l, _) = head_loss(net.heads[ex.head].spec.kind, &logits, &ex.target, 0.0).unwrap_or((0.0, vec![]));
-        *slots[i].lock().unwrap() = Some((l, logits));
+        let mut total = 0f32;
+        let mut main = Vec::new();
+        let (ts, targets) = sequence_of(net, ex);
+        let (ws, starts) = net.windows_over(&ts);
+        let (trs, avg) = forward_windows(net, &ws, &extra, &net.cfg.gains);
+        for (j, (h, t)) in targets.iter().map(|(h, t)| (*h, t)).enumerate() {
+            let hw = head_weight(net, h, t);
+            if t.generative() {
+                let (mut nats, mut count) = (0f64, 0usize);
+                for (w, tr) in trs.iter().enumerate() {
+                    let (l, _, c) = gen_loss(net, &net.gen_logits(tr), tr.tokens(), starts[w], t);
+                    nats += l as f64 * c as f64;
+                    count += c;
+                }
+                if count > 0 {
+                    total += hw * (nats / count as f64) as f32;
+                }
+                if matches!(t, Target::Next { .. }) {
+                    let mut g = gen_nats[i].lock().unwrap();
+                    g.0 += nats;
+                    g.1 += count;
+                }
+            } else {
+                let (l, _) = head_loss(net.heads[h].spec.kind, &avg[h], t, 0.0).unwrap_or((0.0, vec![]));
+                total += hw * l;
+            }
+            if j == 0 && !t.generative() {
+                main = avg[h].clone();
+            }
+        }
+        *slots[i].lock().unwrap() = Some((total, main));
     });
     let (mut loss, mut wsum) = (0f64, 0f64);
     let nh = net.heads.len();
@@ -479,6 +740,9 @@ pub fn evaluate(clf: &Classifier, data: &[Example], idx: &[usize], pool: &Pool)
         loss += ex.weight as f64 * l as f64;
         wsum += ex.weight as f64;
         let h = ex.head;
+        if ex.target.generative() {
+            continue;
+        }
         match (net.heads[h].spec.kind, &ex.target) {
             (HeadKind::Single, Target::Class(c)) => {
                 let mut p = logits;
@@ -506,9 +770,14 @@ pub fn evaluate(clf: &Classifier, data: &[Example], idx: &[usize], pool: &Pool)
             })
         })
         .collect();
+    let (nats, count) = gen_nats
+        .into_iter()
+        .map(|m| m.into_inner().unwrap())
+        .fold((0f64, 0usize), |a, b| (a.0 + b.0, a.1 + b.1));
     Evaluation {
         loss: if wsum > 0.0 { loss / wsum } else { 0.0 },
         heads,
+        bits_per_byte: (count > 0).then(|| nats / count as f64 / std::f64::consts::LN_2),
     }
 }
 
@@ -556,6 +825,9 @@ pub struct TrainOpts {
     /// keep an exponential moving average of the weights with this decay (0: off);
     /// evaluation, early stopping and the result use the average
     pub ema: f32,
+    /// where the forward and backward passes run (the CPU unless asked; see `device`)
+    #[serde(default)]
+    pub device: Device,
 }
 
 impl Default for TrainOpts {
@@ -581,6 +853,7 @@ impl Default for TrainOpts {
             freeze_trunk: false,
             max_steps: 0,
             ema: 0.0,
+            device: Device::Cpu,
         }
     }
 }
@@ -656,12 +929,16 @@ pub struct TrainReport {
 /// checks every example against the classifier's heads
 pub fn check(clf: &Classifier, data: &[Example]) -> Result<(), String> {
     for (i, ex) in data.iter().enumerate() {
-        let h = clf
-            .net
-            .heads
-            .get(ex.head)
-            .ok_or(format!("example {i}: no head {}", ex.head))?;
-        head_loss(h.spec.kind, &vec![0.0; h.width()], &ex.target, 0.0).map_err(|e| format!("example {i}: {e}"))?;
+        for (head, t) in ex.targets() {
+            if t.generative() {
+                if clf.net.generator.is_none() {
+                    return Err(format!("example {i}: the model has no generative head"));
+                }
+                continue;
+            }
+            let h = clf.net.heads.get(head).ok_or(format!("example {i}: no head {head}"))?;
+            head_loss(h.spec.kind, &vec![0.0; h.width()], t, 0.0).map_err(|e| format!("example {i}: {e}"))?;
+        }
         if !ex.extra.is_empty() && ex.extra.len() != clf.net.cfg.extra {
             return Err(format!(
                 "example {i}: {} extra inputs, the classifier takes {}",
@@ -705,7 +982,7 @@ pub fn fit(
     // class counts and balancing weights, per head
     let mut counts: Vec> = clf.net.heads.iter().map(|h| vec![0.0; h.width()]).collect();
     for &i in train {
-        if let Some(c) = data[i].target.class() {
+        if let (Some(c), false) = (data[i].target.class(), data[i].target.generative()) {
             counts[data[i].head][c] += 1.0;
         }
     }
@@ -738,6 +1015,7 @@ pub fn fit(
     let train_mask = trainable(&clf.net, o.freeze_trunk);
     let mut adam = Adam::new(&clf.net);
     let bufs = buffers(&clf.net, pool.threads());
+    let mut dev = Trainer::open(o.device, &clf.net)?;
     let mut grad = clf.net.zeros_like();
     let mut report = TrainReport {
         train_examples: train.len(),
@@ -794,7 +1072,19 @@ pub fn fit(
                     how: How::Crop(key(&[o.seed, base_steps + step as u64, i as u64])),
                 })
                 .collect();
-            let (loss, tk) = batch_grad(&clf.net, data, &items, o.label_smoothing, &pool, &bufs, &mut grad);
+            let (loss, tk) = match dev.as_mut() {
+                Some(dv) => {
+                    let crops: Vec<(usize, f32, u64)> = items
+                        .iter()
+                        .map(|it| match it.how {
+                            How::Crop(kk) => (it.ex, it.coef, kk),
+                            How::Whole => unreachable!("training crops"),
+                        })
+                        .collect();
+                    dv.batch(&clf.net, data, &crops, o.label_smoothing, &mut grad)
+                }
+                None => batch_grad(&clf.net, data, &items, o.label_smoothing, &pool, &bufs, &mut grad),
+            };
             tokens += tk as u64;
             let (scale, norm) = clip_scale(&grad, o.clip, &train_mask);
             let lr = lr_at(step, total, warmup, o.lr, o.min_lr);
@@ -934,6 +1224,8 @@ impl Feedback {
             target,
             weight: self.weight,
             extra: self.extra.clone(),
+            raw: Vec::new(),
+            also: Vec::new(),
         })
     }
 }
@@ -1064,6 +1356,75 @@ impl Classifier {
     }
 }
 
+/// a few AdamW steps at a flat rate on whole examples: every step takes the first
+/// `fresh` examples and `o.replay` drawn from the rest (keyed by seed and step), the
+/// loss on all windows. What `Classifier::feedback` and generator reinforcement share.
+/// Returns each step's loss.
+pub fn tune(clf: &mut Classifier, data: &[Example], fresh: usize, o: &FeedbackOpts) -> Result, String> {
+    check(clf, data)?;
+    let pool = Pool::new(if o.threads == 0 { pool::available() } else { o.threads });
+    if !clf.opt.as_ref().is_some_and(|a| a.fits(&clf.net)) {
+        clf.opt = Some(Adam::new(&clf.net));
+    }
+    let mask = trainable(&clf.net, o.freeze_trunk);
+    let bufs = buffers(&clf.net, pool.threads());
+    let mut grad = clf.net.zeros_like();
+    let adam_o = AdamOpts {
+        b1: 0.9,
+        b2: 0.98,
+        eps: 1e-8,
+        weight_decay: 0.0,
+    };
+    let mut losses = Vec::new();
+    for _ in 0..o.steps {
+        let mut r = Rng::new(key(&[o.seed, 0x7e5e, clf.meta.steps]));
+        let mut pick: Vec = (0..fresh.min(data.len())).collect();
+        if data.len() > fresh {
+            pick.extend((0..o.replay).map(|_| fresh + r.below(data.len() - fresh)));
+        }
+        let wsum: f32 = pick.iter().map(|&i| data[i].weight).sum();
+        if wsum <= 0.0 {
+            break;
+        }
+        let items: Vec = pick
+            .iter()
+            .map(|&i| Item {
+                ex: i,
+                coef: data[i].weight / wsum,
+                how: How::Whole,
+            })
+            .collect();
+        let (loss, _) = batch_grad(&clf.net, data, &items, 0.0, &pool, &bufs, &mut grad);
+        let (scale, _) = clip_scale(&grad, o.clip, &mask);
+        let adam = clf.opt.as_mut().expect("set above");
+        adam.step(&mut clf.net, &grad, o.lr, &adam_o, scale, &mask, Some(&pool));
+        clf.meta.steps += 1;
+        losses.push(loss);
+    }
+    Ok(losses)
+}
+
+/// the generative head's negative log-likelihood of `data[from..]` given what comes
+/// before it (in nats, summed), and how many predictions that is (the end included)
+pub fn nll(clf: &Classifier, data: &[u8], from: usize) -> (f64, usize) {
+    let net = &clf.net;
+    let (ts, from) = net.sequence(data, from);
+    let (ws, starts) = net.windows_over(&ts);
+    let extra = vec![0.0; net.cfg.extra];
+    let (mut nats, mut count) = (0f64, 0usize);
+    let mut seen = 0usize;
+    for (w, &st) in ws.iter().zip(&starts) {
+        let tr = net.forward(w, &extra, &clf.gains(), Mode::EVAL, None);
+        // windows overlap: count each predicted byte once, in the first window holding it
+        let t = Target::Next { from: from.max(seen) };
+        let (l, _, c) = gen_loss(net, &net.gen_logits(&tr), &w.tokens, st, &t);
+        nats += l as f64 * c as f64;
+        count += c;
+        seen = st + w.len() - 1;
+    }
+    (nats, count)
+}
+
 #[cfg(test)]
 mod tests {
     use super::*;
diff --git a/core/src/clsmodule.rs b/core/src/clsmodule.rs
index eb5aeeae..da8f2d42 100644
--- a/core/src/clsmodule.rs
+++ b/core/src/clsmodule.rs
@@ -516,6 +516,8 @@ impl Store {
                 not,
                 head: p.head,
                 preset: p.preset.clone(),
+                // as the weights were trained (retraining keeps the channels)
+                gematria: clf.net.cfg.letters || clf.net.cfg.words || clf.net.cfg.side,
                 steer: p.steer.clone(),
                 inputs: p
                     .inputs
@@ -529,6 +531,7 @@ impl Store {
                 history,
                 outputs: BTreeMap::new(),
                 version: 0,
+                starter: None,
                 seed: p.seed,
                 created: now.clone(),
                 modified: now,
diff --git a/core/src/filters.rs b/core/src/filters.rs
index dace0286..84eb8d2b 100644
--- a/core/src/filters.rs
+++ b/core/src/filters.rs
@@ -710,16 +710,26 @@ impl<'a> Universe<'a> {
                 (self.refs.iter().map(|r| found.contains(r)).collect(), vec![1.0; n])
             }
             Expr::Sum { bucket, from, to } => {
+                // over the entry graph the sums are its own (weum's), and atbash is gone
+                let graph = self.store.texts().is_some();
+                if graph && bucket == "atbash" {
+                    return Err("atbash was removed: sum filters are ordinal or reversed".into());
+                }
                 let m = self
                     .texts
                     .iter()
                     .map(|t| {
-                        let ms = crate::memory::measure(t);
-                        let v = match bucket.as_str() {
-                            "reversed" => ms.reversed,
-                            "atbash" => ms.atbash,
-                            _ => ms.ordinal,
-                        } as i64;
+                        let v = if graph {
+                            let ms = crate::graph::gematria::Measure::of(t);
+                            if bucket == "reversed" { ms.reversed } else { ms.ordinal }
+                        } else {
+                            let ms = crate::memory::measure(t);
+                            (match bucket.as_str() {
+                                "reversed" => ms.reversed,
+                                "atbash" => ms.atbash,
+                                _ => ms.ordinal,
+                            }) as i64
+                        };
                         from.is_none_or(|f| v >= f) && to.is_none_or(|t| v <= t)
                     })
                     .collect();
@@ -731,33 +741,40 @@ impl<'a> Universe<'a> {
                 (self.refs.iter().map(|r| members.contains(r)).collect(), vec![1.0; n])
             }
             Expr::Tags { tags, any } => {
-                if self.notes.is_none() {
-                    self.notes = Some(self.store.all()?.into_iter().map(|x| (x.key, x.tags)).collect());
-                }
-                let notes = self.notes.as_ref().expect("read");
                 let want: Vec = tags.iter().filter_map(|t| crate::note::normalize_tag(t)).collect();
-                let m = self
-                    .refs
-                    .iter()
-                    .map(|r| match r {
-                        Ref::Note(k) => notes.get(k).is_some_and(|have| {
-                            let has =
-                                |t: &String| have.iter().any(|h| crate::note::normalize_tag(h).as_ref() == Some(t));
-                            if *any {
-                                want.iter().any(has)
-                            } else {
-                                want.iter().all(has)
-                            }
-                        }),
-                        Ref::Memory(_) => false,
-                    })
-                    .collect();
+                let matches = |have: &[String]| {
+                    let has = |t: &String| have.iter().any(|h| crate::note::normalize_tag(h).as_ref() == Some(t));
+                    if *any {
+                        want.iter().any(has)
+                    } else {
+                        want.iter().all(has)
+                    }
+                };
+                let m = if let Some(src) = self.store.texts() {
+                    let mut m = Vec::with_capacity(n);
+                    for r in &self.refs {
+                        m.push(matches(&src.tags(r)?));
+                    }
+                    m
+                } else {
+                    if self.notes.is_none() {
+                        self.notes = Some(self.store.all()?.into_iter().map(|x| (x.key, x.tags)).collect());
+                    }
+                    let notes = self.notes.as_ref().expect("read");
+                    self.refs
+                        .iter()
+                        .map(|r| match r {
+                            Ref::Note(k) => notes.get(k).is_some_and(|have| matches(have)),
+                            Ref::Memory(_) => false,
+                        })
+                        .collect()
+                };
                 (m, vec![1.0; n])
             }
             Expr::Kind { kind } => {
                 let notes = kind == "notes";
                 (
-                    self.refs.iter().map(|r| matches!(r, Ref::Note(_)) == notes).collect(),
+                    self.refs.iter().map(|r| self.store.is_note(r) == notes).collect(),
                     vec![1.0; n],
                 )
             }
@@ -813,7 +830,7 @@ impl Store {
                 .map(|i| Found {
                     key: u.refs[i].label(),
                     text: u.shown[i].clone(),
-                    note: matches!(u.refs[i], Ref::Note(_)),
+                    note: self.is_note(&u.refs[i]),
                     score: s[i],
                 })
                 .collect(),
diff --git a/core/src/grammar/corpus.txt b/core/src/grammar/corpus.txt
new file mode 100644
index 00000000..015573dc
--- /dev/null
+++ b/core/src/grammar/corpus.txt
@@ -0,0 +1,2870 @@
+anend is a memory palace for short texts.
+You type a word or phrase and it is stored as an entry with its gematria sums.
+You find it again by its numbers, its words, its tags or the lists it's in, and you can fly through your memories laid out in space.
+It continues weum, whose numbers it reproduces exactly.
+a desktop app, and the same app built to WebAssembly for the browser;
+That includes the entry graph store, gematria, the app's API, and a deterministic transformer engine for classifiers and generators.
+Every view has the command bar at the bottom, and each view keeps its own text there.
+The top bar holds the view icons, the search line with its triangle, undo (Ctrl+Z) and settings.
+Settings are a dialog with folding sections:
+- the memory view's sizes and spacing, and the space's room colour;
+the bars fade while you rest, and the top bar can hide until the pointer reaches the top edge;
+A save is one file, an entry graph in redb.
+Every text, note, tag, list and setting is an entry with timestamps.
+Lists and tags are edges between entries.
+Identical texts are stored once, and an entry can borrow another's text.
+Saves from older anend versions aren't read.
+On Linux the app turns off WebKitGTK's DMA-BUF renderer, which leaves a white window ("Failed to create GBM buffer") on some drivers.
+Before a change goes in, run the checks:
+!the hub   This prints a one-time login link.
+the web app for members, each with their own saves;
+each save is private, unlisted or public.
+Members share saves, star and download each other's, and earn points, levels and badges when others use what they made.
+The admin panel reviews saves and people.
+Anything that speaks JSON can drive a save.
+The same inputs give the same output bits on any machine and thread count.
+classifiers that steer generation, by reranking, guidance or reinforcement.
+docs/guide.md is the guide for people using the app:
+The hub runs the app for the web:
+each member's saves live on the server in a workspace of their own.
+The account must be active.
+Without one, a post's body isn't read and the socket isn't opened.
+A member's app runs at most 4 calls at once (more wait their turn) over at most 8 sockets.
+past that, calls that would add something answer "your saves fill …" while reading and deleting still work.
+every text, note, list name and tag is an entry under a key, and lists, tags and notes-on are edges between entries.
+Sums are weum's ordinal and reversed;
+atbash is gone (it grouped texts as reversed does), and asking for it answers an error.
+In the forge an entry is its mime and rendered text:
+list pairs follow the same rules, tags come with the entries carrying them.
+the note shows that entry's text as it is now, and that entry may hold replacements of its own (recursive;
+one that comes back to itself is an error, shown as the note failing to render).
+Anything else between double braces stays as written.
+when a referenced entry changes, the notes that refer to it directly are indexed again (their sums and words follow).
+the stored note keeps the name.
+any list of the save is a set of words that may stand for each other;
+each is trained on lists, one class per list, the members' texts as examples (a note reads as its title and markdown).
+the hub adds only its quotas and job limits (two trainings or indexings at once per member, two hours each).
+- Training runs on a thread of its own:
+The weights are written when it finishes, so the save stays usable meanwhile;
+feedback on a classifier that's training is refused, and a run whose classifier changed meanwhile (feedback, another run) isn't written.
+a bias per class (added to the logits after the temperature), the temperature, the threshold for membership, and gains on the input channels.
+a few small steps on the text, replaying its earlier feedback and some of its training texts.
+It is left out when there are none, so older bundles read as before.
+Merging a bundle into a save leaves its classifiers out (their lists get new keys there), and so does the forge.
+an edited text is read again too.
+Calls fill what they need lazily;
+weights that no longer fit their definition's shape are unused, and the model answers as untrained.
+A save from before this keeps its definitions in the models file;
+opening it moves them into the save (nothing is lost).
+- Data comes from the save when training starts:
+its title and markdown) is one example.
+- Critics are other spec models of the save, or its trained classifiers (a classifier's head is its own name).
+The same seed gives the same candidates;
+without any the hub loads none.
+A picture is a PNG or JPEG, decoded when it comes in so only ones that read are kept.
+Lists hold pictures by name:
+Spec models train on them (models:
+a text block finds its text in the target by what it says, a picture block its picture by hash).
+A block shows a texture:
+The texture tiles at one tile per unit, so a bigger block shows more tiles rather than a stretched one (the app sets each face's UVs from its size, with repeat wrapping).
+A save as plain JSON:
+Importing it restores the save keys and all;
+merging it leaves the classifiers out and brings the spec models (untrained) and pictures in as described under spec models.
+The old JavaScript web app and its offline engine are retired:
+Running without a hub comes with the Rust core compiled to WebAssembly (next).
+the hub (a site for sharing saves and classifiers, with people, stars, levels and an API the desktop app uses) and the web app (the anend app in the browser, each member working on saves of their own on the server).
+It runs either half or both, over one account system.
+One data folder works in any mode:
+switching modes keeps every account, save and setting.
+A hub built without it still runs;
+A build without a half refuses a mode that needs it when it starts.
+The database code is in every build, so a data folder moves between builds.
+open it and set a password on your page.
+login links and invite links are printed or shown once, and you pass them on.
+A member who loses their password gets a fresh login link from an admin (admin panel → everyone → "make a login link").
+an account needs an invite code.
+trusted members may too when "trusted members may invite" is on in the admin panel.
+A code is shown once (only its hash is kept);
+every invite is listed in the admin panel with who used it, and can be taken back.
+an admin lets them in.
+An invite code skips the wait.
+anyone may join at once.
+Every save and classifier on the hub is private (its owner alone:
+Admins see every one listed in the admin panel and can remove any, but can't open a private one.
+A Caddyfile is two lines:
+requests in flight get up to 20 s to finish.
+Everything is in the data folder.
+For a consistent copy, stop the server (or snapshot the filesystem), then copy the folder:
+To sell access to the web app (with or without the hub):
+the customer joins with it.
+To end an account, ban it in the admin panel (its sessions end at once).
+Set the limits you sell:
+A plan with more room needs its own server today (quotas are per server, not per member).
+Billing is outside the server:
+there are no payment hooks;
+you make and revoke invites and ban accounts by hand (or script the admin panel's forms).
+The module docs hold the same detail next to the code.
+caps lock and the last lead reset at the start of each run (a body, each argument), so arguments decode on their own.
+Evaluation runs on an explicit continuation stack, never native recursion.
+A call in tail position replaces its frame instead of pushing one:
+text before it is already in the frame's output, which the call continues;
+Any other call pushes frames, up to the depth limit, past which evaluation stops with an error.
+refs that transclude themselves are an error;
+its rendered text changes only when it's edited;
+Reading one entry reads one row and skips to its slot.
+varint mime, prefix and suffix byte counts kept from the next newer version, then the packed middle.
+An edit of a plain entry stores the old text as such a delta, usually a few bytes.
+Sources must be within the depth limit and must not themselves read the entry being saved.
+when a source is edited or deleted, every plain entry borrowing from it is stored again from its old rendered text.
+Saving a text equal to an existing entry's (same mime) returns that entry.
+re-packing a value always gives the same bytes (the rotation search runs quantise∘dequantise to a fixed point, or the smallest value of the cycle it falls in).
+What anend is, what each part of it does, and how to use it.
+For building it, running a hub and the APIs, see the README.
+anend is a notes app with a game inside it.
+The notes side is plain:
+The game is a memory palace built on gematria.
+Every word or phrase you type has sums, and texts that share a sum share a room:
+You remember short texts, find what shares their sums (gsearch), fly through them in a 3D room, and gather them into lists.
+Then you grow lists into models:
+small transformers trained on your own lists, which you steer, correct with a yes or a no, and describe as plain data when you want more than a classifier.
+They are deterministic (the same save gives the same answers on any machine, to the last bit) and they are yours.
+There are two ways to run it, the same app in each:
+a window of its own, everything kept on your computer.
+open the hub, join and log in;
+the app keeps your saves on the hub, in a workspace of your own, within the hub's quota.
+the views as icons (hover for their names;
+- The command bar at the bottom:
+one place to type, doing what the open view needs (its placeholder says what).
+Each view keeps its own text.
+- Ctrl+Z outside the bar takes back the latest action:
+a forget, an edit, a list change, a yes or no to a classifier.
+!the memory view with its sum buckets  Weum's memory page:
+The strip over the bar holds the same toggles, the sidecar of the bar's sums (click one to gsearch it) and the sum buckets.
+The menu also says when the text was written and what kind it is (a link, an email address, a number, a date, a name, a phrase, a sentence…), told by its pattern;
+when the guess is wrong, pick the right one there and the save keeps it.
+Drag the field's edges to make it wider or narrower.
+the palette picker in the strip colours every text by its top class (fainter when less sure, grey when in none), with a legend.
+With one picked, C turns on its search:
+a class's name finds the texts it counts in that class, any other text the texts it reads most like.
+texts with the same sum cluster, deeper the higher the sum.
+Type in the bar and press Enter as in the memory view.
+Hover a text for its card of numbers;
+Shift+click and Ctrl+click pick the list and candidate.
+The room's colour is a setting.
+!a list's page  A list is a text heading other texts:
+Lists are how you tell anend what goes together, and what models learn from.
+or in the memory view, Shift+click a text to make it the list.
+or Alt+click several and put them in a list.
+- The lists view shows every list as a tile;
+the bar finds lists by name.
+A list's page has its name (editable), its members a page at a time (edit them, or take one out) and its figures:
+Deleting a list takes two clicks;
+newest first on the left, the editor on the right.
+tags go in their box.
+The bar narrows the list by words.
+notes and texts as cards, a page at a time.
+Click one (or Enter on it) to read it big;
+every tag with its count.
+Click picks one, Ctrl or Shift+click adds or drops it;
+all or any decides how several combine.
+Training runs on a thread of its own with a progress bar and the loss drawn as a line;
+the app stays usable, and cancel stops it without writing anything.
+!a trained classifier  A classifier reads a text and says which of your lists it belongs with:
+each list is a class, its members the examples.
+type in the command bar and each class's probability shows as you type.
+✓ and ✗ on a class teach it on the spot (a few small steps on that text);
+Ctrl+Z (after Esc leaves the bar) takes the latest one back exactly.
+texts like this lists the texts it reads most alike.
+The bias report says how much your steering moved its answers.
+import takes one in (each class goes to the list of its name, made when there's none).
+!a writer and its critic's scores  A spec model is a model described as plain data (the format):
+what it reads, how big it is, what comes out (classes, labels, numbers, or text it writes), what it learns from in this save, and for a writer, which other models judge what it writes.
+- new starts from a template, filled in with your lists:
+a classifier (one class of several), a tagger (any of several labels) or a generator (writes texts like a list's, judged by a trained classifier or spec model of the save when there is one).
+- The spec is a JSON editor.
+It's checked a beat after you stop typing:
+Edits to the data, critics, sampling or training options keep its training;
+a change to its input, trunk, heads or seed means it trains anew.
+loss, bits per byte for a writer (lower is better), each head's accuracy and confusion table when some examples were held out.
+type in the command bar and every head answers as you type.
+ones that break the spec's constraints come last, greyed.
+The same seed writes the same candidates.
+Enter in the command bar writes after the bar's text.
+guided steers each byte toward what the critics want (slower).
+On a shared hub only the folders the hub offers can be named.
+keep saves a filter by name in the save;
+the kept ones are chips to run again.
+The sections fold, and remember it.
+a palette to start from, then any colour by name;
+the top bar sliding away;
+- the memory view and the space:
+every save with its counts and size.
+the hub's address (sharing from the app comes back here when the hub's sharing moves to the entry graph;
+for now share on the hub's site).
+A hub is anend's server:
+Run for others, it's a website where people join, keep their saves in the web app, and share saves and classifiers, with stars, points, levels and badges.
+Everything shared waits for an admin unless you're trusted.
+Running one is in deploy.
+What the app (and anything else) uses to talk to an anend hub.
+Every response is JSON unless it's a download.
+Lists and searches only ever hold public, approved ones;
+Modules are read strictly before anything is kept (magic, version, checksum, sizes before allocating, every part parsed and matched to its hash, a panic is a bad file), on a worker thread;
+Uploads count towards a limit of 20 an hour from an address.
+Ids are lowercase letters and digits;
+A model is described by a spec:
+the planned scripting language and the UI will write the same structure) saying what goes in, how big the trunk is, what comes out, what it learns from, and — for generators — which other models judge what it writes.
+nothing in it assumes gematria.
+Gematria channels are optional input features you list, off unless you do.
+The same holds below the spec:
+Files and stored classifiers made while they defaulted on keep them, and answer bit for bit as before.
+class probabilities with the top class and members, values, or what the generate head writes after the input.
+The codebook is learned from the training pictures (integer k-means, deterministic) and saved with the model.
+the vector is written as fixed-width text for the trunk and given to the heads as numbers too.
+it learns to write the output after the input (sequence to sequence;
+those of a picture list;
+Checks give the first broken rule in words, e.g.
+A text generator steered by that classifier, keeping only short candidates with a byte sum in a range:
+A picture classifier trained on the save's pictures, by list:
+It goes wherever the save file goes:
+They are kept apart because of their size:
+in the save they would make every backup, bundle and hub share carry them, and a shared save would count them in its author's quota whether anyone wanted them or not.
+an edit that changes the shape drops them (as before);
+a definition that changes some other way (a merge, a restored backup) and no longer matches the recorded shape leaves them unused, and the model answers as untrained until it trains again.
+- Merging a save into another brings its definitions in untrained:
+the same spec JSON under the same name is the same model;
+The same machinery is open in Rust:
+the same data, spec and seeds give the same weights and the same samples on any thread count and CPU.
+A spec can start from a pretrained open model instead of fresh weights:
+a sliding window shortens the window to it.
+Anything that changes the computation and isn't supported is refused naming the field:
+Every window starts with the model's BOS (or its end token when it has none, as Qwen) and ends with its end token.
+The engine's own models keep reading bytes.
+classify, multi and regress heads are new and sit on the pretrained trunk (mean pooled), so a pretrained model can be a classifier too.
+Trunk sizes come from the checkpoint:
+critics, constraints, guidance and reinforcement work as for any generator, judging the decoded bytes.
+The saved model carries the weights (as f32) and the tokenizer, so it no longer needs the folder.
+the engine's results are still deterministic across threads and CPUs.
+Every model runs on the CPU unless a run asks for the GPU:
+the trunk (every block's norms, projections, attention with its KV cache when decoding, SwiGLU, the final norm) and the generative head, forward and backward.
+The embedding lookup, pooling, the classification heads, the losses and the optimizer stay on the CPU (a sliver of the work);
+weights are uploaded after each optimizer step.
+Critics judge on the CPU.
+On a device that rounds each operation once it gives the CPU's bits;
+whether a device does is measured, not assumed:
+faster on real GPUs, within about 1e-4 relative of the CPU per kernel, so results are close but not the CPU's bits.
+- Saved models answer on the CPU (the reference) unless a run asks for the GPU;
+a model trained on a device the probe did not find exact is a different (equally valid) set of weights from the CPU's.
+Sizes are bounded by the device:
+the largest buffer the adapter allows (all its limits are requested).
+The main lever to lift the compute limits is the GPU backend (above;
+Where the work stands, for picking it up in a new session.
+Nothing goes away without a line there saying why.
+the user's feedback on the Dioxus app):
+the Bevy frame and one command bar (no view name), Fira bundled, selects centred, the window icon really set;
+the lists view's Bevy cards.
+tags), then a polish pass, then GPU training in the app and hub, spatial saves, the grammar/spelling proof of concept, then the old backlog below.
+Spec JSONs and pictures in the save;
+they travel like the specs.
+word types on hover (tooltip and hover line in the memory view);
+templates, the JSON editor with inline errors, training, run from the bar, the write card with critic scores.
+word types on hover, the search filter panel, then the editor's replacements, the spatial table, space search modes, save checkpoints.
+finish the tints and a classifier search mode in memory.
+the older ones below are history):
+- Classifiers work in the Dioxus app, desktop and web alike.
+search by class with yes/no;
+a class as a list;
+implementation in core, the classifiers view, colouring and classifier search in the memory view);
+the tiny preset is weak on a few dozen texts (more texts help), Ctrl+Z in the bar undoes the bar (Esc first).
+a spec panel in the models view;
+The workspace is core, hub and app.
+That points to Actions billing or settings, not the code.
+Until the jobs run again, those local checks are the only gate.
+- Running when the session ran low:
+- If a track was cut off:
+- turn the gematria presets off by default when the classifiers move to the spec;
+- Were running when the session ran low:
+Then do the desktop side of item 4:
+Shortcuts now match the web app:
+NOT yet verified by driving except where said.
+The classifier list's names no longer wrap word by word (NoWrap).
+Clicking it adds the validator;
+The "indented text in name boxes after a redraw" is NOT investigated yet.
+the bar's tabs drop their words on a phone.
+Notes, memory texts and list names are meant to be one thing, not several.
+With timestamps (and mime types) coming, do a single schema change that unifies them:
+the save carries one, and opening an older save migrates it in place (with a backup copy first) so players never have to start fresh.
+they gain the version too, and old bundles migrate on import.
+- Do this before any more features build on the split.
+Checks to run before every push:
+the JS offline engine is frozen, see step 3)   New module beside the old store (apps not rewired yet;
+Clippy clean on the module.
+Rebuilding the indexes into memory at open:
+a bulk rebuild in key order doesn't help);
+the memory-mode rebuild needs to get faster (or be persisted as a snapshot) before it's the default;
+borrowing only finds sources the new text contains (a shorter variant saved after its longer form isn't stored as a slice);
+structured entries are indexed by their render at save time;
+Clippy clean for the hub's three feature builds and core.
+Open graphs are cached process-wide by file (weak refs), so a save still held by a training thread is shared instead of failing to open twice.
+merging and the forge dedup on that, keep times, and carry lists (in order), tags and other relations whose ends came along.
+Structured entries arrive as rendered text (left:
+whether it's a note comes from its mime.
+it answers the old op set and no longer matches the hub.
+modes are ordinal, reversed and frequency;
+run and yes/no with undo over the backend's classifier calls;
+labels are projected HTML sized by distance, crisp and shrinking near, since WebKitGTK flattens CSS 3D without compositing;
+click puts the triangle in the top bar;
+arrows ease onto the nearest text;
+the room colour is a setting with readable ink;
+the web build in Playwright's chromium renders the same (no hub there, so calls fail).
+each view keeps its bar text;
+the list picker offers the picked list while it's empty;
+zen (fade after a delay) and the top bar's autohide (from the window's top edge, kept while the pointer stays on it) in settings, as the old app's.
+Small screenshots with data for the README:
+a page saying how to build it when missing;
+its CSP allows wasm, the interop's eval and blob scripts;
+Bevy and the old JS app retired;
+keys typed into an input method (IME) while it composes are left to it (Enter doesn't search mid-composition;
+not tested with a real IME here).
+notes read as markdown (notes view's read mode and the reader;
+on a desktop it should), the reader's total, the space's labels under its overlays.
+a real IME session (keys are left to it while composing, untested here).
+The user asked for "the route that provides the most feature coverage and performance and ergonomics" and approved this plan.
+One entry graph is the core.
+runs of 5-bit packed text and references to other entries (borrowing and dedup;
+sums in every mode, tokens, time and classifier buckets.
+They can always be rebuilt from the two tables above.
+none with old saves or blog writs.
+Backups write a texts JSON and an other-data JSON.
+RSX components shared by the desktop app (Dioxus desktop:
+the desktop, web app and hub look the same.
+- The core runs in the browser:
+the Rust core compiles to WebAssembly, with redb on a storage backend over OPFS/IndexedDB.
+served from the same Rust code (Dioxus fullstack/SSR or Salvo serving the built app).
+a canvas in the app, starting with the existing three.js space through interop;
+a wgpu/Rust renderer later if it earns it.
+- Bevy and the old JS app:
+retired once the Dioxus app reaches parity.
+the desktop app is the primary product;
+the browser version exists for reach (the user:
+"only reason I desire the browser action is because it might not be as popular otherwise").
+Build and polish the desktop first.
+The web build follows from the same code, and where something only works well on the desktop, the desktop wins and the web gets a lighter version.
+The desktop, web app, scripts and lenses all use the same calls.
+Views are lenses over one query model:
+The user built and ran the app and imported their weum texts.
+Everything below comes from that feedback.
+Several items (the entry store, the gematria fixes, text quality) come first, because the rest builds on them.
+It's superseded by the store redesign below, apart from the keyboard bits, which may be reused.
+Notes, entries, memory texts, space texts and list names are one concept, on the same keys in one flat redb table of texts.
+Search, tags, classifier search and filters get time filters.
+The data is fat, and the user keeps many variants of a text (with a prefix or suffix missing, written differently).
+An entry can be made of references to other entries (borrowing), so variants share storage instead of duplicating it.
+- An escape code means the next token is a raw byte.
+- An uppercase code makes the next token uppercase.
+- A reference code means a replacement key follows.
+Decoding fetches that entry, which is also how the editor's replacements/templating are represented.
+- Notes are a relation, not a separate kind of thing.
+As in weum, notes go on entries:
+Notes are chronological, not organised by title.
+Rethink what a title is, since nothing else has one.
+- Importing must be a visual, per-save process in settings, because import and save semantics conflict today.
+it gave the same values as reversed, so only ordinal and reversed remain (the store's modes are ordinal 0 and reversed 1).
+colour by shared reversed sums;
+colour by shared ordinal sums;
+Study weum's memory to recreate its behaviour exactly.
+the sidecar's frequency letters grow long.
+Let them be toggled, or shown smaller or in another form.
+it comes to the top so it isn't hidden under another entry.
+The way text expands on hover is blurry and was always buggy;
+spacing between texts as a setting.
+The texts sit too close to the digit sums above them, and long texts need an overflow story (every view needs one for really large texts).
+dragging its edge sets its default width, and it stays centered.
+they stay highlighted, then pick a list visually to put them in.
+- A left-edge strip, shown only on hover and fading in and out:
+a line with circles, one per sum bucket, each with its number and sized by how many entries it holds.
+Hovering shows which bucket it is, for the active mode.
+Prefer no antialiasing at all to bad antialiasing.
+Try other fonts and bigger sizes.
+- Typing feels sluggish in the command bar:
+debounce the sum work, run it async, and cut latency.
+Ctrl and Page Up / Page Down zoom in and out, like a website.
+- clicking a text should put its triangle in the top bar;
+it currently stays plain text;
+- the triangle's middle bar should be centered.
+- the bracketed text at the right needs enough contrast against the space's background;
+- the background colour should be a setting;
+- on a dark background, texts must keep readable contrast.
+it should be dismissable, and its text is blurry.
+- Arrow keys ease the camera onto the nearest text in that direction.
+- Texts shrink as the camera comes close, so they stay readable.
+the camera can't fly through blocks or glTF models.
+- A right-click menu on any text in the memory view and the space:
+the text goes into the bar and the result replaces it under the same key;
+the next thing typed in the bar tags it;
+the bar's typing in the main views and the space can be undone back to the previous state.
+There's also an undo button for any recent action, including yes/no/why given to a classifier.
+a list's page shows its name at the top and its members as editable entries, with pagination.
+From there you go back out to the list of lists.
+A list's figures go at the bottom.
+deleting a list takes two steps.
+you can't really make lists today, so the classifiers are untested.
+- an expand mode for reading one thing big at a time;
+- thousands of tiny texts flowing in a grid instead of one row each.
+should cover the whole app, not just notes.
+- it resizes when the bars fade;
+- long titles show in full on hover, like a website's title attribute.
+remember which menus were collapsed.
+- it closes on a click outside it;
+- the rebind menu closes the same way, with its close button in the same place;
+smaller gaps between elements, none at the window's edges.
+a compile feature that leaves the hub out of the desktop app.
+This matters because the user is thinking of selling access as a cloud service.
+- public and private toggles on everything shared;
+- a professional finish that works nicely with the app, with promise as the app's social side.
+the web app and the hub are kept up to date with the desktop app, and look the same.
+all three builds are clippy-clean and pass their tests.
+settings and classifiers hide hub browsing).
+rewrite it, because it's very out of date (including the old blog import).
+Redo the screenshots or remove them.
+touch it up after these changes land.
+heads and a generative head share a trunk, trained jointly with per-head loss weights;
+gematria channels are opt-in model inputs, off for new models;
+- transpiled to concatenated Rust calls over a state machine, linked against a precompiled preamble so it compiles fast.
+- Views as templated modes of consumption, like little websites over the core's API:
+wgpu, behind the engine's kernel boundary;
+checked against the CPU results;
+benchmarked on the user's hardware, since this container has no GPU.
+the default build and wasm do not pull wgpu):
+On llvmpipe (the container's software Vulkan) every kernel, whole passes, decoding and training match the CPU bit for bit.
+batched decoding of several candidates per submission, AdamW on the device, a faster GEMM for big models, classification inference on the device, the WebGPU (browser) build.
+batched decoding, AdamW on the device, the faster GEMM and the bench table are not started.
+Byte models are unchanged bit for bit.
+Example to run on the user's machine:
+Each synthetic architecture matches an f64 reference written from the transformers code to 2e-3 relative, and the cached decoder equals the full pass bit for bit.
+a run on real checkpoints (outputs vs.
+small sizes only where measured compute requires them, and never gematria by default.
+It is always available as an opt-in input channel (letter, word-sum and side-vector features) and never on unless chosen.
+Spec-built models already work this way.
+generated pictures as block textures.
+a block's placement payload points to a generated or imported texture entry, and the generator (steered by classifiers as critics) makes texture sets in a chosen style.
+Do this after the editable space and blocks exist.
+Overall aim, in the user's words:
+every feature properly supported in the interface, not stubs.
+an icon takes its button's text colour, so the palette and zen reach it.
+hidden while zen fades, placed inside the window, scaled with the interface.
+The memory view's bucket and toggle words carry tips with their keys too.
+every tag with its count, narrowed by the command bar (Enter adds the first match, so typing tag after tag chooses them);
+the notes found show title, date, tags and a preview, and open in the editor when clicked.
+the pad's own glyphs go transparent, so editing, cursor, selection, IME and scrolling are untouched.
+Only visible glyphs are drawn;
+classes are recomputed once per layout change.
+Colours come from the palette, nudged until they read on the pad (night and paper work);
+a settings toggle turns it off.
+If glyphs ever fail to match the text, the pad shows its own text again.
+plain buttons (the note list, the tag list) take the card's text colour and button text picks dark or light by contrast, so dark palettes read;
+the editor's selection and cursor follow the palette instead of a stock blue;
+the memory view says how to start instead of showing an empty page;
+the note list toggle's setting names the right edge too;
+icons in buttons take the button's text colour (ThemedText) and fade with zen.
+the memory view's and space's text toggles in the bar stay words (they carry state);
+the pad doesn't scroll with the mouse wheel (bevy's EditableText;
+the overlay follows whatever offset it has).
+every one with an aria-label and a styled tip (name and shortcut), keyboard focus visible;
+tags with counts, found from the command bar, picked with all/any, their notes beside;
+On a phone it sits under the pad.
+by name when unchanged so counts are kept), keep, write to a list.
+Enter in the bar adds a words condition.
+Offline it says filters need a hub.
+once the name is fixed it can go back to not waiting.
+results from a closed save are dropped;
+steering sliders (bias per class, temperature, threshold, gains, coupling per upstream link) with the bias report measured live on a thread and kept after the hand stops;
+near texts by embedding or verdict;
+index the save with a moving bar and stop, counts per class with confidence histograms, open a bucket;
+the editor's classifier button opens a strip:
+memory results get a class-coloured bar, space texts take the class colour (fainter:
+validators editor and disagreements (core has them;
+the web app shows them), hub browse/take of shared classifiers, sum conditions in the filter builder, a file dialog (no dialog crate;
+built in, rendered with pulldown-cmark, text escaped, raw HTML shown as text, links only to its headings, the repository and https;
+the desktop app's help link (src/), and keeping the guide in step as features land (filters and validators on the desktop, the web space's editing and maps).
+security and CI done, a first UX walk done.
+steering checked when only measured;
+logins for unknown names take the same time as for known ones;
+filter presets are checked and run once each however often they're referred to (it was exponential), a loop from a bundle errors, and imported presets' size is checked;
+the thread names no longer carry the job key, and the web app doesn't wait.
+the classifier's five tabs now fit across a phone (the last hid past the edge), the tags view said "no tags yet" twice, a list card's letters line ran out of its card.
+"one class" / "labels" for a classifier's head reads oddly beside two classes, but the guide and the desktop use the same words, so change all three together if at all;
+the hub's own pages (not the app) weren't re-walked in this pass.
+A deterministic transformer encoder written from scratch, trained on lists.
+one classifier's outputs feed another, and its predictions become lists - feedback:
+yes/no per classifier on a result (the main kind), or end to end through a stack with a coupling strength per link;
+a result lists which classifiers contributed, so each can get its own yes/no - bit-exact on any thread count and CPU:
+make from lists, train with progress and metrics, steer with the bias metric live, classifier search with yes/no per contributing classifier, outputs as lists, near texts).
+Offline the web app says classifiers need a hub.
+a GPU backend behind the kernel boundary (wgpu in the app, WebGPU in the browser).
+Drivers may fuse multiply-adds, so saved models answer on the exact CPU path unless the GPU can be proven exact.
+the stored mime stays text/plain, since the search, classifiers and backups read texts by it.
+the text's kind and the counts with examples go on the hover line and as the tooltip's second line;
+the kind there is the detected one, not a hand-fixed one).
+kept in the app's prefs, a line says how many it hides).
+entry ids as replacements (recursive, with references to saved filter views;
+the note's sums are those of what it renders (a ref where the same text stood changes nothing), and notes referring to an entry are indexed again when it changes (one level:
+a ref to a ref isn't refreshed).
+no separate management view (the lists view is it), and the rendered text, not the stored one, is what's indexed.
+slug texts placed by hand in 3D, with coloured cubes/blocks/bricks and a gimbal to move, scale and rotate.
+redb savepoints, grouped under each save in the save menu.
+This file is the contract.
+Nothing is removed without a line here saying why.
+Change this file in the same commit as any change that adds, moves or drops a feature (docs/next.md's Resuming block says so too).
+the status column is kept current as items close.
+the undo stack and button, the right-click menu with kinds, the memory view's search filter, bucket strip, field width and selection, pictures, spec models, replacements and alternatives in the editor, the reader's pages and big reading, zoom.
+- A shared hub on the internet.
+Strangers can reach every route.
+Members (once admitted) upload saves and classifiers, and run the web app on their own workspace on the server.
+Any of them may be hostile:
+One person on their own machine, with no login.
+Saves and classifiers from the hub reach other people's apps, so notes (markdown) and modules are untrusted data.
+Anyone with an account can share a file by link without an admin looking.
+Admins see every unlisted item in the admin panel and can remove it;
+invite-only joining limits who can do this.
+They see the name, owner and size and can remove one, but not open it.
+redb isn't hardened against crafted files.
+a crafted file that makes redb loop or allocate a lot would cost that one thread or memory.
+Saves downloaded from a hub are opened by the desktop app the same way.
+Anyone holding a live session (a borrowed computer) can change them.
+Cross-site forms can't, thanks to the origin check.
+Names may use any letters, so look-alike names are possible.
+Workspaces are keyed by the lowercased name, so case differences can't share one.
+The 4-calls-per-member limit and the login requirement bound how much one member can hold at once.
+The socket opens on the first call and again after it drops;
+calls made meanwhile wait in a queue.
+the hub that served this page
+they live as long as the socket
+Every call runs on a worker thread and answers through a channel, so the interface never waits on the disk.
+the saves folder and the open save
+the list keeps its member
+made from lists, trained in the background, asked, told yes or no, and the answer taken back
+the classifiers go with the save:
+copied, then deleted with it
+A backend answers one call:
+The typed methods below are what the views use;
+they build on that call and can be overridden.
+The core in WebAssembly slots in the same way:
+a memory or a note as the views show it;
+one sum and how many texts it holds, in a mode
+a classifier) as the models view lists it;
+the rest of its details stay JSON until the declarative model spec lands (docs/models.md)
+what a backup wrote (the desktop:
+where the files went, when the backend wrote them
+what an import put in
+the app's data, wherever it lives
+every typed call goes through it
+whether the saves are files on this machine (backups go to a folder, imports read paths);
+on the web they're downloads and uploads
+a bundle into a save:
+the texts in one JSON, everything else in another;
+on disk the backend writes the two files (their paths come back), a hub hands the two documents back to be downloaded
+remembers a text unless it's there already;
+its key and whether it's new
+a memory's text replaced, keeping its key (or a forgotten one put back)
+every sum in a mode and how many texts it holds, lowest first
+every tag and how many entries carry it, the most used first
+the entries carrying all (or any) of these tags
+weum's notes on an entry, oldest first
+words, a sum range, a creation time range, a tag, a kind
+the time range, here so every backend has it
+a model's outputs for a text:
+the texts most likely in a class
+yes or no on a text for a class
+takes back the latest feedback on a model (the undo of yes/no/why)
+what making or saving a spec would say:
+every head's answer on a text
+candidates from a generator, judged by its critics;
+the other members of the lists a word is in (synonyms, registers), with their sums
+the lists that hold pictures:
+a picture file on this machine (the desktop) into the save
+None when it doesn't read
+The numbers the views show, computed in the app (no round trip):
+the gsearch modes (the memory view's buckets)
+the sum whose shared values colour the underlines in this mode:
+ordinal by reversed groups, reversed by ordinal groups (weum), frequency by ordinal ones
+the sum a text gsearches by in a mode
+weum's letter table as the letters themselves:
+the colour of its grouping sum, when that sum's string is two or more characters long (weum checks the key's length, so a lone text with a two digit sum is underlined too)
+the triangle's angles, or why it lies flat, for its tooltip
+the JavaScript string hash, as weum's seedCLR
+ordinal mode groups by reversed:
+Markdown highlighting in the note editor, ported from the Bevy app's highlight.rs:
+what a stretch of markdown is
+a list item's bullet or number
+a table's pipes and its alignment row
+a fence's char and length, if the line opens or closes one
+indented code (4 spaces or a tab, not inside a list item's text)
+pipes, and the alignment row
+the bullet or number, and a task box
+the matching run of the same length closes it
+a trailing dot ends a sentence, not the tag
+inside a word (snakecase) isn't emphasis
+inner marks and code stay what they are
+step over a whole character
+the CSS class of a span of this class
+a stretch of the text the checker flagged:
+a trailing newline gets a space after it so the layer is as tall as the textarea's content
+where the class changes or a flag starts or ends
+a flag never cuts a character in two
+what a hub sends is untrusted (links must stay on the hub, sizes are capped, names are cleaned before they touch the disk).
+The desktop calls with ureq on a blocking thread;
+the biggest save a download may be
+the biggest JSON answer read
+a typed hub address made tidy:
+a path on the hub;
+a path the hub sent can't lead anywhere else
+percent-encodes a query value
+a hub's ids are lowercase letters and digits
+a multipart/form-data body of text fields and one file, and its content type
+the hub's own words for a failed call, or its status
+the page's fetch, the body going in and out as base64
+The app's own icon is the window's and the web tab's, not the views'.
+an icon's svg by name;
+every keyboard action has a binding (a key and its modifiers) that the keys menu in the settings changes;
+Bindings with Ctrl or Alt work everywhere, even while typing;
+plain keys only act while no text box has focus.
+Each action has a scope:
+two actions only clash (and swap when one takes the other's key) when both can be pressed in the same place.
+where an action's key works
+whether two actions can be pressed in the same place, so can't share a key
+the space's flying keys act while held (space.js reads them), not on a press
+the stable name kept in the settings file
+the keys that can be bound:
+a key event as a binding
+chords work while typing, plain keys don't
+the defaults with the person's changes over them
+the person's changes, as kept in the settings file (action id → binding)
+one of that view's, else a global one
+the bindings the page's key listener should keep from the browser:
+the space's held keys for space.js:
+taking another action's key swaps them
+every default is nameable and distinct where both can be pressed
+the space's keys don't push the memory view's out
+held keys are space.js's
+the backend this build talks to
+first thing in main, before any thread is started.
+else the last save, else main.redb in the saves folder
+weum's texts into the save first
+the worker answers on its own thread;
+the icon goes on the window itself:
+the sand window's colour, so the first frame isn't a different shade
+Wayland desktops (GNOME, KDE) draw a window's icon from the desktop entry matching its app id, not from the window:
+a user-level entry and icon are put in place once (never overwriting one the person changed)
+Markdown to HTML for reading notes:
+raw HTML in a note is shown as text, and links and pictures only go to http(s), mailto or relative addresses.
+the settings keys and the views the app has.
+A key or a view that goes away fails these tests until the expected list here and docs/parity.md are changed together, saying why.
+add new ones here, and never take one out without a line in docs/parity.md
+the views, in their tab order
+every one the Bevy app had that still applies, and the ones added since
+the memory view's gematria underline (the colour of a text's reversed-sum group) stays under word-type labels:
+no rule on a text or its labelled words takes the underline away or draws one of its own
+the space's texts carry the same gematria grouping underline as the memory view's
+blocks keep their tiling UVs, their repeat wrapping and their gizmo, and the space keeps the window that makes them
+the command bar's input spans the bar with the same room at both ends, so its centred text doesn't move when what's beside it changes size
+the reader's note cards show when each note was written
+the web app in localStorage.
+colours changed from the palette's, by role
+the interface's text size in pixels
+the memory view's text size in pixels
+the gap between texts in the memory view, in pixels
+Enter on a text gsearches its sum (weum's gsch), not its words
+the classifier colouring the memory view's texts (empty:
+Enter in the memory view searches with that classifier:
+a class's name finds the texts most likely in it, any other text the texts it reads most like
+the space buckets by the reversed sum
+the space adds new results to what's there
+fade the bars away while the mouse and keys rest
+seconds of stillness before zen fades
+slide the top bar away until the pointer comes near it
+the save the desktop opens (a path)
+the hub (when built with it)
+the memory view's search filter panel is open
+what the memory view's search filter keeps
+the keys changed from their defaults:
+colour the markdown in the note editor
+the note list slid away
+the note list at the editor's right
+the memory view's white mode:
+the memory view labels every text's words with their types
+the space's panels, physics, history and last address
+the memory view's font family (empty:
+the top bar's and the command bar's heights in pixels
+the top bar at the bottom, the command bar at the top
+an app token from the hub's profile page (sharing needs one)
+the memory view's search filter:
+what of the shown texts it keeps (every part empty or off keeps everything)
+leave out notes / texts that aren't notes
+word types a text must have (each of them at least once)
+only texts the colouring classifier was given a yes or no on
+where saves live unless the settings say otherwise (the Bevy app's folder)
+keys the shell or the open view takes, sent to Rust;
+the keys menu waits for a key:
+every key goes to Rust
+its keys are its own, Enter included
+a text box keeps its own editing chords
+the bars fade while the mouse and keys rest;
+the top bar slides in near the top
+shown from the window's top edge, kept while the pointer stays on the bar
+the save's name and counts, and again whenever something changed
+the bar's text measured a beat after typing stops, off the input path
+the page's key listener keeps the keys bound here from the browser
+zoom only when it isn't 1 (WebKit's css zoom upsets the space's 3d transforms)
+a family the person named goes before the built-in ones
+the keys menu is waiting for a key
+the space keeps its own undo (moves, pins, removals) and falls back on this
+each view keeps its own bar text
+the bar names what Enter will do only while it does something else than search;
+it never names the view (the tabs say which one is open)
+when the entry was written, and its kind (told by its pattern;
+picked here when the guess is wrong, kept in the save)
+the prefs, changed and kept
+every one has a role (as in the web and Bevy apps) and a CSS variable.
+Sand is the old admin panel's;
+night, paper and sea start from it.
+the custom one, else the palette's
+whether dark ink reads on it
+the CSS variables for a palette and its custom colours
+from the palette, each readable on the writing pad, the hues the palette doesn't name turned from its link colour so they suit any preset
+readable ink for texts on a background (the space's room):
+dark on light, light on dark
+every highlighting colour reads on the pad
+The state every view shares (signals in a context), and the small pieces they all use:
+what the command bar asks for in this view
+a key press the shell hands to the open view:
+a text box (the bar or another) has the focus
+the action the keymap gives this press here (set by the shell)
+the search line in the top bar:
+what was searched and its triangle
+what the next Enter in the bar does instead of a search
+the bar holds the text;
+Enter puts it back under the same key
+the next text typed tags these
+the right-click menu on a text
+a recent action that can be taken back
+states it was in, coalesced while typing
+the command bar's text, mirrored on every input (the input itself isn't bound to it, so typing never waits on a render)
+the bar's text measured, a beat after typing stops
+bumped when the save's data changed (views reload)
+what the bar held in each view, put back when you return to it
+what each view says at the command bar's right end (its counts, what Enter does)
+the keys menu waits for a key for this action
+a note another view asked the notes view to open
+a tag another view asked the tags view to show
+the defaults with the person's changes
+what the key bound to an action is called, for tooltips
+what the view says at the command bar's right end
+a message in the top bar;
+errors stay a while longer
+puts a text in the command bar (and its undo history)
+a new undo state after a pause or at a word's end
+counts and the save's name again
+takes back the latest action
+an icon from the shared set
+The same view on the desktop and the web, through the backend.
+The left column lists them;
+Every yes/no can be taken back with Ctrl+Z.
+what the open classifier's page is showing
+the classifiers or the spec models
+the try card runs as you type
+the first one is open until another is picked
+the training's progress, while there is one
+a class's hue, spread round the wheel (the memo palette's order)
+the classifier as a file:
+written to Downloads on the desktop, a download on the web
+the CPU (the reference, bit for bit the same everywhere), the GPU in exact precision, or the GPU fast (plain operators, within a hair of the CPU)
+a job's device in words
+points of a line through (x, y) pairs fitted to w × h
+a beat after typing stops
+a class's probability for a text, with yes and no (Ctrl+Z takes either back)
+the buckets (every text filed by class and sureness in tenths, a column or a class opening its texts, index again);
+texts near a text by meaning or by verdict;
+other classifiers that must say a class for a verdict to stand, and the texts they disagree on);
+the growth it went through.
+the growth and training it went through, newest first
+the texts filed nearest a text, by what the classifier represents them as (meaning) or by how it judges them (verdict)
+a key as it is, else a text
+every text filed by class and sureness, in tenths;
+a cell opens its texts
+the validators (classifiers that check this one) and the texts they disagree on
+the classes of the classifier picked as a validator
+The filters view's builder, as the Bevy app's filtersui.rs had it:
+what the builder offers to add
+the expression without empty groups (a group with nothing in it lets everything by)
+"not" and remove, for a condition or a nested group
+your saves on the left, the ingredients chosen in the middle (each with its effect:
+Forging makes a new save;
+connect to an anend hub (its address and an app token from your profile there), browse the saves and classifiers people share, take one in, and share the open save or a classifier.
+On the desktop a taken save lands in the saves folder and opens;
+the setting, else (on the web) the page's own
+a hub save into this app:
+the desktop downloads it into the saves folder and opens it;
+the web asks its own hub to take it into the workspace
+the open save's file, to share
+every class's probability as a bar in that classifier's colours, the class it's put in, and a yes or a no that teaches it.
+Used by the notes editor (the classifier button, Ctrl+I) and the reader's opened item.
+a bare note key is taken as a note's)
+every list as a card with its figures, the list read as one text, its letters as a vector and its members as chips with their sums (× takes one out);
+how alike every two lists are (the cosine of their letter vectors);
+a chosen list the bar fills (Enter adds what's typed, remembering it when new), or, with none chosen, Enter chooses a list by its name or starts one.
+A list's own page (its name clicked) renames it, edits its members a page at a time, and holds its pictures.
+Unlisting takes two clicks, and Ctrl+Z brings a list back.
+Enter adds what's typed to it
+the text joins it (remembered when it's new)
+a list by that name:
+else a new list headed by the text, chosen
+how alike the lists are:
+the cosine of each two lists' letter vectors (1 is the same letters in the same proportions), as the Bevy app's grid
+a list as the Bevy app showed it:
+its name and key, choose and unlist, its figures, the list read as one text, its letters as bars, and its members as chips with their sums
+The results header (the sum and its pfR line) and the texts sit in a centre field whose width is dragged at its edges and stays centered;
+the sidecar and the toggles are on the strip over the bar.
+underlines by the opposite sum's group with seedCLR;
+the sum (or what was searched)
+the number pfR runs on
+the text under the pointer, for its words' types under the hover line
+the list commands typed in the bar
+the list and its members
+Enter in the bar (weum's term onkeydown)
+the right-click menu's edit and tag
+gsearch the text's sum, saturate it, toast its key
+the text itself, when it's there
+a class's name (and words after it) finds the texts most likely in that class;
+any other text, the texts the classifier reads most like it
+the texts it counts in the class;
+when there are none, the likeliest
+the ordinal sum, gsearched in ordinal
+the reversed sum, gsearched in reversed
+each word type's short label
+the spaces and punctuation between words kept as they are
+the words stay inline text, so a text's own underline (the gematria colour of its reversed-sum group) runs under them untouched;
+the type is the label under each word, in its colour, never an underline
+the word types shown, each in its colour, with how many of each
+the lists, and the picked list (Shift+click, or a new one) even while it's empty
+the search filter (the square at the strip's right):
+what it keeps of the results
+each key's class name under the colouring classifier ("unsure" when in none)
+whether the search filter keeps a text
+counts of a thing among the shown texts, most first
+what the shown texts are (their kinds, their words' types, their classes under the colouring classifier, which were given a verdict, the classifier's bias), each a chip that keeps only those
+its numbers go into the bar when clicked
+the tooltip has the word types on a line of their own
+the middle button opens a note in the editor
+each class shown, its colour, and how many texts it has here
+a classifier's tints as each key's colour (its class's, fainter when less sure;
+grey when it's in none) and the legend:
+each class, its colour, how many texts it has here
+the classifier colouring the memory view, picked in the strip, and its search mode
+a circle per sum bucket, sized by how many texts it holds
+the strip over the bar:
+the sidecar (the bar's sums) and the toggles
+Every view stays mounted (the space keeps its scene, each view its page and scroll) and loads when first shown;
+only the open one is visible.
+a view is built the first time it's shown, then kept
+what a view adds at the command bar's right end:
+the memory view's and the space's sums and toggles, the other views' counts and hints
+registers a view's key handler with the shell
+a toggle as small as an icon or a letter;
+its name and key in the tip
+a section that folds, remembered by name
+Filters are kept in the save's settings by name.
+remade when a kept filter or the bar fills it (its inputs aren't bound while typing)
+long titles show in full on hover.
+The layout is a grid, so the editor takes whatever room the window gives it.
+keeps the highlighting layer scrolled with the pad (once per page)
+Enter again on the same words opens the first note found
+leaving the view keeps a titled note's changes, as the Bevy app did
+a note another view asked to open (the reader's edit)
+how many notes there are, or match
+read mode shows the note as saved (its replacements and views put in) until it's edited
+with replacements, the note as written
+the colours, painted under the textarea's transparent glyphs
+not bound to the signal while typing (a round trip per key would drop letters typed fast);
+its text is put in when a note opens
+the text before the selection, the word, the text after, and the word's alternatives
+a word's synonyms and registers come from the lists it is in, those keeping the text's sum first
+(the text before the selection, the word, the text after) and its alternatives
+puts a new text into the pad and the signal
+the pad's text around its selection (the word under the caret when nothing is selected)
+a key as it is, a filter by its name, else the first text with those words
+the save's pictures as thumbnails, added by dropping files on the panel or picking them, put into lists (by name, beside the texts of the list with that head) and taken out, deleted with two clicks.
+In the lists view, for all the save's pictures (with a picker of the picture lists) and on a list's page for that list's (what is added there goes into it).
+the list whose pictures these are (None:
+list names to offer when putting a picture into a list
+the picture list shown when this is the save's panel ("" for all)
+the panel's list gets them too
+on the desktop a file's path works too (where the system's file dialog doesn't)
+bumped to empty the path field (it isn't bound to the signal, so fast typing keeps every letter)
+notes and texts as cards, a page at a time;
+short texts flow in a tight grid.
+The bar narrows by words.
+each note's dates, for its card (as the Bevy reader showed them)
+how long ago, in words
+when it was written and last changed (any entry)
+its rows and a sample
+choose the file, see what's in it, import, done
+into a save that isn't open:
+a weum file's rows read:
+on to the step that shows what's in it
+the desktop reads the file at a path typed in (when a file dialog isn't at hand)
+a file handed to the viewer (the web build's backups)
+the key pressed while it waited for one
+every action and its key:
+a key another action holds where both work is swapped with it;
+kept in the settings file
+the colouring classifier's class), space.js runs the free spread and draws, and they talk over one eval channel.
+As the Bevy app's space had it:
+the texts in the room (memory texts and notes), by key
+what the details window shows:
+the text under the pointer, else the selected one
+each text's bucket axis Q, for the shared-bucket underlines
+how many blocks and textures the save has
+the sliders (defaults and the person's changes)
+the letters of a text as counts a–z, for the "same letters" weight
+the bucket axis Q (r, or s when reversed) and how many of the room share it
+the gematria grouping underline, the memory view's colour for it
+the maps kept in the save:
+the memory texts of the map, with what they are
+the space's words (the Bevy terminal's commands)
+an edit started from the right-click menu or Enter on a text
+forget the memory under the key typed
+the room's texts to a file:
+a download on the web, a file in the data folder on the desktop
+the engine and its channel
+the save's blocks, whenever another save opens
+the room's colour and ink from the settings
+the flying keys as the keymap binds them
+the physics, whenever a slider moves
+the engine flies and hops on the rest itself
+the last address, opened the first time the space is shown
+puts a text in the bar to edit:
+Enter puts it back (a memory under its key, a free text in its place)
+an undo took back blocks just added, or put back blocks just deleted
+its triangle in the top bar
+what the engine needs to draw the textures:
+a text's grouping colour (its labels' underline), a picture's thumbnail as a data URL
+the open save's blocks into the room, in place of what was there
+a hub from before blocks:
+side by side, along its width
+make blocks from the selected text, a picture or a colour;
+the selected block's place and size;
+a window over the room that moves by its title bar and remembers where it was left;
+its close button shows when the pointer is over it
+while dragging, a sheet over everything follows the pointer
+the numbers of a hovered or clicked text (the Bevy app's metrics card), each gsearching itself;
+its key, bucket and whether it's pinned
+the window's width, for placing a window at the right the first time
+every slider (double click its name:
+the keys as they're bound, and what the mouse does
+what the space adds to the command bar:
+the bar's sums, the list state, the chips
+every slider is one of space.js's PHYSICS keys, with the same default
+no spiral and no anchors left in the engine
+A model's page has its spec in a JSON editor (checked as you type, a broken rule shown with where it is;
+candidates judged by its critics, each critic's score shown (Enter in the bar writes after the bar's text).
+what the models view shares with this tab:
+the open model, whether "new" is open, and a count the bar's Enter bumps (the write card writes after the bar's text)
+a judge a generator can use:
+a model's name, its head and a class of it
+a template's spec, filled in with the save's lists (by name), its picture lists and a judge if there is one
+written by hand so the fields keep the order docs/models.md gives them
+the template as it is)
+a judge for a writer:
+a trained classifier, else a spec model's classify head
+a spec's JSON in a monospace textarea, checked a beat after typing stops:
+a broken rule shows under it with where in the spec it is;
+the spec's heads, for their class names
+every head's answer on the command bar's text, as you type
+write after the bar's text
+the score is a weighted mean log;
+its exp is a geometric mean probability
+Stats for the whole app:
+every tag (on any entry, texts and notes alike) with its count;
+click picks one, Ctrl or Shift+click adds or drops it;
+The entries carrying them show beside.
+The bar narrows the tags;
+A save as plain JSON, keys and all:
+what the web app keeps in the browser when it runs without a hub, and how a save moves between the browser and a hub's workspace.
+their classes are lists by key, and merged lists get fresh keys.
+fills an empty save with a bundle, keeping its keys
+a bundle's contents by what they are, for merging into a save that has its own keys
+merges a bundle into a save:
+what's new gets fresh keys there
+merging the same again adds nothing;
+into another save it all arrives
+Classifiers kept in a save:
+Training data is read from the save's lists when training starts, so a classifier follows its lists as they grow.
+Training is split so a caller can run it off its own thread without holding the save:
+the desktop app can do the same.
+how many yes/no answers on a classifier can be taken back
+how many history events a definition keeps (oldest dropped first)
+the feedback it logged, and each classifier it wrote as it was before (its definition's JSON and its weights in base64)
+a list, by its head's label, and the list's name when it was chosen
+an upstream classifier whose steered outputs this one takes as extra inputs
+something that happened to a classifier:
+a training run, growth, a list written
+the head's metrics after training
+a list of texts that are none of the classes:
+an extra class for a single-label head, all labels off for a multi-label one
+definitions saved before it was optional had them on
+bumped by every write of the weights
+one yes or no a player gave
+the memory or note judged, when it was one (a label)
+end to end through the classifiers it builds on
+the class's unsteered probability before and after
+the sizes on offer, smallest first
+seconds for a few lists of short memories
+training options that suit a preset
+the largest batch a training run takes
+a class by name (or its index as text)
+the last training event, if any
+a fresh, untrained classifier for this definition;
+the extra inputs of every text
+the version of the weights it started from
+why it runs on the CPU when a GPU was asked for
+a training run's progress as the caller sees it
+start from new weights instead of the trained ones
+a GPU this build or machine doesn't have falls back to the CPU, saying why
+what yes/no feedback is about:
+a text, and the memory or note it came from
+removes a classifier, its weights and its feedback;
+refused while another classifier builds on it
+the classifier as stored (untrained weights when it has none yet), its steering from the definition
+a classifier and everything it builds on
+a list's members as stored
+what a classifier reads of a memory (its text) or a note (title and markdown)
+every memory and note a classifier can rank:
+the training examples a definition's lists give now
+snapshots what a training run needs
+more threads than the machine has only slows it (and each is a real thread)
+writes a finished run's weights and its history (keeping steering and anything else changed meanwhile)
+the yes/no answers before it can't be taken back past new weights
+prepare, run and commit in one go (for callers that may block)
+every classifier it wrote gets its definition and weights back as they were, and the feedback leaves the log (so training no longer replays it);
+the texts it filed under the classifier answer as before, so the memo stays
+a classifier's feedback log, oldest first
+texts from the classifier's lists to replay beside feedback, so one yes or no doesn't drag the rest along
+yes or no on one classifier's own weights:
+a few small steps, kept in its feedback for replay, and logged
+yes or no end to end:
+through the classifiers it builds on, each link scaled by its coupling;
+every classifier reached is written back
+returns the head and the member count
+a note as a classifier reads it
+a classifier in a bundle:
+writes bundled classifiers as they are (their lists keep their keys on import)
+validators after every classifier is in, since they name each other
+new definitions build without gematria;
+ones saved before the field existed keep the channels they were made with
+two lists of short texts, and a note in the first
+a short run, then everything back out
+the replayed list members outweigh one feedback of weight 1 on this byte-only (no gematria) tiny model
+a bundle carries them, and old bundles without them still read
+training arguments from a caller are kept in bounds, and steering is checked
+presets referring to presets many times over run once each, and a loop brought in by a bundle is an error rather than a hang
+the default preset on three lists of 50 short memories
+deterministic, matches a direct read, buckets filled
+an empty "any of" is refused
+a validator gating everything out
+round trip into another save, corrupt input refused
+a weights file whose header claims huge shapes is refused before allocating
+how fast this computer trains models of a ladder of sizes, and how the cost of a forward pass grows with sequence length.
+Limits here are measured compute, not convenience:
+a size is suggested when the training it implies fits the budget on this machine.
+one rung of the size ladder
+(tokens, milliseconds) for one forward pass of the second rung at that length:
+attention makes it grow faster than linearly
+the sizes measured, smallest first
+bigger ones would not be suggested)
+what a model is for, to size it
+seconds of training the person will wait
+the largest measured size whose training (examples × epochs × maxlen tokens at the measured rate, scaled for the window length by the forward-pass curve) fits the budget;
+the smallest rung when none does
+longer windows cost more per token
+The engine's own models read bytes and keep doing so;
+this is only the vocabulary a pretrained checkpoint was trained with.
+text in decomposed form may split differently than the reference implementation);
+Anything else (WordPiece or Unigram models, other normalizers, BPE dropout, word prefixes and suffixes) is refused with its name.
+text to token ids and back
+id → its piece as written in the vocabulary
+the metaspace character read as a space, and leading spaces stripped
+composed text is the common case;
+longest first, so a token that starts another one doesn't hide it
+the decoder decides how pieces read back
+the id of a piece or added token, as written in the vocabulary
+added tokens written in the text are recognised (as the reference implementation does).
+Nothing is added at the start or end:
+splits at added tokens, applying their lstrip/rstrip
+a linked list of symbols and a heap of candidate merges
+the bytes one token stands for (no leading-space stripping)
+the leading space a SentencePiece-style tokenizer adds is taken off again
+a tokenizer with the tokens a model starts sequences with and ends them with
+put before every window (BOS, or the end token for models without one)
+the end of a text:
+what training windows end in and the generative head's END
+tokens that also end generation (chat models have several)
+whether a token ends generation
+every byte is a token, a few merges, two special tokens
+special tokens in the text, bytes outside ASCII
+read as text, the special token is just bytes
+every byte string round trips
+unknown characters fall back to their bytes
+a generated token after a prompt keeps its space
+Other data as bytes, so the same transformers (classifiers and generators) work on it:
+numbers as fixed-width text, pictures as sequences of patch codes.
+Plus a minimal PNG writer (no compression, no dependencies) to look at generated pictures.
+an image is cut into square patches (8×8 pixels by default) and each patch is replaced by the nearest entry of a codebook learned from the training images (k-means, integer arithmetic, so the same images give the same codebook on any machine).
+Fixed width means every digit has a fixed position, which a model learns more easily than free-form numerals.
+the largest magnitude that fits
+the encoding of x, clamped to what fits and rounded half away from zero
+the nearest double to the decimal written
+an RGB picture, 8 bits a channel, rows top to bottom
+each pixel as an s×s block
+the end of a row of patches
+an entry left without patches keeps its value
+the code of the nearest entry (squared distance, ties to the lower code)
+per row of patches, the codes, then ROW
+bytes back to a width×height picture:
+rows restart at each ROW, a short row is padded with code 0, a long one is cut, codes past the codebook read as code 0
+zlib with stored (uncompressed) deflate blocks, so a few lines replace an image library;
+files are about the raw size
+a toy picture for demos and tests:
+uniform patches are reproduced exactly when the codebook holds them
+the IHDR's CRC as zlib's crc32 gives it
+each may take some earlier classifiers' steered outputs as its extra inputs, so the graph is acyclic by construction.
+the loss on the judged classifier backpropagates through its extra inputs into the classifiers that produced them, scaled by each edge's coupling (0 leaves the upstream classifier alone).
+one classifier's head feeding another classifier
+one node on a tape:
+traces of its windows, its extra inputs, mean logits, steered outputs
+a forward pass through the nodes a result depends on
+what one classifier had to do with a result
+gradnorm over the sum of them
+for the judged classifier's direct inputs:
+the judged class's unsteered probability before and after
+per node, the gradient norm of the last step (0 for nodes not reached)
+the trunk never sees the extra inputs) from one pass, its upstream run first
+each step backpropagates the loss through the graph (edges scaled by coupling) and steps every reached classifier's own optimizer.
+The feedback is remembered by the judged classifier.
+a head's outputs over some texts as lists:
+for each class, the indices of the texts that are members of it
+the same feedback again gives the same bits
+the upstream classifier is left alone
+Where a run's numbers are computed.
+The CPU is the default and the reference:
+the GPU in exact precision:
+the CPU's bits on a device the probe finds exact
+the GPU with plain operators:
+faster, within a small tolerance of the CPU
+whether this build and machine can run on the device;
+a net's training state on the device (uninhabited in builds without the GPU)
+one token at a time through a generative net:
+the logits for the next token
+a net uploaded for inference on the device (uninhabited without the GPU)
+the generator is fine-tuned on samples weighted by reward (critic scores relative to their mean, or a person's yes/no):
+likelihood for good ones, unlikelihood for bad.
+how each next byte is picked
+otherwise logits are divided by it
+keep the fewest most likely bytes whose probabilities reach p (1:
+bytes to write at most (the prompt not counted)
+a byte that ends the output (kept in it);
+picks a next token (an index into the logits) from them;
+Ties go to the lower token.
+reweights scaled next-byte logits in place, given the bytes written so far
+a vocabulary token can end past the limit
+anything that reads bytes into steered head outputs
+one node of a graph of classifiers, its upstream run first
+a regression value in lo, hi:
+a running sum a constraint can bound
+a critic's verdict that must (or must not) hold:
+what a kept candidate must satisfy
+sampling-time steering by the critics
+how many of the generator's most likely next bytes the critics weigh;
+the rest are dropped on guided steps
+added to each weighed byte's scaled logit:
+critics cost a pass each per weighed byte
+otherwise only the written bytes
+where the generator decodes (the CPU unless asked;
+critics stay on the CPU)
+the draw's index (its random stream)
+the generator's log-probability of the bytes
+every critic's outputs and score on some bytes
+each candidate is a function of (generator, critics, opts, its index) only, so the thread count changes nothing
+the generator on the device, when asked (one upload shared by every candidate)
+the scaled logit is raised by strength·score, so temperature still applies
+the candidates that pass the constraints, best score first (ties:
+a sample with how good it was:
+a person's yes on a sample
+candidates that broke constraints get −scale
+rewards with a smaller magnitude are skipped
+weight of the replayed examples (the generator's own training texts, which keep it from drifting off its data)
+sizes chosen for debug-build speed)
+a classifier trained on it
+must contain 'd' and be at most 6 bytes
+guidance raises the mean critic score
+the rewarded samples get likelier, the penalised less likely
+a person's yes and no
+the same WGSL is valid WebGPU, so a browser build can use it later).
+runs every kernel on random data on the device and on the CPU and reports whether the device matched bit for bit.
+The CPU path stays the reference.
+how the shaders do their arithmetic
+every product laundered so it cannot fuse into an add, division and square root correctly rounded in integer arithmetic:
+the CPU's bits on an IEEE device
+the driver may fuse multiply-adds and approximate ÷ and √
+a place in a buffer:
+the buffer and an offset in floats
+an f32 as a WGSL hexadecimal literal holding exactly its value
+the shader source for a precision:
+constants, the arithmetic, then the kernels
+the process's GPU, opened on first use;
+model sizes are bounded by the device, not by us
+the largest buffer the device takes, in f32s
+a zeroed buffer of n floats (at least one, as bindings cannot be empty)
+f32 has no padding and any bytes are valid u8s
+a list of kernel dispatches (and buffer copies and reads) submitted together, in order;
+each dispatch sees the writes of the ones before it
+submits everything and waits for the reads (and only then returns)
+causal limits row r's chain to p ≤ t0 + r (attention over the positions so far)
+with a trace, x̂ and rstd too
+softmax of rows in place;
+causal rows (nq per group, first at position t0) stop at their position
+row) and the stride between batched products
+product z reads this operand's slice z / per (B only)
+the weights uploaded once, each window's embedded tokens uploaded, every block run as a list of kernel dispatches in one submission, and only what the CPU needs read back (the final normed rows, the generative logits).
+The embedding lookup, pooling and the small classification heads stay on the CPU (they are a sliver of the work);
+the decoder keeps its key/value cache on the device.
+a block's weights on the device
+one block's activations for a window of n (the training trace keeps one per block)
+errors when a tensor is larger than the device takes
+writes a net's weights (same shapes) over the uploaded ones, as after an optimizer step
+one window through the trunk:
+the final normed rows n × d and, when asked and the net has one, the generative logits n × genout
+blocks of the same shape share one set of activation buffers
+pooled rows, the side vector and the extra inputs:
+one token at a time with the keys and values of every block cached on the device, the same restarts when the window fills.
+Each step is one submission and one read of the logits.
+keys and values kv × maxlen × dh
+one step's buffers (a single row)
+a decoder that has read the start token and these token ids
+the cache rows past the position are never read, so nothing to clear
+one that does not is still usable within the reported tolerance.
+the largest difference in units in the last place
+every kernel matched bit for bit
+compares device values against the reference
+runs the probe on a device in one precision
+tiled and per-output paths, A plain and transposed, fresh and accumulating
+backward from the device's own forward, so the comparison isolates the backward
+softmax rows (full and causal) and its backward
+rotary positions, forward and back
+tests skip, they do not fail
+zero-initialised output projections would hide the blocks
+past maxlen both restart from the last half window
+the embedding, pooling and head gradients are computed on the CPU into the caller's per-example buffer.
+a block's gradient tensors on the device
+the CPU tensors these mirror, in the same order
+backward's scratch for one window of up to maxlen rows
+a net's training state on the device
+the net's current weights uploaded, the sums zeroed
+the trunk backward on the device
+a group's key and value gradients, its heads summed in head order
+Growing and shrinking a trained classifier.
+Widening and deepening preserve what the classifier computes, so training picks up where it was:
+Same output up to rounding.
+fresh query, key and value weights, and zero rows in the output projection, so the new head adds exactly 0 until it learns.
+accepted only if validation accuracy holds within a tolerance, otherwise reverted.
+grow while accuracy is under target or falls (after new data), prune when it has stayed above target with margin for several evaluations.
+whether heads can be added or pruned:
+not when keys and values are grouped or the projections have biases (imported pretrained models)
+their output rows are zero
+per block, how much each SwiGLU unit and each head matters on some texts
+Texts run in parallel and add up in text order.
+share of each block's SwiGLU units to drop
+also drop each block's least important head when it is under half the mean
+how much validation accuracy may fall for the pruning to stand
+widen every block's feed-forward
+one more head in every block
+one more block at the top
+try pruning (kept only if accuracy holds)
+the validation accuracy aimed for
+accuracy above target + margin counts as spare capacity
+evaluations in a row with spare capacity before pruning
+a fall from the best accuracy this large counts as falling
+evaluations to wait after any change
+feed-forward growth per widening, as a share of the current width
+what counts as falling starts over
+what to do after an evaluation with this accuracy
+returns a line for the log (empty for Keep)
+a round of a growth cycle:
+what training did, the evaluation, the decision
+and they still train, and survive a save
+removing every unit but a few:
+whatever happens, the rule holds
+a pruning that must fail (no tolerance and a crippled net) is reverted
+pruning to a subset keeps the kept units' function
+a fall after new data grows again even above target
+2 adds optional feature channels, NUM tokens, causal models and the generative head;
+version 1 files read as version 2 files with the gematria channels on
+the largest shapes a file may claim, so a damaged or hostile header can't make the reader allocate more than the file itself could hold
+the shape limits for models with their own vocabulary (imported pretrained models), set far past any open checkpoint:
+they only stop a hostile header from asking for absurd tables that the weights' size check can't see (the rotary table)
+a model's tokenizer as saved:
+the tokenizer of a model with its own vocabulary
+the reader is careful, but a file is data:
+a panic anywhere in it is a bad file
+reshape the blocks to what was saved, then fill every tensor
+names a classifier by what it computes:
+its shapes, heads and every weight, but not its steering or history (the same weights steered two ways hash the same)
+how many weights a header's shapes hold, refusing shapes past the limits above
+windows overlap by at most three quarters:
+a stride of 1 on long windows would make every long text cost thousands of times its length to read
+the steering is read for every head, its bias zipped with the logits
+Two summation rules cover everything:
+- matrix products add their products one by one in ascending order of the contraction index, onto the output's current value:
+Each output element is its own chain, so the kernels vectorise across outputs (register tiles of 4 rows × 16 columns) without reordering any chain, and threads split output rows.
+Every multiply is rounded before its add (no fused multiply-add on any path).
+A GPU backend (wgpu/WebGPU compute shaders) would implement the same list.
+To stay bit-exact there it must keep each output's chain in order (one thread per output element, looping over p;
+storing the product through a bitcast or an integer round trip before the add is the usual guard).
+turns the explicit SIMD paths off (true) or back to what the CPU offers (false);
+for benchmarks and the tests that hold both paths to the same bits
+kernel families the profiler times
+times add up over all threads
+buffers given back on this thread, for reuse:
+a forward and backward pass allocate the same sizes over and over, and fresh pages from the system cost more than the arithmetic that fills them
+a zeroed buffer of n floats, reusing one this thread gave back when it can
+the AVX2 build of the same code vectorises it 8 wide
+a row-major rows × cols A
+products above this many multiply-adds split their rows across a pool
+y and b row-major with rows of m
+any split gives the same bits;
+whole tiles keep the kernels busy
+A packed for the register tiles:
+column strips outside, row tiles inside:
+of row r, scalar chains
+the transpose of a row-major rows × cols matrix
+softmax of each row in place:
+each output's chain written out plainly
+a product big enough to go parallel
+plus the seeded random numbers and hashes.
+Nothing here calls the platform's libm.
+Each function documents its operation order;
+a port must keep it, one rounding per written operation, never fusing a multiply and an add.
+Branch free, so loops over it vectorise.
+a key from several parts, order sensitive:
+Fisher–Yates from the back
+FNV-1a over bytes, with a seed folded in first
+How well a head does on labelled texts:
+squared and absolute error and R² for regression heads.
+Sums run in example order in f64, so the numbers are as deterministic as the predictions.
+the confusion matrix as aligned text, rows the truth
+transformer encoders over a text's bytes and its gematria, written here from the matrix products up and deterministic to the bit.
+they are the backend boundary a GPU implementation would replace.
+what a classifier remembers about itself besides its weights
+optimizer steps taken over its life
+training examples per class, per head, from the last training run
+the most recent feedback, replayed by later feedback steps
+growth and pruning events, oldest first
+the declarative spec the model was built from, and anything it learned besides weights (a picture codebook);
+how many feedback examples a classifier keeps
+optimizer moments carried between feedback calls (not saved)
+one text through a classifier, windows averaged
+per head, the mean of the windows' logits
+the mean of the windows' pooled vectors
+a model with pooled heads and optionally a generative head (causal configs only)
+class names of a head
+the input gains in force:
+the windows of any bytes (causal windows for a causal model)
+every window of a text through the net with the given gains, averaged in window order;
+windows run in parallel on the pool, or a lone window's big products do
+every head's steered output on a text
+every head's steered output on any bytes
+the same outputs, bit for bit on a device the probe finds exact
+steered outputs from window-averaged logits
+many texts in parallel (each text's windows in order on one thread);
+the pooled vector of a text, windows averaged:
+the bias metric for a head over some texts:
+how the encoder's token vectors become one vector
+the vector at the CLS token
+the mean over all tokens
+CLS and mean side by side (twice as wide)
+a learned query's softmax-weighted sum over the tokens
+how strongly each input channel is mixed in;
+the letter value embedding added to each token
+the word sum embeddings added to each token
+the text level side vector at the heads
+inputs from other classifiers at the heads
+width of one attention head (even, for the rotary pairs)
+heads per block at creation;
+blocks may grow or lose heads later
+SwiGLU hidden units per block at creation
+tokens per window, CLS and SEP included
+bytes between window starts on long texts
+RMSNorm on each head's queries and keys before the rotation
+whether the heads see the side vector
+width of the inputs from other classifiers
+residual output projections start at zero (each block starts as the identity)
+off for new models, on in files saved before it was optional
+each position sees only itself and what came before (needed by a generative head)
+a token row plus value × a learned direction
+0 means one per query head
+how rotary frequencies are stretched for longer contexts
+rotary frequency scaling, as pretrained checkpoints declare it
+for tests and CI only:
+a few thousand weights, so the suite runs in seconds in a debug build.
+Not a size to offer anyone;
+Like every preset it has no gematria channels;
+the gematria features (letter channel, word sum channels, side vector) on or off
+tokens in the embedding table
+bytes and END, or the vocabulary
+trains on a laptop in minutes
+bytes of text per window
+width of the pooled vector
+one class of K, softmax
+any of K labels, a sigmoid each
+K real values, squared error
+their count is the head's width
+how much this head's loss counts when heads train together
+next byte (or END) at every position of a causal model
+how much its loss counts when heads train together
+SwiGLU gate and up projections d × ff, down ff × d
+what a weight tensor is, which decides weight decay
+rotary angles per position and pair:
+the rotation a configuration asks for
+rotates one row as position t
+byte and special token embeddings vocab × d
+attention pooling query d (empty for other poolings)
+the NUM value direction d (empty without numbers)
+the width of the query, key and value projections together
+tensors new since the first file version draw last, so older shapes start as before
+a net of the same shape, all zeros:
+a gradient or optimizer moment
+what each output is called:
+the pooled heads, then the generative head
+every weight tensor in the fixed order the optimizer and the file format use
+empty when unused, so version 1 files read unchanged
+the transposed weights backward needs, computed once per optimizer step
+causal attention for position t:
+adds a bias to every row (nothing when it is empty)
+how a forward pass runs:
+dropout on with its key, or inference
+rotated keys and values per key/value head (one per head unless grouped);
+everything one window's forward pass leaves for backward
+pooled vector (after the pooling dropout)
+block l's SwiGLU activations n × ff
+block l's attention outputs before the projection n × heads·headdim
+one window through the trunk and every head;
+The pool parallelises big products only.
+this group's keys and values, normed and rotated once
+the probabilities after t stay 0, which backward relies on
+the generative head's logits at every position, n × GENOUT:
+row t predicts the token after position t
+a group's key and value gradients, summed over its heads in head order
+embeddings, token by token in order
+One token (a byte, or a vocabulary token for a pretrained model) at a time through a causal model with a key/value cache, giving the generative head's logits for the next one.
+When the window is full the decoder starts over from the start token (CLS, or the lexicon's) with the last half window.
+the tokens in the current window (after its start token)
+rotated keys and values, rows of headdim
+a model with a vocabulary encodes them with its tokenizer)
+a decoder that has read the start token and then these token ids
+bytes then END, or the vocabulary)
+the bytes the current window holds
+the tokens the current window holds (after the start token)
+reads one more byte (byte models)
+the channels of this position, as a causal window computes them
+the token every window starts with:
+CLS, or the lexicon's start
+END, or the lexicon's end token
+whether a generated index ends the output
+the bytes a generated index (or window token) stands for
+tokens back to bytes (special tokens of a lexicon left out)
+bytes as they are, or ids from the lexicon (prompt and continuation encoded apart)
+every window of a token sequence, and their starts
+a window for this net's sequence length
+central differences against backward for a sample of every tensor's weights
+nonzero gains everywhere, and a little noise on the zero-initialised ones
+a causal model with a generative head, numbers and no gematria:
+finite differences on every tensor through the generative logits and a pooled head
+a little noise at this eps
+decoding with the cache equals the full causal pass, bit for bit, including across a window restart
+past maxlen the decoder keeps the last half window
+Unicode properties use std's tables:
+in a class it must be a single item
+matches one character (for the iterative repeat)
+an empty iteration can't make progress;
+every non-overlapping match, leftmost first, as char ranges
+the matches of a string as substrings
+A small persistent thread pool.
+Which thread runs which index varies;
+callers only hand out independent work (each index writes its own output), so results never depend on the schedule or the thread count.
+threads std reports for this machine, at least 1
+one job at a time;
+claims and runs indices of the current job until none are left
+a slice that pool tasks write disjoint parts of
+Pretrained open models in the engine:
+From there it is an ordinary engine model:
+Anything else in the config that would change the computation is refused with the field named.
+how a pretrained model is brought in
+classifier heads to put on the trunk (new, untrained), besides the generator
+windows no longer than the sliding window see exactly what it lets through
+the engine configuration (biases and QK-norm as the checkpoint has them)
+BOS (or the first end token) to start, the end tokens to stop
+the engine model with the checkpoint's weights
+a pretrained model folder as an engine model
+a synthetic checkpoint's shapes (tests only:
+tiny so the suite stays fast;
+the loader itself has no size limits)
+what the reader will see after the dtype round trip
+the cached decoder gives the same bits as the full pass
+SentencePiece tokenizer with BOS, plain heads
+a missing or misshapen tensor names itself
+the engine's paths on a pretrained model
+a byte-model critic judges what the pretrained model writes
+fine-tuning on a text makes it likelier;
+the classifier head trains alongside
+the file keeps the vocabulary, the tokenizer and every weight
+checks name what a pretrained spec can't set
+the weights travel in the file, not the folder
+Tensors are read on demand (seek + read), so a checkpoint never has to fit in memory twice;
+Integer and quantised dtypes are refused by name.
+the element types read (and written)
+shift the full mantissa (with its hidden bit) into place
+one tensor's entry in a header
+byte range in the file (header included)
+its header read, tensors read on demand
+tensors by name, and the metadata strings
+one safetensors file or the shards of an index
+a sharded checkpoint from its index file
+every tensor the index names must be in its shard
+a tensor as f32, checked against the shape the caller expects
+the format pads the header with spaces to a multiple of 8
+a single file without an index
+the primary way to make a model.
+the newest spec version this build reads
+separates the input from the output of a pair in a sequence-to-sequence generator
+an optional input feature channel (all off unless listed)
+the ordinal, reversed and Atbash sums of the word a token is in, and digit roots
+a vector of named numbers, written as fixed-width text for the trunk and also given to the heads as they are
+on when there is a generate head
+any of several labels (a sigmoid each)
+a value of the model's input type
+where training data comes from:
+texts to learn to write;
+it learns to write the output after the input
+each scaled to the input's width and height
+examples written into the spec
+what a critic wants of its head
+another model judging what a generator writes
+the model's name, resolved when generating
+seconds of training to size an "auto" trunk for
+where the trunk comes from:
+a pretrained model folder instead of new weights
+where training and generation run:
+a model's starting point other than fresh weights
+the spec's classify/multi/regress heads go on its trunk, new
+the save (the entry store implements this), or memory
+by default the two lists side by side, in order
+lists and tags in memory
+the value, its head, its class or values
+a broken rule in a spec, and where:
+empty for the whole spec)
+parses JSON and checks it
+every rule a spec must keep, with the first broken one in words
+a data item's head and target, the path's field that is wrong and why
+parses a spec's JSON and checks it, saying where a problem is:
+the engine configuration this spec asks for
+a model made from a spec:
+the engine's network, and what it learned besides weights
+what the generate head wrote after the input, with the spec's sampling
+a fresh model for a spec;
+an existing classifier as an instance of a spec (sizes and features from its configuration, heads from its heads)
+an input value as the bytes the trunk reads, and the heads' number inputs
+generated bytes back as a value of the input's type
+every head's answer on an input, by head name
+what a generator continues from:
+a sequence-to-sequence model's input and PAIR
+the spec's data queries as training examples
+an "auto" trunk is sized for the data found)
+a critic's model as a generator's critics see it:
+what judges, and its heads (in the order its outputs come;
+this model as a critic
+the kept ones come best first
+a model, a stored classifier stack) and the sampling given;
+every candidate drawn comes back, the ones that keep the constraints first, each part best score first (ties:
+a continuation is judged whole (the start and what was written);
+a sequence to sequence model's output alone
+an old-style classifier converts
+the player's knobs on a trained classifier, which training never touches.
+Per head a logit bias per class, a temperature and a decision threshold;
+for the whole classifier a gain per input channel.
+Applied at inference only, with a bias metric that says how far the knobs move predictions from the model as trained.
+added to each class's logit after the temperature
+logits are divided by it:
+the probability at which a text counts as a member (of the top class, or of each label for multi-label heads)
+multiplies the trained channel gains
+a head's output on a text:
+what the model said, and what the steering makes of it
+window-averaged logits as trained (with the steered input gains)
+classes this text is a member of under the threshold
+the steered reading of a head's logits:
+how far steering moves a head's predictions from the unsteered model, and how skewed the classes were in training
+summed over labels for multi)
+share of texts whose decision changed (top class, or any label's membership)
+mean change in each class's probability
+largest over smallest class count (∞ when a class had no examples)
+compares the steered and unsteered outputs of one head over the same texts
+Whole-classifier tests on the tiny preset:
+learning, determinism across thread counts and kernel paths, the file format, windows, steering and feedback.
+a file whose windows nearly all overlap would make reading long texts endless
+the mean of the windows' own logits
+with the gematria channels, so the side vector's gain has something to change
+channel gains change the inputs, and so the outputs
+saved by the engine before format version 2 (gematria channels then always on)
+one trunk, two outputs trained together:
+a class head and a generative head, each example carrying both targets with per-head loss weights
+it keeps them, and answers with exactly the bits it gave then
+From data to model input.
+no vocabulary is learned or stored.
+Optional feature channels run next to each token.
+In a causal model (one that generates) the word channels are the sums of the word so far, so no token sees a byte after it.
+the token's embedding is its row plus value × a learned direction
+tokens without NUM (the table size of models without number inputs)
+rows of the letter value table:
+length of the side vector
+one window of a text, ready for the embedder
+empty when there are none
+each token's word channels are the sums of its word up to and including it (what a generator may see)
+the value at token t (0 when the window has no numbers)
+every window of some bytes;
+labelled examples, AdamW with linear warmup and cosine decay, global-norm clipping, dropout, label smoothing, class balancing, early stopping on a validation split with the best weights kept, and feedback (a yes or no on one result) applied as a few incremental steps.
+Threads compute examples side by side into their own buffers, a wave of one example per thread at a time, and the buffers are added in order, so the thread count changes the speed only.
+not this class (pushes its probability down, the rest up)
+a distribution over the classes
+one label known to hold or not, the others unknown
+the class an example is about, for balancing
+whether the target is for the generative head
+how much this example counts (feedback can weigh more than a list member)
+more targets on other heads of the same model, trained in the same pass
+an example over bytes that need not be text
+a text for the generative head to learn whole
+another head's target in the same pass
+the generative loss of one window:
+every token is a class (the end token included)
+whether a text falls in the validation share:
+a seeded hash of its bytes, so the same text always lands on the same side
+indices of training and validation examples
+AdamW's moments for every weight
+whether the moments still match the net's shapes (they don't after growth)
+one step, per element in this order:
+Tensors update in parallel on the pool (each element is independent).
+everything, or the heads only when the trunk is frozen (params end with the heads' pairs, then num, then the generative pair)
+one window of a training text:
+the whole text if it fits, else a crop placed by the key
+a causal model's crop ends in SEP only where the data ends
+every window of a text forward, and the mean of their logits (in window order)
+windows forward, and the mean of their logits (in window order)
+the loss weight of the head a target is for
+how an example's gradient is taken
+weighted mean loss, no label smoothing
+per head, when the data had examples for it
+the generative head's mean cross-entropy in bits per predicted byte
+the accuracy of the first head with metrics
+the cosine ends at lr·minlr
+share of all steps spent warming up
+share of examples held out for early stopping (by text hash)
+evaluations without a better validation loss before stopping
+keep an exponential moving average of the weights with this decay (0:
+evaluation, early stopping and the result use the average
+where the forward and backward passes run (the CPU unless asked;
+what the progress callback sees
+this step's weighted training loss
+the step whose weights were kept
+the kept weights on the validation examples
+checks every example against the classifier's heads
+class counts and balancing weights, per head
+a player's yes or no on one result of one classifier
+the text is of this class (or has this label);
+the example it amounts to for a head of this kind
+replayed examples per step, drawn from earlier feedback and the given data
+the probability of each fed-back class before and after (unsteered)
+the unsteered probability of a feedback's class
+applies yes/no feedback on this classifier's own weights:
+newer feedback on the same text, head and class supersedes the old
+a few AdamW steps at a flat rate on whole examples:
+count each predicted byte once, in the first window holding it
+A baked classifier on its own:
+taking a module in maps each class to a list by name (a new list, or the one headed by a memory of that text), or to lists the caller picks.
+sizes are checked before anything is allocated, every part must parse and match its definition (classes, head, inputs' widths, hash), names and numbers must be sane, and a panic anywhere is a bad file.
+the largest module read by default (a hub may take less)
+a classifier's definition as a module carries it:
+classes by name, not by list
+0 when it is only referenced
+the classifier itself (the last part)
+a module read and checked
+each part's weights file, when bundled
+carry the classifiers it builds on (else they're referenced by hash)
+a trained classifier (and what it builds on) as a module file
+a bundled part's weights against its definition
+replayed feedback examples must fit the net (a hand-made file could hold others)
+what taking a module in did
+the classifier's name in the save
+each class of the classifier and the list it went to (key, and whether it's new)
+a name for the classifier itself (its own name if left out, numbered when taken)
+the save's classifiers by weights hash
+takes a module into the save:
+its classifiers (reusing any the save has with the same weights) and lists for its classes
+everything is checked before anything is written
+as the weights were trained (retraining keeps the channels)
+its lists are the save's own already
+a short summary of a module, for pages and listings
+the classifiers it builds on, and whether each is bundled
+include and exclude texts by what classifiers say of them, nested with and / or / not, beside the word, sum, list, tag and kind conditions the searches already have.
+Filters are kept in the save as presets (materialized views, their own list system), can refer to each other, and their results can be written out as lists.
+a classifier can be attached as a validator of another.
+Its verdict gates the other's outputs (a text the validator doesn't pass counts in none of the other's classes) or weighs them (the other's probability times the validator's), in filters and in search;
+how deep presets may refer to presets, and how many conditions an expression holds
+the class must be its top one too
+the words search (with weum's variations)
+a gematria sum in a range:
+a member of a list (by its head's key)
+notes with these tags (all of them, or any)
+the classifiers it asks (presets left unexpanded)
+a short reading of it, for lists of presets
+the list its results were last written to (a label)
+how many texts it found the last time it ran
+a text the validator doesn't pass is in none of the classes
+the probabilities are multiplied by the validator's
+a classifier that checks another:
+a classifier's verdict on a text with its validators applied
+the probabilities after gating or weighing
+each validator's probability for its class, in order
+sets the validators of a classifier (checked:
+the validator's own validators would make a loop when it is checked by them
+takes a deleted classifier out of every validator list (and its own)
+a classifier's rows on texts with its validators applied
+saves a filter (new, or replacing one by that name), after checking it reads
+classifiers and classes exist, presets don't loop, numbers are in range, and it isn't too big
+an empty "any of" could only ever match nothing
+how strongly its classifier conditions hold (the weakest of them;
+the classifiers it read, and those it skipped because they aren't trained
+a classifier read over a run's texts:
+its classes, threshold, and checked rows
+the texts a run looks through, and what's worked out about them once
+the presets being worked out, to catch one that comes back to itself
+which texts match, and the score of each (the weakest positive class condition)
+over the entry graph the sums are its own (weum's), and atbash is gone
+runs a saved filter and writes what it finds as a list headed by the memory "filter:
+returns the head and the count
+notes the last run's count on a preset
+every preset, for a bundle
+a bundle is data from anywhere:
+only its size is checked here (what it reads may come with it), the rest when it runs
+The floating point the spread needs, the same everywhere.
+correctly rounded, so at most an ulp from any decent libm, and exact on easy points
+saves as ingredients, combined into a new save the way Oblivion's altar combines effects into a spell.
+Each ingredient has an effect:
+its memories, notes and lists join the result - take away:
+whatever it shares with the result leaves it (a subset) - keep shared:
+only what the result shares with it stays  applied in order, then the filters (words, sum ranges, which kinds of things) narrow it.
+Saves are compared by content, not by key:
+a memory is its text, a note its title and body, a list link the two things it joins.
+Writing gives everything fresh keys in the target, so the same machinery merges a save into the open one.
+a thing in a save, by what it is rather than where it's kept
+memory texts, each once, in the order they were kept
+drops list links whose ends are gone
+applies the ingredients in order to an empty result
+what the result is narrowed to
+words a memory or note must contain;
+inclusive ranges of a memory's ordinal and reversed sums
+whether the sum ranges narrow anything
+a sum range is about memories;
+notes only answer to words
+puts contents into a save, skipping what it already has;
+new keys after the highest one there
+lists, between the keys things have now
+copies the space's maps and settings from one save to another (a forged save takes its first ingredient's)
+silent left, so its list link did too
+forging the subset into a fresh save
+only what's new goes in, and again adds nothing
+What a save holds besides its entries:
+its spec models' definitions and its pictures, each in tables of the save's own database, so they travel with the file (copies, renames, the hub's share and take) and in its backups and bundles.
+the pictures of list "cats" sit beside the texts of the list whose head is "cats".
+a picture's details (its bytes are kept apart)
+what it was called when added (a file name), or what it was named since
+when it was added, milliseconds since the Unix epoch
+every picture's details, oldest first
+false when it was there already (its details are left as they were)
+takes a picture out of the save and its lists;
+the ids of a list's pictures
+the lists a picture is in
+all the texts in one JSON, everything else in another.
+the forgotten keys in reuse order;
+rows that were replaced (their key was taken), keeping the old text as a version
+entries stored partly as refs to others
+rows without times get the import time.
+borrowing applies in key order, so a variant borrows from shorter texts imported before it.
+shorter texts first within the order keys give, so variants find their sources
+the texts, and everything else
+restores a backup into this store (meant for an empty one;
+entries under the same keys are replaced)
+mimes first, so the texts' mime names map to the same ids
+past versions, newest first per entry:
+each is a delta against the one after
+a backup's spec model records and pictures (rows that don't read are skipped)
+blocks placed in the space, each showing a texture (a text of the save, one of its pictures, or a plain colour) tiled over its faces.
+The values sort by the id (big endian first), so a key's instances come back in the order they were made.
+Moving or scaling a block replaces its value;
+A region query reads every value once (no spatial index yet:
+the values are small and a save's blocks number in the thousands, not millions).
+A block's size is in the space's units;
+the side of one texture tile, in space units
+a side at least and at most
+how far from the origin a block may be
+a text of the save, by its entry label
+a picture of the save, by its content hash
+the key a texture is kept under
+a key's kind and texture
+where a block is and how big:
+its centre and its sides
+the id (big endian, so values sort by it) and six little endian f32s
+finite, inside the world, sides within bounds
+how many times the texture repeats across each face:
+how the blocks table is used:
+places several blocks in one write;
+moves or resizes blocks (each its whole new transform) in one write;
+the ones that weren't there are skipped, the rest come back as they are now
+the ones that were there, as they were (to put them back)
+the ids already in use are skipped
+every block, or (with a region) those whose boxes meet it, by id
+the instances of one texture
+how many blocks and distinct textures
+move and scale replace the value;
+the next id is past the highest
+Caps lock and the last lead start off at the start of every run, so a call's arguments decode on their own.
+A body (what an entry stores) is a run with a 3-bit header holding how many padding bits end its last byte;
+an empty body is zero bytes.
+how deep calls may nest inside a body (decoding recurses per level)
+a function (or any) entry, its body evaluated with the arguments
+a nested run (a call's argument)
+the bits ran out inside a token
+a reserved escape, a bad case token, a run without a lead, a bad digit
+how many continuation bytes a UTF-8 lead byte has
+switch the lock when the case run ahead is long enough to pay for it
+a run of characters sharing the last lead byte
+packs a run into a body
+how many bits a text takes inside a run (no body header), for weighing borrowing
+how many bits a ref to this id takes
+unpacks a body into its run
+the text of a body with no refs or calls in it
+the run's text with refs and calls left out (for a source view or a quick check)
+every entry a run refers to or calls, nested arguments included
+merges adjacent texts and drops empty ones, so equal runs compare equal
+any scalar value at all
+deep nesting is refused, not a stack overflow
+The measures an entry is filed under:
+which number a text is filed under
+everything a text is filed under
+Evaluation is a loop over an explicit continuation stack, so a Rust stack overflow can't happen.
+A call in tail position replaces the frame that makes it instead of pushing a new one, so tail recursion runs in constant stack, bounded only by fuel.
+Limits, each an error rather than a panic:
+fuel (one unit per step, plus the size of builtin work), the continuation stack depth, the size of any one output, and how long a text a builtin may be asked to make.
+evaluation is pure, so naive recursive Fibonacci runs in linear time.
+where the interpreter reads entries' bodies from
+steps an evaluation may take
+continuation frames that may be waiting at once (non-tail nesting)
+bytes any one output (or argument) may grow to
+non-tail calls nested deeper than the limit
+an output grew past the limit
+a ref or call names an entry that isn't there
+a builtin was given something it can't use
+how many calls one memo frame remembers (a tail loop adds one per turn)
+a call's value, to remember under these keys
+an entry's rendered text, to cache and unmark
+the rendered text of an entry
+evaluates a run with no arguments
+calls an entry with arguments
+the last piece of a concat in tail position continues the frame
+concat(x) in tail position is x in tail position
+a call with its arguments evaluated:
+a tail call from a frame that has emitted nothing has that frame's value:
+remember it under the memo just below (up to a few keys, so loops stay flat), or put one there
+a small way to write runs by hand (tests, examples, the backup's readable form)
+the same entry twice, not nested, is fine
+naive Fibonacci, linear thanks to the memo
+the same through a REF to an entry that calls it
+nor is the memo filled by a tail loop
+too little fuel is an error, not a hang
+text before a tail call
+the output limit stops a runaway
+the call is an argument
+a body calling itself forever through a non-tail position
+and through a tail position:
+The same entry can stand in several places and several maps;
+identical placements collapse into one edge.
+smallest-three quantisation alone isn't idempotent.
+When two components are nearly equal, the decoded largest can come out smaller than another decoded component, so re-packing picks another index (or rounds a component one step off after normalising).
+Both ends of a round trip land on the same cycle, so they agree, and the chosen value maps to itself.
+one placement of an entry in a map
+a quaternion, x y z w
+IEEE half precision, rounded to nearest even
+one smallest-three quantisation, without the fixed point search
+still a value both ends agree on
+the cases the first version got wrong:
+two or more components nearly equal
+and again from the decoded value, any number of times
+every 32-bit pattern a corrupt value might hold re-packs to a fixed point
+The content hash index is keyed by the hash's top 14 bits;
+A probe returns every id whose check matches;
+the content hash's bucket bits
+the ids of a chunk's set, ascending
+encodes ascending, distinct ids of one chunk
+adds and removes ids (all of one chunk) in an encoded set;
+the letter frequency term of a frequency key:
+its hash's top 14 bits, so a row holds a few anagram classes and readers check the key (most texts are alone in their class, and a row per class would be a row per entry)
+what an entry is filed under in the derived indexes
+the content hash of a plain entry's text
+an entry this one refers to or calls (what editing that entry must look after)
+words again, ordered, for prefix search
+creation buckets, ordered, for time ranges
+dense sets become bitmaps, and stay exact
+a small set is about a byte an id
+The query model the lenses read through:
+and the figures for a stats view.
+the relation's own order (a list's member order, notes oldest first), when the query has a relation;
+every filter given must hold
+entries with at least three quarters of the query's words
+entries filed under a sum
+entries with a sum in an inclusive range
+anagrams of a text (the same letter frequencies)
+entries carrying a tag entry
+entries related to an entry
+how many matched in all
+ids found under at least three quarters of the query's tokens, in the order they turn up
+candidates by the frequency key's hash, checked
+the first set keeps its order (relation order, search order)
+the figures of a stats view
+what a text measures (for a sidecar)
+packed body bytes of every entry
+The bytes an entry, a past version and an edge are stored as;
+the body holds only text and refs that borrow (its rendered text never changes unless the entry itself is edited);
+such entries are in the content hash index
+the body has refs (borrowed parts for a plain entry, transclusions or calls otherwise)
+how many borrow hops rendering may take (a hint for borrowing)
+mime types every store knows;
+milliseconds since the Unix epoch
+varint mime, prefix and suffix, then the packed middle)
+the target id (big endian) then the payload
+where each weum key length starts among the ids
+the first id with no weum key
+weum's key for an id:
+Ids past the four byte keys are their 8 big endian bytes.
+how weum shows a key:
+a polynomial hash over bytes, so any prefix or suffix hash comes from prefix hashes
+the poly hash of every prefix:
+the content hash the dedup index is keyed by, from a poly hash and a length
+id n + 1 is weum's next key after id n
+a u32 (little endian) with a bit per occupied slot, a varint length per occupied slot in slot order, then the records in slot order
+one slot's record straight from a block row, without decoding the rest
+See the module doc for the tables.
+the names of every table, for stats
+the relations every store knows;
+the payload is a u64 big endian order key
+an entry (from) carries a tag (to, an entry of mime tag whose text is its name)
+posting lists in redb tables
+only entries, edges and history on disk;
+the indexes are rebuilt into memory at open
+bytes a borrowed form must save to be used (a borrow also costs a mentions row)
+how many borrow hops a source may already have
+milliseconds since the Unix epoch from the system clock (0 where there's none, as in a browser without a clock passed in)
+a stored entry with its id
+what deleting an entry took away, enough to put it back
+one version of an entry
+when this version was written (its edited time)
+the tables a reader reads postings from
+what both a read view and a write transaction can read;
+most of the API is here
+the record bytes of an entry
+the ids under a term
+edges from an entry in a relation:
+the entries with an edge in a relation to this one
+every relation an entry has edges in, out and in
+an entry's run as stored (refs and calls unresolved)
+calls a function entry with arguments
+the entries whose text is exactly this (and of this mime, when given)
+every version of an entry, newest (the current one) first
+the members of a list, in order
+the entries a note is noted on
+what a map places, and where
+any reader as the interpreter's source
+a consistent read of the store
+the last few block rows read
+ids created in a bucket range (callers filter exact times)
+every value of a sum mode with how many entries have it, ascending
+every entry with its record, ascending by id
+the last id handed out (or imported)
+the forgotten ids waiting to be reused, in the order they'll be handed out
+index changes made in a transaction, not yet written
+borrowing on or off for this transaction (imports turn it off and on)
+what an entry is filed under
+how a text is to be stored
+the last id handed out (or imported), if any
+the id of a mime type, registering it when it's new
+the plain text of a borrow candidate, if it can be borrowed from
+never changes what it renders to
+prefixes end before a space, longest first
+suffixes start after a space, longest first, after the prefix
+each source costs a row in the mentions index too
+saves a text as a new entry (or returns the entry that already has exactly this text and mime);
+returns its id and whether it's new
+an entry already there is replaced as an edit would (its versions kept)
+a template or function) as a new entry;
+changes an entry's text, keeping the old version
+the plain mentioners of an entry with their texts as they render now
+the structured mentioners of an entry (templates, notes with replacements) with their texts as they render now
+indexes the transcluders of a changed entry by what they render now
+stores the borrowers' texts again after a source changed, so they render the same
+removes an entry, its edges and its versions;
+its id is reused later unless a structured entry still refers to it
+puts a deleted entry back as it was, under its id
+removes one edge with this payload;
+a note on an entry:
+saves the note's text (markdown) and links it
+adds a member at the end of a list (nothing when it's there already)
+puts a list's members in this order (members not named keep their place after)
+the tag entry of a name (made when it's new)
+gives an entry a structured body without keeping a version or touching its times (restores);
+entries borrowing from it are stored again
+writes a past version row (restores)
+marks an id forgotten (restores), so it's handed out again
+sets the last allocated id (restores)
+storage use of one table
+branch keys and other metadata
+bytes of pages the table holds
+how full its leaf pages are with keys and values
+a store held in memory (tests, the browser until a persistent backend is plugged in)
+the browser's, or a test's
+a write that's durable only once a later durable one commits (bulk work)
+the terms of every entry, from entries alone
+rebuilds every derived index from the entries (after a format change, or to check)
+keeps the derived indexes on disk or only in memory (rebuilt at every open)
+gives back space freed by deletes and rewrites (after imports, or on demand)
+a store in memory with a clock the test moves
+the same text of another mime is another entry
+forgotten ids are reused before new ones, in weum's key byte order
+the old words are gone from the index, the new ones are in
+the past versions are deltas:
+saving it again finds it (the hash is over the rendered text)
+a variant of the variant borrows from it
+editing a source doesn't change what borrows from it
+and the indexes still find them by their whole text
+a now becomes a longer text that starts with b's text:
+a ref to a deleted entry is an error, and the id isn't reused while referred to
+removing one placement keeps the reverse edge while the other stands
+deleting x drops its edges both ways, and undelete puts them back
+three quarters of the words must be there
+writes keep the memory index current
+the disk tables are emptied in memory mode
+new ids continue after the highest imported key
+more of everything, then a backup
+and a second backup is the same as the first
+What kind of text an entry is, told by its pattern:
+every kind, in the order they're offered
+the kind a text looks like
+its bytes in the text and its type
+the type of a word from its form alone, when its form tells
+every word of a text with its type:
+a name by its capital (not the first word of a sentence);
+the rest by a small lexicon, then by their endings, then by what comes before them (after a determiner or adjective:
+A tagger of rules, not a model:
+good enough to show what a text is made of.
+a text's word types in a line, for the hover line:
+every type is one of the list, and the byte ranges point at the words
+anend's saves, shared by the desktop app and the hub:
+each list's members, their sums added up and averaged, the list's gematria read as one text, and its letters as a 26-long vector, so lists can be compared like embeddings (the cosine of every two lists' vectors).
+the list head's own text
+all the members' texts as one, for measuring the list whole
+letter counts over all members, normalised to length 1
+texts' letters as a unit vector
+every list, in the order their heads are stored
+the cosine of every two lists' letter vectors, rounded to thousandths
+Turns markdown into simple layout blocks of styled text runs, which the UI then renders with Bevy text spans (there is no HTML to lean on in a native app).
+merge runs with identical styling
+a paragraph inside a list item continues that item
+the gematria idea generalised from letters to any data.
+the byte sums of some data
+how many bytes were summed
+the value of one byte:
+the sum of n's decimal digits
+the byte sum of each word (runs of bytes that are not ASCII whitespace or punctuation;
+each classifier's steered outputs on the save's memories and notes, memoized, so searching by a class, filtering on classifiers, colouring texts by class and finding near texts don't run the network again.
+A fifth bucket family beside the ordinal, reversed, atbash and frequency ones:
+a text is filed under its classifier's class and how sure it was.
+the classifier's and its upstream classifiers' weight versions and steering.
+Training, feedback, a steering change, or a retrain upstream give a new stamp, and the first use under it drops the old rows.
+A row also keeps a hash of the text it read, so an edited note (or a forgotten memory's key given to a new text) is read again.
+the same weights, steering and text give the same bytes on any thread count.
+a text is filed under each class it's a member of (the steered threshold:
+the class number texts in no class are filed under
+bumped when what a row holds changes
+rows written per transaction while indexing
+the band a probability falls in
+a text's hash as rows keep it
+one classifier's memoized reading of one text
+steered probabilities, one per class
+the classes it's in under the steered threshold
+the buckets it's filed under
+what a stack's outputs depend on:
+every classifier's weight version and steering
+one row from one pass of the stack
+rows for many texts at once, in parallel, in the texts' order
+rows read through the network now
+rows that were there already
+a member of a bucket
+what near texts are found by
+texts it reads the same way
+drops a classifier's rows and buckets (it was deleted or replaced)
+the rows kept for these refs, current or not (None where there's none)
+rows for texts (each a ref and what the classifier reads of it):
+the kept ones when current, the rest read now on the pool and kept
+false if the classifier moved on meanwhile
+fills a classifier's rows ahead of use:
+how many current rows a classifier has
+every current row of a classifier, with its ref
+texts that changed since they were read are left out (and counted as the second value)
+how many texts each bucket holds:
+ties by key, so the order is fixed
+a text that changed since is skipped (indexing again brings it back)
+the classifiers chosen to index a memory or note
+chooses the classifiers that index a memory or note (none:
+every memory and note with chosen classifiers
+takes a deleted classifier out of every choice
+drops every row and bucket of one classifier inside a transaction
+a fixed sand-friendly set for the first ten, then golden-angle hues
+how a text is tinted by a classifier:
+the tints of some memories and notes by a classifier, filling what isn't memoized (a ref with no text gets None)
+weum's memory, as tables in the notes database:
+memories are short texts under compact byte keys, and both memories and notes are indexed into the search tables.
+Memory keys come from weum's allocator:
+one byte keys first, then two, three and four byte ones, reusing the keys of forgotten memories before minting new ones.
+what a text is filed under in each gsearch bucket
+a sum for the numeric buckets, a frequency key for the letter table
+the texts a note is indexed by:
+its title for gematria, title and body for tokens
+shorter keys first, then by value
+stores many texts as new memories in one go;
+returns their keys in order
+the key of a memory with exactly this text, if there is one
+saturates a text unless the very same text is already a memory;
+returns its key and whether it was new
+removes a memory, freeing its key for reuse;
+drop it from every list, and drop the list it named
+refs found under at least three quarters of the query's tokens
+the ordinary search of the memory view:
+every query weum's variation expansion produces, results merged in the order they turn up
+everything filed under a key in one of the gsearch buckets
+how many texts share each of these reversed sums
+prefixes come from range scans of the token table
+adds many list members in one go
+every list and its members, as stored
+removes a whole list, returning how many members it had
+puts a forgotten memory back under its old key (undoing a forget)
+forgotten keys are reused before new ones are minted
+new keys continue after the highest imported one
+a forget undone gets its key back, and the key isn't handed out again
+A note is what the anend server called a "writ":
+a markdown document with a title, tags, a creation date and an edit history.
+the text shown in the editor:
+joins a title and a body into editor text
+cleans up a tag typed into the tag input
+every tag with how many notes carry it, the most used first (then by name)
+a tag listed twice on one note counts once
+the start of a note's body as plain text on one line, for previews:
+blocks a save holds at most on a shared hub (one's own machine:
+blocks one call adds or changes at most
+what a block shows, checked against the save:
+blocks as JSON, with what their textures are:
+each text once (however many blocks show it), each picture's size and name
+the fields given replace the block's, the rest stay
+the text is sent once for the two blocks showing it
+move keeps the size, scale keeps the place
+their copies are 3 further back
+a merge finds the text in the target, whatever its key there
+Training runs on a thread of its own:
+how many memories and notes a search, a list or a neighbour search looks through
+a generate head's held-out bits per byte (spec models)
+why it runs on the CPU when the GPU was asked for
+jobs by save file and classifier
+whether jobs may run on the GPU (a shared hub:
+each workspace runs at most this many trainings and indexings
+a hub's for its members
+the workspace folder a job key's save is in
+the job mustn't stay "running" with nothing behind it
+a class given by name or index
+the text a call is about:
+steering from the args over the current one:
+texts to measure the bias on:
+the classifier's own training texts, or the save's
+a list's head isn't one of its texts
+indexing jobs by save file and classifier
+the largest module taken through the app's calls
+every classifiers store open in this process, by file (redb holds a file once)
+shared with whoever has them open already (a training thread, say)
+the last holder may still be closing the file:
+its handle is gone from the map but redb hasn't let go of the lock yet, so wait a moment
+spec model records kept here by older saves move into the save
+the open save's name and classifiers
+the ops that need a save's models:
+the classifiers stay out (their lists would point elsewhere);
+a GPU asked for where there's none trains on the CPU and says so;
+a shared hub refuses the GPU unless its admin allowed it
+in the background, then waited for
+yes raises the class for that text, no lowers it
+taken back, one at a time, to exactly what it said before
+a bias towards fruit moves things, and the report says how much
+outputs become a list another classifier can train on
+it finishes, and another can start after
+merging one entry graph into another, and the forge (several saves added, taken away or kept where they agree, then narrowed by a filter).
+An entry is known by its mime and rendered text, so the same text in two saves is one entry in the result (the target's own, when it has it);
+new entries get fresh ids and keep their times.
+Lists come along as (head, member) pairs in their order, tags with the entries carrying them, and notes-on, placements and other relations when both ends came along.
+an entry as the forge sees it:
+which of the sources it came from
+what a save (or a combination of saves) holds
+where each key a link names can be read from
+everything in a save (tag entries come with what they tag, not on their own)
+the saves in order, each added, taken away or kept where it agrees with what's so far
+what the forge's result is narrowed to
+words a text must contain;
+new memories (entries that aren't notes) and notes
+their ends come along when the filter left them out
+tags, and the relations both of whose ends came
+one whole save into another
+a save's spec models, pictures and blocks into another (a merge's second half;
+Pictures are known by their content hash, so one in both saves stays one;
+A spec model whose name the target has already:
+the same spec (its JSON as written) is the same model and nothing changes;
+Spec models arrive untrained (their weights live in the source's models file).
+a text block finds its text in the target (the entries came first), a picture block its picture
+past this many lists the grid of how alike every two are (lists² numbers) is left out
+a note shows as its title
+everything worth knowing about a text's numbers:
+how many notes and memories (entries that are neither notes nor tags) a save holds
+for each key, its sums, length, kind, word types, when it was written and the lists it is in
+every list a text is in:
+the heads of the member edges pointing at it
+about the size the app's texts are:
+half a unit per character, half a unit high
+the ops that only read, or make room:
+they work whatever a quota says
+the ops that make a save
+saved filters' results where the note names them
+a save as a bundle:
+what a bundle holds to restore:
+its texts rows (weum's or a backup's) and, from a whole backup, everything else
+candidates a generate call draws at most, on a shared hub and on one's own machine
+bytes a generate or run call writes at most on a shared hub
+weights a spec model may have on a shared hub (an estimate from its trunk)
+models kept loaded for run and generate
+without any, a shared hub loads none.
+A machine of one's own (no limits) loads any folder.
+where a spec's pretrained folder is, under the limits
+the model folders a shared hub offers (each holding a config.json)
+a spec under the limits:
+on a shared hub its pretrained folder is one the hub allows, its trunk not too big, and it runs on the CPU
+a spec fit to store:
+checked, under the limits, its name free of the save's classifiers (critics find models by name)
+an entry's text as a value of the spec's input
+what the spec's data queries find in the save, read now (a training's snapshot)
+loaded models by save file and name, with the record version they were loaded at
+the spec with its pretrained folder where it is under the limits
+the model as stored (its current spec over its trained weights), or a fresh one from the spec (a pretrained one as its checkpoint has it)
+a generated or given value as JSON:
+the input of a run or generate call:
+a picture of the save, by id, scaled to a picture model's size
+a device asked for at training time overrides the spec's;
+a GPU this build or machine lacks falls back to the CPU, saying why
+a spec model, or a classifier of the save (its head is its name)
+the spec as text works too
+trained, in the background, then waited for
+it may have finished already
+the critic is the other model;
+the same seed, the same candidates
+a generator's run writes after the input
+a classifier of the save judges too:
+its head is its name
+a spec model can't take a classifier's name
+an edit that keeps the shape keeps the weights;
+one that changes it drops them
+across reopening, the models and their weights are there
+in a bundle, out and back into a new save
+a shape change drops the weights
+one's own machine loads any folder, untrained (as the checkpoint has it) or tuned
+a shared hub only its own folders, by name
+too big a trunk, the GPU
+a save from before records lived in it:
+its models file holds records and weights;
+opening it moves the records into the save, and the trained model answers as before
+put the layout back as it was:
+the record in the models file, no fit row
+the records travel in the save:
+the same spec is the same model)
+a backup's other.json carries them
+a different "kind" in the twin, then the twin merged into notes
+a picture model learns from the save's pictures by list, and reads one by id
+pictures data needs a picture input, and a list that has pictures
+a picture's bytes at most, on a shared hub and on one's own machine
+pictures a save holds at most on a shared hub (one's own machine:
+a side in pixels at most
+a thumbnail's side at most
+what a picture file is:
+its mime and size, decoded to check it reads
+a data URL's prefix is fine too
+a small PNG of one colour
+the same bytes again are the same picture
+a path only on one's own machine
+deleted, out of its lists too
+and a merge (the same picture stays one)
+most saves one forge call reads
+every graph this process has open, by file:
+redb holds a file once per process, so a save that's still busy elsewhere (a training thread, another call) is shared, not opened twice
+the graph in a file, shared with whoever has it open already;
+a file another holder is letting go of is tried again for a moment
+a save's name made safe for a file name
+a folder of saves and the open one
+the save made when there's none
+renamed, copied and deleted with it (the hub's classifiers)
+the open save, opening the last one (or making the default) the first time
+opens another save (made when it's new)
+let go of the old one first
+lets go of a save if it's the open one
+the open one, or another opened for the call
+the open one is counted;
+others only when nothing else has them open
+a new save from texts rows and, from a whole backup, the rest
+one op of the app API:
+the texts in one file, everything else in another
+whether a file is an entry graph save (read only;
+a file that needs repair is checked on a writable open).
+For checking uploads before opening them.
+a materialized view, its results put in as a list when the note is read.
+an entry's text as written:
+None when it holds calls (a function or template made elsewhere)
+a saved filter's results (the filters view's, by name) as a markdown list
+a list wants a line of its own
+the other members of the lists a word is in, with their sums:
+the list's head (its name) stands for the others too
+an entry that refers to another:
+the note with a ref has the sums of the same note written out
+and they're found by the sum they share
+when the referenced entry changes, the note shows it and is found by its words
+saving the source again keeps the ref (not the text it shows)
+a note can't refer to itself
+alternatives from lists, the ones keeping the sum first
+a copy holds the same
+notes take away a save holding only truth
+a note reads as its title and markdown and shows as its title.
+Lists are member edges, tags tag edges.
+an entry's ref, the way the apps' keys name it
+a note as a classifier reads it:
+its title, a blank line, its markdown
+SIMD text kernels, ported from weum:
+the whitespace tokenizer and the gematria dual sum, plus the letter frequency table.
+Each kernel has an AVX2 path (picked at runtime) and a scalar path, which is also the reference the tests hold the AVX2 path to.
+For Latin letters that is the reversed value, so the SIMD dual sum covers them and only text with Greek or Hebrew in it takes a scalar pass over its characters.
+the three gematria measures of a text and its letter count
+AVX2 support was just checked
+the Atbash sum of the Greek and Hebrew letters of a text:
+lowercase once, then one compare + popcount per letter
+the frequency table as a compact key, letters in order with their counts:
+texts that are anagrams of each other share it
+a readable form of a frequency key:
+tokens are the raw bytes between delimiters, in order
+one delimiter bitmask per block, from which word starts and ends fall out as bit transitions (carried across blocks)
+a bit per byte saying whether the byte before it was part of a word
+distinct tokens in order of first appearance
+a small deterministic generator, so failures reproduce
+every byte value, at every alignment
+models made from a declarative spec.
+weights whose shape no longer matches their record are stale and unused.
+one training, as the history keeps it
+the generate head's held-out bits per byte
+per head with validation examples:
+how many weights the trained model has
+a spec model as stored
+the spec's JSON as written (checked when it was stored)
+bumped by every change (an edit, a training), so a training that started before an edit doesn't write over it
+whether it has been trained (its weights may still be missing:
+what an edit does to the trained weights
+a spec model in a bundle:
+its record and the trained model in base64
+the parts of a spec that shape the weights:
+when they change, the trained weights no longer fit and are dropped;
+every spec model with its fitting weights, for a bundle
+puts a bundle's spec models in (replacing ones of the same name);
+moves the records a models file still holds (saves from before records lived in the save) into the save, losslessly:
+each record goes in as it was, its weights stay and are marked as fitting it.
+A record the save has already under that name is kept when its version is as new or newer;
+the save's own is newer:
+the older one is kept beside it, untrained
+its weights (from before fits were kept, so they are its) go with it
+only once they're all in the save do they leave the models file
+a models file from before:
+records and weights both in it
+the save has a newer "b" already
+a's weights fit it still;
+the models file keeps no records
+a shape change makes the weights stale
+memory texts laid out by their sums.
+only ASCII letters count, so bytes do the same
+adds a node, returning its index (an existing node's if the id is taken)
+steps until still, or the step or time budget runs out;
+the hue of a bucket's underline from its Q
+the triangle a text makes:
+the angles opposite s, r and t, in degrees
+t from the left corner, s from the right one
+Note storage in an embedded redb database:
+The same database holds the memories and search tables (see memory.rs);
+every note change updates those in the same transaction.
+Every write is a durable transaction.
+bumped when what gets indexed changes, so existing databases are re-indexed
+where the classifiers' texts and lists come from, when not these tables
+how many notes and memories a save holds, read without taking it over (it can't be the one that's open)
+a save the app didn't close cleanly needs redb's repair, which only a writable open does;
+it's not open anywhere else, so repair it the way loading it would
+how many notes and memories this one holds
+indexes notes written before the search tables existed (or by an older version)
+stores a note, giving new notes a key and creation time and recording an edit time for existing ones;
+writs exported from the old server's database) as they are, keeping their keys and dates
+Where a classifier's texts come from.
+without one, a store reads its own memories, notes and lists as before.
+a list's members, in order
+what a classifier reads of an entry (a note:
+how an entry is shown (a note:
+weum's word search with its variations, in the order found
+the entry with exactly this text (made when there's none);
+returns how many members it had
+whether an entry is a note
+the texts' source, when it isn't this store's own tables
+whether a ref is a note (by its kind, or the source's say)
+one place the app reads, writes, lists and moves them, and opens saves.
+opens (or makes) a redb database at a path, on a desktop or in the browser
+hands a file to the person:
+into Downloads on a desktop, through the browser's own download in the page;
+a piece of the reduction line;
+numbers are clickable in the view
+the prime factors and their sum, times the digit sum, then the chain of (prime factor sum × digit sum) steps until it repeats, its total and digit sums
+browsing and fetching saves and classifiers, sharing one with an app token, and who the token belongs to.
+pending, approved or rejected (only a public one's matters)
+a listed one, an unlisted one by its id, or your own (with your token)
+every save and classifier of yours on the hub, private and unlisted ones too
+the login cookie would ride along on a form another site posts here (the hub's own pages share through /upload, which checks where a form came from)
+the classifiers it builds on:
+the user behind the request's app token (and only a token:
+a cookie can ride along on a request from another site, a bearer token can't)
+The app, run by the hub:
+whose saves a call works on:
+otherwise the signed-in, active member's own
+how many saves a member may keep on a shared hub
+calls that only read, or make room:
+they work whatever the quota says
+the open save's name and graph
+the open save's name and its classifiers
+one operation on a workspace;
+runs off the async threads (redb blocks)
+into the open save instead of beside it)
+every op of the app API on the graph, through a workspace
+a note on an entry
+counts, and notes by all or any of them
+listen and silent are anagrams:
+their letter vectors point the same way
+a bundle it can't read leaves nothing behind
+weum's all-of-it.json and a backup's two documents
+a member's saves stay under the quota:
+past it, only reading and deleting work
+the calls that need room are the ones not listed as making none
+The web app's side of the hub:
+the status for a refusal:
+the page when the web app wasn't built into this binary
+signed in and let in, or off to log in (or a page saying it waits)
+the router matches both here
+how many calls one member's app may have running at once, and how many sockets it may hold open:
+one person's tabs can't take every thread the hub has
+each owner's turnstile for calls, and how many sockets they have open
+too many open) or out
+runs an operation for whoever's asking
+who's asking before anything is read:
+a body from no one isn't parsed at all
+whether a request comes from one of the hub's own pages (a WebSocket carries the login cookie, so another site mustn't open one)
+a WebSocket of calls and answers
+no socket for no one (the app posts instead, and hears why)
+a workspace save to take home
+it must be a save:
+the hub's own check, on a copy
+a hub save into the workspace, beside the others or merged into the open one
+an approved hub classifier into the open save;
+its classes go to lists by name.
+one member's tabs hold at most SOCKETS sockets and CALLSATONCE calls
+Passwords (argon2), sessions (a random cookie whose hash is stored), app tokens (the same, sent as a bearer token by the app), one time login links, and a small limit on how often an address may try to log in, join or upload.
+a random url-safe secret
+a short id for a save
+a hash to check a password against when there's no account by that name, so a login for nobody takes as long as one for someone
+returns it (it's shown once, only its hash is kept)
+makes a login link's secret, good once within an hour
+who an address is, kept as a hash so the hub never stores addresses
+Sharing classifiers on the hub, beside the saves:
+people browse, star and download them, and the web app takes one into its open save or shares one from it.
+Points and badges come the same way as for saves.
+the largest module the hub reads, whatever the upload limit
+a module read and summed up, off the async threads;
+a bad file (or a panic while reading it) is an error, never a crash
+the largest classifier module taken
+reads it strictly, files it, and queues it for review (or lets it straight in for trusted users).
+an empty name or description comes from the module.
+written beside, then moved in, so a half written file is never served
+stars or unstars a classifier;
+its author gets points for it
+counts a download (or a take into a save);
+the author gets a point the first time each person takes it
+an admin's verdict on a classifier:
+deletes a shared classifier and its file
+whether a user may change or delete a shared classifier:
+its author or an admin
+takes a hub classifier's module into a workspace's open save:
+Runs on a blocking thread.
+a classifier from a workspace's open save as module bytes, everything it builds on bundled.
+a workspace with a trained classifier "kind" telling fruit from rocks
+the save stars aren't the classifier's
+taken into another save, where it predicts
+its classes became lists of the same names there, new ones
+a new version keeps its stars and downloads;
+a trusted one goes straight in
+only its author or an admin may change it
+one flipped byte anywhere breaks the checksum
+forged with the checksum fixed up:
+a huge manifest length, weights that don't match their hash, a manifest that isn't JSON
+too big for the hub
+nothing filed, nothing left in the scratch place
+the good one still goes in
+a waiting account can't share
+The classifier sharing site end to end, through the router:
+sharing from a workspace save, review, the grid and the API, downloads, taking into another save where it predicts, and the doors that must stay shut (other sites, other people, bad files, odd ids).
+saul's workspace has a trained classifier (made, then let go so the hub opens it)
+another site can't make saul share
+not in the grid, not for others to see, nor to take
+the admin panel shows it waiting
+only an admin's verdict counts
+ann takes it into her save, where it predicts
+ann can't change or delete saul's
+the API takes uploads with a token only, and refuses bad files
+it's gone, file and all
+the doors around the app and the API:
+who may post what, from where, and what every answer says about framing
+sharing a save through the API takes a token:
+the login cookie alone, which another site's form would carry, is turned away
+no one gets the app's calls or a socket
+bea does, from the hub's own page only
+nothing is framed by another site;
+the app's page runs only the hub's scripts
+the app's page has no inline script for that policy to stop
+a classifier the asker may see:
+approved ones, their own, or any for an admin
+a classifier the asker may change
+a file name for a module's download
+the new version is the author's, even when an admin sends it
+a visibility as a form sent it:
+The game in the hub:
+points for sharing saves people use, levels with titles from the scribes and cipherers of old, and badges for milestones.
+Points come from what other people do with your saves, so they can't be farmed alone:
+a download counts once per person, a star once per account, and starring your own save earns nothing.
+Shared classifiers earn the same way as saves, and have badges of their own.
+an admin let one of your saves in
+someone starred one of your saves
+someone took one of your saves for the first time
+an admin featured one of your saves
+each level costs a little more than the last
+points needed to reach a level
+the badges a user has earned, from their saves, their classifiers and what they've done
+Both are built into the binary, so the page is the same static text for everyone.
+The markdown is turned into HTML here, every text escaped and any raw HTML in it shown as text, links kept to the page's own headings and to https.
+where the guide's links to the rest of the repository go
+a heading's anchor, the way GitHub makes them, so the guide's links work in both places
+where a link may go:
+the page's own headings, the repository's files, https
+Anything else is left out, and raw HTML shows as text.
+its source and alt text
+every link to a heading finds it, and every picture is built in
+What the server does, apart from how it's asked:
+The web pages and the API both call these.
+the address people reach the server at, for links printed in the terminal
+how to reach whoever runs the server, for the about page (may be empty)
+how many bytes of saves and classifiers each member may keep on the hub, private and unlisted ones included (0:
+the terms of use and the privacy note, as markdown files (they may be missing)
+how people get an account
+anyone may join, and is in at once
+an admin lets them in (an invite code skips the wait)
+only with an invite code from an admin (or a trusted member, if the admins allow it)
+in a few words, for the about page and the admin panel
+what an uploader says about a save
+none keeps what a new version replaces (or public, for a new one)
+with a visibility as sent:
+empty keeps it, anything else must be private, unlisted or public
+whether a user may share saves and star them, and use the web app
+whether trusted members may make invites too (admins always may)
+whether a user may make invite codes
+how many bytes a member keeps shared on the hub:
+every save and classifier of theirs, private and unlisted ones too
+takes an uploaded file in:
+checks it's a save, files it, and queues it for review (or lets it straight in for trusted users).
+check a copy, so nothing outside the hub's folder is opened
+the stored record, not the caller's copy:
+stars and downloads may have moved since
+who may see a save:
+A public one that wasn't let in yet waits for an admin (private and unlisted ones skip the review);
+one let in before earns its points the first time it's public.
+the save's author gets points for it
+counts a download of a listed save;
+the author gets a point the first time each person takes it (private and unlisted ones aren't counted)
+an admin's verdict on a save
+the points come with its first approval in public (a private one's when it's made public)
+deletes a save and its file
+an admin's verdict on an account
+makes or promotes an admin from the command line and returns a login link
+approving again pays nothing more
+a trusted user's new version goes straight in
+Looking inside an uploaded save:
+it has to be an entry graph the app made (a redb file with the graph's tables and format, docs/format.md), and its counts, some memories with their sums and the note titles go on its page.
+The hub opens its own copy of the upload, and a file that makes redb fail (or panic) is turned down rather than taking the hub with it.
+how many memories and titles a save's page shows
+(the web app only checks a file is a save;
+the hub keeps what it found)
+a save copied while the app has it open (the usual case) needs redb's repair, which a read only open won't do;
+the hub only ever reads its own copy, so it may write to it
+spread the sample over the whole save rather than its first keys
+a save like the app's:
+a note "Hello" and these memories
+a redb file without the graph's tables (an old save, say)
+the app still has it open, the way it does when it shares its save
+codes that let people join.
+Admins make them, and trusted members too when the admins allow it;
+each has a number of uses and may run out after some days.
+Only a code's hash is kept, so its link is shown once, when it's made.
+A code typed at the join form counts against the address (10 an hour), so codes can't be guessed.
+the most uses one invite may have, and the longest it may last
+spaces around it and the case don't matter
+twelve letters and digits easy to read aloud, in threes of four
+where an invite's code takes people
+until used up or taken back);
+its maker or an admin
+an invite in a list
+live, used up, run out or taken back
+someone who may make invites, or a page saying why not
+your invites, and a form for a new one
+shown once, on this page
+its maker or an admin takes it back
+the join form with the code filled in
+a self-hosted server for the anend notes app.
+As a hub it's a place to share saves and classifiers:
+people join (by invitation, application or freely), share saves, star and download each other's, and earn points, levels and badges for saves others use;
+the app browses and shares through its JSON API.
+As the app's server it runs the web app on each member's own saves.
+the server's routes for a mode:
+a route the mode doesn't serve doesn't exist
+between the app and the hub:
+only when both are served
+the router with the error pages
+the join policy at start:
+else what the database keeps;
+and for a new one, invite-only
+uploads that were being checked when the server stopped
+the flags, or what the admin panel saved
+made in the first admin's name
+the web app (each member's saves in a workspace of their own) and the app's API;
+all of it, over one account system;
+the web app alone for one person on their own machine, with no login.
+a mode the build doesn't carry is refused when the server starts.
+the sharing site and its API
+the web app and its API
+one workspace and no login (implies the app alone)
+what this build carries, which is also the default mode
+refused when the build left that half out
+whether this build can run the mode
+the mode the server started in (set once, by main)
+one workspace for everyone and no login:
+a daemon on your own machine
+Through the router, for each mode:
+a member still waiting for an admin, with a session
+a GET's status, where it redirects, and its body
+every mode has the account pages and the pages about the server;
+the hub's and the app's routes exist only in their modes, and the nav offers only what's there
+the app and the hub meet only in both
+the nav and the front page follow the mode
+a missing page is the hub's own page;
+no secrets in the log's paths
+the web app needs a signed-in, admitted member:
+its page sends others to log in, and its files, calls and socket refuse them;
+the app's page says which server it's on
+logging in goes back where it was asked from, and only to this server
+the policy, codes with uses and an end, taking them back, who may make them
+only admins invite, until they let trusted members
+an invite for two, shown once
+its link fills in the join form
+two people join with it, a third can't
+the admin panel lists every invite, and takes one back
+someone else can't take it back;
+its maker (or an admin) can
+a code that ran out
+under apply, a code skips the wait;
+private and unlisted saves and classifiers stay out of every list;
+a private one is its owner's alone, an unlisted one anyone's with the link
+the public one waits, so the classifier tests' grid stays theirs
+the owner sees theirs on their own page, marked
+its owner only (not other members, not admins, not the API without the token)
+downloads of unlisted ones aren't counted, so they earn nothing
+only the owner changes it;
+going public from a member's account waits for review
+a bad visibility is refused
+its script and wasm come with the right types
+built without the web app:
+plain lines, or one JSON object a line for a log collector
+a path fit for the log:
+the secrets in login links and invite links left out
+logs each request when its answer is ready:
+No addresses or names are logged.
+an error answer with nothing in it (a refused socket, a method not allowed, a panic) gets the hub's own page, or a JSON error for the APIs
+The pages about the server itself:
+what a quota allows, for people
+where the save or classifier it's about lives
+starring, unstarring and starring again is one thing worth telling
+only point at saves and classifiers everyone can see
+a listed one, an unlisted one by its link, their own, or (for an admin) a public one waiting for a verdict
+a file name for a save's download
+what an upload form sent
+an admin can only remove, not reveal)
+what changing who sees something did, in words
+back where the admin came from, unless the save is gone
+the https certificate and key.
+Saved in server.json in the data folder;
+the hub reads it when it starts.
+a browser on the hub's own machine:
+the connection comes from loopback and no proxy passed it on (a reverse proxy on the same machine makes every request look local, so anything carrying a forwarding header isn't, whatever --behind-proxy says)
+a PEM file that holds what it should
+only a browser on this machine, not one a proxy here passed on
+Everything is JSON in redb tables, like the app's notes.
+Every build has all of it (a hub-only or app-only build reads the same database), so the parts one build doesn't use aren't dead code to fix.
+settings kept in the database (the join policy, who may invite)
+their uploads skip the review
+waiting for an admin to let them in
+empty until they set one (an admin made by a login link)
+what they wrote when applying
+the order they joined in, from 1
+who made the invite they joined with
+the first characters, so a list of tokens can be told apart
+who may see a save or a classifier on the hub
+never listed, never reviewed, downloaded by its owner alone
+listed in the grids, search, feeds and the API once an admin lets it in (everything shared before visibility existed is public)
+a private one only its author;
+an unlisted one anyone with the link;
+a public one anyone once it's approved, and its author and the admins before
+a memory from a save, shown on its page
+why an admin turned it down
+its uploader got the points for its first approval
+and for its first feature
+in the grid, search, feeds and the API's lists:
+public and not yet looked at (private and unlisted ones skip the review)
+a classifier module shared on the hub:
+what its uploader said and what its file holds
+the classifier's own name inside the module
+weights bundled in the module
+public and not yet looked at
+its key in the stars and downloads tables, apart from the saves'
+the prefix of a classifier's key in the stars and downloads tables
+a record with stars and downloads counted on it
+an id the hub made (letters and digits only), so it's safe in a file's name
+a code (kept only as its hash) that lets people join an invite-only hub
+the start of the code's hash, as hex:
+how lists and links name it
+the code's first characters, so a list can be told apart
+what it's for, for whoever made it
+it doesn't run out by time
+how many people may join with it
+why it can't be used now, if it can't
+a save id, when it's about one
+where a save's file lives
+a scratch place for uploads being checked
+fails if the name is taken
+changes a user in place
+removes a user (a turned down application)
+ends every session of a user (banned, or their password changed)
+a user's tokens, with their hashes (as hex) to revoke them by
+uses up a login link
+removes a save's record, its stars and downloads (the file is the caller's)
+stars or unstars a save;
+returns whether it's starred now and its star count
+how many saves, and how many classifiers, a user has starred
+how many saves a user has starred
+true the first time this downloader takes this save
+removes a classifier's record, its stars and downloads (the file is the caller's)
+true the first time this downloader takes this classifier
+changes the invite with this id in place
+a classifier's stars and downloads sit beside the saves', apart
+What the router tests share:
+one hub for the whole test run (it's a global, set once), people with sessions, and requests through a router built for a mode.
+Not every build's tests use every helper.
+the hub every router test shares (it's a global, set once)
+an active member with a session;
+the server as main builds it, for a mode
+the server in both modes
+a GET in a mode
+a form POST in a mode, without a cookie when it's empty
+The pages every mode has, and what they share:
+The hub's own pages are in saves.rs and clsweb.rs.
+forms post back and redirect with a one-line message in a cookie.
+what the server runs, for this request
+A page on another site can make the browser send requests to a name it controls that resolves to this machine (DNS rebinding);
+such a request carries that name as its Host.
+no framing by other sites (the admin panel's buttons can't be clicked through a disguise), no sniffing a download into a page, and addresses kept to the hub when following a link out.
+The web app's page also gets a content security policy:
+scripts only from the hub, so a note that slipped some html past the markdown renderer still couldn't run anything.
+its own scripts, its WebAssembly, and what it builds in the page (Dioxus's interop evaluates JavaScript it sends;
+pictures from anywhere on the web;
+loads the user behind the session cookie (or app token), turns away forms posted from other sites, and picks up the message left by the last redirect
+leaves a message for the next page and goes there;
+a colour for a name, from its gematria
+saves and people waiting for an admin
+the sharing site is served
+the web app is served
+the web app alone, for one person, with no login
+the asker may make invite codes
+the server's line about itself, for the pages' description
+the front page, named for what's on it
+the logged in, active user, or a message saying why not
+a save the asker may see:
+approved ones, or their own, or any for an admin a classifier in the grid
+classes not shown on the card
+a share as a whole percent, or empty
+a classifier's row in the admin panel
+one of the three visibilities, as the controls show it
+private, unlisted and public, with their icons and what each means
+the join form, with an invite code filled in when there is one
+who sent the invite, when it's good
+checked before anything is made (a wrong one counts against the address, so codes can't be guessed)
+the invite's use is taken before the account is made:
+two people can't share its last use
+as slow as a real check, so the answer's time doesn't say who has an account
+a one time link from the terminal or an admin
+the owner's own that aren't in the grid:
+private, unlisted, waiting or turned down
+who the token or session belongs to
+the admin panel (with a just-made invite link shown once, when there is one)
+a new build that changes them changes the version
+asked for with this build's version:
+keep it for a year;
+It is only a picture:
+the control it sits in carries the name (its words, or an aria-label and a data-tip when it is only the icon)
+the icon beside a form's button, by what the button says
+every icon a page asks for is in the sprite (scripts/icons.mjs makes it from assets/icons), and the sprite is only shapes
+the sprite has the whole set:
+run scripts/icons.mjs when it changes
diff --git a/core/src/grammar/mod.rs b/core/src/grammar/mod.rs
new file mode 100644
index 00000000..baa8988c
--- /dev/null
+++ b/core/src/grammar/mod.rs
@@ -0,0 +1,976 @@
+//! A proof of concept for the classifiers: finding spelling and word-choice errors in a
+//! text, and suggesting what was meant.
+//!
+//! Two small trained models, both logistic regressions with deterministic training:
+//!
+//! - the **detector** reads each word in its context and gives the probability that it is
+//!   an error: a word no lexicon knows (with what its letters look like and whether a
+//!   known word is one edit away), a word repeated by mistake ("the the"), or a word of a
+//!   confusable set ("their / there / they're", "its / it's", "then / than", ...) where
+//!   another member fits its neighbours better;
+//! - the **suggester** ranks replacements for a flagged word: known words one edit away
+//!   (a letter dropped, added, swapped with its neighbour or replaced), the confusable
+//!   set's other members, or taking a repeated word out; by the kind of edit, how common
+//!   the candidate is and how well it fits between its neighbours.
+//!
+//! Both learn from deterministic corruptions of clean text: `corpus.txt` (the project's
+//! own prose, from its docs and doc comments: 2870 sentences) has words dropped, doubled,
+//! swapped, mistyped with a keyboard neighbour, repeated and confused, and the models
+//! learn to find the corrupted words and to bring back the originals. A fifth of the
+//! sentences are held out and corrupted the same way to measure them ([`Report`]):
+//! precision and recall of the detector per word, how often the suggester's first (and
+//! first three) suggestions hold the original, and how often clean text is flagged.
+//!
+//! The lexicon is `words.fc` (the MIT licensed `word-list` package, 269 870 lowercase
+//! English words, front coded), the corpus's words, a list of contractions and, when
+//! checking a save's text, every word the save holds, so one's own names and terms
+//! aren't errors. Words with digits, or two capitals or more, are never flagged.
+//!
+//! What it is not: a grammar checker. It knows nothing of agreement or tense; its
+//! word-choice sense is the neighbour counts of a 30 000 word corpus, so it is right
+//! about common pairs ("more than", "it's a") and guesses elsewhere.
+
+use std::collections::{HashMap, HashSet};
+use std::sync::OnceLock;
+
+use serde::Serialize;
+
+const WORDS_FC: &str = include_str!("words.fc");
+const CORPUS: &str = include_str!("corpus.txt");
+
+const CONTRACTIONS: &[&str] = &[
+    "it's",
+    "don't",
+    "doesn't",
+    "isn't",
+    "aren't",
+    "can't",
+    "won't",
+    "i'm",
+    "you're",
+    "they're",
+    "we're",
+    "i've",
+    "you've",
+    "we've",
+    "they've",
+    "i'll",
+    "you'll",
+    "he'll",
+    "she'll",
+    "we'll",
+    "they'll",
+    "he's",
+    "she's",
+    "that's",
+    "there's",
+    "what's",
+    "who's",
+    "let's",
+    "didn't",
+    "wasn't",
+    "weren't",
+    "hasn't",
+    "haven't",
+    "hadn't",
+    "couldn't",
+    "wouldn't",
+    "shouldn't",
+    "mustn't",
+    "i'd",
+    "you'd",
+    "he'd",
+    "she'd",
+    "we'd",
+    "they'd",
+    "here's",
+    "where's",
+    "how's",
+    "it'll",
+    "that'll",
+    "a",
+    "i",
+];
+
+/// words easily written for one another
+const CONFUSABLE: &[&[&str]] = &[
+    &["their", "there", "they're"],
+    &["its", "it's"],
+    &["your", "you're"],
+    &["then", "than"],
+    &["to", "too"],
+    &["a", "an"],
+    &["affect", "effect"],
+    &["lose", "loose"],
+    &["were", "where"],
+    &["whose", "who's"],
+    &["of", "off"],
+    &["accept", "except"],
+    &["quiet", "quite"],
+    &["weather", "whether"],
+    &["principal", "principle"],
+];
+
+/// what a repeated word may be without being a mistake
+const MAY_REPEAT: &[&str] = &["that", "had", "is", "very", "bye", "no", "ha", "so"];
+
+const KEYBOARD: [&str; 3] = ["qwertyuiop", "asdfghjkl", "zxcvbnm"];
+
+fn neighbours(c: char) -> Vec {
+    let mut out = Vec::new();
+    for (r, row) in KEYBOARD.iter().enumerate() {
+        if let Some(i) = row.find(c) {
+            for (rr, other) in KEYBOARD.iter().enumerate() {
+                if rr.abs_diff(r) > 1 {
+                    continue;
+                }
+                for (j, d) in other.char_indices() {
+                    let shift = if rr == r { 0 } else { 1 };
+                    if d != c && j.abs_diff(i) <= shift.max(1) && (rr == r || j + 1 >= i && j <= i + 1) {
+                        out.push(d);
+                    }
+                }
+            }
+        }
+    }
+    out
+}
+
+fn is_neighbour(a: char, b: char) -> bool {
+    neighbours(a).contains(&b)
+}
+
+// ---------------------------------------------------------------- words in a text
+
+/// a word in a text: its byte span
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub struct Span {
+    pub start: usize,
+    pub end: usize,
+}
+
+/// the words of a text: runs of letters, with an apostrophe inside (it's, don't)
+pub fn words(text: &str) -> Vec {
+    let b: Vec<(usize, char)> = text.char_indices().collect();
+    let mut out = Vec::new();
+    let mut i = 0;
+    while i < b.len() {
+        if b[i].1.is_alphabetic() {
+            let start = b[i].0;
+            let mut j = i;
+            while j + 1 < b.len()
+                && (b[j + 1].1.is_alphabetic()
+                    || ((b[j + 1].1 == '\'' || b[j + 1].1 == '’') && j + 2 < b.len() && b[j + 2].1.is_alphabetic()))
+            {
+                j += 1;
+            }
+            let end = b.get(j + 1).map(|x| x.0).unwrap_or(text.len());
+            out.push(Span { start, end });
+            i = j + 1;
+        } else {
+            i += 1;
+        }
+    }
+    out
+}
+
+fn lower(w: &str) -> String {
+    w.to_lowercase().replace('’', "'")
+}
+
+/// a word that is never flagged: a name in capitals, an acronym, with digits
+fn exempt(w: &str) -> bool {
+    w.chars().filter(|c| c.is_uppercase()).count() >= 2 || w.chars().any(|c| c.is_ascii_digit()) || !w.is_ascii()
+}
+
+// ---------------------------------------------------------------- the lexicon and counts
+
+struct Lexicon {
+    words: HashSet,
+}
+
+impl Lexicon {
+    fn load() -> Lexicon {
+        let mut words = HashSet::with_capacity(280_000);
+        let mut prev = String::new();
+        for line in WORDS_FC.lines() {
+            let mut cs = line.chars();
+            let k = cs.next().and_then(|c| c.to_digit(10)).unwrap_or(0) as usize;
+            let mut w: String = prev.chars().take(k).collect();
+            w.push_str(cs.as_str());
+            words.insert(w.clone());
+            prev = w;
+        }
+        for c in CONTRACTIONS {
+            words.insert(c.to_string());
+        }
+        Lexicon { words }
+    }
+}
+
+#[derive(Default)]
+struct Counts {
+    uni: HashMap,
+    bi: HashMap<(String, String), u32>,
+}
+
+impl Counts {
+    fn add(&mut self, sentence: &str) {
+        let ws: Vec = words(sentence)
+            .iter()
+            .map(|s| lower(&sentence[s.start..s.end]))
+            .collect();
+        for (i, w) in ws.iter().enumerate() {
+            *self.uni.entry(w.clone()).or_default() += 1;
+            let prev = if i == 0 { "".to_string() } else { ws[i - 1].clone() };
+            *self.bi.entry((prev, w.clone())).or_default() += 1;
+        }
+        if let Some(last) = ws.last() {
+            *self.bi.entry((last.clone(), "".into())).or_default() += 1;
+        }
+    }
+
+    fn uni(&self, w: &str) -> f32 {
+        (1.0 + *self.uni.get(w).unwrap_or(&0) as f32).ln()
+    }
+
+    fn bi(&self, a: &str, b: &str) -> f32 {
+        (1.0 + *self.bi.get(&(a.to_string(), b.to_string())).unwrap_or(&0) as f32).ln()
+    }
+
+    /// how well `w` fits between `prev` and `next`
+    fn fit(&self, prev: &str, w: &str, next: &str) -> f32 {
+        self.bi(prev, w) + self.bi(w, next)
+    }
+}
+
+// ---------------------------------------------------------------- a word in its context
+
+struct Ctx<'a> {
+    /// the word as written, and lower case
+    raw: &'a str,
+    w: String,
+    prev: String,
+    next: String,
+    /// only spaces between it and the word before
+    spaced: bool,
+    first: bool,
+}
+
+fn contexts<'a>(text: &'a str, spans: &[Span]) -> Vec> {
+    let low: Vec = spans.iter().map(|s| lower(&text[s.start..s.end])).collect();
+    spans
+        .iter()
+        .enumerate()
+        .map(|(i, s)| {
+            let gap = if i == 0 {
+                &text[..s.start]
+            } else {
+                &text[spans[i - 1].end..s.start]
+            };
+            let first = i == 0 || gap.contains(['.', '!', '?', '\n']);
+            Ctx {
+                raw: &text[s.start..s.end],
+                w: low[i].clone(),
+                prev: if i == 0 || first {
+                    "".into()
+                } else {
+                    low[i - 1].clone()
+                },
+                next: low.get(i + 1).cloned().unwrap_or_else(|| "".into()),
+                spaced: i > 0 && !gap.is_empty() && gap.chars().all(|c| c == ' ' || c == '\t'),
+                first,
+            }
+        })
+        .collect()
+}
+
+fn confusable_set(w: &str) -> Option<&'static [&'static str]> {
+    CONFUSABLE.iter().copied().find(|s| s.contains(&w))
+}
+
+/// every string one edit from `w`: (the string, the kind of edit)
+fn edits1(w: &str) -> Vec<(String, Edit)> {
+    let cs: Vec = w.chars().collect();
+    let letters = "abcdefghijklmnopqrstuvwxyz'";
+    let mut out = Vec::new();
+    for i in 0..cs.len() {
+        // a letter that shouldn't be there: the original had it deleted... the other way
+        // round: the candidate is `w` with letter i taken out (the writer added it)
+        let mut d = cs.clone();
+        d.remove(i);
+        out.push((d.iter().collect(), Edit::Added));
+        if i + 1 < cs.len() {
+            let mut t = cs.clone();
+            t.swap(i, i + 1);
+            out.push((t.iter().collect(), Edit::Swapped));
+        }
+        for l in letters.chars() {
+            if l != cs[i] {
+                let mut r = cs.clone();
+                r[i] = l;
+                let kind = if is_neighbour(cs[i], l) {
+                    Edit::Neighbour
+                } else {
+                    Edit::Replaced
+                };
+                out.push((r.iter().collect(), kind));
+            }
+        }
+    }
+    for i in 0..=cs.len() {
+        for l in letters.chars() {
+            let mut a = cs.clone();
+            a.insert(i, l);
+            out.push((a.iter().collect(), Edit::Dropped));
+        }
+    }
+    out
+}
+
+/// what the writer did, as a candidate undoes it
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+enum Edit {
+    /// the writer added a letter (the candidate takes it out)
+    Added,
+    /// the writer dropped a letter
+    Dropped,
+    Swapped,
+    /// a key next to the right one
+    Neighbour,
+    Replaced,
+    Confused,
+    Repeated,
+}
+
+const EDITS: [Edit; 7] = [
+    Edit::Added,
+    Edit::Dropped,
+    Edit::Swapped,
+    Edit::Neighbour,
+    Edit::Replaced,
+    Edit::Confused,
+    Edit::Repeated,
+];
+
+// ---------------------------------------------------------------- the two models
+
+const DET_BITS: u32 = 16;
+
+fn fnv(s: &str) -> u64 {
+    let mut h: u64 = 0xcbf2_9ce4_8422_2325;
+    for b in s.bytes() {
+        h ^= b as u64;
+        h = h.wrapping_mul(0x100_0000_01b3);
+    }
+    h
+}
+
+fn sigmoid(z: f32) -> f32 {
+    1.0 / (1.0 + (-z).exp())
+}
+
+/// a sparse logistic regression over hashed features
+struct Detector {
+    w: Vec,
+}
+
+impl Detector {
+    fn score(&self, feats: &[u32]) -> f32 {
+        sigmoid(feats.iter().map(|&i| self.w[i as usize]).sum())
+    }
+}
+
+/// the suggester's features for replacing `c.w` by `cand`
+const SUG_N: usize = 9 + EDITS.len();
+
+struct Suggester {
+    w: [f32; SUG_N],
+}
+
+/// a deterministic generator (xorshift)
+struct Rng(u64);
+
+impl Rng {
+    fn next(&mut self) -> u64 {
+        let mut x = self.0;
+        x ^= x << 13;
+        x ^= x >> 7;
+        x ^= x << 17;
+        self.0 = x;
+        x
+    }
+
+    fn below(&mut self, n: usize) -> usize {
+        (self.next() % n.max(1) as u64) as usize
+    }
+
+    fn chance(&mut self, p: f64) -> bool {
+        (self.next() % 1_000_000) as f64 / 1_000_000.0 < p
+    }
+}
+
+/// how well the two models did on the held-out sentences
+#[derive(Clone, Debug, Default, Serialize, PartialEq)]
+pub struct Report {
+    pub train_sentences: usize,
+    pub test_sentences: usize,
+    /// per word, at the default threshold
+    pub precision: f32,
+    pub recall: f32,
+    pub f1: f32,
+    pub errors: usize,
+    pub flagged: usize,
+    pub caught: usize,
+    /// the share of caught errors whose first suggestion is the original, and whose first
+    /// three hold it
+    pub top1: f32,
+    pub top3: f32,
+    /// clean held-out text: words flagged per thousand
+    pub false_alarms_per_1000: f32,
+    pub threshold: f32,
+    /// recall by the kind of error: (caught, errors) for misspellings, confused words
+    /// and repeated words
+    pub by_kind: Vec<(String, usize, usize)>,
+}
+
+/// the trained models
+pub struct Model {
+    lex: Lexicon,
+    counts: Counts,
+    det: Detector,
+    sug: Suggester,
+    pub report: Report,
+}
+
+/// a flagged word
+#[derive(Clone, Debug, Serialize, PartialEq)]
+pub struct Flag {
+    /// byte offsets in the text
+    pub start: usize,
+    pub end: usize,
+    /// UTF-16 offsets (a browser's text field counts these)
+    pub from: usize,
+    pub to: usize,
+    pub word: String,
+    /// the detector's probability that it's an error
+    pub p: f32,
+    /// what it was, probably: (replacement, probability among the candidates); an empty
+    /// replacement takes the word out (with the space before it)
+    pub suggestions: Vec,
+    /// spelling, repeated or confused
+    pub kind: &'static str,
+}
+
+#[derive(Clone, Debug, Serialize, PartialEq)]
+pub struct Suggestion {
+    pub text: String,
+    pub p: f32,
+}
+
+pub const THRESHOLD: f32 = 0.5;
+
+impl Model {
+    fn known(&self, w: &str, user: &dyn Fn(&str) -> bool) -> bool {
+        self.lex.words.contains(w)
+            || self.counts.uni.contains_key(w)
+            || w.strip_suffix("'s").is_some_and(|s| self.lex.words.contains(s))
+            || user(w)
+    }
+
+    fn det_features(&self, c: &Ctx, user: &dyn Fn(&str) -> bool) -> Vec {
+        let mask = (1u64 << DET_BITS) - 1;
+        let mut f: Vec = vec!["bias".into()];
+        let known = self.known(&c.w, user);
+        let len = c.w.chars().count().min(12);
+        f.push(format!("k{}", known as u8));
+        f.push(format!("len{}|k{}", len, known as u8));
+        if !known {
+            let near = edits1(&c.w).iter().filter(|(s, _)| self.known(s, user)).count();
+            f.push(format!("near{}", near.min(4)));
+            let padded: Vec = format!("^{}$", c.w).chars().collect();
+            for t in padded.windows(3) {
+                f.push(format!("t:{}", t.iter().collect::()));
+            }
+            if c.raw.chars().next().is_some_and(char::is_uppercase) && !c.first {
+                f.push("name".into());
+            }
+        } else {
+            f.push(format!("uf{}", (self.counts.uni(&c.w) * 2.0) as i32));
+        }
+        if c.spaced && c.w == c.prev && !MAY_REPEAT.contains(&c.w.as_str()) {
+            f.push("rep".into());
+        }
+        if let Some(set) = confusable_set(&c.w) {
+            let mine = self.counts.fit(&c.prev, &c.w, &c.next);
+            let best = set
+                .iter()
+                .filter(|a| **a != c.w)
+                .map(|a| self.counts.fit(&c.prev, a, &c.next))
+                .fold(f32::MIN, f32::max);
+            let d = ((best - mine) * 2.0).round().clamp(-4.0, 4.0) as i32;
+            f.push(format!("cb{d}"));
+            f.push(format!("cw:{}", c.w));
+            f.push(format!("cw:{}|n:{}", c.w, c.next));
+            f.push(format!("cw:{}|p:{}", c.w, c.prev));
+            // a / an by the next word's first sound, roughly
+            if (c.w == "a" || c.w == "an") && c.next != "" {
+                let vowel = c.next.starts_with(['a', 'e', 'i', 'o', 'u']);
+                f.push(format!("aan:{}|{}", c.w, vowel));
+            }
+        }
+        f.iter().map(|s| (fnv(s) & mask) as u32).collect()
+    }
+
+    fn candidates(&self, c: &Ctx, user: &dyn Fn(&str) -> bool) -> Vec<(String, Edit)> {
+        let mut out: Vec<(String, Edit)> = Vec::new();
+        if c.spaced && c.w == c.prev {
+            out.push((String::new(), Edit::Repeated));
+        }
+        if let Some(set) = confusable_set(&c.w) {
+            for a in set.iter().filter(|a| **a != c.w) {
+                out.push((a.to_string(), Edit::Confused));
+            }
+        }
+        let mut seen: HashSet = out.iter().map(|(s, _)| s.clone()).collect();
+        seen.insert(c.w.clone());
+        for (s, e) in edits1(&c.w) {
+            if !s.is_empty() && !s.starts_with('\'') && self.known(&s, user) && seen.insert(s.clone()) {
+                out.push((s, e));
+            }
+        }
+        out
+    }
+
+    fn sug_features(&self, c: &Ctx, cand: &str, e: Edit) -> [f32; SUG_N] {
+        let mut f = [0.0; SUG_N];
+        f[0] = 1.0;
+        f[1] = self.counts.uni(cand);
+        f[2] = self.counts.bi(&c.prev, cand);
+        f[3] = self.counts.bi(cand, &c.next);
+        f[4] = crate::kinds::closed_class(cand) as u8 as f32;
+        f[5] = (cand.chars().next() == c.w.chars().next()) as u8 as f32;
+        f[6] = cand.chars().count().abs_diff(c.w.chars().count()) as f32;
+        f[7] = self.counts.uni.contains_key(cand) as u8 as f32;
+        f[8] = (cand.chars().count() as f32).ln_1p();
+        let k = EDITS.iter().position(|x| *x == e).unwrap_or(0);
+        f[9 + k] = 1.0;
+        f
+    }
+
+    fn sug_score(&self, f: &[f32; SUG_N]) -> f32 {
+        f.iter().zip(self.sug.w.iter()).map(|(a, b)| a * b).sum()
+    }
+
+    fn suggest(&self, c: &Ctx, user: &dyn Fn(&str) -> bool, n: usize) -> Vec {
+        let cands = self.candidates(c, user);
+        if cands.is_empty() {
+            return Vec::new();
+        }
+        let scores: Vec = cands
+            .iter()
+            .map(|(s, e)| self.sug_score(&self.sug_features(c, s, *e)))
+            .collect();
+        let m = scores.iter().cloned().fold(f32::MIN, f32::max);
+        let z: f32 = scores.iter().map(|s| (s - m).exp()).sum();
+        let mut ranked: Vec<(usize, f32)> = scores.iter().enumerate().map(|(i, s)| (i, (s - m).exp() / z)).collect();
+        ranked.sort_by(|a, b| b.1.total_cmp(&a.1).then(a.0.cmp(&b.0)));
+        ranked
+            .into_iter()
+            .take(n)
+            .map(|(i, p)| Suggestion {
+                text: recase(c.raw, &cands[i].0),
+                p,
+            })
+            .collect()
+    }
+
+    /// the words of `text` the detector flags at `threshold`, with suggestions; `user`
+    /// says whether a (lower case) word is one of the save's own
+    pub fn check(&self, text: &str, user: &dyn Fn(&str) -> bool, threshold: f32) -> Vec {
+        let spans = words(text);
+        let ctx = contexts(text, &spans);
+        let mut out = Vec::new();
+        for (s, c) in spans.iter().zip(&ctx) {
+            if exempt(c.raw) {
+                continue;
+            }
+            let p = self.det.score(&self.det_features(c, user));
+            if p < threshold {
+                continue;
+            }
+            let repeated = c.spaced && c.w == c.prev && !MAY_REPEAT.contains(&c.w.as_str());
+            let kind = if repeated {
+                "repeated"
+            } else if !self.known(&c.w, user) {
+                "spelling"
+            } else {
+                "confused"
+            };
+            let mut start = s.start;
+            if repeated {
+                // taking it out takes the space before it too
+                start = text[..s.start].trim_end_matches([' ', '\t']).len();
+            }
+            out.push(Flag {
+                start,
+                end: s.end,
+                from: text[..start].encode_utf16().count(),
+                to: text[..s.end].encode_utf16().count(),
+                word: c.raw.to_string(),
+                p,
+                suggestions: self.suggest(c, user, 3),
+                kind,
+            });
+        }
+        out
+    }
+}
+
+/// a replacement written the way the word was: Capitalised or not
+fn recase(raw: &str, s: &str) -> String {
+    if raw.chars().next().is_some_and(char::is_uppercase) {
+        let mut c = s.chars();
+        match c.next() {
+            Some(f) => f.to_uppercase().chain(c).collect(),
+            None => String::new(),
+        }
+    } else {
+        s.to_string()
+    }
+}
+
+// ---------------------------------------------------------------- corruptions
+
+/// a sentence with errors put in: the new text and, for each word, what it was (None:
+/// left alone; Some(""): a repeated word that should go)
+pub fn corrupt(sentence: &str, seed: u64, lex: &dyn Fn(&str) -> bool) -> (String, Vec>) {
+    let mut rng = Rng(seed.wrapping_mul(0x9e37_79b9_7f4a_7c15) | 1);
+    let spans = words(sentence);
+    let mut out = String::new();
+    let mut labels = Vec::new();
+    let mut at = 0;
+    for s in &spans {
+        out.push_str(&sentence[at..s.start]);
+        let raw = &sentence[s.start..s.end];
+        let w = lower(raw);
+        at = s.end;
+        if exempt(raw) {
+            out.push_str(raw);
+            labels.push(None);
+            continue;
+        }
+        if let Some(set) = confusable_set(&w)
+            && rng.chance(0.3)
+        {
+            let others: Vec<&&str> = set.iter().filter(|a| **a != w).collect();
+            out.push_str(&recase(raw, others[rng.below(others.len())]));
+            labels.push(Some(raw.to_string()));
+            continue;
+        }
+        if w.chars().count() >= 3 && w.chars().all(|c| c.is_ascii_lowercase()) && rng.chance(0.12) {
+            let mut done = None;
+            for _ in 0..6 {
+                let mut cs: Vec = w.chars().collect();
+                let i = rng.below(cs.len());
+                match rng.below(5) {
+                    0 if cs.len() >= 4 => {
+                        cs.remove(i);
+                    }
+                    1 => cs.insert(i, cs[i]),
+                    2 if i + 1 < cs.len() && cs[i] != cs[i + 1] => cs.swap(i, i + 1),
+                    3 => {
+                        let n = neighbours(cs[i]);
+                        if n.is_empty() {
+                            continue;
+                        }
+                        cs[i] = n[rng.below(n.len())];
+                    }
+                    4 => {
+                        let n = neighbours(cs[i]);
+                        if n.is_empty() {
+                            continue;
+                        }
+                        cs.insert(i, n[rng.below(n.len())]);
+                    }
+                    _ => continue,
+                }
+                let s: String = cs.iter().collect();
+                // a misspelling that is no word (real-word errors are the confusables')
+                if s != w && !lex(&s) {
+                    done = Some(s);
+                    break;
+                }
+            }
+            if let Some(s) = done {
+                out.push_str(&recase(raw, &s));
+                labels.push(Some(raw.to_string()));
+                continue;
+            }
+        }
+        out.push_str(raw);
+        labels.push(None);
+        if !MAY_REPEAT.contains(&w.as_str()) && rng.chance(0.015) {
+            out.push(' ');
+            out.push_str(raw);
+            labels.push(Some(String::new()));
+        }
+    }
+    out.push_str(&sentence[at..]);
+    (out, labels)
+}
+
+// ---------------------------------------------------------------- training
+
+/// the models, trained from the corpus the first time they're asked for
+/// the clean sentences the checker learns from (the project's own prose)
+pub fn corpus() -> &'static str {
+    CORPUS
+}
+
+fn lexicon() -> &'static Lexicon {
+    static L: OnceLock = OnceLock::new();
+    L.get_or_init(Lexicon::load)
+}
+
+/// whether the bundled lexicon (`words.fc`) knows a lowercase word
+pub fn is_word(w: &str) -> bool {
+    lexicon().words.contains(w)
+}
+
+/// the bundled lexicon's words, sorted
+pub fn word_list() -> &'static [String] {
+    static W: OnceLock> = OnceLock::new();
+    W.get_or_init(|| {
+        let mut v: Vec = lexicon().words.iter().cloned().collect();
+        v.sort();
+        v
+    })
+}
+
+pub fn model() -> &'static Model {
+    static M: OnceLock = OnceLock::new();
+    M.get_or_init(train)
+}
+
+fn train() -> Model {
+    let lex = Lexicon::load();
+    let sentences: Vec<&str> = CORPUS.lines().filter(|l| !l.trim().is_empty()).collect();
+    type Numbered<'a> = Vec<(usize, &'a str)>;
+    let (test, trainset): (Numbered, Numbered) = sentences.iter().copied().enumerate().partition(|(i, _)| i % 5 == 0);
+    let mut counts = Counts::default();
+    for (_, s) in &trainset {
+        counts.add(s);
+    }
+    let mut m = Model {
+        lex,
+        counts,
+        det: Detector {
+            w: vec![0.0; 1 << DET_BITS],
+        },
+        sug: Suggester { w: [0.0; SUG_N] },
+        report: Report::default(),
+    };
+    let none = |_: &str| false;
+    // the corrupted training sentences, three ways each
+    let mut det_ex: Vec<(Vec, bool)> = Vec::new();
+    let mut sug_ex: Vec<([f32; SUG_N], bool)> = Vec::new();
+    for (i, s) in &trainset {
+        for k in 0..3u64 {
+            let (text, labels) = corrupt(s, (*i as u64) * 7 + k, &|w| m.lex.words.contains(w));
+            let spans = words(&text);
+            let ctx = contexts(&text, &spans);
+            for (c, label) in ctx.iter().zip(&labels) {
+                if exempt(c.raw) {
+                    continue;
+                }
+                det_ex.push((m.det_features(c, &none), label.is_some()));
+                if let Some(orig) = label {
+                    let orig = lower(orig);
+                    let cands = m.candidates(c, &none);
+                    if cands.iter().any(|(s, _)| *s == orig) {
+                        for (cand, e) in &cands {
+                            sug_ex.push((m.sug_features(c, cand, *e), *cand == orig));
+                        }
+                    }
+                }
+            }
+        }
+    }
+    // the detector: SGD on the log loss, errors weighted up to balance them
+    let pos = det_ex.iter().filter(|e| e.1).count().max(1);
+    let neg = det_ex.len() - pos;
+    let wpos = ((neg as f32 / pos as f32).sqrt()).max(1.0);
+    let mut rng = Rng(0x5eed);
+    let mut order: Vec = (0..det_ex.len()).collect();
+    for epoch in 0..6 {
+        for i in (1..order.len()).rev() {
+            order.swap(i, rng.below(i + 1));
+        }
+        let lr = 0.2 / (1.0 + epoch as f32);
+        for &i in &order {
+            let (f, y) = &det_ex[i];
+            let p = m.det.score(f);
+            let g = (p - *y as u8 as f32) * if *y { wpos } else { 1.0 };
+            for &j in f {
+                let w = &mut m.det.w[j as usize];
+                *w -= lr * (g + 1e-5 * *w);
+            }
+        }
+    }
+    // the suggester: the same on its dense features
+    let mut order: Vec = (0..sug_ex.len()).collect();
+    for epoch in 0..8 {
+        for i in (1..order.len()).rev() {
+            order.swap(i, rng.below(i + 1));
+        }
+        let lr = 0.05 / (1.0 + epoch as f32);
+        for &i in &order {
+            let (f, y) = &sug_ex[i];
+            let p = sigmoid(m.sug_score(f));
+            let g = p - *y as u8 as f32;
+            for (w, x) in m.sug.w.iter_mut().zip(f.iter()) {
+                *w -= lr * (g * x + 1e-4 * *w);
+            }
+        }
+    }
+    m.report = evaluate(
+        &m,
+        &test.iter().map(|(i, s)| (*i, *s)).collect::>(),
+        trainset.len(),
+    );
+    m
+}
+
+fn evaluate(m: &Model, test: &[(usize, &str)], train_n: usize) -> Report {
+    let none = |_: &str| false;
+    let (mut tp, mut fp, mut fneg, mut top1, mut top3) = (0usize, 0usize, 0usize, 0usize, 0usize);
+    let (mut clean_words, mut clean_flags) = (0usize, 0usize);
+    let mut kinds: Vec<(String, usize, usize)> = ["spelling", "confused", "repeated"]
+        .iter()
+        .map(|k| (k.to_string(), 0, 0))
+        .collect();
+    for (i, s) in test {
+        let (text, labels) = corrupt(s, (*i as u64) * 7 + 1000, &|w| m.lex.words.contains(w));
+        let spans = words(&text);
+        let ctx = contexts(&text, &spans);
+        for (c, label) in ctx.iter().zip(&labels) {
+            if exempt(c.raw) {
+                continue;
+            }
+            let flagged = m.det.score(&m.det_features(c, &none)) >= THRESHOLD;
+            if let Some(orig) = label {
+                let k = if orig.is_empty() {
+                    2
+                } else if confusable_set(&c.w).is_some_and(|set| set.contains(&lower(orig).as_str())) {
+                    1
+                } else {
+                    0
+                };
+                kinds[k].2 += 1;
+                kinds[k].1 += flagged as usize;
+            }
+            match (flagged, label) {
+                (true, Some(orig)) => {
+                    tp += 1;
+                    let sug = m.suggest(c, &none, 3);
+                    let orig = lower(orig);
+                    if sug.first().is_some_and(|x| lower(&x.text) == orig) {
+                        top1 += 1;
+                    }
+                    if sug.iter().any(|x| lower(&x.text) == orig) {
+                        top3 += 1;
+                    }
+                }
+                (true, None) => fp += 1,
+                (false, Some(_)) => fneg += 1,
+                (false, None) => {}
+            }
+        }
+        clean_words += words(s).len();
+        clean_flags += m.check(s, &none, THRESHOLD).len();
+    }
+    let precision = tp as f32 / (tp + fp).max(1) as f32;
+    let recall = tp as f32 / (tp + fneg).max(1) as f32;
+    Report {
+        train_sentences: train_n,
+        test_sentences: test.len(),
+        precision,
+        recall,
+        f1: if precision + recall > 0.0 {
+            2.0 * precision * recall / (precision + recall)
+        } else {
+            0.0
+        },
+        errors: tp + fneg,
+        flagged: tp + fp,
+        caught: tp,
+        top1: top1 as f32 / tp.max(1) as f32,
+        top3: top3 as f32 / tp.max(1) as f32,
+        false_alarms_per_1000: 1000.0 * clean_flags as f32 / clean_words.max(1) as f32,
+        threshold: THRESHOLD,
+        by_kind: kinds,
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn corruptions_are_deterministic_and_labelled() {
+        let lex = |w: &str| ["the", "cat", "sat", "on", "mat", "their", "there"].contains(&w);
+        let s = "The cat sat on the mat over there, and their hat too.";
+        let a = corrupt(s, 3, &lex);
+        assert_eq!(a, corrupt(s, 3, &lex));
+        let n = words(&a.0).len();
+        assert_eq!(a.1.len(), n);
+        // over many seeds every kind of change shows up
+        let all: Vec<_> = (0..200).map(|k| corrupt(s, k, &lex)).collect();
+        assert!(all.iter().any(|(_, l)| l.iter().any(|x| x.as_deref() == Some(""))));
+        assert!(
+            all.iter()
+                .any(|(t, _)| t.contains("there hat") || t.contains("they're hat"))
+        );
+        assert_eq!(words("it's a dog's life, isn't it"), {
+            let t = "it's a dog's life, isn't it";
+            let mut v = Vec::new();
+            for w in ["it's", "a", "dog's", "life", "isn't", "it"] {
+                let st = if w == "it" { t.rfind(w) } else { t.find(w) }.unwrap();
+                v.push(Span {
+                    start: st,
+                    end: st + w.len(),
+                });
+            }
+            v
+        });
+    }
+
+    #[test]
+    fn finds_and_fixes_errors_and_says_how_well() {
+        let m = model();
+        let r = &m.report;
+        eprintln!("{r:?}");
+        assert!(r.test_sentences > 400 && r.errors > 200, "{r:?}");
+        // the measured numbers (STATUS.md has them); these are floors, not targets
+        assert!(r.precision > 0.6, "{r:?}");
+        assert!(r.recall > 0.6, "{r:?}");
+        assert!(r.top3 > 0.6, "{r:?}");
+        assert!(r.false_alarms_per_1000 < 40.0, "{r:?}");
+
+        let none = |_: &str| false;
+        let flags = m.check("I recieve the the letter and it was definately mine.", &none, THRESHOLD);
+        let words: Vec<&str> = flags.iter().map(|f| f.word.as_str()).collect();
+        assert!(words.contains(&"recieve") && words.contains(&"definately"), "{flags:?}");
+        let rep = flags.iter().find(|f| f.kind == "repeated").expect("the repeated the");
+        assert_eq!(rep.suggestions[0].text, "");
+        let fix = flags.iter().find(|f| f.word == "recieve").unwrap();
+        assert!(fix.suggestions.iter().any(|s| s.text == "receive"), "{fix:?}");
+        // one's own words aren't errors
+        let mine = |w: &str| w == "anendish";
+        assert!(m.check("an anendish word", &mine, THRESHOLD).is_empty());
+        // UTF-16 offsets for the browser
+        let f = m.check("é recieve", &none, THRESHOLD);
+        assert_eq!((f[0].from, f[0].to), (2, 9));
+    }
+}
diff --git a/core/src/grammar/words-LICENSE b/core/src/grammar/words-LICENSE
new file mode 100644
index 00000000..65ff5a81
--- /dev/null
+++ b/core/src/grammar/words-LICENSE
@@ -0,0 +1,13 @@
+words.fc: the word list of the npm package word-list 4.1.0 (lowercase alphabetic words up to
+15 letters, front coded: each line is how many letters it shares with the line before,
+then the rest). Its licence:
+
+MIT License
+
+Copyright (c) Sindre Sorhus  (https://sindresorhus.com)
+
+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.
diff --git a/core/src/grammar/words.fc b/core/src/grammar/words.fc
new file mode 100644
index 00000000..204c89a1
--- /dev/null
+++ b/core/src/grammar/words.fc
@@ -0,0 +1,269870 @@
+0aa
+2h
+3ed
+3ing
+3s
+2l
+3ii
+5s
+3s
+2rdvark
+8s
+4wolf
+7ves
+3gh
+3rgh
+6h
+3ti
+5s
+2s
+3vogel
+8s
+1b
+2a
+3c
+4a
+5s
+4i
+4k
+4s
+4terial
+5inal
+9ly
+5or
+7s
+4us
+6es
+3ft
+3ka
+5s
+3lone
+7s
+3mp
+5ere
+8s
+5s
+3nd
+5ed
+5ing
+5on
+7ed
+9ly
+8e
+9s
+8r
+9s
+7ing
+7ment
+9nts
+7s
+7ware
+9res
+5s
+3pical
+3s
+4e
+5d
+6ly
+5ment
+9s
+5r
+6s
+5s
+4h
+5ed
+7ly
+6s
+5ing
+5less
+5ment
+9s
+4ia
+6s
+5ng
+4k
+3table
+4e
+5d
+5ment
+9s
+5r
+6s
+5s
+4ing
+5s
+6es
+4or
+6s
+4tis
+7es
+5oir
+8s
+5u
+4ure
+7s
+3xial
+5le
+3ya
+5s
+2b
+3a
+4cies
+5y
+4s
+4tial
+3e
+4d
+4s
+5s
+6es
+4y
+5s
+3ot
+5cies
+6y
+5s
+6hip
+9s
+3reviate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+9ory
+9ure
+9ures
+3s
+2cee
+5s
+3oulomb
+9s
+2dabs
+3icable
+6nt
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+3omen
+7s
+5ina
+8l
+9ly
+9s
+7oplasty
+8us
+3uce
+6d
+6ns
+7t
+8es
+6s
+5ing
+5t
+6ed
+7e
+8s
+6ing
+7on
+9s
+6or
+8es
+8s
+6s
+2eam
+4r
+5ing
+5s
+3cedarian
+9ans
+3d
+3gging
+3igh
+3le
+5s
+4ia
+6n
+6s
+4mosk
+8s
+3rdevine
+9es
+4nethies
+8y
+4rance
+9s
+8ies
+8y
+7t
+8ly
+8s
+6te
+8d
+8s
+7ing
+8on
+9nal
+9ns
+3ssive
+8s
+3t
+4ment
+8s
+4s
+4tal
+7s
+5ed
+6r
+7s
+5ing
+5or
+7s
+3yance
+8s
+7ies
+7y
+6t
+2farad
+7s
+2henries
+6y
+7s
+3ominable
+4r
+5red
+7nce
+9es
+9ies
+9y
+8t
+9ly
+7r
+8s
+6ing
+9s
+5s
+2id
+4ance
+8s
+4den
+4e
+5d
+5r
+6s
+5s
+4ing
+7ly
+7s
+3es
+4tic
+3gail
+7s
+3lities
+6y
+3ogeneses
+9is
+8tic
+9ically
+7ic
+9ally
+8st
+9ts
+4logical
+4ses
+5is
+4tic
+7ally
+5rophic
+9ies
+9y
+3rritant
+9ts
+8te
+9ed
+9es
+9ing
+3tur
+6ient
+9ts
+6s
+2ject
+6ed
+6ing
+7on
+9s
+6ly
+6ness
+9ses
+6s
+3oint
+7ed
+7ing
+7s
+3unction
+9ns
+4ration
+9ns
+5e
+6d
+6r
+7s
+6s
+5ing
+2lactation
+9ons
+4te
+6d
+6s
+5ing
+6on
+8s
+6tious
+6val
+7e
+8ly
+8s
+5or
+7s
+4ut
+6s
+4ze
+3e
+4d
+4gate
+8s
+4ism
+7s
+6t
+7s
+4r
+4s
+5t
+4t
+5s
+3ing
+6s
+5s
+3oom
+4w
+3uent
+7s
+4sh
+4ted
+5ion
+8ary
+8s
+5omane
+9es
+3y
+2mho
+5s
+2negate
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+3ormal
+8ism
+9sms
+9ties
+9ty
+8ly
+8s
+6ities
+8y
+6ous
+2o
+3ard
+3de
+5d
+5ment
+9s
+5s
+4ing
+3hm
+5s
+3ideau
+8s
+8x
+4l
+4teau
+8s
+8x
+3lish
+7able
+7ed
+8r
+9s
+8s
+7ing
+7ment
+9nts
+5tion
+9al
+9ary
+9ism
+9isms
+9ist
+9ists
+9s
+4la
+6e
+6s
+3ma
+5s
+6a
+7l
+6i
+6um
+7s
+4inable
+9eness
+9y
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+3ndance
+9s
+4nement
+9ts
+3on
+3ral
+6ly
+4d
+5ed
+5ing
+5s
+4e
+4igen
+8s
+6in
+8al
+9lism
+9lisms
+9lities
+9lity
+9lly
+9ls
+8e
+9s
+8s
+4ne
+5ing
+4t
+5ed
+6e
+7s
+6r
+7s
+5icide
+9es
+6facient
+9ients
+6ng
+6on
+8al
+8ist
+9sts
+8s
+6ve
+8ly
+8ness
+9esses
+5s
+5uaries
+8y
+6s
+7es
+3s
+3ught
+4lia
+7s
+6c
+4nd
+6ed
+6ing
+6s
+4t
+5s
+3ve
+5board
+5ground
+5s
+2racadabra
+9ras
+5hia
+8s
+4dable
+6nt
+8s
+5e
+6d
+6r
+7s
+6s
+5ing
+4id
+6ed
+6ing
+6s
+4m
+4nchial
+9te
+4sax
+7es
+5ion
+8s
+6ve
+8ly
+8ness
+9esses
+8s
+4xas
+7es
+4y
+5ed
+5ing
+5s
+4zo
+6s
+3eact
+7ed
+7ing
+8on
+9ns
+8ve
+7s
+5st
+4ge
+6s
+3i
+4cock
+8s
+4dgable
+6e
+7able
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+6ment
+9ts
+4m
+4n
+5s
+4s
+3oach
+5d
+6s
+4gable
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+4oke
+7d
+7s
+6ing
+4sia
+7s
+3upt
+6er
+7st
+6ion
+9s
+6ly
+6ness
+9ses
+6s
+2s
+3cess
+7ed
+8s
+7ing
+4ind
+7ed
+7ing
+7s
+5se
+7d
+7s
+6ic
+7n
+8g
+8s
+6s
+7a
+8e
+8s
+7e
+8s
+7in
+9s
+8on
+9ns
+4ond
+7ed
+8nce
+9ces
+8r
+9s
+7ing
+7s
+3eil
+6ed
+6ing
+9s
+6s
+4nce
+7s
+5t
+6ed
+7e
+8ism
+9sms
+8s
+7r
+8s
+6ing
+6ly
+6minded
+9dedly
+6s
+4y
+5s
+3inth
+7e
+8s
+7iated
+8sm
+9ms
+7s
+4t
+5s
+3olute
+8ly
+8ness
+9esses
+8r
+8s
+9t
+7ion
+9ns
+8se
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ve
+8ze
+9ed
+9es
+9ing
+7ory
+5vable
+6e
+7d
+7nt
+9s
+7r
+8s
+7s
+6ing
+7tor
+9rs
+4nant
+4rb
+6abilities
+9lity
+8le
+7nce
+9es
+9ies
+9y
+8t
+9s
+7te
+9s
+6ed
+8ly
+7facient
+9cients
+7ncies
+9y
+8t
+9s
+7r
+8s
+6ing
+9ly
+6s
+5ptance
+9ces
+7iometer
+9meters
+9n
+9ns
+8ve
+9eness
+9ities
+9ity
+3quatulate
+9ated
+9ates
+9ating
+3tain
+7ed
+8r
+9s
+7ing
+7s
+4emious
+9sly
+9sness
+5ntion
+9nism
+9nisms
+9nist
+9nists
+9ns
+9us
+5rge
+8d
+8nt
+9ts
+8s
+7ing
+6sion
+9ns
+8ve
+9es
+4inence
+9es
+9ies
+9y
+8t
+9ly
+4ract
+8able
+8ed
+9dly
+9dness
+9r
+9rs
+9st
+8ing
+9on
+9onal
+9onism
+9onisms
+9onist
+9onists
+9ons
+9ve
+9vely
+9ves
+8ly
+8ness
+9esses
+8or
+9rs
+8s
+5ict
+8ed
+8ing
+9on
+9ons
+8s
+5use
+8ly
+8ness
+9esses
+8r
+8st
+7ities
+9y
+3urd
+6er
+7st
+6ism
+9s
+8t
+9s
+7ties
+8y
+6ly
+6ness
+9ses
+6s
+2thane
+7s
+2ubble
+3ilding
+3lia
+6s
+5c
+3na
+5s
+4dance
+9s
+8ies
+8y
+7t
+8ly
+4e
+3rst
+3sable
+5ge
+7s
+4e
+5d
+5r
+6s
+5s
+4ing
+5on
+7s
+5ve
+7ly
+7ness
+9sses
+3t
+4ilon
+8s
+4ment
+8s
+4s
+4tal
+7s
+5ed
+6r
+7s
+5ing
+3zz
+2volt
+6s
+2watt
+6s
+2y
+3e
+4ing
+4s
+3ing
+3s
+4m
+5al
+7ly
+5s
+4s
+5al
+5es
+5opelagic
+1cacia
+6s
+3deme
+7s
+6ia
+8s
+7c
+8al
+9lism
+9lisms
+9lly
+9ls
+8ian
+9ans
+9sm
+9sms
+8s
+7es
+7sm
+9s
+8t
+9s
+6y
+3i
+4s
+3jou
+6s
+3lculia
+9s
+4eph
+7ae
+8n
+9s
+7e
+8s
+7s
+3naceous
+4th
+6a
+7ceous
+7e
+7s
+6i
+7n
+8e
+8s
+6ocephalan
+7id
+7us
+6s
+6us
+8es
+3pnia
+7s
+3rbose
+8s
+4i
+5an
+6ses
+7is
+5cidal
+8e
+9s
+5d
+6an
+8s
+6ean
+9s
+6ian
+9s
+6omatia
+9tium
+6s
+5ne
+7s
+4odomatia
+9tium
+5id
+5logies
+9st
+9sts
+8y
+5philies
+9y
+4pellous
+7ous
+5ous
+4us
+3talectic
+9ics
+7psies
+9y
+8tic
+9ics
+5mathesia
+9esias
+4er
+6s
+5s
+4hisia
+9s
+4our
+7s
+3udal
+6te
+4lescent
+5ine
+5ose
+6us
+2ca
+4ble
+4s
+3ede
+6d
+6nce
+9s
+6r
+7s
+6s
+5ing
+4lerable
+8ndo
+9dos
+9t
+9ts
+8te
+9ed
+9es
+9ing
+9ingly
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+7ometer
+9eters
+4nd
+6ed
+6ing
+6s
+5sion
+9s
+5t
+6ed
+6ing
+6less
+6or
+8s
+6s
+6ual
+9ities
+9ity
+9ly
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+4pt
+6abilities
+9lity
+8le
+9eness
+9y
+7nce
+9es
+9ies
+9y
+8t
+9s
+7tion
+9ons
+6ed
+8ly
+7e
+8s
+7r
+8s
+6ilation
+9tions
+7ng
+9ly
+9ness
+9nesses
+7ve
+8ities
+9ty
+6or
+8s
+6s
+4ss
+6aries
+9ly
+9ness
+9nesses
+8y
+6ed
+7s
+6ibilities
+9lity
+8le
+9eness
+9y
+7ng
+7on
+9al
+9ed
+9ing
+9s
+6orial
+9es
+9i
+9ly
+9ness
+9nesses
+9se
+9sed
+9ses
+9sing
+9us
+9ze
+9zed
+9zes
+9zing
+8y
+3iaccatura
+9uras
+9ure
+4dence
+9s
+7t
+8al
+9lism
+9lisms
+9lities
+9lity
+9lly
+9lness
+9ls
+8ed
+8ly
+8ologies
+9logy
+8s
+5ia
+7s
+6e
+7s
+4nge
+7d
+7s
+6ing
+4piter
+9s
+7ral
+8ine
+9nes
+4te
+6d
+6s
+5ing
+3laim
+7ed
+8r
+9s
+7ing
+7s
+5mation
+9ons
+8ory
+4imatable
+9tion
+9tions
+8e
+9d
+9s
+8ing
+9on
+9ons
+9sable
+9sation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9zable
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+5vities
+8ous
+8y
+6ous
+4oy
+6ed
+6ing
+6s
+3oast
+7ed
+7ing
+7s
+4ied
+5l
+6s
+4lade
+8d
+8s
+7ing
+4mmodable
+9te
+9ted
+9tes
+9ting
+9tingly
+9tion
+9tional
+9tions
+9tive
+9tor
+9tors
+5panied
+9er
+9ers
+9es
+9ment
+9ments
+9st
+9sts
+8y
+9ing
+9ist
+9ists
+6lice
+9es
+8sh
+9hable
+9hed
+9her
+9hers
+9hes
+9hing
+9hment
+9hments
+6t
+7able
+8nt
+9ts
+7ed
+7ing
+7s
+4rage
+8d
+8s
+7ing
+5d
+6able
+7nce
+9es
+9ies
+9y
+8t
+9ly
+6ed
+7r
+8s
+6ing
+9ly
+7on
+9ist
+9ists
+9s
+6s
+4st
+6able
+6ed
+6ing
+6s
+4uchement
+9ents
+8ur
+9rs
+9se
+9ses
+5nt
+7ability
+9le
+9leness
+9ly
+8ncies
+9cy
+9t
+9ts
+9tship
+9tships
+7ed
+7ing
+9gs
+7s
+5plement
+9ents
+5rage
+9d
+9s
+8ing
+6t
+7ed
+7ing
+7s
+5strement
+9ments
+5ter
+8ed
+8ing
+8ment
+9ents
+8s
+6re
+8d
+8ment
+9ents
+8s
+7ing
+4y
+5ed
+5ing
+5ld
+5s
+3redit
+8able
+9tion
+9tions
+8ed
+8ing
+8s
+5scence
+9ces
+9t
+5te
+7d
+7s
+6ing
+7on
+9ary
+9s
+7ve
+5w
+6ed
+6ing
+6s
+4oides
+4uable
+6l
+7s
+5e
+6d
+6ment
+9ts
+6s
+5ing
+3ubation
+9ns
+4ltural
+9te
+9ted
+9tes
+9ting
+9tion
+9tional
+9tions
+9tive
+4mbencies
+9y
+8t
+5ulable
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9ively
+9or
+9ors
+4racies
+7y
+6te
+8ly
+8ness
+9esses
+5se
+7d
+8ly
+8ness
+9esses
+7s
+6ing
+6t
+4sable
+8y
+6l
+7s
+6nt
+8s
+6tion
+9ns
+8val
+9e
+9ely
+9es
+7orial
+9y
+5e
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+5tom
+8ary
+9tion
+9tions
+8ed
+9dness
+8ing
+8s
+6rement
+9ents
+2e
+3d
+4ia
+6s
+3ldama
+8s
+4lular
+3ntric
+8s
+3phalic
+7ous
+3quia
+7s
+3r
+4aceous
+5te
+7d
+4b
+5ate
+8d
+8s
+7ing
+5er
+6st
+5ic
+7ally
+6ties
+7y
+4ola
+7s
+5se
+5us
+4s
+4vate
+8ly
+7ion
+9ns
+5uli
+7us
+3s
+4cence
+9s
+8ies
+8y
+7t
+8s
+3ta
+5bula
+9r
+8um
+9ms
+5l
+6dehyde
+9ydes
+6s
+5mid
+8e
+9s
+8s
+7nophen
+9phens
+5nilid
+9de
+9des
+9ds
+5te
+7d
+7s
+5zolamide
+9mides
+4ic
+5fication
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5n
+6s
+4ometer
+9rs
+5naemia
+9ias
+6e
+7mia
+9as
+7s
+6ic
+7trile
+9iles
+6uria
+9as
+5phenetidin
+5se
+5us
+5xyl
+8s
+4um
+4yl
+6ate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+6choline
+9lines
+6ene
+9s
+8ic
+6ic
+7de
+9s
+6s
+7alicylic
+2h
+3aenia
+7um
+9s
+6ocarp
+9rps
+4ge
+6s
+4lasia
+9s
+4r
+5ne
+5s
+5ya
+7s
+4tes
+3e
+4d
+4ne
+6s
+5ia
+7l
+6um
+8s
+4s
+3ier
+5st
+5vable
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+4llea
+8s
+4menes
+4ness
+8es
+5g
+6ly
+6s
+4ote
+7s
+4ral
+3kan
+6s
+3lamydeous
+4orhydria
+9rias
+9ric
+3olia
+7s
+4ndrite
+9es
+9ic
+7oplasia
+9lasias
+9lastic
+4o
+3romat
+8ic
+9cally
+9cities
+9city
+9n
+9ns
+9sation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9zation
+9ze
+9zed
+9zes
+9zing
+8opsia
+9psias
+9us
+8s
+6ic
+6ous
+3y
+2iclovir
+9s
+4ula
+7e
+7r
+7s
+7te
+9d
+6um
+8s
+3d
+4anthera
+9ras
+4emia
+8s
+5r
+5st
+4head
+8s
+4ic
+6ally
+5er
+6st
+5fiable
+7cation
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5meter
+9rs
+8ric
+9ical
+9ically
+9ies
+9y
+5ties
+6y
+4ly
+4ness
+8es
+4ometer
+9rs
+5phil
+9e
+9es
+9ic
+9ous
+9s
+9us
+9uses
+5ses
+6is
+5tic
+4s
+4ulate
+9d
+9s
+8ing
+9on
+9ons
+6ent
+6ous
+5ria
+8s
+4y
+3erage
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+3form
+3naceous
+6iform
+5r
+4etobacter
+9cters
+4g
+4i
+5c
+5form
+4ose
+5us
+4us
+2kee
+5s
+4r
+5s
+3new
+4ow
+6ing
+6ledge
+9geable
+9geably
+9ged
+9gedly
+9gement
+9ger
+9gers
+9ges
+9ging
+9gment
+9gments
+6n
+7e
+6s
+2linic
+2matic
+3e
+4s
+3ic
+4te
+6s
+2ne
+4d
+4s
+3odal
+5e
+6s
+2ock
+3elomate
+9es
+6us
+4meti
+3ld
+4outhic
+9te
+9tes
+8os
+9ses
+4uthic
+4yte
+7s
+6h
+7s
+3nite
+7s
+6ic
+7ne
+9s
+6um
+8s
+3rn
+5ed
+5s
+3smism
+8s
+7t
+8s
+3tyledon
+9nous
+9ns
+3uchi
+7es
+7s
+6y
+4stic
+8al
+9lly
+8ian
+9ans
+8s
+2quaint
+8ance
+9nces
+8ed
+8ing
+8s
+4est
+7s
+4iesce
+9d
+9nce
+9nces
+9nt
+9ntly
+9nts
+9s
+8ing
+9ngly
+5ght
+8ing
+8s
+5rabilities
+9lity
+8le
+7l
+8s
+6e
+7d
+7e
+8s
+7ment
+9nts
+7r
+8s
+7s
+6ing
+5s
+6ition
+9onal
+9ons
+9ve
+9vely
+9veness
+8or
+9rs
+6t
+7s
+5t
+6e
+7s
+6ing
+6ment
+9ts
+6s
+6tal
+9s
+8nce
+9ced
+9ces
+9cing
+7ed
+8r
+9s
+7ing
+2rasia
+7s
+6n
+7s
+4tic
+4wl
+3e
+4age
+7s
+4d
+4s
+3id
+5er
+6st
+5in
+7e
+8s
+7s
+6ties
+7y
+5ly
+5ness
+9es
+4flavin
+9ne
+9nes
+9ns
+4monies
+8ous
+9usly
+9usness
+7y
+4tarch
+9s
+5ical
+3oamatic
+9cal
+4bat
+7ic
+9ally
+9s
+8sm
+9ms
+7s
+4carpous
+5entric
+9ics
+5yanoses
+9sis
+4dont
+8s
+5rome
+8ous
+4gen
+7ic
+7ous
+9sly
+7s
+4lect
+8s
+6in
+8s
+5ith
+8ic
+8s
+4megalic
+9ics
+9ies
+9y
+5ia
+7l
+6on
+8s
+4nic
+7al
+9ly
+5ycal
+9ly
+7hal
+9lly
+6m
+7ania
+9ias
+7ic
+9ally
+7ous
+7s
+4paresthesia
+5etal
+9ly
+5hobe
+9s
+8ia
+9as
+9c
+9cs
+7netic
+8ic
+9es
+8y
+5olis
+9es
+4somal
+7e
+8s
+5pire
+9s
+5s
+5tic
+8al
+9lly
+8s
+4ter
+7ia
+9l
+8on
+8um
+9ms
+7s
+5ic
+6sm
+8s
+3ylamide
+9es
+6te
+8s
+5ic
+7s
+5onitrile
+9riles
+5yl
+7s
+2t
+3a
+4bilities
+9y
+5le
+4nt
+6s
+3ed
+3in
+5al
+7ly
+5g
+6s
+5ia
+7e
+7n
+8s
+7s
+6c
+7ally
+6de
+8s
+6form
+6sm
+8s
+6um
+8s
+5obacilli
+9illus
+7iologies
+9logy
+6chemistry
+6id
+8s
+6lite
+9es
+6mere
+9es
+8ter
+9ers
+9ric
+9rical
+9ries
+9ry
+7orphic
+9phies
+9phous
+9phy
+7yces
+9ete
+9etes
+9etous
+9in
+9ins
+9oses
+9osis
+9otic
+6n
+7s
+6pod
+9s
+6therapies
+9rapy
+6uranium
+9niums
+6zoan
+5s
+4on
+6able
+9y
+6ed
+7r
+8s
+6ing
+7st
+9s
+6less
+6s
+4vate
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5e
+6ly
+6ness
+9ses
+6s
+5ise
+8d
+8s
+7ing
+7m
+8s
+7t
+8ic
+8s
+6ties
+7y
+6ze
+8d
+8s
+7ing
+3omyosin
+9ns
+4n
+5s
+4r
+5ish
+5ly
+5s
+3ress
+7es
+7y
+3s
+3ual
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8t
+9s
+7te
+9s
+8ies
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+6s
+5rial
+9ly
+7es
+6y
+5te
+7d
+7s
+6ing
+7on
+9s
+6or
+8s
+4re
+6s
+2uate
+3ities
+5y
+3leate
+8d
+8s
+5i
+5us
+3men
+6s
+4inate
+9d
+9s
+8ing
+9on
+9ons
+6ous
+3point
+8s
+4ressure
+9res
+4unctural
+9re
+9res
+9rist
+9rists
+3shla
+7s
+3tance
+8s
+4e
+5ly
+5ness
+9es
+5r
+5s
+6t
+2yclic
+5ovir
+9s
+3l
+4ate
+7d
+7s
+6ing
+7on
+9s
+4oin
+7s
+4s
+1d
+2actylous
+3ge
+5s
+4ial
+5o
+6s
+3mance
+8s
+7ies
+7y
+6t
+7ean
+7ine
+7ly
+7s
+4site
+8s
+3pt
+5abilities
+9ity
+7le
+9ness
+9nesses
+6tion
+9nal
+9nally
+9ns
+8ve
+5ed
+7ness
+9sses
+6r
+7s
+5ing
+6on
+8s
+6ve
+8ly
+8ness
+9esses
+7ities
+9y
+5ogen
+9ic
+9s
+6r
+7s
+5s
+3w
+4ed
+4ing
+4s
+3xial
+3ys
+2d
+3able
+4x
+5es
+3ebted
+4d
+5ly
+4em
+6ed
+6ing
+6s
+4nd
+6a
+6s
+6um
+8s
+4r
+5s
+6tone
+9es
+5wort
+9s
+3ible
+4ct
+6ed
+8ness
+9esses
+6ing
+7on
+9s
+7ve
+6s
+4es
+4ng
+6s
+4o
+4tament
+9ts
+5ion
+8al
+9lities
+9lity
+9lly
+8s
+6tious
+6ve
+8ly
+8s
+7ities
+9y
+5ory
+3le
+5d
+5ment
+9s
+5pated
+5s
+4ing
+3oom
+6ed
+6ing
+6s
+4rsed
+3ress
+7ability
+9le
+7ed
+8e
+9s
+8r
+9s
+8s
+7ing
+7or
+9s
+6t
+3s
+3uce
+6able
+6d
+6nt
+6r
+7s
+6s
+5ible
+6ng
+5t
+6ed
+6ing
+7on
+9s
+7ve
+6or
+8s
+6s
+3y
+2eem
+5ed
+5ing
+5s
+3lantado
+9os
+3mption
+9s
+3nectomies
+9y
+4ine
+7s
+5tis
+8es
+4ocarcinoma
+9inomas
+5hypophyses
+9physis
+5id
+7al
+7ectomies
+9tomy
+7s
+5ma
+7s
+7ta
+8ous
+5pathies
+9y
+5ses
+6ine
+9s
+7s
+5viral
+8us
+9ses
+4yl
+6ic
+6s
+3pt
+5er
+6st
+5ly
+5ness
+9es
+5s
+3quacies
+7y
+6te
+8ly
+8ness
+9esses
+7ive
+3rmin
+7s
+3spota
+4sive
+8s
+2han
+5s
+4rma
+7s
+3erable
+5e
+6d
+6nce
+9s
+7d
+8s
+7t
+8ly
+8s
+6r
+7s
+6s
+5ing
+4sion
+8al
+8s
+6ve
+8ly
+8ness
+9esses
+8s
+3ibit
+7ed
+7ing
+8on
+9ns
+7s
+3ocracies
+8y
+2iabatic
+9ally
+9s
+4ctinic
+4phora
+8ism
+9sms
+9st
+9stic
+9sts
+8on
+9us
+4thermancies
+9ancy
+9anous
+9ic
+3eu
+5s
+5x
+3os
+3pic
+4ocere
+9s
+8ous
+6yte
+9s
+5se
+7s
+6is
+7ties
+8y
+5us
+4sia
+7s
+3t
+4s
+2jacence
+9s
+8ies
+8y
+7t
+8ly
+8s
+3ectival
+9lly
+8e
+9ly
+9s
+3igo
+6s
+3oin
+6ed
+6ing
+6s
+6t
+7s
+4urn
+7ed
+7ing
+7ment
+9nts
+7s
+3udge
+7d
+7ment
+9nts
+7s
+6ing
+6ment
+9ts
+5icate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+4nct
+7ion
+9ns
+8ve
+9ely
+7ly
+7s
+4ration
+9ns
+7ory
+5e
+6d
+6r
+7s
+6s
+5ing
+5or
+7s
+4st
+6abilities
+9lity
+8le
+9y
+6ed
+7r
+8s
+6ing
+7ve
+6ment
+9tal
+9ts
+6or
+8s
+6s
+4tage
+8s
+6ncies
+8y
+7t
+8s
+4vancies
+8y
+7t
+8s
+2land
+6s
+2man
+4ss
+6es
+3easure
+9d
+9ment
+9ments
+9s
+8ing
+4n
+3in
+5icle
+9s
+7ular
+9ate
+9ated
+9ates
+9ating
+6ster
+9red
+9ring
+9rs
+8rable
+9ant
+9ants
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+9ator
+9ators
+9atrix
+5s
+4rabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6l
+7s
+8hip
+9ips
+7ties
+8y
+6nce
+9s
+6tion
+9ns
+8ve
+6unce
+9es
+5e
+6d
+6r
+7s
+6s
+5ing
+8ly
+4ssibilities
+9lity
+8le
+9eness
+9y
+7on
+9s
+7ve
+4t
+5s
+5table
+7nce
+9es
+6ed
+8ly
+7e
+8s
+7r
+8s
+6ing
+4x
+5ed
+6s
+5ing
+5t
+6ure
+9s
+3onish
+8ed
+9r
+9rs
+9s
+8ing
+9ngly
+8ment
+9ents
+6tion
+9ns
+8ve
+7or
+9ily
+9s
+9y
+2nascent
+4te
+5ion
+8s
+3exa
+6l
+3ominal
+9s
+4un
+6s
+2o
+3be
+5like
+5s
+4o
+5s
+3lescence
+9ces
+9t
+9tly
+9ts
+3nis
+6e
+7d
+7s
+6ing
+5ze
+7d
+7s
+6ing
+3ors
+3pt
+5abilities
+9ity
+7le
+5ed
+6e
+7s
+6r
+7s
+5ianism
+9sms
+9st
+9sts
+6ng
+6on
+8ism
+9sms
+9st
+9sts
+8s
+7us
+6ve
+8ly
+5s
+3rabilities
+9ty
+6le
+8ness
+9esses
+7y
+5tion
+9s
+4e
+5d
+5r
+6s
+5s
+4ing
+7ly
+4n
+5ed
+6r
+7s
+5ing
+5ment
+9s
+5s
+3s
+3wn
+3ze
+2press
+7ed
+8s
+7ing
+2rad
+3ead
+6ed
+6ing
+6s
+4d
+4nal
+7ectomies
+9tomy
+7in
+9e
+9es
+9s
+8sed
+8zed
+7ly
+7s
+5ergic
+9cally
+5ochrome
+9omes
+7ortical
+3ift
+3oit
+6er
+7st
+6ly
+6ness
+9ses
+3y
+2s
+3cititious
+9ously
+4ript
+8ion
+9ons
+8s
+3orb
+6abilities
+9lity
+8le
+7te
+9s
+6ed
+7nt
+9s
+7r
+8s
+6ing
+6s
+5ption
+9ns
+8ve
+3uki
+6s
+4m
+2uki
+5s
+3larescence
+9ences
+9ent
+6ia
+8s
+5te
+7d
+7s
+6ing
+7on
+9s
+6or
+8s
+8y
+4t
+5erant
+9ts
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7er
+9s
+8ss
+9ses
+7ies
+8ne
+9es
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7ous
+9sly
+7y
+6scent
+9nts
+5hood
+9s
+5like
+6y
+5ness
+9es
+5ress
+9es
+5s
+3mbral
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9vely
+3nc
+5ate
+8d
+5ities
+7y
+5ous
+3st
+5ed
+5ing
+5s
+2vance
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9ly
+5tage
+9able
+9d
+9ous
+9ously
+9s
+8ing
+3ect
+6ed
+6ing
+7on
+9s
+7ve
+6s
+4ne
+6d
+6s
+5ing
+5t
+6itia
+9al
+9as
+9ous
+9ously
+7ve
+9s
+6s
+6ure
+9d
+9ful
+9r
+9rs
+9s
+9some
+9ss
+9sses
+8ing
+9sm
+9sms
+9st
+9stic
+9sts
+8ous
+9usly
+9usness
+4rb
+6ial
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9ly
+9s
+6s
+5saria
+9al
+9es
+9ness
+9nesses
+8y
+7tive
+9vely
+9ves
+6e
+7ly
+7ness
+9sses
+7r
+7st
+6ities
+8y
+5t
+6ed
+7nce
+9es
+9ies
+9y
+8t
+9ly
+6ing
+7se
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+9ngs
+7ze
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+9ngs
+6orial
+9als
+6s
+4w
+5ed
+5ing
+5s
+3ice
+6ful
+6s
+4sabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6tory
+5e
+6d
+7ly
+7ness
+9sses
+6e
+7s
+6ment
+9ts
+6r
+7s
+8hip
+9ips
+6s
+5ing
+8s
+5or
+7ate
+9es
+7ies
+7s
+7y
+3ocaat
+8s
+6cies
+7y
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+9y
+4utrer
+9s
+7ies
+7y
+4wson
+8s
+2ward
+6ed
+6ing
+6s
+5e
+6s
+3oman
+5en
+2ynamia
+8s
+7c
+3ta
+4um
+2z
+3e
+4d
+4s
+3ing
+3uki
+6s
+1e
+2cia
+5l
+4dia
+7l
+6ospore
+9ores
+6um
+5ospore
+9res
+4ospore
+9es
+4um
+2des
+3icule
+8s
+4le
+6s
+7hip
+9ps
+4ne
+2fald
+4uld
+2girine
+8s
+6te
+8s
+4s
+5es
+3logue
+8s
+3rotat
+8s
+2mule
+6d
+6s
+5ing
+2neous
+4us
+2olian
+5pile
+9s
+6yle
+9s
+4otropic
+9ies
+9y
+3n
+4ian
+5c
+4s
+2pyornis
+9es
+2quorin
+8s
+2rate
+6d
+6s
+5ing
+6on
+8s
+5or
+7s
+3enchyma
+9as
+9ata
+9atous
+3ial
+6ist
+9s
+7ties
+8y
+6ly
+6s
+4e
+5d
+5r
+5s
+6t
+4fication
+9ions
+6ed
+7s
+5orm
+5y
+6ing
+4ly
+3o
+4acoustics
+4ballistics
+6t
+7ic
+9s
+7s
+5e
+6s
+5ia
+6c
+7ally
+7ise
+9ed
+9es
+9ing
+9t
+9ts
+8ze
+9ed
+9es
+9ing
+7s
+6ological
+9gies
+9gist
+9gists
+9gy
+7nt
+9s
+7ses
+8is
+7tic
+9cally
+6um
+5omb
+8s
+6t
+7s
+5rake
+9d
+9s
+8ing
+9ngs
+4dart
+8s
+5igestive
+5onetics
+5rome
+9s
+5uct
+8s
+5ynamic
+9ical
+9ically
+9icist
+9icists
+9ics
+7e
+8s
+4elastic
+9ician
+9icians
+9icity
+5mbolism
+9isms
+4foil
+8s
+4gel
+7s
+6nerator
+9ators
+5ram
+8me
+9es
+8s
+7ph
+9ies
+9s
+9y
+4hydroplane
+9planes
+4lite
+8s
+7h
+8ologies
+9logy
+8s
+7ic
+5ogic
+9al
+8es
+8st
+9ts
+7y
+4magnetic
+6ncies
+8y
+5echanic
+9nical
+9nics
+6dical
+9ine
+9ines
+6ter
+9s
+7ric
+9es
+8y
+5otor
+9s
+4naut
+8ic
+9cal
+9cally
+9cs
+8s
+5euroses
+9sis
+5omer
+9s
+7ic
+9al
+8es
+8st
+9ts
+7y
+4pause
+9s
+5hagia
+9as
+9es
+8y
+6obe
+9s
+8ia
+9as
+9c
+7ne
+9s
+7re
+9s
+6yte
+9s
+5lane
+9s
+8kton
+9tons
+5ulse
+9s
+4s
+5at
+7s
+5cope
+9s
+5hell
+9s
+5iderite
+9ites
+5ol
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7s
+5pace
+9s
+6here
+9es
+6ike
+9s
+5tat
+8ic
+9cal
+9cs
+9on
+9ons
+8s
+6ructure
+9tures
+4tactic
+6xes
+7is
+5one
+8s
+5rain
+9s
+6opic
+9sm
+9sms
+3uginous
+5o
+6s
+3y
+2sc
+4es
+4ulin
+8s
+3ir
+3theses
+7ia
+9s
+8ogen
+9genic
+9gens
+8s
+6te
+8s
+7ic
+9al
+9ally
+9ian
+9ians
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+9s
+4ival
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+2ther
+6eal
+9ities
+9ity
+9ly
+6ic
+6s
+4rioscope
+9opes
+3iological
+9cally
+9es
+9st
+9sts
+8y
+1fald
+3r
+4a
+5s
+4s
+3wld
+2ear
+5d
+5ed
+5ing
+5s
+3brile
+2f
+3abilities
+9y
+5le
+6y
+4ir
+6e
+7s
+6s
+3ear
+6d
+6e
+7d
+7s
+6ing
+6s
+4ct
+6abilities
+9lity
+8le
+7tion
+9ons
+6ed
+8ly
+8ness
+9esses
+7r
+8s
+6ing
+9ly
+7on
+9al
+9ally
+9ate
+9ately
+9ed
+9ing
+9less
+9s
+7ve
+9ly
+9ness
+9nesses
+8ities
+9ty
+6less
+9sness
+6s
+4er
+6ed
+6ing
+6ment
+9ts
+6s
+4npinscher
+9chers
+4rent
+8ly
+8s
+4ttuoso
+3iance
+8d
+8s
+7ing
+6t
+7s
+4che
+7s
+5ionado
+9dos
+4davit
+9s
+4ed
+5s
+4liable
+7te
+9d
+9s
+8ing
+9on
+9ons
+4nal
+5e
+6d
+6ly
+6s
+5ities
+8ve
+7y
+4rm
+6able
+7nce
+9es
+8t
+9s
+7tion
+9ons
+9ve
+9vely
+9ves
+8ory
+6ed
+7r
+8s
+6ing
+9ly
+6s
+4x
+5able
+6l
+6tion
+9ns
+5ed
+6r
+7s
+6s
+5ial
+6ng
+5ment
+9s
+5ture
+9s
+3lated
+6ion
+9s
+6us
+8es
+4ict
+7ed
+8r
+9s
+7ing
+9gs
+8on
+9ns
+8ve
+9ely
+7s
+4uence
+9s
+8ies
+8y
+7t
+8ial
+9als
+8ly
+8ness
+9esses
+8s
+7za
+9s
+5x
+6es
+6ion
+9s
+3oord
+7ed
+7ing
+7s
+4rce
+7d
+7ment
+9nts
+7s
+6ing
+5d
+6abilities
+9lity
+8le
+9y
+6ed
+6ing
+6s
+5est
+8able
+9tion
+9tions
+8ed
+8ing
+8s
+3ranchise
+9sed
+9sement
+9ses
+9sing
+5p
+6ped
+7ing
+6s
+5y
+6ed
+7r
+8s
+6ing
+6s
+4eightment
+9ments
+5nded
+5t
+6s
+4icate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9ves
+5ght
+8ed
+9dly
+9n
+9ned
+9ning
+9ns
+8ful
+8ing
+8ment
+9ents
+8s
+4ont
+7e
+8d
+8e
+7ing
+9gly
+9gs
+8ve
+7s
+3usion
+8s
+3y
+4de
+4ing
+2ghan
+6i
+7s
+6s
+2icionada
+9as
+9o
+9os
+3eld
+3re
+2laj
+4me
+4toxin
+9s
+3oat
+3utter
+2oot
+3re
+5hand
+5mentioned
+5said
+5thought
+9ghts
+6ime
+3ul
+2raid
+3eet
+6s
+4sh
+3it
+5s
+3o
+4nt
+4rmosia
+9as
+4s
+2t
+3er
+5birth
+9hs
+6odies
+8y
+6rain
+9ns
+6urner
+9ers
+9ing
+9ings
+5care
+9s
+6lap
+9s
+5damp
+9s
+6eck
+9s
+5effect
+9cts
+6ye
+8d
+8ing
+8s
+7ing
+5game
+9s
+6low
+9s
+6rass
+9ses
+7owth
+9ths
+6uard
+9ds
+5heat
+9s
+5image
+9es
+6ngs
+5life
+9s
+7ves
+5market
+9ets
+7th
+9s
+6ost
+5noon
+9s
+5pain
+9s
+7rties
+9y
+6eak
+9s
+6iece
+9es
+5s
+6ales
+6ensation
+9ations
+6haft
+9ts
+8ve
+9es
+7ock
+9ks
+8w
+9s
+6un
+8s
+7pper
+9ers
+6warm
+9ms
+5taste
+9es
+7x
+6hought
+9ghts
+6ime
+9s
+5ward
+9s
+6ord
+9s
+8ld
+9ds
+3most
+3osa
+6s
+1g
+2a
+3cant
+7e
+4erie
+8s
+3in
+5st
+3lactia
+9s
+4loch
+8s
+4matolite
+9ites
+4wood
+8s
+3ma
+5s
+4ete
+7s
+4i
+5c
+6ally
+5d
+6s
+5s
+4ogeneses
+9sis
+9tic
+6onies
+8y
+5id
+7s
+5nt
+7s
+5spermies
+9my
+5us
+3pae
+5i
+5nthus
+9ses
+4e
+5ic
+5s
+3r
+4ic
+6aceous
+6s
+4ose
+7s
+4s
+3s
+4t
+3te
+5s
+5ware
+9s
+4hodaimon
+9mons
+4ise
+7d
+7s
+6ing
+5ze
+7d
+7s
+6ing
+4oid
+3ve
+5s
+3ze
+5d
+2e
+3d
+4ly
+4ness
+8es
+3e
+3ing
+6s
+4sm
+6s
+5t
+6s
+3last
+7ic
+7s
+4ess
+7ly
+7ness
+9sses
+4ong
+3mate
+7s
+3n
+4cies
+5y
+4da
+6less
+6s
+5um
+7s
+4e
+5s
+6es
+6ia
+8s
+7s
+5tic
+4ise
+7d
+7s
+6ing
+5ze
+7d
+7s
+6ing
+4t
+5ed
+5ial
+6ng
+8s
+6val
+7e
+8s
+7ities
+9y
+5ries
+6y
+5s
+3r
+4atum
+8s
+4s
+3s
+3usia
+7s
+2gada
+6h
+7s
+6s
+5ic
+5ot
+7h
+3er
+5s
+3ie
+5s
+4ornamenti
+9ento
+9entos
+3lomerate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+4utinability
+9ble
+9nt
+9nts
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+8in
+9ns
+8ogen
+9genic
+9gens
+3race
+7d
+7s
+6ing
+5dation
+9ons
+6e
+7d
+7s
+6ing
+5ndise
+9ed
+9ement
+9ements
+9er
+9ers
+9es
+9ing
+8ze
+9ed
+9ement
+9ements
+9er
+9ers
+9es
+9ing
+5te
+7d
+7s
+6ing
+5vate
+9d
+9s
+8ing
+9ngly
+9on
+9ons
+4egate
+9d
+9ly
+9ness
+9nesses
+9s
+8ing
+9on
+9onal
+9ons
+9ve
+9vely
+8or
+9rs
+5ss
+7ed
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+9eness
+9ities
+9ity
+7or
+9s
+4i
+5eve
+8d
+9ly
+8ment
+9ents
+8s
+7ing
+4o
+5s
+4y
+2ha
+4s
+5t
+2ila
+5s
+4e
+5ly
+5ness
+9es
+5r
+5st
+4ities
+6y
+3n
+4g
+5s
+4ner
+7s
+3o
+4s
+4tage
+8s
+3sm
+5s
+4t
+5ed
+6r
+7s
+5ing
+5ment
+9s
+5or
+7s
+5s
+3ta
+5ble
+5ns
+5s
+5te
+7d
+8ly
+7s
+6ing
+7on
+9al
+9s
+7ve
+6o
+7r
+8s
+4pop
+7s
+5rop
+8s
+2lare
+3eam
+4e
+4t
+5s
+4y
+3immer
+4tter
+3oo
+5s
+4ssal
+7te
+6ia
+8s
+4w
+3u
+4s
+3y
+4con
+7e
+8s
+7s
+2ma
+4s
+3inate
+2nail
+6s
+4me
+6d
+6s
+4te
+6s
+5han
+8s
+6ous
+5ic
+7al
+9ly
+6on
+8s
+3ise
+6d
+6s
+5ing
+4ze
+6d
+6s
+5ing
+3oiologies
+9y
+4men
+7s
+5ina
+8l
+4sia
+7s
+6c
+5tic
+8ism
+9sms
+8s
+2o
+3g
+4e
+5s
+4ic
+6s
+3ing
+3n
+4al
+4e
+5s
+4ic
+5es
+5se
+7d
+8ly
+7s
+6ing
+9ly
+6t
+7es
+7ic
+9al
+9ally
+9s
+7s
+5ze
+7d
+8ly
+7s
+6ing
+9ly
+4othetes
+4s
+4y
+3od
+3ra
+5e
+5phobe
+9es
+9ia
+9ias
+9ic
+9ics
+5s
+4ot
+6h
+3uta
+6s
+5i
+6es
+6s
+5y
+2rafe
+6s
+5fe
+7s
+4nulocyte
+9ytes
+9ytoses
+9ytosis
+8ses
+9is
+4pha
+6ia
+8s
+7c
+6on
+4rian
+8ism
+9sms
+8s
+4ste
+4vic
+3ee
+5abilities
+9ity
+7le
+9ness
+9nesses
+8y
+5d
+5ing
+5ment
+9s
+5s
+4gation
+9ns
+5e
+6s
+4mens
+7t
+8s
+4stal
+6ial
+7c
+3ia
+5s
+4business
+9esses
+9essman
+9essmen
+4chemical
+9cals
+5ultural
+9ralist
+9rally
+9re
+9res
+9rist
+9rists
+4monies
+7y
+4n
+4ologies
+8y
+4product
+9cts
+4se
+6d
+6s
+5ing
+4tourism
+9sms
+9st
+9sts
+4ze
+6d
+6s
+5ing
+3obiological
+9gies
+9gist
+9gists
+9gy
+5usiness
+9esses
+4chemical
+9cals
+4dolce
+9s
+4forester
+9ters
+9tries
+9try
+4industrial
+9tries
+9try
+4logic
+9al
+8es
+8st
+9ts
+7y
+4nomial
+8c
+9al
+9ally
+9s
+8es
+8st
+9ts
+7y
+4stemma
+9as
+9ata
+6ological
+9gies
+9gist
+9gists
+9gy
+4terrorism
+9risms
+5ourism
+9sms
+9st
+9sts
+4und
+3ypnia
+8s
+6otic
+9cs
+4ze
+6d
+6s
+5ing
+2s
+2terskot
+9s
+2uacate
+8s
+4rdiente
+9tes
+3e
+4d
+4like
+4s
+4weed
+8s
+3ise
+6d
+6s
+5h
+6ly
+5ing
+4ze
+6d
+6s
+5ing
+3na
+5h
+4ot
+3ti
+5s
+1h
+2a
+2choo
+2ead
+4p
+3d
+3ight
+3m
+4eral
+3nt
+2i
+3gh
+3msa
+6s
+3nd
+4g
+4t
+3s
+4toric
+9al
+2old
+5s
+3rse
+6back
+3y
+2s
+2ull
+3ngered
+5ry
+3ru
+5huru
+9s
+5s
+1i
+2a
+3s
+2blins
+2chmophobia
+9bias
+2d
+3a
+4nce
+7s
+5t
+4s
+3e
+4d
+4r
+5s
+4s
+3ful
+3ing
+3less
+3man
+4en
+3oi
+4s
+3s
+2eries
+4y
+2ga
+4s
+3ht
+3let
+6s
+3ret
+6s
+6te
+8s
+3uille
+8s
+8tte
+9tes
+2kido
+6s
+3ona
+2l
+3anthic
+7us
+9es
+6o
+7s
+3ed
+4ron
+7s
+4tte
+7s
+3ing
+3ment
+7s
+3ourophile
+9iles
+9ilia
+9ilias
+9ilic
+9obe
+9obes
+9obia
+9obias
+9obic
+3s
+3urophile
+9les
+9lia
+9lias
+9lic
+8obe
+9bes
+9bia
+9bias
+9bic
+2m
+3ed
+4r
+5s
+3ful
+6ly
+3ing
+3less
+7ly
+7ness
+9sses
+3s
+2n
+3e
+4e
+3ga
+5s
+3s
+4ell
+7s
+2oli
+5s
+2r
+3bag
+6s
+5se
+7s
+4oard
+8ing
+9ngs
+8s
+6t
+7s
+5rne
+5und
+4rick
+8s
+5ush
+8ed
+9s
+8ing
+4urst
+8ed
+8ing
+8s
+5s
+6es
+6ses
+3check
+8s
+4oach
+8es
+5n
+6s
+4raft
+8man
+9en
+8sman
+9men
+9woman
+9women
+8woman
+9omen
+5ew
+7s
+3date
+7s
+4rawn
+5ome
+8s
+6p
+7ped
+8ing
+7s
+3ed
+4r
+5s
+4st
+3fare
+7s
+4ield
+8s
+4low
+7s
+4oil
+7s
+4rame
+8s
+5eight
+9ted
+9ting
+9ts
+3gap
+6s
+4low
+7s
+4raph
+8s
+4un
+6s
+3head
+7ed
+7s
+4ole
+7s
+3ier
+5st
+4ly
+4ness
+8es
+5g
+6s
+3less
+7ness
+9sses
+4ift
+7ed
+7ing
+7s
+5ke
+5ne
+7r
+8s
+7s
+4ock
+7s
+3mail
+7ed
+7ing
+7s
+5n
+6ship
+9ps
+4en
+4obile
+3n
+4ed
+4ing
+4s
+3park
+7s
+4lane
+8s
+6y
+7s
+4ort
+7s
+5st
+7s
+5wer
+8s
+4roof
+8ed
+8ing
+8s
+6x
+7es
+3s
+4cape
+8s
+5rew
+8s
+4haft
+8s
+5ed
+7s
+5ip
+7s
+5ot
+7s
+6w
+7s
+4ick
+7ness
+9sses
+5de
+7s
+4pace
+8s
+5eed
+8s
+4top
+7s
+5ream
+9s
+6ike
+9s
+7p
+8s
+3t
+4ed
+4h
+5ed
+5ing
+5s
+4ight
+8ness
+9esses
+5me
+7s
+5ng
+4s
+3ward
+7s
+5ve
+7s
+5y
+6s
+4ise
+4oman
+6en
+5rthier
+9est
+9ness
+9nesses
+8y
+3y
+2s
+3le
+5d
+5less
+5s
+5way
+8s
+4ing
+7s
+2t
+3ch
+5bone
+9s
+5es
+3s
+3u
+4s
+2ver
+5s
+2zle
+5s
+1jar
+2ee
+2iva
+5s
+2owan
+6s
+2uga
+5s
+3tage
+7s
+2wan
+5s
+1ka
+3ryote
+8s
+7ic
+3s
+3tea
+6s
+4hisia
+9s
+2e
+3ake
+6s
+3d
+4ah
+6s
+3e
+4s
+3la
+5s
+3ne
+5s
+4ial
+3s
+2hara
+6s
+2imbo
+3n
+4eses
+6ia
+8s
+7s
+5tic
+4g
+3raho
+7s
+3ta
+5s
+2kas
+2olouthos
+9ses
+4uthos
+9es
+2rasia
+7s
+4tic
+2vavit
+7s
+1l
+2a
+3ap
+5s
+3bamine
+9s
+5ndine
+9es
+8te
+9es
+5ster
+9s
+7rine
+4laster
+9rs
+3chlor
+8s
+4k
+5aday
+4rities
+7ous
+7y
+3e
+3iment
+8s
+3lagmoi
+8s
+4ia
+6s
+3meda
+7s
+4o
+5de
+7s
+5rt
+5s
+3n
+4d
+5s
+4e
+4g
+5s
+4in
+6e
+7s
+6s
+4nah
+7s
+4s
+4t
+5s
+4yl
+6s
+3p
+4a
+5s
+4s
+3r
+4m
+5able
+5ed
+7ly
+5ing
+8ly
+6sm
+8s
+7t
+8s
+5s
+4um
+6ed
+6ing
+6s
+4y
+3s
+4ka
+6s
+4tor
+7s
+5rim
+8s
+3te
+5d
+5s
+4ion
+7s
+3y
+4ed
+4ing
+4s
+2b
+3a
+4core
+8s
+4relli
+8o
+9s
+4s
+4ta
+6s
+5ross
+9es
+3e
+4do
+6es
+6s
+4e
+4it
+4rghi
+6o
+5t
+6ite
+9s
+6s
+4scence
+9es
+8t
+5pine
+9s
+6yne
+9s
+3icore
+8s
+4nal
+5ess
+8es
+5ic
+6sm
+8s
+7tic
+5o
+6ism
+9s
+6s
+6tic
+4te
+6s
+5ic
+7al
+6se
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+4zia
+7s
+5zia
+8s
+3s
+3ugineous
+5o
+6s
+4m
+5blatt
+9ter
+9ts
+5en
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7s
+5in
+7ate
+9es
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7oid
+9ds
+8us
+7s
+7uria
+9ias
+9ic
+5ose
+8s
+5s
+4rnous
+6um
+8s
+4terol
+9s
+2cade
+6s
+4hest
+8s
+4ic
+6eria
+9as
+6s
+5de
+7s
+4lde
+7s
+4rraza
+9s
+4tras
+8es
+4yde
+7s
+4zar
+7s
+3hemic
+8al
+9lly
+7es
+7se
+9d
+9s
+8ing
+8t
+9ic
+9ical
+9s
+7ze
+9d
+9s
+8ing
+6y
+5ra
+7s
+6inga
+9as
+4ymies
+6y
+3id
+5ine
+5s
+3o
+4hol
+7ic
+9ally
+9ities
+9ity
+9s
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ometer
+9eters
+9etries
+9etry
+7s
+4lock
+8s
+4ol
+6s
+4pop
+7s
+4rza
+7s
+4s
+4ve
+6d
+6s
+3yonarian
+9ans
+2dea
+5s
+4hyde
+8s
+7ic
+4r
+5flies
+7y
+5man
+8ic
+9ties
+9ty
+8like
+9y
+8ries
+9y
+8ship
+9hips
+6en
+5n
+5s
+5woman
+8en
+3icarb
+8s
+3ohexose
+9es
+4l
+5ase
+8s
+5isation
+9ions
+6zation
+9ions
+5s
+4pentose
+9ses
+4se
+6s
+5terone
+9nes
+9nism
+9nisms
+4xime
+8s
+3rin
+6s
+2e
+3atoric
+8es
+7y
+3bench
+8es
+3c
+4ithal
+4k
+5s
+4ost
+7s
+4s
+3e
+3f
+4s
+4t
+3gar
+6s
+4ge
+6aunce
+9ces
+6d
+6s
+5ing
+3house
+8s
+3mbic
+7ated
+9ion
+9ions
+7s
+5roth
+9s
+3ncon
+7s
+4gth
+3ph
+5s
+4ine
+7s
+3rce
+6s
+4ion
+7s
+4t
+5ed
+6r
+6st
+5ing
+5ly
+5ness
+9es
+5s
+3s
+3thic
+3uron
+7e
+8s
+7ic
+7s
+3vin
+6s
+3w
+4ashed
+4ife
+5ves
+4s
+3xander
+9s
+9ses
+7rine
+9nes
+9te
+9tes
+4ia
+6s
+5c
+5n
+6e
+7s
+6ic
+6s
+5pharmakon
+9makons
+9mic
+9mics
+3ye
+5d
+5s
+4ing
+2f
+3a
+4ki
+6s
+4lfa
+7s
+4qui
+7n
+8s
+7s
+4s
+3ereces
+6z
+3ilaria
+9s
+5eria
+9s
+3orja
+7s
+3redo
+5sco
+3s
+2ga
+4e
+5cide
+9s
+4l
+4roba
+8s
+5roba
+9s
+8o
+9s
+4s
+4te
+6s
+3ebra
+7ic
+9al
+9ally
+8st
+9ts
+7s
+4rine
+8s
+4ses
+5ia
+7s
+6c
+6s
+4tic
+3icidal
+7e
+8s
+4d
+5ities
+7y
+5ness
+9es
+4n
+5ate
+8s
+5ic
+5s
+3oid
+4lagnia
+9ac
+9acs
+9as
+9c
+9st
+9sts
+5ogical
+9ally
+8es
+8st
+9ts
+7y
+4meter
+9s
+7ries
+8y
+4phobia
+9as
+4r
+5ism
+8ic
+8s
+6thm
+9ic
+9ically
+9s
+5s
+3uacil
+8s
+5zil
+8s
+4m
+5s
+2ias
+5ed
+6s
+5ing
+8s
+3bi
+5ed
+6s
+5ing
+5s
+4le
+3cant
+7s
+4yclic
+3dad
+6e
+7s
+6s
+3en
+5abilities
+9ity
+7le
+6ge
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5ed
+6e
+7s
+6r
+7s
+5ing
+6sm
+8s
+7t
+8s
+5ly
+5ness
+9es
+5or
+7s
+5s
+3f
+4orm
+4s
+3garta
+8s
+4ht
+6ed
+6ing
+6ment
+9ts
+6s
+4n
+5ed
+6r
+7s
+5ing
+5ment
+9s
+5s
+3ke
+5ness
+9es
+3ment
+7al
+8ry
+8tion
+9ions
+9ive
+7ed
+7ing
+8veness
+7s
+4onied
+8s
+6y
+3ne
+5ation
+9ns
+5d
+5ment
+9s
+5r
+6s
+5s
+4ing
+3ped
+6s
+4hatic
+3quant
+5ot
+7s
+3sma
+6ceous
+6s
+4on
+6s
+4t
+3t
+4eracies
+8y
+7te
+9s
+3unde
+3ve
+5ness
+9es
+3ya
+5h
+6s
+5s
+4os
+5t
+6h
+3zari
+7n
+8e
+9s
+8s
+7s
+2kahest
+8ic
+8s
+4lescence
+9nces
+9ncies
+9ncy
+9nt
+5i
+6c
+6es
+6fied
+9s
+7y
+8ing
+6meter
+9ers
+9ric
+9ries
+9ry
+6n
+7e
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+6s
+7able
+7e
+8d
+8r
+9s
+8s
+7ing
+6zable
+7e
+8d
+8r
+9s
+8s
+7ing
+5oid
+8al
+8s
+6ses
+7is
+6tic
+4ne
+6s
+6t
+7s
+5nin
+8s
+3ene
+6s
+3ie
+5s
+4ne
+6s
+3o
+4s
+4xide
+8s
+5y
+3y
+4d
+5s
+4l
+5ate
+8d
+8s
+7ing
+8on
+9ns
+5ic
+5s
+4ne
+6s
+2l
+3anite
+8s
+5toic
+8d
+9al
+9es
+9s
+8n
+9s
+8s
+9es
+4rgando
+4tive
+8s
+4y
+5ed
+6r
+7s
+5ing
+8s
+5ment
+9s
+5s
+3comers
+3edge
+7d
+7s
+6ing
+4e
+5s
+4gation
+9ns
+5e
+6ance
+9es
+6d
+7ly
+6r
+7s
+6s
+5ge
+7d
+7s
+6ing
+5iance
+9es
+8t
+9s
+6ng
+5oric
+9al
+9ally
+9alness
+8es
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9t
+9ts
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7y
+5retto
+9os
+6o
+7s
+4l
+5e
+6s
+5ic
+6sm
+8s
+5omorph
+9phic
+9phism
+9phisms
+9phs
+6pathic
+9hies
+9hy
+5s
+5uia
+8h
+9s
+8s
+4mande
+9s
+4narly
+4rgen
+8ic
+9cities
+9city
+8s
+6ic
+8s
+7es
+7n
+8s
+7st
+9s
+6y
+5ion
+8s
+4thrin
+9s
+4viant
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+4y
+5cat
+8s
+5ed
+5s
+5way
+8s
+3hallond
+8wen
+9n
+4eal
+7s
+4ollown
+3iable
+5ceous
+5nce
+8s
+4ce
+6s
+5holies
+8y
+5in
+7s
+4ed
+5s
+4garta
+9s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+4neation
+9ons
+4s
+5es
+4terate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9ively
+4um
+6s
+3ness
+7es
+4ight
+8er
+9rs
+3oantibodies
+9ody
+8gen
+9ens
+4bar
+7s
+4cable
+6rpies
+8y
+6table
+7e
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5heiria
+9ias
+6iria
+9as
+6thonous
+5ution
+9ns
+4d
+5ia
+7l
+6um
+8s
+5s
+5ynia
+9s
+4gamies
+7ous
+7y
+5eneic
+7ic
+5raft
+9ed
+9ing
+9s
+7ph
+9ic
+9s
+4iostrophos
+4meric
+8sm
+9ms
+7ous
+6tric
+9es
+8y
+5one
+8s
+6rph
+9ic
+9ism
+9isms
+9s
+4nge
+7s
+5s
+5ym
+7ous
+7s
+4path
+8ic
+9cally
+9es
+9st
+9sts
+8s
+8y
+7ric
+9cally
+9es
+8y
+5hane
+9s
+6one
+9s
+8ic
+5lasm
+9ic
+9s
+8tic
+5olyploid
+9loids
+9loidy
+5urinol
+9ols
+4saur
+8s
+8us
+9ses
+5teric
+9cally
+9es
+8y
+4t
+5etraploid
+9ploids
+9ploidy
+5heism
+9ms
+5ment
+9s
+5riomorphic
+6ope
+9s
+8ic
+9cally
+9es
+9sm
+9sms
+8ous
+8y
+5s
+5ted
+7e
+8s
+7r
+8ies
+8s
+8y
+6ing
+5ype
+8s
+7ic
+9ally
+8es
+7y
+4ver
+7s
+4w
+5abilities
+9ity
+7le
+9ness
+9nesses
+9s
+8y
+6nce
+9d
+9s
+8ing
+5ed
+7ly
+5ing
+5s
+4xan
+7s
+4y
+5ed
+5ing
+5s
+4zyme
+8s
+3s
+4eed
+7s
+4orts
+4pice
+8s
+3ude
+6d
+6s
+5ing
+4re
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+4sion
+8s
+6ve
+8ly
+8ness
+9esses
+4via
+7l
+8s
+6on
+8s
+6um
+8s
+3weather
+9rs
+3y
+4chollies
+9y
+4ing
+4l
+5ic
+5s
+4ou
+2ma
+4cantar
+9rs
+4gest
+8s
+4h
+5s
+4in
+6s
+4nac
+7k
+8s
+7s
+5dine
+9s
+7te
+9s
+4s
+3e
+4h
+5s
+4mar
+7s
+4ries
+5y
+4s
+3ightily
+8ness
+9esses
+7y
+4rah
+7s
+3ner
+6s
+3ond
+6s
+6y
+5er
+7s
+5ries
+6y
+4st
+4us
+3s
+4giver
+9s
+7ing
+9gs
+4house
+9s
+4man
+5en
+4woman
+7en
+3ucantar
+9rs
+5e
+6s
+4d
+5e
+6s
+5s
+4g
+5s
+2nage
+6r
+7s
+6s
+3ico
+6es
+6s
+2ocasia
+8s
+3d
+4ia
+6l
+5um
+7s
+4s
+3e
+4d
+4s
+4tic
+7s
+3ft
+3gia
+6s
+5cal
+8ly
+3ha
+5s
+3in
+5s
+3ne
+5ly
+5ness
+9es
+4g
+5shore
+9eman
+9emen
+6ide
+6t
+3o
+4f
+5ly
+5ness
+9es
+4s
+3pecia
+8s
+7c
+6oid
+3ud
+3w
+4e
+2p
+3aca
+6s
+5ca
+7s
+4rgata
+9s
+3een
+6s
+4nglow
+9s
+5horn
+9s
+5stock
+9ks
+4strine
+3ha
+5bet
+8arian
+9rians
+8ed
+8ic
+9cal
+9cally
+9form
+9ng
+9sation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8s
+5meric
+9cal
+9cally
+7tic
+9cs
+5numeric
+9rical
+9rics
+5s
+6ort
+9ed
+9ing
+9s
+5test
+9ed
+9ing
+9s
+4orn
+7s
+5sis
+8es
+4yl
+6s
+3ine
+6ly
+6s
+5ism
+8s
+7t
+8s
+3s
+2ready
+3ight
+2s
+3ike
+6s
+3o
+4on
+6e
+3troemeria
+9rias
+2t
+3altissimo
+9imos
+4r
+5age
+8s
+5piece
+9es
+5s
+5wise
+4zimuth
+9hs
+3er
+5abilities
+9ity
+7le
+8y
+6nt
+8s
+6tion
+9ns
+8ve
+9es
+5cate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+5ed
+6r
+7s
+5ing
+6ties
+7y
+5n
+6ance
+9es
+8t
+9s
+7t
+8e
+9d
+9ly
+9s
+8im
+9ng
+9on
+9ons
+9ve
+9vely
+9veness
+9ves
+8or
+9rs
+8s
+6e
+7s
+5s
+4sse
+7s
+4za
+6s
+5za
+7s
+3haea
+7s
+4ea
+6s
+4o
+5rn
+7s
+5ugh
+3igraph
+9s
+4meter
+9s
+7rical
+9cally
+9es
+8y
+4plano
+9s
+4sonant
+5simo
+9s
+4tonant
+5ude
+8s
+7inal
+9arian
+9arians
+9ous
+3o
+4cumuli
+9us
+4gether
+9rs
+4ist
+7s
+4ruffled
+4s
+5trati
+9us
+3rices
+6ial
+9s
+4uism
+8s
+7t
+8ic
+9cally
+8s
+3s
+2u
+3del
+6s
+3la
+5e
+5r
+5s
+3m
+4in
+6a
+7s
+7te
+9s
+6e
+7s
+6ic
+7ferous
+7se
+9d
+9s
+8ing
+7um
+9s
+7ze
+9d
+9s
+8ing
+6osilicate
+9ties
+9ty
+7thermies
+9ermy
+7us
+6s
+6um
+8s
+5sh
+5um
+7s
+4na
+6e
+5i
+5us
+4root
+8s
+4s
+5tone
+9s
+3nite
+7s
+3re
+5s
+3s
+2vearies
+6y
+5ted
+4olar
+8ly
+8s
+7te
+8ion
+9ons
+6e
+7s
+6i
+7tis
+9ses
+6us
+3ine
+2way
+5s
+2ycompaine
+9nes
+3ssum
+7s
+1m
+2a
+3bile
+3davat
+8s
+4oda
+5u
+6s
+3h
+4s
+3in
+3kosi
+4werekwere
+3lgam
+7ate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+7s
+3ndine
+8s
+5la
+7s
+4ita
+7s
+6in
+8s
+4tadine
+9es
+4uenses
+8is
+3racus
+8es
+5nt
+7aceous
+7h
+8aceous
+8ine
+8s
+7in
+9e
+7s
+4elle
+8s
+5tti
+7o
+8s
+4na
+4one
+7s
+4yllid
+9aceous
+9s
+8s
+9es
+3s
+4s
+5able
+5ed
+6r
+7s
+6s
+5ing
+5ment
+9s
+3te
+5d
+5s
+5ur
+7ish
+9hly
+9hness
+9m
+9ms
+7s
+8hip
+9ips
+4ing
+5on
+7s
+5ve
+7ly
+7ness
+9sses
+4ol
+6s
+5rial
+9ly
+8n
+7ous
+6y
+3uroses
+7is
+6tic
+4t
+5s
+3ze
+5d
+6ly
+6ness
+9ses
+5ment
+9s
+5s
+4ing
+7ly
+4on
+6ian
+9s
+7te
+9s
+6s
+7tone
+9nes
+2bach
+6es
+4ge
+6s
+5ious
+6tory
+4n
+5s
+4ri
+6es
+6s
+5y
+4ssador
+9rial
+9rs
+9rship
+9rships
+8ress
+9esses
+7ge
+9s
+6ies
+6y
+4tch
+7es
+3eer
+6s
+4r
+5ed
+5gris
+9es
+5ies
+6na
+8s
+6te
+8s
+5jack
+9s
+5oid
+8s
+6us
+5s
+5y
+3iance
+8s
+4dentate
+6xter
+9rities
+9rity
+9rous
+9rs
+8rous
+9ously
+4ence
+8s
+6t
+7s
+4guities
+8y
+6ous
+9ly
+9ness
+9nesses
+4lateral
+4ophonies
+9y
+4polar
+4sexual
+9lities
+9lity
+9ls
+4t
+5ion
+8ed
+8ing
+8less
+8s
+7us
+9ly
+9ness
+9nesses
+5s
+5ty
+4valence
+9ces
+9cies
+9cy
+9t
+9tly
+5ersion
+9ons
+7t
+8s
+3le
+5d
+5r
+6s
+5s
+4ing
+7s
+4ygonite
+9tes
+5opia
+9s
+8c
+3o
+4ceptor
+9rs
+4ina
+7s
+4nes
+4s
+5exual
+4yna
+7s
+3ries
+4oid
+7s
+5sia
+8l
+9ly
+8n
+8s
+5type
+9s
+4y
+3sace
+7s
+3ulacra
+9l
+8um
+6nce
+9man
+9men
+9s
+9woman
+9women
+7t
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9ies
+9ily
+9s
+9y
+5ette
+9s
+4scade
+9d
+9r
+9rs
+9s
+8ing
+8o
+9es
+9s
+5h
+6ed
+7r
+8s
+7s
+6ing
+6ment
+9ts
+2e
+3arst
+3ba
+5e
+5n
+5s
+4ean
+4iases
+7is
+5c
+4ocyte
+9s
+5id
+3er
+5ate
+8s
+5s
+3ioses
+6is
+3lcorn
+8s
+4ia
+6s
+5orable
+8nt
+9ts
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+4oblast
+9ts
+5geneses
+9sis
+3n
+4abilities
+9ty
+6le
+8ness
+9esses
+7y
+5ge
+7d
+7s
+6ing
+5unce
+9s
+4d
+5able
+6tory
+5e
+6d
+6r
+7s
+6s
+5ing
+5ment
+9s
+5s
+4e
+5d
+4ing
+5ties
+6y
+4orrhea
+9as
+9ic
+8oea
+9eas
+4s
+4t
+5a
+6ceous
+6l
+5ia
+7s
+6ferous
+5s
+5um
+3rce
+6able
+6d
+6ment
+9ts
+6r
+7s
+6s
+5iable
+7ment
+9nts
+6ng
+4icium
+9s
+3s
+4ace
+7s
+3tabolic
+9sm
+9sms
+8ous
+4hyst
+8ine
+8s
+4ropia
+9s
+8c
+2i
+3a
+4bilities
+9y
+5le
+7ness
+9sses
+6y
+4nthine
+7oid
+9dal
+7us
+9es
+6us
+8es
+4s
+3cabilities
+9ty
+6le
+8ness
+9esses
+7y
+4e
+5s
+4i
+4us
+3d
+4ase
+7s
+4e
+5s
+4ic
+5n
+6e
+7s
+6s
+4most
+4o
+5gen
+8s
+5l
+6s
+5ne
+7s
+4s
+5hip
+8s
+5t
+3e
+4s
+3ga
+5s
+4o
+5s
+3ldar
+7s
+3n
+4e
+5s
+4ic
+5ties
+6y
+4o
+5aciduria
+9urias
+5benzoic
+6utene
+9nes
+5peptidase
+9idases
+6henazone
+9azones
+9ol
+9ols
+7ylline
+9lines
+6terin
+9ins
+6yrine
+9nes
+4s
+3r
+4ate
+7s
+4s
+3s
+4es
+4s
+5es
+5ibilities
+9ity
+7le
+6ng
+3ties
+4oses
+6is
+5tic
+8ally
+4riptyline
+9lines
+5ole
+8s
+5yptyline
+9lines
+4y
+2la
+4s
+2man
+5s
+3eter
+7s
+3ine
+6s
+5o
+4ral
+7s
+3o
+4cete
+8s
+5oete
+9s
+4n
+5al
+7s
+6te
+8s
+5ia
+7c
+8al
+8s
+8um
+9ms
+7s
+7te
+9d
+9s
+8ing
+9on
+9ons
+6c
+7al
+6fication
+9ations
+8ed
+9s
+7y
+8ing
+6te
+8s
+7ic
+6um
+8s
+5o
+6id
+8s
+6lyses
+9is
+5s
+4philous
+4s
+3unition
+9ned
+9ning
+9ns
+2nesia
+7c
+8s
+7s
+6c
+7s
+5tic
+7ed
+8s
+6y
+7ing
+3ia
+4c
+4o
+5centeses
+9esis
+5n
+6ic
+6s
+5s
+5te
+7s
+6ic
+6omies
+8y
+2obarbital
+9als
+3eba
+6e
+7an
+6n
+6s
+5ean
+5iases
+8is
+6c
+6form
+5ocyte
+9es
+6id
+3k
+4s
+4ura
+7s
+3le
+5s
+3mum
+6s
+3ng
+5st
+4tillado
+9dos
+3ove
+6d
+6s
+5ing
+3ral
+6ism
+9s
+8t
+9s
+7ties
+8y
+6ly
+5nce
+8s
+6t
+4ce
+6s
+4et
+6s
+6ti
+7o
+8s
+4ini
+6o
+5sm
+7s
+6t
+7ic
+7s
+4nings
+4osa
+7s
+6ities
+8y
+6o
+7s
+5us
+7ly
+7ness
+9sses
+4phism
+9s
+6ous
+9ly
+9ness
+9nesses
+4t
+5isable
+8tion
+9ions
+7e
+8d
+8ment
+9ents
+8s
+7ing
+6zable
+8tion
+9ions
+7e
+8d
+8ment
+9ents
+8s
+7ing
+3site
+7s
+3tion
+7s
+3unt
+6ed
+6ing
+6s
+4r
+5ette
+9s
+5s
+3ve
+5d
+5s
+4ing
+3wt
+5s
+3xicillin
+9ins
+4ycillin
+9ins
+2p
+3assies
+6y
+3ed
+4lographies
+9phy
+6pses
+8is
+4rage
+8s
+5e
+6s
+5ometric
+5sand
+9s
+5zand
+9s
+3hetamine
+9nes
+4iarthroses
+9rosis
+6ster
+9rs
+5bia
+8n
+9s
+7otic
+8us
+9sly
+9sness
+6lastic
+9tula
+9tulae
+6ole
+9s
+8ic
+9es
+9te
+9tes
+8ogical
+9gies
+9gy
+9us
+8y
+6rach
+9hic
+9hs
+5chroic
+9matic
+6oelous
+6tyon
+9nic
+9nies
+9ns
+9ny
+5dentate
+6iploid
+9oidies
+9oids
+9oidy
+5gastria
+9rium
+6oric
+9es
+8y
+7uri
+9is
+5macer
+9rs
+6ictic
+7xes
+8is
+5oxi
+7us
+9es
+5path
+9ic
+6hile
+9es
+9ic
+6loid
+9dies
+9ds
+9dy
+6od
+8ous
+8s
+6rostylar
+9tyle
+9tyles
+8tic
+5sbaena
+9nae
+9nas
+9nic
+6cian
+9ns
+6tomatal
+9atic
+9ous
+7ylar
+9ars
+5theater
+9ters
+9tral
+9tre
+9tres
+9tric
+9trical
+8cia
+9ium
+6richa
+9hous
+7opous
+4olyte
+9s
+5ra
+7e
+7l
+7s
+6ic
+5teric
+3icillin
+9ns
+4ng
+3le
+5ness
+9es
+5r
+5st
+5xicaul
+6us
+8es
+4iation
+9ns
+8ve
+5dyne
+9s
+5fiable
+7cation
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5tude
+9s
+4osome
+9s
+4y
+3oule
+7s
+3s
+3ul
+5e
+6s
+5la
+7ceal
+9ous
+7e
+7r
+8y
+6osities
+9ty
+5s
+4tate
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5ee
+7s
+2reeta
+7s
+3it
+5a
+6s
+6ttva
+9as
+5s
+2sinckia
+9s
+2tman
+6s
+3rac
+6k
+7s
+6s
+2u
+3ck
+5s
+3let
+6ic
+6s
+3s
+4able
+4e
+5able
+5d
+6ly
+5ment
+9s
+5r
+6s
+5s
+5tte
+8s
+4ia
+6s
+5c
+5ng
+7ly
+7ness
+9sses
+5ve
+7ness
+9sses
+2ygdal
+7a
+8ceous
+8e
+8te
+7e
+8s
+7in
+9e
+9s
+7oid
+9dal
+9ds
+7s
+5ule
+8s
+3l
+4aceous
+5se
+7s
+4ene
+7s
+4ic
+4ogen
+8s
+5id
+7al
+7oses
+9is
+9ises
+7s
+5lyses
+8is
+7tic
+5pectin
+9ins
+6last
+9ts
+6sin
+9s
+5se
+7s
+4s
+4um
+6s
+3otonia
+9s
+5rophic
+9ies
+9y
+1n
+2a
+3baena
+8s
+5ntid
+9s
+5ptise
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ze
+9ed
+9es
+9ing
+5s
+6es
+6is
+5tic
+4ioses
+7is
+6tic
+4leps
+8es
+4olic
+7sm
+9s
+7te
+9s
+8ic
+4ranch
+9es
+3cardiaceous
+8um
+9ms
+5tharses
+9sis
+9tic
+9tics
+4haris
+9es
+5orism
+9ms
+5ronic
+9cal
+9cally
+9sm
+9sms
+9stic
+8ous
+9usly
+4lastic
+5inal
+6ses
+7is
+6tic
+4olutha
+9ia
+9ias
+9ic
+9ically
+9on
+9ons
+5nda
+8s
+5ustic
+4reontic
+9ically
+9ics
+5uses
+7is
+7tic
+3dem
+6s
+4iploses
+9is
+4romous
+4yomene
+3emia
+7s
+6c
+7ally
+4robe
+8s
+7ia
+8c
+9ally
+8ont
+9nts
+9ses
+9sis
+9tic
+8um
+4stheses
+9ia
+9ias
+9iology
+9is
+8tic
+9ically
+9ics
+9ise
+9ised
+9ises
+9ising
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+3geneses
+8is
+4lyph
+8ic
+9cal
+9es
+8s
+8y
+7tic
+9cal
+4norises
+9is
+4oge
+7s
+6ic
+8al
+9lly
+7es
+6y
+4ram
+7matic
+9tical
+9tise
+9tised
+9tises
+9tising
+9tism
+9tisms
+9tist
+9tists
+9tize
+9tized
+9tizes
+9tizing
+8ed
+9r
+9rs
+8ing
+7s
+3lcime
+8s
+7ic
+6te
+8s
+4ecta
+7ic
+7s
+5mma
+8s
+8ta
+9ic
+5ptic
+9s
+4gesia
+9s
+8c
+9s
+6tic
+9s
+5ia
+7s
+4ities
+6y
+4ly
+4og
+6a
+6ic
+8al
+9lly
+7es
+7se
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7ze
+9d
+9s
+8ing
+6on
+8s
+7us
+9ly
+9ness
+9nesses
+6s
+6ue
+8s
+6y
+4phabet
+9te
+9tes
+9tic
+9tics
+9tism
+9tisms
+9ts
+4ysable
+7nd
+9s
+7tion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+7s
+6t
+7s
+5te
+7s
+6ic
+8al
+9lly
+8ities
+9ty
+8s
+5zabilities
+9lity
+8le
+7tion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+3mneses
+7is
+7tic
+9cally
+5iote
+9s
+8ic
+4orphic
+9sm
+9sms
+8oscope
+9scopes
+9ses
+9sis
+9us
+3n
+4a
+5s
+6es
+4damide
+9es
+5rous
+4ke
+6s
+4thous
+3paest
+8ic
+9cal
+8s
+4est
+7ic
+9s
+7s
+4hase
+8s
+7ic
+5or
+7a
+8l
+8s
+7eses
+9is
+7ic
+9al
+9ally
+7s
+5rodisia
+9siac
+9siacs
+9sias
+5ylactic
+9toid
+8xes
+9ies
+9is
+9y
+4lasia
+9s
+7moses
+9sis
+7tic
+9es
+8y
+5eroses
+9is
+8tic
+4tyctic
+9cal
+6xes
+7is
+3rch
+6al
+6ial
+7c
+8al
+9lly
+7es
+7se
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ically
+9s
+7ze
+9d
+9s
+8ing
+6s
+6y
+4thria
+9s
+8c
+7ous
+9sly
+9sness
+3s
+4arca
+8s
+7ous
+4tases
+7is
+6tic
+5igmat
+9tic
+9tism
+9tisms
+9ts
+5omose
+9ed
+9es
+9ing
+9is
+8tic
+5rophe
+9es
+7zole
+9les
+3ta
+5s
+6e
+7s
+4exes
+6is
+4hema
+8s
+8ta
+9ical
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+4man
+7s
+4omic
+8al
+9lly
+7es
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8t
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6y
+5xin
+8s
+4ropies
+7ous
+7y
+4ta
+6s
+5o
+6s
+3xial
+2buries
+5y
+2ce
+4stor
+8ed
+8ial
+9ng
+8s
+6ral
+9ly
+9s
+7ess
+9ses
+7ies
+7y
+3ho
+5r
+6age
+9s
+6ed
+7ss
+9es
+7t
+8ic
+9cal
+8s
+8te
+9es
+6ing
+7te
+9s
+8ic
+9cal
+9cally
+6less
+6man
+7en
+6people
+8rson
+9sons
+6s
+6woman
+9en
+5s
+5veta
+9s
+8ta
+9as
+6ies
+6y
+4usa
+7s
+6in
+8s
+4ylose
+9d
+9s
+8ing
+9s
+7tic
+3ient
+7er
+8st
+7ly
+7ness
+9sses
+7ries
+8y
+7s
+4le
+5ia
+5la
+7e
+7ries
+8y
+7s
+4pital
+7ous
+3le
+5s
+3ome
+6s
+4n
+5al
+5e
+6al
+6s
+5oid
+4ra
+3ress
+7es
+3ylostomiases
+9miasis
+2d
+3alusite
+9es
+4nte
+7s
+6ini
+8o
+9s
+3esine
+8s
+6te
+8s
+7ic
+5yte
+8s
+3iron
+7s
+3ouille
+9s
+9tte
+9ttes
+3radite
+9s
+4o
+5centric
+9rism
+9risms
+7phalous
+6linia
+9ium
+5dioecious
+9cism
+9cisms
+5ecia
+9l
+8um
+9ms
+5gen
+8eses
+9sis
+9tic
+8ic
+8ous
+8s
+6yne
+9s
+8ies
+8ophore
+9phores
+9us
+8y
+5id
+7s
+5logies
+9st
+9sts
+8y
+5meda
+9s
+8otoxin
+9toxins
+6onoecious
+9ecism
+9ecisms
+5pause
+9es
+6hore
+9es
+5s
+6phinges
+9nx
+9nxes
+6terone
+9ones
+3s
+3vile
+7s
+2e
+3ar
+5ed
+5ing
+5s
+4th
+3cdota
+8ge
+9es
+8l
+9ism
+9isms
+9ist
+9ists
+9ly
+7e
+8s
+7ic
+9al
+9ally
+8st
+9ts
+5yses
+7is
+4hoic
+3lace
+7s
+5stic
+9ities
+9ity
+4e
+5d
+5s
+4ing
+4li
+3mia
+6s
+5c
+6ally
+4ochore
+9es
+9ous
+5gram
+9s
+8ph
+9hic
+9hies
+9hs
+9hy
+5logies
+8y
+5meter
+9rs
+8ric
+9ical
+9ies
+9y
+5ne
+7s
+5philies
+9ous
+9y
+7obia
+9ias
+5scope
+9es
+6es
+6is
+3ncephalia
+9lias
+9lic
+9lies
+9ly
+4st
+4t
+3rgia
+7s
+6c
+6es
+5y
+4ly
+4oid
+7s
+3s
+4thesia
+9as
+9ology
+7tic
+9cally
+9cs
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9zation
+9ze
+9zed
+9zes
+9zing
+5ra
+6i
+6ous
+6um
+7s
+8es
+3thol
+7e
+8s
+7s
+4ic
+3uploid
+9ies
+9s
+9y
+4rin
+7s
+6sm
+8al
+9lly
+9tic
+8s
+5ysm
+8al
+9lly
+9tic
+8s
+3w
+2fractuosities
+9sity
+9us
+2ga
+4kok
+7s
+4ria
+7s
+6es
+5y
+4s
+5hore
+9s
+3ekkok
+8s
+5ok
+7s
+4l
+5ed
+5fish
+9es
+5hood
+9s
+5ic
+7a
+8l
+9ly
+8s
+6ng
+5olatries
+9ry
+7ogies
+9ist
+9ists
+9y
+6phanies
+9ny
+5s
+5us
+7es
+4r
+5ed
+5ing
+5less
+6y
+5s
+3ico
+6s
+4na
+6l
+6s
+5ose
+6us
+4ocarpous
+5geneses
+9sis
+8ic
+6ram
+9s
+8phic
+9hies
+9hy
+5logies
+8y
+5ma
+7s
+7ta
+8ous
+5plasties
+9ty
+5sarcoma
+9omas
+9omata
+6perm
+9mal
+9mous
+9ms
+6tomatous
+9ous
+5tensin
+9ins
+3klung
+8s
+3le
+5berries
+9y
+5d
+6ozer
+9rs
+6ug
+8s
+5pod
+8s
+5r
+6fish
+9hes
+6s
+5s
+6ite
+9s
+5twitch
+9ches
+5wise
+6orm
+9s
+4ice
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+5fied
+8s
+6y
+7ing
+5ng
+7s
+5st
+7ics
+7s
+4o
+5mania
+9ac
+9acs
+9as
+5phil
+9e
+9es
+9ia
+9ias
+9ic
+9s
+7obe
+9es
+9ia
+9iac
+9ias
+9ic
+8ne
+9es
+9ic
+5s
+3ola
+4phora
+9s
+4ra
+6s
+4stura
+9s
+3rier
+6s
+7t
+5ly
+5ness
+9es
+4y
+3st
+5ier
+7st
+5rom
+8s
+5s
+5y
+3uifauna
+9ae
+9as
+6orm
+5lliform
+5ne
+5ped
+8e
+5sh
+7ed
+8s
+7ing
+4lar
+7ities
+9y
+7ly
+7ness
+9sses
+6te
+8d
+8s
+7ing
+8on
+9ns
+5ose
+6us
+4stifoliate
+7rostrate
+3wantibo
+9os
+2harmonic
+3edonia
+9s
+8c
+5ral
+4lation
+9ns
+3idroses
+8is
+7tic
+9cs
+4nga
+7s
+3ungered
+6red
+3ydrase
+9s
+6ide
+9s
+7te
+9s
+6ous
+2i
+3cca
+6s
+4onic
+7sm
+9s
+8t
+9s
+4ut
+6s
+3droses
+7is
+3gh
+5t
+3l
+4e
+4in
+6ctus
+9ses
+6e
+7s
+6guses
+6s
+5ties
+6y
+4s
+3ma
+5cies
+6y
+5dversion
+9sions
+9t
+9ted
+9ter
+9ters
+9ting
+9ts
+5l
+6cula
+9ar
+9e
+9es
+9ism
+9isms
+9ist
+9ists
+9um
+6ian
+7c
+7er
+9s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6like
+7y
+6s
+5s
+5te
+7d
+8ly
+7ly
+7ness
+9sses
+7r
+8s
+7s
+6ic
+8s
+7ng
+9ly
+7on
+9s
+7sm
+9s
+8t
+9s
+6o
+7r
+8s
+6ronic
+9ically
+9ics
+4e
+5s
+4i
+5s
+6m
+7s
+6t
+7ic
+7s
+4osities
+8y
+4us
+6es
+3on
+5ic
+5s
+3ridia
+8s
+7c
+3s
+4e
+5ed
+7s
+5ikonia
+9ias
+9ic
+5s
+5tte
+8s
+4ic
+4ocercal
+5dactyl
+9ylous
+9yls
+5gamies
+8ous
+8y
+5le
+7s
+5meric
+8ous
+7tric
+9opia
+9opias
+9opic
+6orphic
+5phyllies
+9lous
+9ly
+5tropic
+9ically
+9ies
+9ism
+9isms
+9y
+2ker
+5ite
+8s
+5s
+3h
+4s
+3le
+5bone
+9s
+5d
+5s
+5t
+6s
+4ing
+4ong
+7s
+4ung
+7s
+3us
+5es
+5h
+6es
+3ylosaur
+9rs
+9rus
+9ruses
+7e
+8d
+8s
+7ing
+8s
+7tomiases
+9miasis
+6tic
+2lace
+6s
+4ge
+6n
+6s
+4s
+5es
+2n
+3a
+4bergite
+9tes
+4l
+5ise
+8d
+8s
+7ing
+7t
+8ic
+8s
+6ze
+8d
+8s
+7ing
+5s
+4s
+4t
+5es
+5s
+5ta
+7s
+6o
+7s
+3eal
+6ed
+7r
+8s
+6ing
+9s
+6s
+4ctent
+4lid
+7an
+9s
+7s
+4x
+5able
+6tion
+9nal
+9nism
+9nisms
+9nist
+9nists
+9ns
+5e
+6d
+6s
+5ing
+6on
+8s
+5ment
+9s
+5ure
+8s
+3icut
+7s
+4hilable
+8te
+9ed
+9es
+9ing
+9ion
+9ionism
+9ions
+9ive
+9or
+9ors
+9ory
+4versaries
+9ry
+3o
+4na
+6s
+4tatable
+7e
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+4unce
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+4y
+5ance
+9s
+5ed
+6r
+7s
+5ing
+8ly
+5s
+3s
+3ual
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6ly
+6s
+4itant
+9s
+6ies
+6y
+4l
+5ar
+7ities
+9y
+7ly
+7s
+6te
+8d
+8s
+7ion
+9ns
+5et
+7s
+5i
+5lable
+6ed
+6ing
+5ment
+9s
+5ose
+5s
+5us
+7es
+4nciate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+5tiate
+9ed
+9es
+9ing
+2oa
+4s
+3biid
+7s
+3dal
+6ly
+4e
+5s
+4ic
+6ally
+5sation
+9ons
+6e
+7d
+7s
+6ing
+5zation
+9ons
+6e
+7d
+7s
+6ing
+4ontia
+9s
+4yne
+7s
+6ic
+3eses
+5is
+5tra
+7i
+7ous
+7um
+8s
+4tic
+3int
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+3le
+5s
+4yte
+7s
+3malies
+7stic
+9ical
+9ically
+6ous
+9ly
+9ness
+9nesses
+6y
+4ic
+5e
+6s
+4y
+3n
+4aceous
+4ym
+6a
+7s
+6ise
+9d
+9s
+8ing
+7ties
+8y
+7ze
+9d
+9s
+8ing
+6ous
+9ly
+9ness
+9nesses
+6s
+3opsia
+8s
+3pheles
+7ine
+9es
+4ia
+6s
+4sia
+7s
+3rak
+6s
+4ectal
+7ic
+9s
+5tic
+8s
+5xia
+8s
+7c
+8s
+7es
+7genic
+6y
+4thic
+7te
+9s
+8ic
+6osite
+9tes
+9tic
+3smatic
+5ia
+7s
+6c
+3ther
+7guess
+3ugh
+4rous
+3vulant
+9s
+7r
+7tion
+9ons
+8ory
+3w
+3xaemia
+9s
+8c
+4emia
+8s
+7c
+4ia
+6s
+5c
+2s
+3a
+4e
+4te
+6d
+3erine
+8s
+5ous
+3wer
+6abilities
+9lity
+8le
+9eness
+9y
+6ed
+7r
+8s
+6ing
+6less
+6phone
+9nes
+6s
+2t
+3a
+4cid
+7s
+4e
+4gonisable
+9ation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8zable
+9ation
+9ations
+9e
+9ed
+9es
+9ing
+4lgic
+8s
+5kali
+9es
+9ne
+9nes
+9s
+4phrodisiac
+9isiacs
+4r
+5a
+6s
+5ctic
+5s
+5thritic
+9tics
+4s
+5thmatic
+9tics
+3bear
+7s
+4ird
+7s
+3e
+4ater
+8s
+4bellum
+4cede
+8d
+8nce
+9ces
+9t
+9tly
+9ts
+8s
+7ing
+6ssor
+9rs
+5hamber
+9ers
+7pel
+9ls
+6oir
+9s
+4d
+5ate
+8d
+8s
+7ing
+5iluvial
+9ially
+9ian
+9ians
+4ed
+4fix
+7a
+8e
+8l
+7es
+4ing
+4lope
+8s
+5ucan
+4meridian
+5ortem
+5undane
+4natal
+9ly
+9s
+7i
+5na
+7e
+7l
+7ry
+7s
+6iferous
+8orm
+6ular
+8e
+9s
+5uptial
+4orbital
+4past
+8s
+5endia
+9um
+9ums
+7ult
+9tima
+9timas
+9timate
+9ts
+5osition
+9ions
+5randial
+4rior
+8ities
+9ty
+8ly
+5ograde
+6om
+8s
+4s
+4type
+8s
+4version
+9ons
+7t
+8ed
+8ing
+8s
+3helia
+7ces
+7on
+9s
+7x
+8es
+6minthic
+9thics
+9tic
+9tics
+5m
+6ed
+6ia
+7c
+7ng
+7on
+6s
+6wise
+5r
+6al
+6id
+8ia
+9al
+9um
+8s
+6ozoid
+9ids
+9oid
+9oids
+6s
+7mut
+9ts
+5ses
+6is
+4ill
+7s
+4ocarp
+9ous
+9s
+6hlore
+9res
+6yan
+9in
+9ins
+9s
+5dia
+7um
+5id
+5logical
+9es
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8y
+5mania
+9ac
+9acs
+9as
+5philous
+7ore
+9es
+7yllite
+9lites
+5taxies
+8y
+5xanthin
+9hins
+5zoan
+9s
+7ic
+4racene
+9es
+8s
+7ic
+8te
+9es
+9ic
+7nose
+9ses
+7oid
+8ses
+9is
+6nilate
+9ates
+6quinone
+9nones
+6x
+7es
+5opic
+9al
+7obiology
+8centric
+8geneses
+9enesis
+9enetic
+9enic
+9enies
+9eny
+9onies
+9ony
+9raphy
+8id
+9dal
+9ds
+8latries
+9atry
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+8metric
+9etries
+9etrist
+9etry
+9orph
+9orphic
+9orphs
+8pathic
+9athies
+9athism
+9athy
+9hagi
+9hagic
+9hagies
+9hagite
+9hagous
+9hagus
+9hagy
+9hobia
+9hobias
+9hobic
+9hobics
+9huism
+9huisms
+9hyte
+9hytes
+9sychic
+8sophic
+9ophies
+9ophist
+9ophy
+8tomies
+9omy
+4urium
+9s
+3i
+4abortion
+9ionist
+6use
+5cademic
+9mics
+6ne
+5ditis
+9ses
+5ggression
+6ing
+5ir
+7craft
+9afts
+5lcohol
+9olism
+9olisms
+6ien
+6lergenic
+9genics
+5nemia
+6xiety
+5partheid
+9heids
+6hrodisiac
+5r
+6in
+8s
+6mor
+6rhythmic
+9thmics
+6s
+6thritic
+9itics
+9itis
+5sthma
+9atic
+9atics
+5tom
+8s
+5uthority
+6xin
+9s
+4bacchii
+9ius
+7klash
+7terial
+9rials
+6llistic
+6rbarus
+9ruses
+7yon
+9ns
+5ias
+6lious
+7lboard
+6oses
+8is
+7tic
+9cally
+9cs
+5lack
+9ism
+9isms
+5odies
+7y
+6ss
+6urgeois
+6ycott
+9tts
+5ug
+6rglar
+9ary
+6ser
+9s
+7iness
+9g
+4c
+5aking
+6l
+7ly
+6ncer
+6pitalism
+9alisms
+9alist
+9alists
+6r
+7cinogen
+9nogens
+7ies
+6talyst
+9ysts
+7hode
+9des
+9lic
+5ellulite
+6nsorship
+5hlor
+9istic
+9s
+6oice
+9er
+9ers
+7lesterol
+8inergic
+6rist
+9tian
+9tianly
+9ts
+6thones
+6urch
+5igarette
+6pant
+9ts
+8table
+9e
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9ively
+9or
+9orily
+9ors
+9ory
+6se
+8d
+8s
+7ing
+6ty
+6vic
+8sm
+9ms
+6ze
+8d
+8s
+7ing
+5k
+6e
+7d
+6ing
+6s
+5lassical
+8tic
+6erical
+9calism
+9calist
+9cals
+6imactic
+9ctical
+9x
+9xes
+7nal
+9ls
+8e
+9s
+8g
+8oria
+9rium
+9riums
+6ockwise
+7tting
+6y
+5oagulant
+9lants
+6don
+9s
+6incidence
+6ld
+7lision
+7onial
+9ialism
+9ialist
+9ials
+6mmercial
+8unism
+9nisms
+9nist
+9nists
+7petitive
+6nsumer
+9mers
+7vulsant
+9lsants
+9lsive
+9lsives
+6rporate
+7rosion
+9sive
+9sives
+8uption
+9ptions
+6us
+5rack
+6eative
+6ime
+6uelty
+5s
+5ult
+8s
+8ural
+5yclone
+9nes
+9nic
+4dandruff
+6zzle
+5efamation
+6mocratic
+6pressant
+9ssants
+9ssion
+9ssions
+6rivative
+9atives
+6siccant
+9cants
+6velopment
+5iabetic
+7rrheal
+9heals
+6lution
+6uretic
+9tics
+5ogmatic
+6ra
+6tal
+9ly
+7e
+8d
+8s
+7ing
+5raft
+6omic
+9cally
+6ug
+5umping
+6ne
+8s
+4economic
+5ducational
+5galitarian
+5lectron
+9rons
+6ite
+9s
+8ism
+9sms
+9st
+9sts
+5metic
+9cs
+5nt
+7ropic
+7s
+5pilepsy
+9ptic
+9ptics
+5strogen
+9gens
+5volution
+4family
+6scism
+9sms
+9st
+9sts
+7hion
+9onable
+9ons
+6t
+7igue
+5ebrile
+9les
+6deralist
+9alists
+6male
+7inine
+9ism
+9isms
+9ist
+9ists
+6rromagnet
+7tility
+5ilibuster
+9usters
+5lu
+5oam
+8ing
+6g
+7ging
+6reclosure
+8ign
+9gner
+7malist
+9lists
+6uling
+9ngs
+5raud
+6eeze
+9es
+6iction
+9ions
+5ungal
+9ls
+6r
+4gambling
+6ng
+6y
+5en
+7e
+8s
+7ic
+9ally
+9ities
+9ity
+7s
+5lare
+6obulin
+9lins
+5overnment
+5raft
+7vities
+9ty
+6opeloes
+9los
+7wth
+5uerrilla
+9illas
+6n
+4halation
+9ions
+5elices
+8x
+9es
+7minthic
+9nthics
+6ro
+8es
+8ic
+9ne
+9nes
+7pes
+5ijack
+6stamine
+9mines
+9minic
+9minics
+8orical
+5omosexual
+5uman
+9ism
+9isms
+9istic
+6nter
+8ing
+9ngs
+5ydrogen
+9gens
+6steric
+9rics
+4jacobin
+9ins
+6m
+7ming
+9ngs
+4kickback
+6ng
+8s
+5nock
+9s
+4labor
+5eak
+6ft
+6gomena
+6prosy
+7ton
+9ns
+6ukemic
+5iberal
+9alism
+9alisms
+9als
+9tarian
+6fe
+8r
+9s
+6terate
+9ates
+7ter
+9ring
+5ock
+6g
+7arithm
+9ithmic
+9ithms
+7ical
+8es
+7ous
+7s
+7y
+6pine
+5ynching
+4macassar
+9sars
+7ho
+6gnetic
+6laria
+9ial
+9ials
+7e
+6n
+7agement
+9ements
+6rijuana
+7ket
+6sk
+8s
+7que
+9es
+6terialism
+9ialist
+7ter
+9rs
+5echanist
+9nists
+6re
+8s
+7ger
+7ic
+8sm
+9ms
+6tabole
+9oles
+9olic
+9olics
+9olite
+9olites
+8theses
+9hesis
+5icrobial
+9bials
+6litarism
+9arisms
+9arist
+9arists
+9ary
+6ne
+6ssile
+9les
+6totic
+9ics
+5nemonic
+9nics
+5odern
+9nist
+9nists
+9ns
+6narchical
+9chist
+9chists
+8te
+9es
+7ial
+9ls
+9te
+9tes
+8c
+8de
+9es
+8es
+8ous
+8te
+9es
+7opolist
+9olists
+9oly
+8us
+7y
+8l
+9s
+6squito
+5uon
+8s
+6sic
+9al
+9s
+6tagen
+9ens
+5ycin
+9s
+7otic
+4narrative
+9tives
+6tional
+9nalist
+7ural
+9e
+9es
+6usea
+5eoplastic
+6phritic
+9itics
+7otism
+9isms
+6utrino
+9inos
+9on
+9ons
+5g
+6s
+5odal
+7e
+8s
+6ise
+9s
+6me
+8s
+7ian
+9nism
+9nisms
+9ns
+8c
+9al
+9ally
+8es
+7y
+6vel
+9ist
+9ists
+9s
+5uclear
+9arist
+9arists
+9on
+9ons
+6ke
+8r
+9s
+8s
+4obesities
+9ty
+6scenities
+9nity
+5dontalgic
+9algics
+5xidant
+9nts
+5zonant
+9nts
+4papal
+6rallel
+9lels
+8sitic
+9itics
+7ticle
+9cles
+9es
+8y
+6sti
+8o
+9s
+6thetic
+9tical
+8ic
+9es
+9st
+9sts
+8y
+5eriodic
+9dics
+8stalses
+9talsis
+9taltic
+9tases
+9tasis
+7sonnel
+8pirant
+9irants
+6sticide
+6talous
+5hlogistic
+9istics
+6on
+8al
+9lly
+9ls
+9ries
+9ry
+8er
+9rs
+8ic
+9cal
+9cally
+9es
+8s
+8y
+6rases
+9is
+9tic
+9tical
+5ill
+6racies
+9y
+5lague
+9es
+7que
+6easure
+9ures
+5oaching
+6dal
+9s
+7e
+8an
+9ns
+8s
+6etic
+6lar
+7e
+8s
+7ice
+8tical
+9ics
+7lution
+9tions
+6pe
+8s
+7ular
+6t
+6verty
+5redator
+9tors
+7ss
+6ogressive
+7ton
+9ns
+6uritic
+9tics
+5sychiatry
+9otic
+9otics
+5yic
+8s
+6reses
+9is
+8tic
+9ics
+7ine
+9es
+4quarian
+9anism
+9anisms
+9ans
+9es
+8k
+9s
+8y
+7te
+9d
+9dness
+9s
+8ing
+9on
+9ons
+6e
+7d
+7ly
+7ness
+9sses
+7r
+8s
+7s
+7y
+6ing
+7tarian
+9rians
+8ies
+8y
+4rabies
+6chitic
+9tics
+7ism
+9ms
+9t
+9ts
+6dar
+9s
+7ical
+9alism
+9alisms
+6pe
+6tional
+9nalism
+9nalist
+9nality
+5ealism
+9sms
+9st
+9sts
+6cession
+9sions
+6d
+6flection
+9ctive
+7orm
+6gulatory
+6jection
+6ligion
+9ious
+6publican
+9licans
+6troviral
+9virals
+5heumatic
+9atics
+5iot
+6tualism
+9lisms
+5ock
+6ll
+6mantic
+9ticism
+9tics
+6yal
+9ist
+9ists
+5rhinum
+9ums
+5ust
+8s
+4s
+5ag
+6tellite
+5cian
+9s
+7ence
+9ces
+9tific
+6orbutic
+9utics
+6riptural
+5ecrecy
+6gregation
+6izure
+6nse
+7timental
+6palous
+8ratist
+9atists
+7ses
+8is
+7tic
+9cally
+9cise
+9cised
+9cises
+9cising
+9cism
+9cisms
+9cize
+9cized
+9cizes
+9cizing
+9cs
+6ra
+7um
+9s
+6x
+7ist
+9ts
+7ual
+9lities
+9lity
+5hake
+9s
+7rk
+6ip
+6ock
+9s
+7plifting
+5kid
+5laveries
+9ry
+6eep
+6ip
+5mog
+7ke
+9r
+9rs
+8ing
+6uggling
+7t
+5nob
+8s
+5ocial
+9lism
+9lisms
+9list
+9lists
+9lities
+9lity
+9lly
+6lar
+5pam
+7smodic
+9odics
+8t
+9ic
+9s
+6eculation
+9lative
+7nding
+5tat
+8e
+8ic
+9cs
+8s
+6ick
+6ories
+8y
+6ress
+7ike
+7ophe
+9hes
+9hic
+9hon
+9hons
+6udent
+6yle
+9s
+5ubmarine
+7sidy
+7version
+9rsions
+9rsive
+9rsives
+6icide
+5ymmetric
+6philitic
+9litics
+6zygies
+9y
+4takeover
+6nk
+6rnish
+6x
+5echnology
+6rrorism
+9risms
+9rist
+9rists
+5halian
+6eft
+7ism
+9ms
+9t
+9tic
+9ts
+7oretical
+7ses
+8is
+7t
+8ic
+9cal
+9cally
+8s
+6rombin
+9bins
+9botic
+9botics
+6yroid
+5obacco
+6xic
+8n
+9s
+5rade
+9s
+8itional
+7gi
+8us
+7nspirant
+6initarian
+6ust
+9er
+9ers
+5ubercular
+9culous
+6mor
+9al
+9s
+6ssive
+9ves
+5ypal
+7e
+8s
+7hoid
+7ic
+9al
+9ally
+4ulcer
+5nion
+7versity
+5rban
+4venene
+9es
+7in
+9s
+7om
+9s
+5iolence
+6ral
+9s
+7us
+9es
+6tamin
+9ins
+6visection
+4war
+5ear
+6ed
+6lfare
+5haling
+6ite
+5oman
+6rld
+9s
+5rinkle
+3ler
+6ed
+6s
+4ia
+6e
+6te
+5ke
+5on
+7s
+3oninianus
+9nuses
+5omasia
+9ias
+9tic
+5ym
+7ic
+8es
+7ous
+7s
+7y
+3pitta
+8s
+3ra
+5l
+4e
+5s
+4orse
+8ly
+4um
+6s
+3s
+4ier
+6st
+5ness
+9es
+4y
+3wackie
+2ucleate
+9d
+3ral
+5n
+6s
+4eses
+6is
+5tic
+4ia
+6s
+5c
+4ous
+2vil
+5ed
+5ing
+5led
+6ing
+5s
+5top
+8s
+2xieties
+6y
+4olytic
+9cs
+5us
+7ly
+7ness
+9sses
+2y
+3bodies
+6y
+3how
+3more
+3on
+5e
+6s
+5s
+3place
+3road
+3thing
+8arian
+9rians
+8s
+4ime
+3way
+6s
+4hen
+6re
+8s
+5ither
+4ise
+2ziani
+1orist
+6ic
+8ally
+6s
+3ta
+5e
+5l
+5s
+4ic
+5tis
+8es
+4ographic
+9hies
+9hy
+2udad
+6s
+1pace
+4he
+6s
+3dana
+7s
+3ge
+4oge
+7s
+6ic
+8al
+9lly
+3id
+3nage
+7d
+7s
+3rejo
+7s
+4t
+5heid
+9s
+6otel
+9ls
+5ment
+9al
+9s
+5ness
+9es
+3tetic
+4haton
+9s
+5etic
+9al
+9ally
+5ies
+5y
+4ite
+7s
+4osaur
+9s
+9us
+9uses
+3y
+4d
+4ing
+4s
+2e
+3ak
+3d
+4om
+6s
+3ek
+3hood
+7s
+3like
+3man
+4en
+3psia
+7s
+6es
+5y
+3r
+4cu
+6s
+4ient
+8s
+6s
+5odic
+9ally
+9ities
+9ity
+5tif
+8s
+7ve
+9s
+4s
+4t
+5ness
+9es
+5ural
+7e
+8d
+8s
+4y
+3s
+3talies
+6ous
+6y
+3x
+4es
+2gar
+2haereses
+8is
+7tic
+4gia
+7s
+4kia
+7s
+4nipterous
+6te
+8s
+7ic
+4sia
+7c
+8s
+7s
+6c
+7s
+3elandra
+9as
+5ia
+7n
+6on
+8s
+7tropic
+9opism
+9opisms
+4reses
+7is
+6tic
+4ses
+5is
+4tic
+7ally
+6se
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+3icide
+8s
+4d
+5es
+5ian
+8s
+6cide
+9es
+6ous
+5s
+4s
+3olate
+8s
+4nia
+7s
+6c
+7s
+6es
+5ous
+5y
+4rise
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+9cally
+8s
+6ze
+8d
+8r
+9s
+8s
+7ing
+4tic
+3rodisia
+9ac
+9acal
+9acs
+9as
+7te
+9s
+3tha
+6e
+5ous
+3yllies
+6ous
+6y
+2iaceous
+4n
+4rian
+8s
+6es
+6st
+8s
+5y
+3cal
+6ly
+6s
+4es
+4ian
+4ulate
+6i
+6tural
+9e
+9es
+9ist
+9ists
+6us
+3ece
+4zon
+3mania
+8s
+3ng
+3ol
+5ogies
+7y
+5s
+3sh
+5ly
+5ness
+9es
+4m
+5s
+3therapies
+9y
+3vorous
+2lacental
+4nat
+7ic
+9ally
+8sm
+9ms
+7s
+5etic
+5ogamete
+9etes
+6spore
+9res
+4sia
+7s
+5tic
+3enty
+3ite
+6s
+5ic
+3omb
+6s
+3ustre
+8s
+2nea
+5l
+5s
+4ic
+4uses
+6is
+6tic
+3oea
+6l
+6s
+5ic
+2o
+3apses
+6ides
+7s
+3calypse
+9es
+8tic
+9ical
+9ically
+9icism
+9icisms
+9ism
+9isms
+9ist
+9ists
+5rp
+7ies
+7ous
+7s
+7y
+5tastases
+9asis
+4hromat
+9tic
+9tism
+9tisms
+9ts
+4opate
+9d
+9s
+8ing
+9on
+9ons
+6e
+7s
+6ic
+4rine
+5ypha
+9l
+9lly
+9lness
+8on
+4ynaceous
+6thion
+9ons
+3d
+4al
+4e
+5ictic
+9cal
+9cally
+5s
+4ictic
+9al
+9ally
+4oses
+6is
+5us
+4s
+4yterium
+9ums
+3enzyme
+9s
+3gaeic
+5mic
+7es
+6ous
+9ly
+6y
+4eal
+6n
+5e
+6s
+5ic
+5otropic
+9pism
+9pisms
+4raph
+8s
+3laustic
+9cs
+4ipoprotein
+9oteins
+5tical
+9lities
+9lity
+9lly
+8ism
+9sms
+4lo
+6nian
+8con
+9ons
+6s
+4og
+6al
+6etic
+9cal
+9cally
+9cs
+6ia
+8e
+8s
+7es
+7se
+9d
+9r
+9rs
+9s
+8ing
+8t
+9s
+7ze
+9d
+9r
+9rs
+9s
+8ing
+6s
+6ue
+8s
+6y
+4une
+7s
+3mict
+7ic
+9al
+9ally
+7s
+5xes
+6is
+4orphia
+9as
+9ne
+9nes
+3neuroses
+9is
+8tic
+3op
+3pemptic
+4hases
+7is
+6tic
+5legmatic
+9atics
+5onies
+7y
+5thegm
+9matic
+9matise
+9matist
+9matize
+9ms
+5yge
+8s
+6llite
+9tes
+6sate
+7eal
+8s
+7ial
+8s
+4last
+8s
+5ectic
+9cal
+9cally
+9cs
+6x
+7ed
+8s
+7ies
+8ng
+7y
+4rotein
+9ns
+4toses
+7is
+6tic
+3retic
+4ia
+6s
+4t
+3s
+4ematic
+9cally
+4iopeses
+9is
+8tic
+5tia
+8s
+7c
+4poric
+8es
+7ous
+7y
+4tacies
+7y
+6sies
+7y
+6te
+8s
+7ic
+9al
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+5il
+7le
+9s
+7s
+5le
+7s
+8hip
+9ips
+5olate
+9es
+7ic
+9al
+9ally
+9ism
+9isms
+9ities
+9ity
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+5rophe
+9es
+9ic
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9us
+9uses
+3thecaries
+9y
+7e
+8s
+7ia
+9l
+8um
+6gm
+8atic
+9tical
+9tise
+9tised
+9tises
+9tising
+9tist
+9tists
+9tize
+9tized
+9tizes
+9tizing
+8s
+6m
+7s
+6oses
+8is
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+4ropaic
+9cally
+9sm
+9sms
+7ous
+3zem
+6s
+2p
+3aid
+5r
+6ed
+6ing
+6s
+4l
+5l
+6ed
+6ing
+9ly
+6s
+5oosa
+9s
+5s
+5ti
+6o
+4nage
+8d
+8s
+4rat
+7chik
+9iki
+9iks
+7s
+7us
+9es
+5el
+7ed
+7ing
+7led
+8ing
+7ment
+9nts
+7s
+6ncies
+8y
+7t
+8ly
+8ness
+9esses
+8s
+5ition
+9nal
+9ns
+7or
+9s
+5tement
+9nts
+4ssionato
+4y
+5d
+5ing
+5s
+3each
+7ed
+8s
+7ing
+7ment
+9nts
+5l
+6abilities
+9lity
+8le
+6ed
+7r
+8s
+6ing
+9ly
+9ness
+9nesses
+6s
+5r
+6ance
+9es
+6ed
+7r
+8s
+6ing
+6s
+5sable
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9ly
+4l
+5lant
+9s
+7te
+8ion
+9onal
+9ons
+9ve
+9vely
+9ves
+6ee
+8s
+6or
+8s
+5s
+4nd
+6age
+9s
+7nt
+9s
+6ectomies
+9omy
+7d
+7nt
+9s
+6icectomy
+9s
+8ites
+9tides
+9tis
+9tises
+8le
+9es
+8ular
+9larian
+9late
+7ng
+7x
+8es
+6s
+4rceive
+9ed
+9es
+9ing
+7ption
+9ions
+9ive
+6ipient
+5il
+7l
+8s
+7s
+5tain
+9ance
+9ances
+9ed
+9ing
+9ment
+9ments
+9s
+6inent
+9nts
+4stat
+8s
+4teezement
+9ments
+6nce
+9s
+8ies
+8y
+7t
+5ible
+6se
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+9gly
+6te
+8s
+7ion
+9ns
+8ve
+6ze
+8d
+8r
+9s
+8s
+7ing
+9gly
+3laud
+7able
+9ly
+7ed
+8r
+9s
+7ing
+9gly
+7s
+6se
+8s
+7ive
+9ely
+4e
+5cart
+9s
+5drain
+9ns
+5jack
+9s
+5ringie
+9ies
+5s
+6auce
+9es
+5t
+6s
+5y
+4iable
+6nce
+9s
+5cabilities
+9lity
+8le
+9eness
+9y
+7nt
+9s
+7te
+8ion
+9ons
+9ve
+9vely
+8or
+9rs
+9ry
+5ed
+6r
+7s
+6s
+5que
+8d
+8ing
+8s
+4y
+5ing
+3oggiatura
+9uras
+9ure
+4int
+7ed
+8e
+9s
+8r
+9s
+7ing
+8ve
+7ment
+9nts
+7or
+9s
+7s
+4rt
+6ion
+9able
+9ed
+9er
+9ers
+9ing
+9ment
+9ments
+9s
+6s
+4sable
+5e
+6d
+6r
+7s
+6s
+5ing
+6te
+8ly
+8ness
+9esses
+7ion
+9nal
+9ns
+8ve
+9ely
+9es
+3raisable
+8l
+9s
+7e
+8d
+8e
+9s
+8ment
+9ents
+8r
+9s
+8s
+7ing
+9gly
+8ve
+9ely
+4eciable
+9ly
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9ively
+9or
+9orily
+9ors
+9ory
+5hend
+9ed
+9ing
+9s
+8sible
+9ibly
+9ion
+9ions
+9ive
+9ively
+5ntice
+9ed
+9ehood
+9ehoods
+9ement
+9ements
+9es
+9eship
+9eships
+9ing
+5ss
+7ed
+8s
+7ing
+7oria
+9ium
+4ise
+7d
+7r
+8s
+7s
+6ing
+9s
+5ze
+7d
+7r
+8s
+7s
+6ing
+9s
+4o
+5ach
+8ability
+9ble
+8ed
+9s
+8ing
+5bate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8ory
+5of
+7s
+5pinquate
+9uated
+9uates
+9uating
+9uation
+9ue
+9ued
+9ues
+9uing
+9uities
+9uity
+6riable
+9cies
+9cy
+9te
+9ted
+9tely
+9teness
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+5s
+5vable
+9y
+7l
+8s
+7nce
+9es
+6e
+7d
+7r
+8s
+7s
+6ing
+9ly
+5ximal
+9te
+9ted
+9tely
+9tes
+9ting
+9tion
+9tions
+9tive
+3s
+3ui
+5ed
+5s
+4lse
+7s
+6ive
+9ly
+4rtenance
+9nces
+9nt
+9nts
+4y
+5ed
+5ing
+5s
+2ractic
+4xia
+7s
+6c
+3es
+3icate
+8d
+8s
+7ing
+8on
+9ns
+5ock
+8s
+6t
+7s
+4orism
+9s
+8t
+9s
+7ties
+8y
+3on
+5ed
+5ful
+8s
+5ing
+5like
+5s
+4pos
+4tic
+2saras
+7es
+3e
+4s
+3idal
+5es
+5iole
+9s
+4s
+3o
+4s
+2t
+3amer
+7s
+3ed
+4r
+5al
+5ia
+6sm
+8s
+6um
+5ous
+5ygial
+6x
+7es
+4st
+3ing
+4tude
+8s
+7inal
+9ally
+3ly
+3ness
+7es
+3ote
+6s
+5ic
+3s
+2yrase
+7s
+4etic
+5xia
+8s
+1qua
+4batic
+9s
+5oard
+9s
+4cade
+8s
+5eutical
+9cals
+5ultural
+9re
+9res
+9rist
+9rists
+4drome
+9s
+4e
+5robics
+4farm
+8ed
+8ing
+8s
+5er
+7s
+5it
+7ness
+9sses
+7s
+5ortis
+9ses
+9st
+9sts
+4leather
+9ers
+5ung
+8s
+4manale
+9es
+7ile
+9es
+6rine
+9es
+4naut
+8ics
+8s
+4phobe
+9s
+8ia
+9as
+9c
+9cs
+5lane
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+5orin
+9s
+4relle
+9s
+8ist
+9sts
+5ia
+7l
+7n
+8s
+6ist
+9s
+6st
+8s
+6um
+8s
+5obic
+9s
+4s
+5how
+8s
+4tic
+7ally
+7s
+6nt
+8a
+9s
+8ed
+9r
+9rs
+8ing
+9st
+9sts
+8s
+5one
+8s
+4vit
+7s
+3educt
+8s
+4ous
+7ly
+3icultural
+9re
+9res
+9rist
+9rists
+4fer
+7ous
+7s
+5oliaceous
+4legia
+9s
+5ine
+7ities
+9y
+5on
+7s
+4ver
+1r
+2aara
+6s
+3ba
+5s
+4esk
+7s
+6que
+9d
+9s
+4ic
+6a
+7s
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+5lities
+8y
+5n
+6ose
+9s
+8ide
+9des
+6s
+5s
+6ation
+9ons
+6e
+7d
+7s
+6ing
+5zation
+9ons
+6e
+7d
+7s
+6ing
+4le
+6s
+3ceous
+4hidonic
+6s
+7es
+5nid
+8an
+9ns
+8s
+6oid
+9al
+9itis
+9itises
+9s
+7logical
+9gies
+9gist
+9gists
+9gy
+7phobe
+9obes
+9obia
+9obias
+9obic
+9obics
+3eometer
+9rs
+8ric
+9ical
+9ies
+9y
+5style
+9es
+6ystyle
+9yles
+3gonite
+9s
+8ic
+3ise
+6d
+6s
+5ing
+3k
+4s
+3lia
+6ceous
+6s
+3me
+5s
+4id
+6s
+3neid
+7an
+7s
+5ous
+3paima
+8s
+4onga
+8s
+4unga
+8s
+3r
+4oba
+7s
+4s
+3ucaria
+9n
+9s
+3yse
+6d
+6s
+5ing
+2b
+3a
+4lest
+8er
+9rs
+8s
+5ist
+8er
+9rs
+8s
+4s
+3elest
+8s
+3iter
+7s
+5rable
+7ge
+9d
+9r
+9rs
+9s
+9ur
+9urs
+8ing
+7l
+7ment
+9nts
+7rily
+9ness
+9nesses
+8y
+7te
+9d
+9s
+8ing
+9on
+9onal
+9ons
+9ve
+8or
+9rs
+8rices
+9ix
+9ixes
+6ement
+9nts
+7ss
+9es
+6ium
+9s
+3last
+7er
+9s
+7s
+3or
+5aceous
+5eal
+8ly
+6d
+6ous
+6s
+7cence
+9nces
+9nt
+6t
+7a
+7s
+7um
+9s
+5icultural
+9ture
+9tures
+9turist
+6o
+7s
+6sation
+9ions
+7e
+8d
+8s
+7ing
+7t
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ous
+5s
+5vitae
+9es
+4ur
+6ed
+6s
+4viral
+7us
+9es
+3s
+3uscle
+8s
+6ular
+4te
+6an
+6s
+5us
+7es
+2c
+3ade
+6d
+6s
+5ia
+7n
+8s
+7s
+6ng
+8s
+4na
+6s
+5e
+6ly
+6ness
+9ses
+5ist
+8s
+5um
+7s
+4ture
+8s
+3cosine
+9s
+3ed
+3h
+4aea
+7l
+7n
+8s
+6bacteria
+9terium
+6i
+6obotanies
+9tanist
+9tany
+7logical
+9gies
+9gist
+9gists
+9gy
+7metric
+9tries
+9trist
+9trists
+9try
+7n
+7pteryx
+9eryxes
+7rnis
+9ises
+7zoology
+6us
+6zoologies
+9logy
+5ic
+7al
+9ly
+7ism
+9ms
+6se
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+8s
+6ze
+8d
+8r
+9s
+8s
+7ing
+5ngel
+9ic
+9s
+4bishop
+9pric
+9prics
+9ps
+4deacon
+9nries
+9nry
+9ns
+5iocesan
+9se
+9ses
+5ruid
+9s
+5ucal
+7hess
+9sses
+8ies
+8y
+6ke
+8dom
+9oms
+8s
+4ean
+5d
+5gonia
+9al
+9ate
+9ates
+9um
+5i
+5nemies
+8y
+6tera
+9ic
+9on
+9ons
+5oastronomy
+6botanies
+9anist
+9anists
+9any
+6logical
+9ically
+9ies
+9ist
+9ists
+9y
+6magnetism
+7etries
+9ry
+6zoologies
+9logist
+9logy
+5r
+6ess
+9es
+6fish
+9hes
+6ies
+6s
+6y
+5s
+6pore
+9es
+9ia
+9ial
+9ium
+6t
+5typal
+9lly
+8e
+9s
+8ical
+9cally
+5us
+4fiend
+9s
+5oe
+7s
+4genethliac
+9hliacs
+4icarp
+9s
+5diaconal
+9onate
+9onates
+5episcopacy
+9copal
+9copate
+5l
+6owe
+9s
+6s
+5mage
+9s
+7ndrite
+9rites
+5ne
+7s
+6g
+7s
+5pelagian
+9gic
+9go
+9goes
+9gos
+6honeme
+9emes
+6lasm
+9mic
+9ms
+5tect
+9ed
+9ing
+9onic
+9onics
+9s
+9ural
+9urally
+9ure
+9ures
+6rave
+9ed
+9es
+6ype
+9s
+5val
+6e
+7d
+7s
+6ing
+7st
+9s
+6olt
+9s
+4let
+7s
+5ute
+8s
+5y
+4ness
+8es
+4ologies
+8y
+5n
+6s
+7hip
+9ps
+6tate
+9es
+7ic
+5plasm
+9mic
+9ms
+5saur
+9ian
+9s
+4priest
+9thood
+9thoods
+9ts
+9tship
+9tships
+4rival
+9s
+4stone
+9s
+4way
+7s
+5ise
+3iform
+4ng
+6s
+3ked
+4ing
+7s
+3min
+6s
+6ute
+9s
+3o
+4graph
+9s
+4logies
+7y
+4s
+3s
+4ec
+6ond
+9s
+6s
+4ine
+7s
+3tangent
+9ts
+4ic
+6ally
+6s
+5id
+7s
+4oid
+5phil
+9e
+9es
+9ia
+9ias
+9ies
+9ist
+9ists
+9s
+9y
+3uate
+7d
+7ly
+6ion
+9s
+4balist
+9ts
+4s
+5es
+2d
+3eb
+5s
+4ncies
+6y
+5t
+6ly
+3or
+5s
+4ur
+6s
+3ri
+5gh
+7s
+5s
+3s
+3uous
+7ly
+7ness
+9sses
+2e
+3a
+4ch
+6ed
+7s
+6ing
+4d
+5ing
+5s
+4e
+4l
+5ly
+4r
+4s
+4way
+7s
+3ca
+5s
+4oline
+9s
+3d
+4d
+4e
+5s
+4ing
+3faction
+9ns
+4ied
+6s
+4y
+5ing
+3g
+3ic
+3na
+5ceous
+5s
+5tion
+9s
+4e
+5s
+4icolous
+5te
+7s
+6ic
+4ose
+5us
+3ocentric
+4graphic
+9ies
+9y
+4la
+6e
+6r
+6s
+6te
+8d
+7ion
+9ns
+5e
+6s
+5ogies
+7y
+4meter
+9s
+4style
+9s
+5ystile
+9les
+3pa
+5s
+3re
+3s
+3t
+4e
+5s
+4husa
+8s
+4s
+4t
+5ed
+5ing
+5s
+3w
+2f
+3s
+3vedsonite
+9ites
+2gal
+5a
+6s
+5i
+6s
+5s
+4n
+5d
+6s
+5s
+3emone
+8s
+4nt
+6al
+6ic
+7ferous
+7ne
+9s
+7te
+9s
+6ous
+6s
+6um
+8s
+3h
+4an
+6s
+3il
+5laceous
+6iferous
+7te
+9s
+8ic
+5s
+4nase
+8s
+5ine
+8s
+3le
+5d
+5s
+4ing
+3ol
+5s
+4n
+5aut
+8ic
+8s
+5on
+7s
+5s
+4sies
+5y
+4t
+5ic
+5s
+3uable
+7y
+4e
+5d
+5r
+6s
+5s
+4fied
+7r
+8s
+7s
+5y
+6ing
+4ing
+4li
+5us
+4ment
+8a
+9tion
+9tions
+9tive
+9tively
+8ive
+8s
+8um
+9ms
+4s
+5es
+4te
+6ly
+6ness
+9ses
+3yle
+6s
+5l
+6s
+4ria
+7s
+6te
+8s
+5odite
+9es
+2hat
+5s
+6hip
+9s
+3ythmia
+9s
+8c
+2ia
+4ry
+4s
+3boflavinoses
+9inosis
+3d
+4er
+5st
+4ities
+6y
+4ly
+4ness
+8es
+3el
+5s
+4tta
+7s
+6e
+7s
+3ght
+3ki
+5s
+3l
+4ed
+4lary
+6te
+8d
+5i
+5ode
+8s
+6id
+5us
+4s
+3ose
+5i
+5o
+6s
+4t
+3pple
+3s
+4e
+5n
+5s
+4h
+5es
+4ing
+4ta
+6e
+6s
+6te
+5o
+6cracies
+9cy
+9t
+9tic
+9tical
+9tism
+9tisms
+9ts
+6lochia
+9hias
+8gies
+9y
+6s
+6tle
+9s
+3thmetic
+9cal
+9cally
+9cian
+9cians
+9cs
+6omania
+9nias
+8eter
+9ters
+7phobia
+9obias
+2k
+3ed
+3ing
+4te
+6s
+3ose
+6s
+5ic
+3s
+2le
+4d
+4s
+3ing
+2m
+3ada
+6s
+5illo
+9s
+4gnac
+8s
+4ment
+8aria
+9rium
+9riums
+8s
+4ture
+8d
+8s
+7ing
+3band
+7s
+3chair
+8s
+3ed
+4r
+5s
+4t
+5s
+3ful
+6s
+3gaunt
+3hole
+7s
+3ies
+4ger
+7al
+7o
+8s
+8us
+7s
+4l
+5la
+7e
+7ria
+9as
+8y
+7s
+5s
+4ng
+6s
+4potence
+9ces
+9t
+4stice
+9s
+3less
+5t
+6s
+4ike
+4oad
+7s
+5ck
+7ed
+7ing
+7s
+3oire
+7s
+4nica
+8s
+4r
+5ed
+6r
+7s
+5ial
+8ly
+8s
+6es
+6ng
+6st
+8s
+5less
+5s
+5y
+4ur
+6ed
+7r
+8s
+6ies
+7ng
+6less
+6s
+6y
+4zeen
+8s
+5ine
+8s
+3pit
+6s
+3rest
+7s
+3s
+4ful
+3ure
+6s
+3y
+4worm
+8s
+2na
+4s
+4tto
+7s
+3ica
+6s
+3otto
+7s
+3ut
+5s
+2oba
+5s
+3ha
+5s
+3id
+5s
+4nt
+6ed
+6ing
+6s
+3lla
+6s
+3ma
+5s
+5tase
+9s
+6herapies
+9apist
+9apists
+9apy
+6ic
+8ally
+8ities
+9ty
+8s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+3se
+3und
+4sable
+6l
+7s
+5e
+6d
+6r
+7s
+6s
+5ing
+3w
+3ynt
+6ed
+6ing
+6s
+2pa
+4s
+3eggiate
+9ed
+9es
+9ing
+9ion
+9ions
+7o
+8ne
+9es
+8s
+4n
+5s
+5t
+6s
+3illera
+9s
+2quebus
+8ade
+9des
+8es
+8ier
+9ers
+2racacha
+9s
+5k
+6s
+4gonite
+9es
+4h
+4ign
+7ed
+8r
+9s
+7ing
+9gs
+7ment
+9nts
+7s
+4nge
+7able
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+5t
+6ly
+4s
+5ed
+6ne
+8s
+6s
+4ught
+4y
+5al
+7s
+5ed
+6r
+7s
+5ing
+5ment
+9s
+5s
+3ear
+6age
+9s
+6s
+4ct
+4ede
+7s
+6ing
+4st
+6able
+7nt
+9s
+7tion
+9ons
+6ed
+7e
+8s
+7r
+8s
+6ing
+9ly
+7ve
+6ment
+9ts
+6or
+8s
+6s
+4t
+5s
+3henotokies
+9ky
+4izal
+4ythmia
+9as
+9c
+3iage
+7s
+4ba
+4de
+6d
+6s
+5ing
+4ere
+6o
+7s
+4s
+5es
+5h
+6es
+4val
+7s
+6nce
+9s
+8ies
+8y
+5e
+6d
+7erci
+6r
+7s
+6s
+5ing
+6sme
+9s
+7te
+9s
+3oba
+6s
+4gance
+9s
+8ies
+8y
+7t
+8ly
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+4ndissement
+9ements
+4w
+5ed
+5grass
+9ses
+5head
+9s
+5ing
+5less
+6ike
+5root
+9s
+5s
+5wood
+9s
+7rm
+9s
+5y
+4yo
+6s
+2s
+3enal
+7s
+6te
+8s
+5iate
+9s
+6c
+7al
+9s
+7s
+6de
+8s
+6ous
+6te
+8s
+5o
+6pyrite
+9ites
+6us
+3heen
+7s
+4in
+6e
+7s
+6s
+3ier
+5st
+4ne
+6s
+5g
+5o
+4s
+3metrick
+9ks
+3on
+5ist
+8s
+6te
+8s
+5ous
+5s
+3phenamine
+9ines
+3y
+2t
+3al
+3efact
+8s
+8ual
+4l
+5s
+4misia
+9s
+8nin
+9ins
+4rial
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+6es
+6ogram
+9ams
+9aphic
+9aphies
+9aphy
+7lar
+8e
+9s
+7tomies
+9my
+7venous
+6tides
+8s
+9es
+5y
+4sian
+3ful
+6ly
+6ness
+9ses
+3house
+8s
+4ralgia
+9as
+9c
+5ectomies
+9my
+5itic
+9ally
+9s
+8des
+8s
+9es
+5odeses
+9is
+7ia
+9e
+9l
+6graphies
+9phy
+6mere
+9es
+9ic
+6pathies
+9hy
+7lasties
+9sty
+7od
+9al
+9an
+9ous
+9s
+6scope
+9pes
+9pic
+9pies
+9py
+7es
+7is
+7pore
+9res
+9ric
+9rous
+3i
+4c
+5hoke
+9s
+5le
+7d
+7s
+6ing
+5s
+5ulable
+8cies
+9y
+8r
+8te
+9ed
+9ely
+9eness
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+4er
+5s
+6t
+4fact
+8s
+8ual
+5ice
+8r
+9s
+8s
+7ial
+9lise
+9lised
+9lises
+9lising
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9lness
+4lleries
+9st
+9sts
+8y
+9man
+9men
+5y
+4ness
+8es
+4odactyl
+9ylous
+9yls
+4s
+5an
+7al
+7s
+8hip
+9ips
+5t
+6e
+7s
+6ic
+8al
+9lly
+6ries
+7y
+6s
+3less
+7ly
+7ness
+9sses
+3ocarpus
+9ses
+3s
+4ier
+6s
+7t
+5ness
+9es
+4man
+5en
+4y
+3work
+7s
+3y
+2ugola
+7s
+4ula
+7s
+3he
+5s
+3m
+4s
+3ndinaceous
+3spex
+5ices
+2val
+3icole
+8s
+7ine
+3o
+4s
+2y
+3balloid
+8s
+9es
+3l
+4s
+3taenoid
+9ds
+4enoid
+9al
+9s
+4hmia
+8s
+7c
+1s
+2afetida
+9s
+4oetida
+9as
+3na
+5s
+3r
+4abacca
+9as
+4um
+6s
+2bestic
+7form
+7ne
+6os
+8es
+8is
+7us
+6us
+8es
+2cared
+5iases
+8is
+6d
+7es
+7s
+6s
+4unt
+3end
+6able
+7nce
+9es
+9ies
+9y
+8t
+9ly
+9s
+6ed
+7nce
+9es
+9ies
+9y
+8t
+9s
+7r
+8s
+7ur
+9s
+6ible
+7ng
+6s
+5sion
+9al
+9ist
+9ists
+9s
+7ve
+5t
+6s
+4rtain
+9able
+9ably
+9ed
+9ing
+9ment
+9ments
+9s
+4ses
+5is
+4tic
+7al
+9ly
+7ism
+9ms
+7s
+3i
+4an
+6s
+4dia
+7n
+8s
+7te
+6um
+4tes
+5ic
+7al
+6tious
+3lepiad
+9aceous
+9s
+8s
+9es
+3ocarp
+8ic
+8s
+4gonia
+8um
+4mycete
+9es
+9ous
+4nce
+4rbate
+9s
+6ic
+4spore
+9s
+8ic
+4t
+5s
+3ribable
+6e
+7d
+7s
+6ing
+5ption
+9ns
+8ve
+3us
+2dic
+5s
+2ea
+3ismic
+4ties
+5y
+3palous
+4ses
+5is
+4tate
+5ic
+7ally
+7ise
+9ed
+9es
+9ing
+9m
+9ms
+8ze
+9ed
+9es
+9ing
+7s
+3xual
+7ities
+9y
+7ly
+2h
+3ake
+4me
+6d
+7ly
+7ness
+9sses
+6s
+5ing
+3cake
+7s
+5n
+6s
+3ed
+4n
+4ries
+5y
+4s
+4t
+5s
+3fall
+7s
+3ier
+5st
+4ne
+6ss
+8es
+5g
+4ver
+3key
+6s
+3lar
+6ed
+6ing
+9s
+6s
+4er
+6ed
+6ing
+9s
+6s
+5ss
+3man
+4en
+3ore
+3plant
+8s
+3raf
+5m
+6a
+7s
+6ite
+9s
+6s
+3tanga
+8s
+4ray
+7s
+3y
+2iago
+6s
+3de
+5s
+3nico
+7s
+5ne
+7ly
+6ities
+8y
+2k
+3ance
+7d
+7s
+6ing
+5t
+6ed
+6ing
+6s
+4ri
+6s
+3ed
+4r
+5s
+4ses
+5is
+4w
+5ness
+9es
+3ing
+6s
+3lent
+3oi
+4s
+3s
+2lake
+6d
+6s
+5ing
+4nt
+3eep
+3ope
+4sh
+2mear
+3oulder
+2ocial
+7s
+2p
+3araginase
+9ases
+9e
+9es
+7us
+9es
+5kle
+5tame
+9s
+7te
+9s
+6ic
+3ect
+6able
+6ed
+6ing
+6s
+6ual
+4n
+5s
+4r
+5ate
+8d
+8s
+7ing
+5gation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ill
+9a
+9i
+9oses
+9osis
+9s
+9um
+9ums
+9us
+7ng
+5ities
+7y
+5mia
+8s
+5ous
+5s
+6e
+7d
+7r
+8s
+7s
+6ing
+7on
+9s
+7ve
+9ly
+6oir
+9s
+7r
+8ia
+9es
+9um
+9ums
+8s
+8y
+3halt
+7ed
+8r
+9s
+7ic
+8ng
+8te
+9es
+7s
+7um
+9s
+4eric
+8al
+5terise
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+4odel
+8s
+4yxia
+8l
+8nt
+9ts
+8s
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7es
+6y
+3ic
+5k
+6s
+5s
+4dia
+6oid
+6stra
+9as
+6um
+4ne
+6s
+4rant
+8s
+6ta
+8e
+7e
+8d
+8s
+7ing
+8on
+9nal
+9ns
+7or
+9s
+9y
+5e
+6d
+6r
+7s
+6s
+5in
+7g
+8ly
+8ness
+9esses
+7s
+4s
+5es
+5h
+3lanchnic
+4enium
+9s
+3ort
+6ation
+9ons
+6ed
+6ing
+6s
+4ut
+3rawl
+4ead
+4o
+5s
+5ut
+3s
+2quat
+4int
+2rama
+6s
+2safetida
+9as
+5oetida
+9das
+4gai
+7ed
+7ing
+7s
+4i
+5l
+6able
+7nt
+9s
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+5s
+4m
+5s
+4rt
+6ed
+6ing
+6s
+4ssin
+8ate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+8s
+4ult
+7ed
+8r
+9s
+7ing
+8ve
+9ely
+9eness
+7s
+4y
+5able
+5ed
+6r
+7s
+5ing
+8s
+5s
+3egaai
+8ed
+8ing
+8s
+6i
+7ed
+7ing
+7s
+4mblage
+9es
+9ist
+9ists
+8nce
+9ces
+8unce
+9nces
+7e
+8d
+8r
+9s
+8s
+7ies
+8ng
+7y
+8man
+9en
+8woman
+9omen
+4nt
+6aneous
+7tion
+9ons
+8or
+9rs
+6ed
+7r
+8s
+6ient
+9ts
+7ng
+9ly
+7ve
+9ness
+9nesses
+6or
+8s
+6s
+4rt
+6able
+6ed
+8ly
+7r
+8s
+6ible
+7ng
+7on
+9s
+7ve
+9ly
+9ness
+9nesses
+6or
+8ic
+8s
+8y
+6s
+4ss
+6able
+6ed
+7s
+6ing
+6ment
+9ts
+6or
+8ial
+8s
+9hip
+9hips
+4t
+5less
+5s
+4ver
+7ate
+9ed
+9es
+9ing
+9ingly
+9ion
+9ions
+9ive
+7ed
+7ing
+7s
+4z
+3ibilate
+9ed
+9es
+9ing
+9ion
+9ions
+4duities
+8y
+6ous
+9ly
+9ness
+9nesses
+4ege
+7d
+7s
+6ing
+5nto
+8s
+4gn
+6abilities
+9lity
+8le
+9y
+7t
+8ion
+9ons
+8s
+6ed
+7e
+8s
+7r
+8s
+6ing
+6ment
+9ts
+6or
+8s
+6s
+4milability
+9le
+9ly
+8te
+9ed
+9es
+9ing
+9ion
+9ionism
+9ionist
+9ions
+9ive
+9ively
+9or
+9ors
+9ory
+4st
+6ance
+9es
+8t
+9s
+9ship
+9ships
+6ed
+7r
+8s
+6ing
+7ve
+6or
+8s
+6s
+4ze
+6d
+6r
+7s
+6s
+5ing
+3like
+3ociabilities
+9lity
+8le
+7te
+9d
+9s
+9ship
+9ships
+8ing
+9on
+9onal
+9onism
+9onisms
+9onist
+9onists
+9ons
+9ve
+9vely
+9vities
+9vity
+8or
+9rs
+9ry
+4il
+6ed
+6ing
+6ment
+9ts
+6s
+6zie
+9d
+9ing
+9s
+4nance
+9s
+7t
+8al
+8s
+6te
+8d
+8s
+7ing
+4rt
+6ative
+9vely
+6ed
+8ness
+9esses
+7r
+8s
+6ing
+7ve
+6ment
+9ts
+6s
+4t
+5s
+5t
+6ed
+6ing
+3uage
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9s
+5sive
+4bjugate
+9ted
+9tes
+9ting
+4efaction
+9ions
+5tude
+9s
+4mabilities
+9ity
+7le
+8y
+5e
+6d
+7ly
+6r
+7s
+6s
+5ing
+8ly
+8s
+5psit
+9s
+6tion
+9ns
+8ve
+9ely
+4rable
+6nce
+9s
+5e
+6d
+7ly
+7ness
+9sses
+7s
+6r
+7s
+6s
+5gencies
+9y
+8t
+5ing
+5or
+7s
+3wage
+7d
+7s
+6ing
+3ythment
+9ts
+2table
+4cological
+9ies
+9ist
+9ists
+9y
+4rboard
+5e
+5t
+6ed
+6ing
+6s
+4sia
+7s
+4tic
+7ally
+7ism
+9ms
+6de
+8s
+6ne
+8s
+5ki
+7s
+3eism
+7s
+4lic
+6es
+5y
+4r
+5eognoses
+9osis
+5ia
+7s
+7ted
+6d
+7ian
+9ns
+7s
+6sk
+8ed
+8ing
+8less
+8s
+7m
+8s
+5n
+6al
+5oid
+8al
+8ean
+9ans
+8s
+5s
+5t
+6ed
+6ing
+6s
+3henia
+8s
+7c
+8s
+7es
+6opia
+9as
+9c
+7sphere
+9heres
+9heric
+6y
+4ma
+6s
+6tic
+9al
+9ally
+9s
+4ore
+7s
+3ichous
+4gmatic
+9cally
+9cs
+9sm
+9sms
+6ia
+8s
+4lbe
+7s
+4r
+3omatal
+7ous
+5ous
+4ne
+6d
+6s
+5ied
+7s
+6ng
+6sh
+8ed
+9s
+8ing
+9ngly
+8ment
+9ents
+5y
+6ing
+4op
+4und
+7ed
+7ing
+9gly
+7ment
+9nts
+7s
+3rachan
+9s
+5ddle
+5gal
+8i
+8s
+8us
+5khan
+9s
+5l
+6ly
+6s
+5nd
+6tia
+9s
+5phobia
+9ias
+9ic
+6ophobia
+9obias
+5y
+4ict
+7ed
+7ing
+8on
+9ns
+8ve
+9ely
+7s
+5de
+5nge
+8d
+8nce
+9ces
+9cies
+9cy
+9t
+9tly
+9ts
+8r
+9s
+8s
+7ing
+4obiologies
+9ogist
+9ogists
+9ogy
+6leme
+9es
+6otanies
+9ny
+5chemistry
+6ompass
+9asses
+6yte
+9s
+8ic
+8oma
+9mas
+9mata
+5dome
+9s
+6ynamicist
+9mics
+5fell
+9s
+5geologies
+9ogist
+9ogists
+9ogy
+5hatch
+9hes
+5id
+7s
+5labe
+9s
+7tries
+9y
+6oger
+9rs
+8ic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+5metric
+9ical
+9ies
+9y
+5naut
+9ic
+9ical
+9ically
+9ics
+9s
+7vigation
+9gator
+9gators
+6omer
+9rs
+8ic
+9cal
+9cally
+9es
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+8y
+5phel
+9s
+7obia
+9ias
+9ic
+8tograph
+7ysical
+9ically
+9icist
+9icists
+9ics
+5sphere
+9res
+5tourism
+9isms
+9ist
+9ists
+6urfer
+9ers
+9ing
+9ings
+4ut
+3ucious
+9ly
+6ties
+7y
+4n
+5ned
+6ing
+5s
+4te
+6ly
+6ness
+9ses
+6r
+6st
+3ylar
+2udden
+3nder
+2warm
+4y
+3im
+4ng
+4rl
+3oon
+2yla
+4ee
+6s
+4labic
+4um
+6s
+3mmetric
+9cal
+9cally
+9es
+8y
+4ptomatic
+7te
+9s
+8ic
+9cal
+9cally
+3napses
+7is
+5rtete
+9es
+9ic
+4chronies
+9ism
+9isms
+9ous
+9ously
+9y
+4deta
+7ic
+9ally
+7on
+9s
+4ergia
+9s
+8es
+7y
+4tactic
+3stole
+8s
+7ic
+8sm
+9ms
+1t
+2aata
+6s
+3bal
+6s
+4eg
+6s
+5k
+6s
+4rin
+7e
+8s
+7s
+3camite
+9s
+4tic
+3ghan
+7s
+3laya
+7s
+3man
+6s
+5sco
+8s
+3p
+4s
+3ractic
+9s
+5xia
+8s
+7c
+8s
+7es
+6y
+3vic
+5sm
+7s
+6t
+7ic
+9ally
+7s
+3xia
+6s
+5c
+6s
+5es
+4y
+2chieve
+8d
+8s
+7ing
+2e
+3brin
+7s
+3chnic
+3lectases
+9is
+8tic
+5ioses
+8is
+4ic
+5er
+7s
+3moya
+7s
+4poral
+3nolol
+8s
+3s
+2hame
+6s
+4nasies
+7y
+5or
+7s
+3eise
+7d
+7s
+6ing
+6m
+7s
+6t
+7ic
+9al
+9ally
+7s
+5ze
+7d
+7s
+6ing
+4ling
+8s
+4matic
+9ally
+4naeum
+9s
+5eum
+8s
+4ological
+9es
+8y
+5retical
+5us
+4rine
+8s
+5mancies
+9y
+8ous
+5ogeneses
+9esis
+9ic
+6ma
+8s
+8ta
+9ous
+6scleroses
+9erosis
+9erotic
+4teses
+7is
+5ise
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5oid
+6ses
+7ic
+8s
+6tic
+3irst
+3leta
+7s
+6e
+7s
+6ic
+8ally
+8ism
+9sms
+8s
+3odyd
+7s
+3rill
+4ob
+5cyte
+9s
+8oses
+9sis
+3wart
+7ship
+9ips
+2igi
+5s
+3lt
+3mies
+4y
+3ngle
+3shoo
+7s
+2lantes
+4s
+5es
+4tl
+6s
+2ma
+4n
+5s
+4s
+3ologies
+8st
+9ts
+7y
+5yse
+8d
+8s
+7ing
+8s
+6ze
+8d
+8s
+7ing
+4meter
+9s
+7ries
+8y
+4sphere
+9ed
+9es
+9ic
+9ical
+9ically
+9ics
+2oc
+4ia
+6s
+4s
+3k
+4al
+4e
+5s
+4ous
+4s
+3ll
+5s
+3m
+4ic
+6al
+8ly
+6ities
+8y
+6s
+5es
+5sation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+6m
+7s
+6t
+7ic
+9al
+9ally
+7s
+5zation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+4s
+4y
+3nable
+5l
+6ism
+9s
+8t
+9s
+7ties
+8y
+6ly
+4e
+5able
+5d
+5ment
+9s
+5r
+6s
+5s
+4ia
+6s
+5c
+6ities
+8y
+6s
+5es
+5ng
+7ly
+4y
+3p
+4ic
+5es
+4y
+2rabiliar
+8ous
+9usness
+4curium
+9ms
+4ment
+8al
+8ous
+8s
+4zine
+8s
+3emble
+4sia
+7s
+6c
+4tic
+3ia
+5l
+4p
+4um
+6s
+3ocious
+9ly
+9ness
+9nesses
+6ties
+7y
+4phia
+8s
+7c
+7ed
+8s
+6y
+7ing
+5ia
+7s
+6n
+7e
+8s
+7s
+6sm
+8s
+5ous
+2s
+2t
+3aboy
+4ch
+6able
+6e
+7d
+7r
+8s
+7s
+6ing
+6ment
+9ts
+5k
+6able
+6ed
+7r
+8s
+6ing
+6man
+7en
+6s
+4girl
+4in
+6abilities
+9lity
+8le
+9eness
+6der
+9s
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+6t
+7ed
+7ing
+7ment
+9nts
+7s
+7ure
+9es
+4p
+5s
+4r
+5s
+4sk
+6ed
+6ing
+6s
+6t
+3emper
+8ed
+8ing
+8ment
+9ents
+8s
+6t
+7ability
+9le
+7ed
+8r
+9s
+7ing
+7s
+4nd
+6ance
+9es
+9ies
+9y
+8t
+9s
+6ed
+7e
+8s
+7ment
+9nts
+7r
+8s
+6ing
+9s
+6ment
+9ts
+6s
+5t
+6at
+8s
+6ion
+9al
+9s
+7ve
+9ly
+9ness
+9nesses
+6s
+5uant
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+4rcop
+8s
+4st
+6able
+7nt
+9s
+7tion
+9ons
+9ve
+8or
+9rs
+6ed
+7r
+8s
+6ing
+6or
+8s
+6s
+3ic
+5ise
+8d
+8s
+7ing
+7m
+8s
+7t
+8s
+6ze
+8d
+8s
+7ing
+5s
+4re
+6d
+6ment
+9ts
+6s
+5ing
+8s
+4tude
+8s
+7inal
+9ally
+9arian
+9arians
+9ise
+9ised
+9iser
+9isers
+9ises
+9ising
+9isings
+9ize
+9ized
+9izer
+9izers
+9izes
+9izing
+9izings
+3olaser
+9s
+5lens
+8t
+9s
+4nce
+5e
+6d
+6s
+5ing
+4physics
+4rn
+6ed
+7y
+8dom
+9oms
+8ed
+8ing
+9sm
+9sms
+8s
+9hip
+9hips
+6ing
+6ment
+9ts
+6s
+3ract
+7able
+8nce
+9ces
+9cies
+9cy
+9t
+9ts
+7ed
+8r
+9s
+7ing
+9gly
+8on
+9ns
+8ve
+9ely
+9eness
+7or
+9s
+7s
+5hens
+8t
+9s
+5p
+6ped
+7ing
+6s
+4ibutable
+8e
+9d
+9r
+9rs
+9s
+8ing
+9on
+9onal
+9ons
+9ve
+9vely
+9veness
+9ves
+8or
+9rs
+5st
+7ed
+7ing
+7s
+5t
+6e
+7d
+7s
+6ing
+7on
+9al
+9s
+7ve
+6s
+6ted
+7ing
+3uent
+4ite
+7d
+7s
+6ing
+7on
+9al
+9s
+7ve
+9ly
+4ne
+6d
+6ment
+9ts
+6s
+5ing
+2ua
+4s
+2wain
+3eel
+5n
+3itter
+4xt
+2ypic
+6al
+8ities
+9ty
+8ly
+1ua
+3s
+2bade
+6s
+3erge
+7s
+6ine
+9s
+7ste
+9es
+3retia
+8s
+4ieta
+8s
+7ia
+9s
+3urn
+6s
+2ceps
+6es
+3tion
+7ary
+7ed
+8er
+9red
+9ring
+9rs
+7ing
+7s
+4orial
+3uba
+6s
+2dacious
+9ly
+9ness
+9nesses
+6ties
+7y
+4d
+5s
+3ial
+4bilities
+9y
+5le
+7d
+7ness
+9sses
+7s
+6ing
+6y
+4ence
+8s
+7ia
+9s
+6t
+7s
+4le
+6s
+4ng
+6s
+4o
+5book
+9s
+5cassette
+9ettes
+5genic
+6ram
+9s
+8ph
+9hs
+5logic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+5meter
+9rs
+8ric
+9ically
+9ician
+9icians
+9ies
+9ist
+9ists
+9y
+5phil
+9e
+9es
+9s
+5s
+5tape
+9d
+9s
+8ing
+6yping
+9ngs
+9st
+9sts
+5visual
+9ally
+9als
+4phone
+9s
+4t
+5able
+5ed
+6e
+7s
+5ing
+6on
+8ed
+9r
+9rs
+8ing
+8s
+6ve
+8s
+5or
+7ia
+9l
+8es
+8ly
+8um
+9ms
+7s
+8hip
+9ips
+7y
+5ress
+9es
+5s
+2e
+2f
+3gabe
+7s
+3s
+2gend
+6s
+4r
+5s
+3ht
+5s
+3ite
+6s
+5ic
+3ment
+7able
+8tion
+9ions
+9ive
+9ively
+9ives
+7ed
+8r
+9s
+7ing
+7or
+9s
+7s
+3ur
+5al
+5ed
+6r
+7s
+5ies
+6ng
+5s
+6hip
+9s
+5y
+4st
+6e
+7r
+7s
+8t
+6ly
+6ness
+9ses
+6s
+2k
+3let
+6s
+3s
+2la
+4rian
+8s
+4s
+3d
+4er
+5st
+3ic
+3nage
+7r
+8s
+7s
+3oi
+4s
+2mail
+6ed
+6ing
+6s
+3bries
+5y
+3il
+5s
+2ne
+4s
+3t
+4er
+6s
+4hood
+8s
+4ie
+6s
+4lier
+7st
+6ke
+5y
+4s
+4y
+2ra
+4e
+4l
+5ities
+7y
+5ly
+4r
+4s
+4te
+6d
+6s
+3eate
+7ly
+7ness
+9sses
+4i
+5ties
+6y
+4lia
+7n
+8s
+7s
+4ola
+7e
+7s
+6e
+7d
+7s
+6ing
+4s
+4us
+3ic
+5le
+7d
+7s
+5ula
+8e
+8r
+9ly
+9s
+8s
+8te
+9ed
+9ely
+4ferous
+5ied
+7s
+5orm
+5y
+6ing
+4s
+5cope
+9s
+8ic
+5t
+6s
+3ochs
+7es
+4ra
+6e
+6l
+7ly
+6s
+5ean
+4us
+3um
+5s
+2scultate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+3form
+7ed
+7ing
+7s
+3lander
+9s
+3pex
+4icate
+9d
+9s
+8ing
+6e
+7s
+6ious
+9sly
+9sness
+3tenite
+9s
+8ic
+5re
+7ly
+7ness
+9sses
+7r
+7st
+6ities
+8y
+4ral
+7es
+7is
+8te
+9es
+7s
+5inger
+9rs
+3ubo
+6s
+2tacoid
+8s
+4rch
+7ic
+9al
+8es
+8st
+9ts
+7s
+7y
+5kic
+8al
+7es
+7st
+9s
+6y
+3ecious
+6sm
+8s
+5ologic
+9ical
+9ies
+9y
+4ur
+6ism
+9s
+8t
+9s
+6s
+3hentic
+9al
+9ally
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ator
+9ators
+9ities
+9ity
+4igenic
+4or
+6craft
+9fts
+6ed
+7ss
+9es
+6ial
+7ng
+9s
+7sable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8h
+8ing
+8m
+9s
+7tarian
+9rians
+9tive
+9tively
+8ies
+8y
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6less
+6s
+7hip
+9ps
+3ism
+6s
+5t
+6ic
+8ally
+8s
+6s
+3o
+4allogamies
+9amy
+5ntibodies
+9ody
+4bahn
+8en
+8s
+5iographer
+9aphers
+9aphic
+9aphies
+9aphy
+5us
+7es
+7ses
+4cade
+8s
+6r
+7p
+8s
+7s
+6talyse
+9ysed
+9yses
+9ysing
+9ysis
+9ytic
+9yze
+9yzed
+9yzes
+9yzing
+5ephalic
+9lies
+9lous
+9ly
+5hanger
+9ers
+6thon
+9nal
+9nes
+9nic
+9nies
+9nism
+9nisms
+9nous
+9nously
+9ns
+9ny
+5idal
+5lave
+9d
+9s
+8ing
+5oid
+8s
+6prophagy
+6rrelation
+5racies
+8y
+7t
+8ic
+9cal
+9cally
+8s
+6ime
+9s
+7ne
+7tique
+9ques
+6oss
+9es
+5ue
+7s
+6tie
+9s
+5ycle
+9s
+4destruct
+9ucted
+9ucting
+9uctive
+9ucts
+5idact
+9tic
+9ticism
+9ts
+5yne
+8s
+4ecious
+9sly
+7sm
+9s
+5d
+5xposure
+9ures
+4flare
+9s
+5ocus
+9es
+4gamic
+8es
+7ous
+7y
+5eneses
+9is
+8tic
+7ic
+9s
+8es
+7ous
+9sly
+7y
+5iro
+8s
+5raft
+9ed
+9ing
+9s
+7ph
+9ed
+9ic
+9ical
+9ically
+9ies
+9ing
+9s
+9y
+7vure
+9res
+5uide
+9s
+5yro
+8s
+4harp
+8s
+5ypnoses
+9sis
+9tic
+4icous
+5mmune
+9ities
+9ity
+5nfection
+9tions
+6g
+6oculation
+5onisation
+9ations
+8zation
+9ations
+4jumble
+9es
+4kineses
+9is
+8tic
+4latries
+8y
+5oading
+6gies
+7ous
+7y
+5ysate
+9es
+7e
+8d
+8s
+7in
+9g
+9s
+8s
+6tic
+6zate
+9es
+7e
+8d
+8s
+7ing
+4magic
+9ally
+6ker
+9s
+6n
+6t
+7a
+8ble
+7e
+8d
+8s
+7ic
+9al
+9ally
+9ities
+9ity
+9s
+8ng
+8on
+9ns
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7on
+9s
+8us
+7s
+5en
+6ter
+9s
+5obile
+9ed
+9es
+9ia
+9ing
+9ism
+9isms
+9ist
+9ists
+9ities
+9ity
+6rphic
+9ically
+9ism
+9isms
+6tive
+4nomic
+9al
+9ally
+9s
+8es
+8st
+9ts
+7ous
+9sly
+7y
+5ym
+7s
+4pen
+7s
+5hagia
+9as
+9es
+8ous
+8y
+7nous
+6obia
+9as
+9es
+8y
+7nies
+8y
+6yte
+9s
+8ic
+9cally
+5ilot
+9s
+6sta
+9s
+5lastic
+9ies
+9y
+5oint
+9s
+6lyploid
+9loids
+9loidy
+5sia
+8s
+7c
+7ed
+8s
+7st
+9s
+6y
+7ing
+5tic
+8al
+9lly
+5ut
+7s
+4radiogram
+9grams
+9graph
+9graphs
+9graphy
+5eplies
+8y
+5ickshaw
+9haws
+5otate
+9ed
+9es
+9ing
+9ion
+9ions
+6ute
+9s
+4s
+5ave
+8d
+8s
+7ing
+5chediasm
+9iasms
+9iastic
+9iaze
+9iazed
+9iazes
+9iazing
+6opic
+9es
+8y
+5exing
+5omal
+9ly
+7e
+8s
+5pore
+9s
+5tabilities
+9lity
+6rada
+9as
+9e
+5uggest
+9sted
+9sting
+9stion
+9stions
+9stive
+9sts
+4telic
+7ler
+9rs
+6st
+8s
+6traploid
+9ploids
+9ploidy
+5heism
+9ms
+9t
+9ts
+5imer
+9s
+5omic
+8es
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7ous
+7y
+6xaemia
+9mias
+7emia
+9ias
+7ic
+8n
+9s
+5ransformer
+9fusion
+6oph
+9ic
+9ically
+9ies
+9s
+9y
+5une
+8s
+5ype
+8d
+8s
+7ic
+8es
+8ng
+7ography
+7y
+4vac
+7s
+4winder
+9rs
+5orker
+9rs
+4xidation
+9ions
+3umn
+6al
+8ly
+6s
+6y
+4nite
+8s
+2xanometer
+9ers
+3eses
+5is
+4tic
+7s
+3iliar
+8ies
+8s
+8y
+4n
+5ic
+5s
+3ochrome
+9es
+5yte
+8s
+4meter
+9s
+4spore
+9s
+4tonic
+5roph
+9ic
+9ies
+9s
+9y
+1va
+3davat
+8s
+3il
+5abilities
+9ity
+7le
+9ness
+9nesses
+8y
+5e
+6d
+6s
+5ful
+5ing
+8ly
+5s
+3l
+4anche
+9d
+9s
+8ing
+4e
+5d
+5s
+4ing
+3nt
+5i
+6st
+8s
+5urine
+9es
+3rice
+7s
+6ious
+9sly
+9sness
+3s
+4cular
+9ities
+9ity
+4t
+3tar
+6s
+3unt
+6ed
+6ing
+6s
+2e
+3l
+4lan
+7e
+4s
+3naceous
+4ge
+6d
+6ful
+6ment
+9ts
+6r
+7ess
+9ses
+7s
+6s
+5ing
+4ir
+6s
+4s
+5es
+4tail
+8e
+9s
+8s
+5re
+7d
+7s
+6ing
+5ure
+8s
+7in
+9e
+9es
+9s
+4ue
+6s
+3r
+4age
+7d
+7ly
+7ness
+9sses
+7s
+6ing
+9s
+4ment
+8s
+4rable
+5ed
+5ing
+5uncate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+4s
+5e
+6ly
+6ness
+9ses
+5ion
+8s
+6ve
+8ly
+8ness
+9esses
+8s
+4t
+5able
+5ed
+7ly
+6r
+7s
+5ible
+6ment
+9ts
+6ng
+5s
+3s
+2gas
+5es
+5ses
+3olemono
+9os
+2ian
+5ise
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5s
+4ries
+6st
+8s
+5y
+4te
+6d
+6s
+5ic
+6ng
+6on
+8s
+5or
+7s
+5ress
+9es
+6ice
+9s
+7x
+8es
+3cular
+6ture
+9es
+9ist
+9ists
+3d
+4er
+5st
+4in
+6s
+5ties
+6y
+4ly
+4ness
+8es
+3ette
+7s
+3fauna
+8e
+8l
+8s
+4orm
+3gator
+8s
+3ne
+3on
+5ic
+7s
+5s
+3rulent
+3sandum
+9s
+4e
+5d
+5ment
+9s
+5s
+4ing
+4o
+5s
+3tal
+5minoses
+9sis
+9tic
+3zandum
+9s
+4e
+5d
+5full
+5s
+4ing
+2o
+3cado
+7es
+7s
+5tion
+9al
+9ally
+9s
+4et
+6s
+3dire
+7s
+3id
+5able
+8y
+6nce
+9s
+7t
+5ed
+6r
+7s
+5ing
+5s
+4rdupois
+9ises
+4sion
+8s
+3parcin
+9s
+3s
+4et
+6s
+3uch
+6able
+6ed
+7r
+8s
+7s
+6ing
+6ment
+9ts
+4re
+6s
+4terer
+9s
+5rer
+8s
+6ies
+6y
+3w
+4able
+8ness
+9esses
+7y
+5l
+6s
+4ed
+6ly
+5r
+6s
+4ing
+4ries
+5y
+4s
+3yer
+6s
+2ruga
+6s
+2ulse
+6d
+6s
+5ing
+6on
+8s
+3ncular
+9ities
+9ity
+9ly
+8te
+9es
+2vogadore
+9es
+2yze
+5d
+5s
+4ing
+1w
+2a
+3it
+5ed
+6r
+7s
+5ing
+5s
+3ke
+5d
+5n
+6ed
+7r
+8s
+6ing
+9s
+6s
+5s
+4ing
+7s
+3nting
+3rd
+5able
+5ed
+6e
+7s
+6r
+7s
+5ing
+5s
+4e
+5ness
+9es
+5r
+5st
+4n
+5ed
+5ing
+5s
+3sh
+3tch
+4o
+5s
+3ve
+3y
+4day
+7s
+4es
+4ness
+8es
+4s
+2dl
+4s
+2e
+3aried
+5y
+4ther
+3d
+3e
+4l
+3igh
+4ng
+3less
+7ness
+9sses
+3s
+4ome
+7ly
+7ness
+9sses
+4tricken
+6uck
+3to
+5s
+2ful
+5ler
+7st
+6y
+5ness
+9es
+3y
+2hape
+6d
+6s
+5ing
+4to
+6s
+3eel
+6s
+4to
+6s
+3ile
+4rl
+2ing
+2k
+3s
+3ward
+7er
+8st
+7ish
+7ly
+7ness
+9sses
+2l
+3bird
+7s
+3ess
+3s
+3wort
+7s
+2mous
+3rie
+6s
+4y
+2n
+3ed
+4r
+5s
+3ier
+5st
+4ng
+6ed
+6s
+3less
+3s
+3y
+2oke
+5n
+3l
+4s
+3rk
+2rack
+3ong
+3y
+2some
+1x
+2al
+2e
+3bird
+7s
+3d
+3l
+4s
+3man
+4en
+3nic
+6ally
+3rophthol
+9ols
+3s
+2ial
+5ities
+7y
+5ly
+3l
+4e
+5mma
+8s
+4la
+6e
+6r
+7ies
+7s
+7y
+6s
+4s
+3ng
+4ite
+7s
+4omancies
+9y
+3ological
+9ally
+8es
+8st
+9ts
+7y
+4m
+5atic
+9al
+9ally
+9s
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5s
+4n
+5s
+3s
+4ed
+5s
+4ymmetric
+9rical
+9ries
+9ry
+3te
+5s
+2le
+4d
+4s
+4tree
+8s
+3ike
+2man
+3en
+2oid
+5s
+3lemma
+8s
+8ta
+4otl
+7s
+3n
+4al
+4e
+5mal
+6e
+7s
+5s
+4ic
+4ometric
+9ies
+9y
+4s
+3plasm
+8ic
+8s
+2seed
+6s
+1y
+2ah
+4s
+4uasca
+9s
+8o
+9s
+3tollah
+9s
+2e
+3lp
+3nbite
+8s
+3s
+2gre
+2in
+4s
+2ont
+2re
+4s
+3ie
+5s
+2s
+2u
+3ntamiento
+9ntos
+3rveda
+8s
+7ic
+9s
+3s
+2word
+6s
+1zalea
+6s
+3n
+4s
+3thioprine
+9ines
+2edarach
+9s
+3otrope
+9s
+8ic
+9es
+8y
+3rty
+2ide
+5s
+4o
+5thymidine
+9idines
+3muth
+7al
+9ly
+7s
+3ne
+5s
+3one
+6s
+2lon
+5s
+2o
+3benzene
+9es
+3ic
+3le
+5s
+4la
+6s
+3n
+4al
+4ic
+4s
+3ospermia
+9ias
+9ic
+3taemia
+9s
+8c
+4e
+5d
+5mia
+8s
+7c
+5s
+4h
+5s
+4ic
+5se
+7d
+7s
+6ing
+5ze
+7d
+7s
+6ing
+4obacter
+9ers
+5us
+4uria
+8s
+2uki
+5s
+3lejo
+7s
+3re
+5an
+5s
+4ine
+7s
+5te
+7s
+4n
+4y
+2ygies
+4os
+6es
+6pore
+9es
+5us
+7ly
+4y
+3m
+4e
+5s
+4ite
+7s
+4ous
+4s
+0ba
+2a
+3ed
+3ing
+6s
+3l
+4ebatim
+6os
+4im
+5sm
+7s
+4s
+3s
+4es
+4kaap
+8s
+6p
+7s
+4skap
+8s
+2ba
+4co
+6ote
+9s
+6s
+4las
+4s
+5su
+7s
+3belas
+4itries
+7y
+6t
+7ed
+7ing
+7ries
+8y
+7s
+4lative
+5e
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5y
+3e
+4l
+5dom
+8s
+5esque
+5ish
+7m
+8s
+5s
+4s
+5ia
+7s
+8es
+8is
+6oses
+8is
+9ses
+3iche
+7s
+4ed
+5r
+5s
+6t
+4ngtonite
+9ites
+4roussa
+9as
+5usa
+8s
+7sa
+9s
+3ka
+5s
+3lah
+6s
+3oo
+5l
+6s
+5n
+6eries
+8y
+6ish
+6s
+5s
+6h
+7es
+4uche
+8s
+3u
+4che
+7s
+4dom
+7s
+4ism
+7s
+4l
+5s
+4s
+5hka
+8s
+3y
+4doll
+8s
+4food
+8s
+4hood
+8s
+4ing
+5sh
+7ly
+4proof
+9ed
+9ing
+9s
+4sat
+5it
+7s
+7ter
+9rs
+8ing
+2c
+3alao
+7s
+3ca
+5e
+5laurean
+9eate
+9eates
+5ra
+7s
+7t
+8s
+6e
+5s
+5te
+7d
+4hanal
+9ia
+9ian
+9ianism
+9ians
+9s
+7t
+8e
+9s
+8s
+5iac
+7n
+6c
+6i
+6us
+4ies
+5ferous
+6orm
+5vorous
+4o
+5es
+5s
+4y
+3h
+4a
+5rach
+9s
+5s
+4cha
+7s
+4ed
+5lor
+8dom
+9oms
+8ette
+9ttes
+8hood
+9oods
+8ism
+9sms
+8s
+9hip
+9hips
+5s
+4ing
+4s
+3illaemia
+9ias
+7r
+8y
+6emia
+9as
+6i
+7cide
+9des
+7form
+6uria
+9as
+7s
+4tracin
+9ns
+3k
+4ache
+8s
+5re
+4band
+8s
+5eat
+8s
+6nch
+9er
+9ers
+9es
+7d
+8s
+5it
+7e
+8r
+9s
+8s
+7ing
+9gs
+7ten
+5lock
+9er
+9ers
+9s
+5oard
+9s
+6nd
+8s
+7e
+8d
+8less
+8s
+5reaker
+9ers
+9ing
+5urn
+8ed
+8ing
+8s
+4cast
+8ing
+8s
+5hat
+8s
+8ted
+9ing
+6eck
+9ed
+9ing
+9s
+5loth
+9s
+5omb
+8ed
+8ing
+8s
+6untries
+9ry
+7rt
+9man
+9men
+9s
+5ross
+9ed
+9es
+9ing
+4date
+8d
+8s
+7ing
+5oor
+6wn
+8s
+5raft
+9s
+7ught
+9hts
+6op
+8ped
+9ing
+8s
+8t
+4ed
+5r
+6s
+5t
+6s
+4fall
+8s
+5ield
+9s
+6le
+8s
+7l
+8ed
+8ing
+9ngs
+8s
+6re
+8d
+8s
+7ing
+6sch
+9es
+6t
+7s
+7ted
+8ing
+9ngs
+5lip
+8ped
+9ing
+8s
+6ow
+8s
+4gammon
+9ned
+9ning
+9ns
+5round
+9ded
+9der
+9ders
+9ding
+9ds
+4hand
+8ed
+9dly
+9dness
+9r
+9rs
+8ing
+8s
+6ul
+8ed
+8ing
+8s
+5oe
+7d
+7ing
+7s
+6use
+9s
+4ie
+6s
+5ng
+7s
+4land
+8s
+6sh
+8ed
+9r
+9rs
+9s
+8ing
+5ess
+5ift
+8s
+6ght
+9ed
+9ing
+9s
+6st
+8ed
+8ing
+8s
+6t
+5oad
+8ed
+8ing
+8s
+6g
+7ged
+8ing
+7s
+6t
+7s
+4marker
+9rs
+5ost
+4out
+7s
+4pack
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+5edal
+9ed
+9ing
+9led
+9ling
+9s
+5iece
+9s
+5late
+9s
+4ra
+6s
+5est
+8s
+5oom
+8s
+5ush
+8es
+4s
+5aw
+7s
+5catter
+9ered
+9ering
+9erings
+9ers
+6ratch
+9ched
+9cher
+9chers
+9ches
+9ching
+9chings
+5eat
+8s
+6t
+7s
+6y
+7s
+5heesh
+9hed
+9hes
+9hing
+6ish
+9ed
+9es
+9ing
+6ore
+9s
+5ide
+8s
+6ght
+9s
+5lap
+8ped
+9er
+9ers
+9ing
+8s
+7sh
+9es
+6id
+8den
+8e
+9r
+9rs
+9s
+8ing
+9ngs
+5pace
+9d
+9r
+9rs
+9s
+8ing
+6eer
+9ed
+9ing
+9s
+7ir
+9ed
+9ing
+9s
+6in
+8s
+6lash
+9hes
+5tab
+8bed
+9er
+9ers
+9ing
+9ings
+8s
+7ge
+9s
+7ir
+9s
+7ll
+9s
+7mp
+9ed
+9ing
+9s
+7rting
+7y
+8s
+6itch
+9hed
+9hes
+9hing
+6op
+8ped
+9ing
+8s
+7ries
+8y
+6reet
+9ts
+8tch
+9ches
+7oke
+9es
+5wept
+6ing
+9s
+6ord
+9man
+9men
+9s
+9sman
+9smen
+4track
+9ed
+9ing
+9ings
+9s
+4up
+6s
+4veld
+8er
+9rs
+8s
+4ward
+8ation
+9tions
+8ly
+8ness
+9esses
+8s
+6sh
+8ed
+9s
+8ing
+6ter
+9s
+5ood
+8s
+9man
+9men
+9y
+6rd
+8s
+7k
+8er
+9rs
+8s
+5rap
+8s
+4yard
+8s
+3lava
+7s
+4ofen
+8s
+3on
+5er
+7s
+5s
+3s
+3teraemia
+9ias
+6emia
+9as
+9c
+6ia
+8l
+9ly
+9s
+8n
+8s
+7c
+8idal
+9dally
+9de
+9des
+7n
+8s
+7ocin
+9ins
+8id
+9ds
+8logic
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+9yses
+9ysin
+9ysins
+9ysis
+9ytic
+8phage
+9hages
+9hagic
+9hagies
+9hagous
+9hagy
+8ses
+9is
+9tases
+9tasis
+9tat
+9tatic
+9tats
+8toxin
+9oxins
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7um
+8ria
+9ias
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6oid
+9s
+6uria
+9as
+3ula
+5iform
+6ne
+6te
+8s
+5ovirus
+9uses
+5um
+7s
+2d
+3ass
+6ed
+7s
+3deleyite
+9tes
+5r
+6lock
+9ks
+5st
+4ie
+6s
+5sh
+4y
+3e
+3ge
+5d
+5less
+5r
+6ed
+6ing
+6ly
+6s
+5s
+4ing
+3inage
+8d
+8s
+7ing
+5erie
+9s
+4ous
+3land
+7s
+4y
+3man
+5sh
+7es
+4en
+4inton
+9s
+4outh
+8ed
+8ing
+8s
+3ness
+7es
+3s
+3ware
+7s
+2el
+4s
+3tyl
+6s
+2ff
+4ed
+4ies
+5ng
+4le
+6d
+6gab
+9s
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+4s
+4y
+3t
+4s
+2g
+3arre
+7s
+4ss
+6e
+7s
+6oses
+8is
+4telle
+9s
+3el
+5s
+3ful
+6s
+3gage
+7s
+4ed
+5r
+6s
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+5t
+6s
+4y
+3h
+4ouse
+8s
+4s
+3ie
+5s
+3less
+4ike
+3man
+4en
+3nette
+8s
+4io
+6s
+3pipe
+7d
+7r
+8s
+7s
+6ing
+9s
+3s
+4ful
+4winger
+9rs
+3uet
+6s
+6te
+8s
+4io
+6s
+3wash
+7es
+4ig
+6s
+4orm
+7s
+2h
+3ada
+6s
+5ur
+7s
+3t
+4s
+3u
+4s
+4t
+5s
+4vrihi
+9s
+2idarka
+8s
+3gnoire
+9s
+3l
+4able
+4bond
+8s
+4ed
+5e
+6s
+5r
+6s
+5y
+6s
+4ie
+6s
+7hip
+9ps
+5ff
+7s
+8hip
+9ips
+5ng
+5wick
+9s
+4li
+6age
+9s
+6e
+7s
+8hip
+9ips
+6s
+4ment
+8s
+4or
+6s
+5ut
+7s
+4s
+5man
+6en
+3nin
+6s
+5te
+7s
+3rn
+5ish
+5lier
+8st
+7ke
+6y
+5s
+3semain
+9s
+3t
+4ed
+5r
+6s
+4fish
+8es
+4h
+4ing
+7s
+4s
+3za
+5s
+4e
+5d
+5s
+4ing
+2jada
+6s
+4n
+5s
+3ra
+5s
+4ee
+6s
+4i
+5s
+3u
+4s
+2ke
+4apple
+9s
+4board
+9s
+4d
+4house
+9s
+4lite
+8s
+4meat
+8s
+4n
+4off
+7s
+4r
+5ies
+5s
+5y
+4s
+5hop
+8s
+5tone
+9s
+4ware
+8s
+3gat
+3hshish
+9ed
+9es
+9ing
+3ing
+6s
+3kie
+6s
+3lava
+7s
+5wa
+7s
+3ra
+5s
+3sheesh
+9ed
+9es
+9ing
+5ish
+8ed
+9s
+8ing
+2l
+3aclava
+9s
+4din
+7e
+8s
+7s
+4laika
+9s
+4nce
+7able
+7d
+7r
+8s
+7s
+6ing
+9s
+5itis
+9es
+4s
+5es
+4ta
+6s
+3boa
+6s
+4riggan
+9ns
+4utient
+3conet
+8s
+8te
+9es
+6ied
+8s
+6y
+3d
+4achin
+9o
+9os
+9s
+5quin
+9s
+4ed
+5r
+6dash
+9hes
+6locks
+9kses
+5st
+4faced
+4head
+8ed
+8s
+4icoot
+9s
+5e
+6r
+6s
+7t
+5ng
+5sh
+4ly
+4money
+9s
+4ness
+8es
+4pate
+8d
+8s
+4ric
+7k
+8s
+7s
+4s
+4y
+3e
+4ction
+9s
+4d
+4en
+6s
+4fire
+8s
+5ul
+7ly
+7ness
+9sses
+4r
+5s
+4s
+3ibuntal
+9ls
+4ng
+4saur
+8s
+5e
+6s
+5ta
+7e
+7s
+3k
+4anisation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+4ed
+5r
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7ly
+7s
+4line
+8s
+4s
+4y
+3l
+4abile
+9s
+8i
+5d
+6e
+7d
+7er
+9ed
+9ing
+9s
+7s
+6ic
+7n
+8e
+9s
+8g
+8s
+7st
+9s
+6monger
+9gers
+6ries
+7y
+6s
+5n
+6s
+6t
+7ed
+7ing
+7s
+6wrasse
+9sses
+5st
+7ed
+8r
+9s
+7ing
+7s
+5t
+6ed
+6ing
+6s
+4breaker
+9ers
+4carrier
+9ers
+5lay
+8s
+5ock
+8s
+4ed
+5r
+6ina
+9s
+8e
+6s
+5t
+6ed
+6ic
+8ally
+7ng
+6omane
+9nes
+9nia
+9nias
+6s
+4flower
+9rs
+4game
+8s
+4handling
+9ings
+6wk
+8s
+4icatter
+9ers
+5es
+5ng
+7s
+5sta
+8e
+8s
+7ic
+9ally
+9s
+8te
+9es
+7ospore
+9pores
+5um
+7s
+4ocks
+8ed
+9s
+8ing
+5n
+6et
+8s
+6ne
+8s
+6s
+5on
+7ed
+7ing
+9gs
+8st
+9ts
+7s
+5t
+6ed
+7e
+8s
+7r
+8s
+6ing
+8i
+6s
+6tement
+9ents
+5w
+6s
+4park
+8s
+5een
+5layer
+9rs
+5oint
+9s
+4room
+8s
+4sier
+7st
+6ness
+9ses
+5y
+4up
+6s
+5te
+7s
+4y
+5ard
+8s
+5hoo
+8ed
+8ing
+8s
+5rag
+8ged
+9ing
+8s
+3m
+4acaan
+9s
+4ed
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4like
+4oral
+8ities
+9ty
+8s
+4s
+4y
+3neal
+6ries
+7y
+6tion
+9ns
+5ological
+9ies
+9ist
+9ists
+9y
+6therapies
+9rapy
+3oney
+7s
+4o
+5s
+3s
+4a
+5m
+6ed
+6ic
+7ferous
+7naceous
+8g
+6s
+6y
+5s
+5wood
+9s
+3thasar
+9s
+6zar
+9s
+4i
+5c
+5s
+3u
+4n
+5s
+4s
+5ter
+8ed
+8s
+6rade
+9ed
+9es
+3zarine
+9s
+2m
+3bi
+5ni
+6o
+7s
+5s
+4oo
+6s
+6zle
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+3med
+5r
+6s
+4ing
+3pot
+6s
+3s
+2n
+3ak
+5s
+4l
+5er
+6st
+5isation
+9ions
+7e
+8d
+8s
+7ing
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ly
+4na
+6s
+4usian
+7c
+3c
+4assurance
+9ances
+9er
+9ers
+4o
+5s
+4s
+3d
+4a
+5ge
+7d
+7r
+8s
+7s
+6ing
+5id
+5lore
+9s
+5na
+7s
+6na
+8s
+5r
+6i
+7s
+6s
+5s
+4box
+7es
+5rake
+9s
+4eau
+7s
+7x
+5d
+5ira
+8nte
+9tes
+8s
+5let
+8s
+6ier
+9s
+5r
+6illa
+9as
+9ero
+9eros
+6ol
+8e
+9s
+8s
+6s
+7natch
+9tches
+4fish
+8es
+4h
+5s
+4icoot
+9ed
+9ing
+9s
+5ed
+6r
+6s
+7t
+5ness
+9es
+6g
+7s
+5t
+6o
+7s
+6ries
+7y
+6s
+6ti
+8s
+4leader
+9rs
+4master
+9rs
+6te
+8s
+4obast
+9s
+6ust
+9s
+5g
+6s
+5leer
+9ed
+9s
+7on
+9s
+7ro
+9s
+6ier
+9ed
+9s
+7ne
+9d
+9s
+8ing
+5neon
+9s
+6ion
+9s
+5ok
+7s
+5ra
+7s
+6e
+7s
+4rol
+7s
+4s
+5aw
+7s
+5hell
+9s
+5man
+6en
+5preading
+9dings
+5tand
+9s
+6er
+8s
+4ura
+7s
+4wagon
+9s
+5idth
+9s
+4y
+5ing
+8s
+5man
+6en
+3e
+4berries
+8y
+4d
+4ful
+7ly
+7ness
+9sses
+4s
+3g
+4alay
+8s
+6ore
+7w
+8s
+4ed
+5r
+6s
+4ing
+4kok
+7s
+4le
+6d
+6s
+4s
+5ring
+9s
+5ter
+8s
+4tail
+8s
+3i
+4a
+5n
+6s
+5s
+4ng
+4sh
+6ed
+7r
+8s
+7s
+6ing
+6ment
+9ts
+5ter
+8ed
+8s
+3jax
+6ed
+7s
+6ing
+4o
+5es
+5ist
+8s
+5s
+4ulele
+9s
+3k
+4abilities
+9ty
+6le
+4book
+8s
+4card
+8s
+4ed
+5r
+6ly
+6s
+5t
+6s
+4ing
+7s
+5t
+6s
+4note
+8s
+4roll
+8ed
+9r
+9rs
+8ing
+8s
+5upt
+8cies
+9y
+8ed
+8ing
+8s
+4s
+5ia
+7s
+6de
+8s
+5man
+6en
+3lieue
+8s
+3nable
+4ed
+5r
+6all
+9s
+6ed
+7t
+8s
+8te
+9es
+6ing
+6ol
+8s
+6s
+5t
+6s
+4ing
+5ster
+9s
+4ock
+7s
+4s
+3offee
+8s
+6i
+7s
+3quet
+7ed
+8er
+9rs
+8r
+9s
+7ing
+9gs
+7s
+7te
+9s
+3s
+4ela
+7s
+4hee
+7s
+5ie
+7s
+3t
+4am
+6s
+6weight
+9ghts
+4ed
+5ng
+7s
+5r
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+4ies
+5ng
+7ism
+9ms
+7s
+4ling
+8s
+4s
+4u
+5s
+4y
+3xring
+8s
+3ya
+5n
+6s
+5s
+3zai
+6s
+2obab
+6s
+2p
+3hometic
+3s
+3tise
+7d
+7r
+8s
+7s
+6ia
+8s
+7ng
+6m
+7al
+9ly
+7s
+6t
+7eries
+9y
+7ries
+8y
+7s
+5ze
+7d
+7r
+8s
+7s
+6ing
+3u
+4s
+2r
+3acan
+7s
+5hois
+4esthesia
+9sias
+4gouin
+9s
+4singa
+9s
+8ha
+9as
+4thea
+8s
+6rum
+9s
+4za
+6s
+3b
+4al
+5resque
+6ian
+9ism
+9isms
+9s
+7c
+8ally
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ous
+9ly
+9ness
+9nesses
+5sco
+8es
+8s
+6tel
+9le
+9les
+9s
+5te
+7d
+4e
+5cue
+8d
+8r
+9s
+8s
+7ing
+5d
+5l
+6l
+7ate
+7s
+6s
+5que
+8d
+8s
+7ing
+5r
+6ed
+6ing
+6ries
+7y
+6s
+7hop
+9ps
+5s
+5t
+6s
+6te
+8s
+4ican
+8s
+6el
+8s
+5e
+6s
+5ng
+5tal
+8s
+6one
+9s
+6urate
+9tes
+8ic
+4less
+4ola
+7s
+5tine
+9s
+4s
+4ule
+7s
+5t
+6s
+4wire
+8s
+4y
+3ca
+5role
+9s
+8le
+9es
+5s
+4han
+7e
+8s
+7s
+4ode
+7d
+7s
+3d
+4ash
+7es
+4e
+5d
+5s
+4ic
+5e
+6r
+6s
+7t
+5ng
+5sm
+7s
+4ling
+8s
+4o
+5later
+9rs
+8ries
+9ous
+9y
+5s
+4s
+5hip
+8s
+4y
+3e
+4backed
+8ing
+8s
+5oat
+8s
+6ne
+8d
+8s
+4d
+4faced
+9ly
+9ness
+9nesses
+5it
+5oot
+8ed
+4ge
+6s
+5ine
+8s
+4hand
+8ed
+8ing
+8s
+5ead
+8ed
+4land
+5egged
+5y
+4ness
+8es
+4r
+4s
+5ark
+8s
+5t
+6hesia
+9ias
+3f
+4ed
+4ing
+4lies
+5y
+4s
+4ul
+3gain
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5nder
+9s
+4e
+5board
+9ds
+5d
+5e
+6s
+7e
+5llo
+8s
+5man
+7ster
+9ers
+6en
+5pole
+9s
+5s
+6t
+7s
+4hest
+8s
+4ing
+4oon
+7s
+6se
+4uest
+8s
+3hop
+6ped
+7ing
+6s
+3iatric
+9s
+4c
+4lla
+7s
+4ng
+4sh
+5ta
+7s
+4te
+6s
+5onal
+7e
+8s
+4um
+6s
+3k
+4an
+6s
+6tine
+9es
+4ed
+5ep
+7er
+9s
+7s
+5n
+6ed
+6ing
+6s
+6tine
+9es
+5r
+6s
+4han
+7s
+4ier
+6st
+5ng
+4less
+4s
+4y
+3leduc
+8s
+5ss
+5y
+6corn
+9ns
+6s
+4ow
+6s
+3m
+4aid
+7s
+5n
+4brack
+9s
+4en
+4ie
+6r
+6st
+5ness
+9es
+5tsvah
+9hs
+6zvah
+9hs
+4kin
+7s
+4pot
+7s
+4s
+4y
+3n
+4acle
+8d
+8s
+4brack
+9s
+4ed
+5t
+6s
+5y
+6ed
+6ing
+6s
+4ier
+6st
+5ng
+4like
+4s
+5breaking
+9kings
+5torm
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+4y
+5ard
+8s
+3occo
+7s
+5eptor
+9rs
+5k
+6s
+4dynamics
+4gnoses
+8is
+5ram
+8s
+7ph
+9ic
+9s
+4lo
+6s
+4meter
+9s
+7ric
+9cal
+9cally
+9es
+8y
+7z
+8es
+4n
+5age
+8s
+5ess
+8es
+6t
+7age
+9es
+7cies
+8y
+7ess
+9ses
+7ical
+7s
+5g
+6s
+5ial
+6es
+5ne
+7s
+5s
+5y
+4phile
+9s
+8ic
+6oreses
+9sis
+4que
+7ly
+7s
+4receptor
+9tors
+4saur
+8s
+5cope
+9s
+8ic
+5tat
+8s
+4titis
+9es
+5rauma
+9as
+9ata
+4uche
+8s
+3p
+4erson
+9s
+4s
+3quantine
+9nes
+5e
+6ntine
+9nes
+6s
+6tte
+9s
+3ra
+5ble
+5can
+8s
+6e
+7s
+6k
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6oon
+9s
+7uta
+9as
+6uda
+9s
+5ge
+7d
+7s
+6ing
+5munda
+9as
+9i
+9ies
+9is
+5nca
+8s
+7o
+8s
+5s
+5t
+6er
+8s
+6or
+8s
+6ries
+7ous
+9sly
+7y
+6s
+4e
+5d
+5ed
+5full
+5ing
+5l
+6age
+9s
+6ed
+6ful
+9s
+6head
+9ds
+7ouse
+9ses
+6ing
+6led
+7ing
+6s
+7ful
+5n
+6er
+7st
+6ly
+6ness
+9ses
+6s
+6wort
+9ts
+5s
+5t
+6or
+8s
+6ries
+7ous
+9sly
+7y
+6s
+6te
+8r
+9s
+8s
+4icade
+9d
+9r
+9rs
+9s
+8ing
+8o
+9ed
+9es
+9ing
+9s
+6o
+7es
+7s
+5e
+6r
+7ed
+7ing
+7s
+6s
+7t
+5ng
+7s
+5o
+6s
+5ster
+9ial
+9s
+9ship
+9ships
+4o
+5om
+7s
+5w
+6ful
+9s
+6s
+4ulet
+8s
+4y
+3s
+4tool
+8s
+3tend
+7ed
+8r
+9s
+7ing
+7s
+5r
+6ed
+7r
+8s
+6ing
+6s
+4isan
+8s
+5zan
+8ed
+8s
+4on
+6s
+4sia
+7s
+3ware
+7s
+4ood
+7s
+3ycentre
+9es
+9ic
+4e
+5s
+4on
+6ic
+6s
+4sphere
+9es
+4ta
+6s
+5e
+6s
+5ic
+5on
+7e
+8s
+7s
+2s
+3al
+5ly
+5t
+6es
+6ic
+7ne
+6s
+6ware
+9es
+4n
+5ite
+8s
+5s
+5t
+6s
+3cinet
+8s
+4ule
+7s
+3e
+4ball
+8er
+9rs
+8s
+6nd
+8s
+5oard
+9s
+6rn
+5urner
+9rs
+4d
+4ej
+4lard
+8s
+5ess
+8ly
+8ness
+9esses
+5ine
+8r
+9s
+8s
+5y
+4man
+5en
+7t
+8less
+8s
+4n
+5ess
+8es
+5ji
+7s
+4plate
+9s
+4r
+5unner
+9rs
+8ing
+9ngs
+4s
+5t
+3h
+4aw
+6ism
+9s
+6s
+7hip
+9ps
+4ed
+5r
+6s
+5s
+4ful
+7ly
+7ness
+9sses
+4ibazouk
+9uks
+5ng
+7s
+4less
+5ik
+7s
+5yk
+7s
+4ment
+8s
+4o
+3ic
+5ally
+5ities
+7y
+5ranial
+5s
+4dia
+7l
+6ocarp
+9rps
+7mycete
+9cetes
+9cetous
+7spore
+9ores
+9orous
+6um
+4fication
+9ions
+6ed
+7r
+8s
+7s
+6xed
+5ugal
+5y
+6ing
+4j
+4l
+5ar
+7y
+5ect
+8s
+5ic
+7a
+8e
+8l
+8n
+8s
+7on
+9s
+6sk
+8s
+5s
+4n
+5al
+5ed
+6t
+7s
+5ful
+8s
+5g
+5like
+5s
+4on
+6s
+4petal
+9ly
+4s
+3k
+4ed
+5t
+6ball
+9ls
+6ful
+9s
+6like
+6ries
+7y
+6s
+7ful
+6weave
+9ver
+9vers
+9ves
+7ork
+9ks
+4ing
+4s
+3mati
+7s
+4itzvah
+9hs
+3net
+6s
+3oche
+7s
+4n
+5s
+4phil
+8e
+9s
+8ia
+9as
+9c
+8s
+3que
+6d
+6s
+5ine
+8s
+3s
+4e
+5d
+5r
+5s
+6t
+5t
+6ed
+6ing
+6s
+6t
+7ed
+7ing
+7s
+4i
+5er
+6st
+5net
+8s
+6g
+5st
+7s
+4line
+8s
+5y
+4ness
+8es
+4o
+5on
+7ist
+9ts
+7s
+5s
+4wood
+8s
+4y
+3t
+4a
+5rdies
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7ries
+8y
+7y
+4e
+5d
+5r
+6s
+5s
+4i
+5de
+7s
+5le
+7s
+6le
+8s
+5nade
+9d
+9s
+8ing
+8oed
+9es
+9ing
+6g
+7s
+5on
+7ed
+7s
+5s
+4le
+6s
+4naesite
+9tes
+6site
+9es
+4o
+5s
+4s
+3uco
+6s
+2t
+3able
+4ta
+6s
+4via
+7s
+3boy
+6s
+3ch
+5ed
+6r
+7s
+6s
+5ing
+8s
+3e
+4au
+6x
+4d
+4less
+6ur
+8s
+4ment
+8s
+4s
+3fish
+7es
+4owl
+7ed
+8r
+9s
+7ing
+9gs
+7s
+3girl
+7s
+3h
+4cube
+8s
+4e
+5d
+5r
+6s
+5s
+5tic
+8ally
+4house
+9s
+4ing
+4less
+4mat
+7s
+5ic
+6sm
+8s
+6tsvah
+9ahs
+7zvah
+9ahs
+6zvah
+9hs
+4ochrome
+9mes
+9mic
+5lite
+9s
+8h
+9ic
+9s
+8ic
+5meter
+9rs
+8ric
+9ically
+9ies
+9y
+5philous
+7obia
+9ias
+5rse
+8s
+5s
+6es
+4robe
+8s
+6om
+8s
+4s
+4tub
+7s
+4water
+9s
+4yal
+5bius
+9es
+5graphical
+5limnetic
+7te
+9s
+8h
+9ic
+9s
+8ic
+5meter
+9rs
+8ric
+9ical
+9ically
+9ies
+9y
+5pelagic
+5scape
+9es
+9h
+9he
+9hes
+9hs
+6phere
+9res
+3ik
+5ed
+5ing
+5s
+4ng
+4ste
+7s
+3ler
+6s
+5t
+6s
+4ike
+3man
+4en
+4itzvah
+9hs
+3ological
+8es
+8st
+9ts
+7y
+4n
+5ed
+5ing
+5s
+4on
+6ed
+6ing
+6s
+3rachia
+9n
+9ns
+7ophobia
+9hobias
+9hobic
+3s
+4man
+7ship
+9ips
+5en
+4wing
+5oman
+7en
+3t
+4a
+5ilous
+5lia
+8s
+7on
+9s
+5s
+4eau
+7x
+5d
+5ilant
+5l
+6ed
+7r
+8s
+6ing
+6led
+7ing
+6s
+5ment
+9s
+5n
+6ed
+7r
+8s
+6ing
+9s
+6s
+5r
+6ed
+7r
+8s
+6ie
+8s
+7ng
+9s
+6o
+7s
+6s
+6y
+4ier
+6s
+7t
+5k
+6s
+5ll
+7ed
+7ing
+7s
+5ness
+9es
+6g
+7s
+4le
+6ax
+8e
+9s
+6bus
+9es
+9ses
+6d
+7oor
+9rs
+8re
+9es
+7ress
+9sses
+6field
+9lds
+7ront
+9nts
+6ground
+9unds
+6ment
+9ted
+9ts
+6piece
+9ces
+7lane
+9nes
+6r
+7s
+6s
+7hip
+9ps
+6wagon
+9ons
+5ing
+4ological
+9es
+8y
+4s
+4u
+5e
+6s
+5ta
+7s
+6o
+7s
+4y
+3wing
+4oman
+6en
+2ubee
+6s
+4le
+6s
+5ing
+3chle
+7d
+7s
+6ing
+3d
+4ekin
+8s
+4ric
+7k
+8e
+9s
+8s
+7s
+5ons
+8es
+4s
+3era
+6s
+3hinia
+8s
+3k
+4ed
+4ing
+4s
+3lk
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5s
+5y
+3r
+4s
+3sond
+3xite
+7s
+6ic
+2vardage
+9s
+5ois
+8es
+3in
+5s
+2wbee
+6s
+4le
+6s
+3cock
+7s
+3d
+4ier
+6s
+7t
+5ly
+5ness
+9es
+4kin
+7s
+4ric
+7s
+6es
+5y
+4s
+4y
+5house
+9es
+3l
+4ed
+5r
+6s
+5y
+6s
+4ing
+7s
+4s
+3n
+4een
+7s
+4s
+3r
+4s
+3sunt
+3tie
+6s
+4y
+2xter
+6s
+2y
+3adeer
+8s
+6re
+8s
+4mo
+6s
+4rd
+6s
+3berries
+7y
+3e
+4d
+4s
+3ing
+3le
+5s
+3man
+4en
+3onet
+7ed
+7ing
+7s
+7ted
+8ing
+4u
+5s
+3s
+3t
+4ed
+4ing
+4s
+3wood
+7s
+3yan
+6s
+2zaar
+6s
+4r
+5s
+4zz
+6es
+3illion
+9s
+3oo
+5ka
+7s
+5ms
+5s
+4uki
+7s
+3zazz
+7es
+1dellium
+8s
+1e
+2ach
+5ball
+9s
+6oy
+8s
+5comb
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+5ed
+6s
+5front
+9ts
+5goer
+9s
+5head
+9s
+5ier
+7st
+6ng
+5side
+5wear
+9s
+5y
+4on
+6ed
+6ing
+6s
+3d
+4blast
+9ed
+9er
+9ers
+9ing
+9s
+4ed
+5r
+6s
+4house
+9s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4le
+6dom
+9s
+6hood
+9ds
+6s
+7hip
+9ps
+5ike
+4man
+5en
+4roll
+8s
+4s
+5man
+6en
+5woman
+8en
+4work
+8s
+4y
+3gle
+6d
+6r
+7s
+6s
+5ing
+8s
+3k
+4ed
+5r
+6ful
+9s
+6s
+4ier
+6st
+4less
+5ike
+4s
+4y
+3m
+4ed
+5r
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7ly
+7s
+5sh
+7ly
+4less
+6t
+7s
+5ike
+4s
+4y
+3n
+4bag
+7s
+6ll
+8s
+4ed
+5ries
+6y
+4feast
+9s
+4ie
+6s
+5ng
+4like
+4o
+5s
+4pole
+8s
+4s
+5talk
+9s
+4y
+3r
+4abilities
+9ty
+6le
+8ness
+9esses
+7y
+4baiting
+9ngs
+5erries
+8y
+5ine
+8s
+4cat
+7s
+4d
+5ed
+7ness
+9sses
+5ie
+7r
+7s
+8t
+6ng
+5less
+9ness
+9nesses
+5s
+5tongue
+9ues
+5y
+4e
+5d
+5r
+6s
+5s
+4grass
+9es
+4hug
+7s
+4ing
+7s
+5sh
+7ly
+7ness
+9sses
+4like
+4naise
+9s
+4s
+5kin
+8s
+4ward
+8s
+5ood
+8s
+3st
+5ed
+5hood
+9s
+5ie
+7s
+6ly
+6ng
+8s
+5lier
+8st
+7ke
+7ness
+9sses
+6y
+5s
+3t
+4able
+4box
+7er
+9s
+8s
+7ing
+9gs
+4en
+5r
+6s
+4h
+5ed
+5ing
+5s
+4ier
+6st
+5fic
+8al
+9lly
+9tion
+9tions
+7ed
+8s
+6y
+7ing
+5ng
+7s
+5tude
+9s
+4less
+4nik
+7s
+4s
+4y
+3u
+4coup
+8s
+4fet
+7s
+5fet
+8s
+5in
+7s
+4ish
+4jolais
+9ses
+4montage
+9ges
+9gue
+9gues
+4s
+4t
+5eous
+9ly
+9ness
+9nesses
+5ician
+9ns
+6ed
+7s
+6fication
+9ations
+8ed
+9r
+9rs
+9s
+7ul
+9er
+9est
+9ler
+9lest
+9ly
+9ness
+9nesses
+7y
+8ing
+5s
+5y
+6ing
+4x
+5ite
+8s
+3ver
+6board
+9rds
+6ed
+6ies
+7ng
+6s
+6y
+2beerine
+9s
+6u
+7s
+3lood
+7ed
+7ing
+7s
+4ubbered
+3op
+5ped
+7r
+8s
+6ing
+5s
+3ung
+6s
+2call
+6ed
+6ing
+6s
+5m
+6ed
+6ing
+6s
+4me
+4p
+5ped
+6ing
+5s
+4rpet
+8ed
+8ing
+8s
+4sse
+7s
+4use
+3caccia
+9s
+5fico
+9s
+3halk
+7ed
+7ing
+7s
+5mel
+8s
+5nce
+8d
+8s
+7ing
+5rm
+7ed
+7ing
+7s
+3k
+4e
+5d
+5s
+5t
+6s
+4ing
+4on
+6ed
+7r
+8s
+6ing
+9s
+6s
+4s
+3lamor
+8ed
+8ing
+8s
+5sp
+7ed
+7ing
+7s
+4oak
+7ed
+7ing
+7s
+5g
+6ged
+7ing
+6s
+5the
+8d
+8s
+7ing
+5ud
+7ed
+7ing
+7s
+5wn
+7ed
+7ing
+7s
+3ome
+6s
+5ing
+8ly
+8ness
+9esses
+8s
+4ward
+8ed
+8ing
+8s
+3querel
+9s
+3rawl
+7ed
+7ing
+7s
+4ime
+7d
+7s
+6ing
+4owd
+7ed
+7ing
+7s
+4ust
+7ed
+7ing
+7s
+3udgel
+8ed
+8ing
+8led
+9ing
+8s
+4rl
+6ed
+6ing
+6s
+5se
+7d
+7s
+6ing
+6t
+2d
+3abble
+8d
+8s
+7ing
+4d
+4ggle
+8d
+8s
+7ing
+4mn
+6ed
+6ing
+6s
+4rken
+8ed
+8ing
+8s
+4sh
+6ed
+7s
+6ing
+4ub
+6ed
+6ing
+6s
+4win
+7s
+4ze
+6d
+6s
+5ing
+5zle
+8d
+8ment
+9ents
+8s
+7ing
+3bath
+7s
+4oard
+8s
+4ug
+6s
+3chair
+8s
+6mber
+9rs
+4lothes
+4over
+8ing
+9ngs
+8s
+3dable
+4ed
+5r
+6s
+4ing
+7s
+3e
+4afen
+8ed
+8ing
+8s
+4ck
+6ed
+6ing
+6s
+4guar
+8s
+4house
+9s
+4l
+5l
+6s
+7hip
+9ps
+5s
+6hip
+9s
+4man
+5en
+4ral
+7s
+4s
+5man
+6en
+4vil
+7ed
+7ing
+7led
+8ing
+7ment
+9nts
+7s
+4w
+5ed
+5ing
+5s
+3fast
+4ellow
+9s
+4rame
+8s
+3gown
+7s
+3head
+7s
+3iaper
+8ed
+8ing
+8s
+4de
+4ght
+7ed
+7ing
+7s
+4m
+5med
+6ing
+9s
+5ple
+8d
+8s
+7ing
+5s
+4rtied
+8s
+6y
+7ing
+4zen
+7ed
+7ing
+7ment
+9nts
+7s
+3lam
+6ism
+9s
+7te
+9s
+6p
+7s
+6s
+4ess
+4ike
+3maker
+8s
+5te
+7s
+3otted
+4uin
+7s
+3pan
+6s
+4late
+8s
+4ost
+7s
+4resser
+9rs
+3quilt
+8s
+3raggle
+9d
+9s
+8ing
+5il
+7s
+5l
+6s
+5pe
+7d
+7s
+6ing
+4ench
+8ed
+9s
+8ing
+4id
+6den
+5ght
+8s
+5te
+7s
+5vel
+8ed
+8ing
+8led
+9ing
+8s
+4ock
+7s
+5ll
+7s
+5om
+7ed
+7s
+5p
+6ped
+7ing
+6s
+6t
+4ug
+6ged
+7ing
+6s
+3s
+4heet
+8s
+4ide
+7s
+5t
+6s
+6ter
+9s
+7ing
+4ocks
+5nia
+8e
+8s
+5re
+7s
+4pread
+9s
+6ing
+9s
+4tand
+8s
+5ead
+8s
+5raw
+8s
+3tick
+7s
+5me
+7s
+3u
+4ck
+6ed
+6ing
+6s
+4in
+6s
+4mb
+6ed
+6ing
+6s
+4nce
+7d
+7s
+6ing
+5g
+6ed
+6ing
+6s
+4st
+6ed
+6ing
+6s
+3ward
+7s
+6f
+7ed
+7ing
+7s
+6mer
+9s
+4etter
+9s
+3yde
+4e
+5d
+5ing
+5s
+2e
+3bee
+6s
+4read
+8s
+3ch
+5drops
+5en
+6s
+5ier
+7st
+5mast
+9s
+5nut
+8s
+5wood
+9s
+5y
+3di
+5e
+6s
+3f
+4alo
+7es
+7s
+4burger
+9rs
+4cake
+8s
+4eater
+9s
+5d
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4less
+4s
+5teak
+9s
+4wood
+8s
+4y
+3gah
+6s
+3hive
+7s
+3keeper
+9s
+7ing
+9gs
+3like
+5ne
+7d
+7s
+6ing
+3n
+4ah
+6s
+4to
+6s
+3p
+4ed
+5r
+6s
+4ing
+4s
+3r
+4age
+7s
+4hall
+8s
+4ier
+6st
+5ly
+5ness
+9es
+4s
+4y
+3s
+4ome
+4ting
+8s
+5ung
+4wax
+7ed
+8s
+7ing
+5ing
+8ed
+8s
+3t
+4ed
+4flies
+6y
+4ing
+4le
+6brain
+9ined
+9ins
+6d
+6head
+9ded
+9ds
+6r
+7s
+6s
+5ing
+4master
+9rs
+5ister
+9rs
+4root
+8s
+4s
+3ves
+3yard
+7s
+3zer
+6s
+2fall
+6en
+6ing
+6s
+4na
+6s
+3eld
+5l
+3fana
+7s
+3inger
+8ed
+8ing
+8s
+5ned
+4t
+5s
+5ted
+6ing
+9ly
+3lag
+6ged
+7ing
+6s
+4ea
+6ed
+6ing
+6s
+5ck
+7ed
+7ing
+7s
+4ower
+8ed
+8ing
+8s
+4um
+6med
+7ing
+6s
+3oam
+6ed
+6ing
+6s
+4g
+5ged
+6ing
+5s
+4ol
+6ed
+6ing
+6s
+4re
+6hand
+6time
+5tune
+9d
+9s
+8ing
+4ul
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+3ret
+6s
+6ted
+7ing
+4iend
+8ed
+9r
+9rs
+8ing
+8s
+5nge
+8d
+8s
+7ing
+3uddle
+8d
+8ment
+9ents
+8s
+7ing
+2g
+3ad
+4ll
+6ed
+6ing
+6s
+4n
+4r
+5s
+4t
+4ze
+6d
+6s
+5ing
+3em
+5med
+6ing
+5s
+4t
+5s
+5ter
+8s
+6ing
+3gar
+6dom
+9s
+6ed
+6hood
+9ds
+6ies
+7ng
+6liness
+9esses
+7y
+6s
+6weed
+9ds
+6y
+4ed
+4ing
+7ly
+7s
+3hard
+7s
+3ift
+6ed
+6ing
+6s
+4ld
+6ed
+6ing
+6s
+5t
+4n
+5ne
+7r
+8s
+7s
+6ing
+9less
+9s
+5s
+4rd
+6ed
+6ing
+6le
+8d
+8s
+7ing
+6s
+5t
+6ing
+3lad
+6ded
+7ing
+6s
+5mor
+8ed
+8ing
+8s
+7ur
+9ed
+9ing
+9s
+4erbeg
+9s
+4oom
+7ed
+7ing
+7s
+3naw
+6ed
+6ing
+6s
+3o
+4es
+4ggled
+4ing
+4ne
+5ia
+7s
+4rah
+5ed
+5ra
+7h
+4t
+5ten
+3rim
+6e
+7d
+7s
+6ing
+6med
+7ing
+6s
+4oan
+7ed
+7ing
+7s
+4udge
+8d
+8r
+9ies
+9s
+9y
+8s
+7ing
+9gly
+3s
+3uile
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9ly
+5n
+6age
+9s
+6e
+7s
+6s
+4lf
+6ed
+6ing
+6s
+4m
+5s
+4n
+5k
+6ed
+6ing
+6s
+2half
+5ves
+4ppen
+8ed
+8ing
+8s
+4tted
+4ve
+6d
+6r
+7s
+6s
+5ing
+6or
+8al
+9lly
+8ism
+9sms
+9st
+9stic
+9sts
+8s
+7ur
+9al
+9ally
+9ism
+9isms
+9ist
+9istic
+9ists
+9s
+3ead
+6al
+8s
+6ed
+7r
+8s
+6ing
+9s
+6s
+4ld
+4moth
+8s
+4st
+6s
+3ight
+7ing
+7s
+4nd
+6hand
+6s
+3old
+6en
+7r
+8s
+6ing
+9s
+6s
+4of
+6s
+5ve
+7d
+7s
+6ing
+4te
+6s
+5ing
+4ve
+6d
+6ful
+6ly
+6s
+5ing
+4wl
+6ed
+6ing
+6s
+2ige
+5l
+6s
+5s
+4ier
+6st
+4ne
+6s
+6t
+7s
+4y
+3n
+4g
+5less
+5ness
+9es
+5s
+4ked
+4ness
+8es
+2jabbers
+5ers
+4de
+6d
+6s
+5ing
+4nt
+6s
+3eebers
+5zus
+4suit
+8ed
+8ing
+8s
+6s
+7es
+4wel
+7ed
+7ing
+7led
+8ing
+7s
+3umble
+8d
+8s
+7ing
+2kah
+5s
+3iss
+6ed
+7s
+6ing
+3nave
+7d
+7s
+6ing
+4ight
+8ed
+8ing
+8s
+4ot
+6s
+6ted
+7ing
+5wn
+2l
+3abor
+7ed
+7ing
+7s
+6ur
+8ed
+8ing
+8s
+4ce
+6d
+6s
+5ing
+4died
+7s
+5y
+6ing
+4h
+5s
+4mies
+5oure
+9s
+5y
+4r
+5s
+4te
+6d
+7ly
+7ness
+9sses
+6s
+5ing
+4ud
+6ed
+6ing
+6s
+4y
+5ed
+6r
+7s
+5ing
+5s
+3ch
+5ed
+6r
+7s
+6s
+5ing
+3dam
+6e
+7s
+6s
+3eaguer
+9ed
+9ing
+9ment
+9ments
+9s
+5p
+6ed
+6ing
+6s
+6t
+4e
+5d
+5ing
+5s
+4mnite
+9s
+6oid
+3fried
+7s
+5y
+3ga
+5rd
+7s
+5s
+3ie
+5d
+5f
+6less
+6s
+5r
+6s
+5s
+5vabilities
+9lity
+8le
+9y
+6e
+7d
+7r
+8s
+7s
+6ing
+9ly
+9s
+4ke
+4quor
+8ed
+8ing
+8s
+4ttle
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+9gly
+4ve
+3l
+4adonna
+9as
+5moure
+9es
+5rmine
+9es
+4bind
+8s
+6rd
+8s
+5oy
+7s
+4cote
+8s
+4e
+5d
+5ek
+7s
+5s
+5ter
+8s
+6rism
+9ms
+9t
+9tic
+9tical
+9ts
+6trist
+9sts
+4flower
+9rs
+5ounder
+9ers
+9ries
+9ry
+4hanger
+9rs
+5op
+7s
+4ibone
+9s
+5cose
+9ly
+8ities
+9ty
+5ed
+6s
+5gerati
+8ence
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9nts
+5ng
+7s
+4man
+5en
+4ock
+7ed
+7ing
+7s
+5w
+6ed
+7r
+8s
+6ing
+6s
+4pull
+8s
+4s
+4wether
+9rs
+5ort
+8s
+4y
+5ache
+9d
+9r
+9rs
+9s
+8ing
+5band
+9s
+6utton
+9ons
+5ful
+8s
+5ing
+8s
+5like
+3omancies
+8y
+4n
+5g
+6ed
+7r
+8s
+6ing
+9ness
+9nesses
+9s
+6s
+5s
+4ve
+6d
+7s
+6s
+5ing
+4w
+5decks
+5ground
+5s
+6tairs
+3s
+4hazzar
+9rs
+3t
+4course
+9es
+4ed
+5r
+6s
+4ing
+7s
+4less
+5ine
+8s
+4man
+5en
+4s
+4way
+7s
+3uga
+6s
+3vedere
+9s
+3ying
+2ma
+4d
+5am
+7ed
+7ing
+7s
+5ded
+7n
+8ed
+8ing
+8s
+6ing
+5s
+4s
+4ta
+4ul
+6ed
+6ing
+6s
+4zed
+3bex
+6es
+4ix
+6es
+3ean
+6ed
+6ing
+6s
+6t
+4dal
+7ed
+7led
+8ing
+7s
+4te
+6d
+6s
+5ing
+3ingle
+8d
+8s
+7ing
+4re
+6d
+6s
+5ing
+4st
+6ed
+6ing
+6s
+4x
+5ed
+6s
+5ing
+5t
+3oan
+6ed
+7r
+8s
+6ing
+9s
+6s
+4ck
+6ed
+6ing
+6s
+4il
+6ed
+6ing
+6s
+4nster
+9ed
+9ing
+9s
+4uth
+7ed
+7ing
+7s
+3ud
+5ded
+6ing
+6le
+8d
+8s
+7ing
+5s
+4ffle
+8d
+8s
+7ing
+4rmur
+8ed
+8ing
+8s
+4se
+6d
+7ly
+6ment
+9ts
+6s
+5ing
+4zzle
+8d
+8s
+7ing
+2n
+3adryl
+8s
+4me
+6d
+6s
+5ing
+3ch
+5ed
+6r
+7s
+8hip
+9ips
+6s
+5ier
+7st
+6ng
+5land
+9s
+6ess
+5mark
+9ed
+9ing
+9ings
+9s
+5top
+5warmer
+9ers
+5y
+3d
+4able
+5y
+6ed
+6ing
+6s
+4ed
+5e
+6s
+5r
+6s
+4ier
+6st
+5ng
+7ly
+7s
+4let
+7s
+4s
+4ways
+5ise
+4y
+5s
+3e
+4ath
+4dicite
+9es
+7k
+8s
+7t
+8ion
+9onal
+9ons
+9ve
+8ory
+8s
+8us
+9ses
+6ght
+4fact
+8ed
+8ing
+9on
+9ons
+8or
+9rs
+9ry
+8ress
+9esses
+8s
+5ic
+7e
+8d
+8nce
+9ces
+9t
+9tial
+9tly
+8s
+7ial
+9lly
+9lness
+9ls
+9ries
+9ry
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+8ng
+6t
+7ed
+8r
+9s
+7ing
+7s
+7ted
+8ing
+4mpt
+7ed
+4placito
+4s
+4t
+5s
+5ted
+6ing
+4volence
+9ces
+9t
+9tly
+9tness
+3ga
+5line
+9s
+5s
+3i
+4ght
+7ed
+9ly
+9ness
+9nesses
+8n
+9ed
+9ing
+9ings
+9s
+8r
+9s
+7ing
+9gs
+7ment
+9nts
+7s
+5n
+6ancies
+9y
+8t
+9ly
+6er
+7st
+6ities
+8y
+6ly
+4s
+5eed
+8s
+5on
+7s
+4tier
+8s
+3j
+4amin
+8s
+4es
+3ne
+5s
+5t
+6s
+4i
+5es
+5s
+4y
+3omyl
+7s
+3s
+3t
+4grass
+9es
+4hal
+5ic
+5oal
+6n
+7ic
+7s
+6pelagic
+6s
+7cope
+9pes
+7es
+4ier
+6st
+4o
+5nite
+9s
+8ic
+5s
+4s
+4wood
+8s
+4y
+3umb
+6ed
+8ness
+9esses
+6ing
+9ly
+6ment
+9ts
+6s
+3zal
+6dehyde
+9ydes
+6s
+5nthracene
+9acenes
+4ene
+7carbonyl
+7s
+6oid
+9s
+4idin
+8e
+9s
+8s
+5l
+6s
+5midazole
+9zoles
+5n
+6e
+7s
+6s
+4oapyrene
+9enes
+6te
+8s
+5caine
+9es
+5diazepine
+9epines
+5furan
+9ns
+5ic
+6n
+7s
+5l
+6e
+7s
+6ine
+9s
+6s
+5phenone
+9ones
+5quinone
+9ones
+5yl
+7s
+4pyrene
+9es
+4yl
+6ic
+7dine
+9nes
+6s
+2paint
+7ed
+7ing
+7s
+4t
+5ched
+5s
+5ted
+6ing
+3earl
+7ed
+7ing
+7s
+4lt
+6ed
+6ing
+6s
+4pper
+8ed
+8ing
+8s
+4ster
+8ed
+8ing
+8s
+3imple
+8d
+8s
+7ing
+4tied
+7s
+5y
+6ing
+3laster
+9ed
+9ing
+9s
+4umed
+3ommel
+8led
+9ing
+8s
+4wder
+8ed
+8ing
+8s
+3raise
+8d
+8s
+7ing
+4ose
+7d
+7s
+6ing
+3uff
+6ed
+6ing
+6s
+2queath
+8able
+9l
+9ls
+8ed
+9r
+9rs
+8ing
+8ment
+9ents
+8s
+5st
+7s
+2rake
+6d
+6s
+5ing
+4scal
+8ed
+8ing
+8s
+4te
+6d
+6s
+5ing
+4y
+5ed
+5ing
+5s
+3bere
+7s
+6idaceous
+7n
+8e
+9s
+8s
+7s
+8es
+4ice
+3ceau
+7x
+5use
+8s
+3dache
+8s
+5sh
+7es
+3e
+4ave
+7d
+7ment
+9nts
+7n
+7r
+8s
+7s
+6ing
+4ft
+4s
+4t
+5s
+5ta
+7s
+3g
+4ama
+7s
+8k
+9s
+6ot
+8s
+5nder
+9s
+4en
+6ia
+8s
+6s
+5re
+7s
+4fall
+8s
+4haan
+8s
+4mehl
+8s
+4omask
+9s
+4s
+5chrund
+9nds
+4ylt
+7s
+3hyme
+7d
+7s
+6ing
+3ibboned
+5eri
+8s
+4mbau
+8s
+5e
+6d
+6s
+5ing
+4nged
+3k
+4elium
+9s
+4o
+4s
+3ley
+6ed
+6ing
+6s
+4in
+6e
+7s
+6s
+3m
+4e
+5d
+5s
+4ing
+4s
+4udas
+3nicle
+8s
+3ob
+5bed
+6ing
+5ed
+5s
+4uged
+3ret
+6s
+6ta
+8s
+4ied
+6s
+5gan
+8s
+4y
+5fruit
+9ts
+5ing
+8s
+5less
+6ike
+3sagliere
+9ri
+4eem
+7s
+5rk
+7er
+9s
+7ly
+7s
+3th
+5a
+6ge
+8s
+6s
+5e
+6d
+6s
+5ing
+5s
+4illonage
+9ages
+3yl
+5ine
+5lia
+8s
+7oses
+9is
+7um
+9s
+5s
+2s
+3aint
+7ed
+7ing
+7s
+4ng
+4t
+4w
+3catter
+9ed
+9ing
+9s
+4orch
+8ed
+9s
+8ing
+5ur
+7ed
+7ing
+7s
+4rawl
+8ed
+8ing
+8s
+5een
+8ed
+8ing
+8s
+5ibble
+9ed
+9es
+9ing
+3ee
+5ch
+7ed
+8r
+9s
+8s
+7ing
+9gly
+9gness
+9gs
+5ing
+5ke
+7s
+6ing
+5m
+6ed
+6ing
+9ly
+9ness
+9nesses
+9s
+6ly
+6s
+5n
+5s
+4s
+4t
+5ment
+9s
+5s
+5ter
+8s
+6ing
+3hadow
+8ed
+8ing
+8s
+5me
+7d
+7s
+6ing
+4ine
+7s
+6ing
+5ver
+8ed
+8ing
+8s
+4one
+5ut
+7ed
+7ing
+7s
+4rew
+7ed
+7ing
+7s
+5oud
+8ed
+8ing
+8s
+3ide
+6s
+4ege
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9ly
+9s
+4gh
+6ed
+6ing
+6s
+4ng
+6ing
+6s
+4t
+5s
+5ting
+3lave
+7d
+7r
+8ed
+8ing
+8s
+7s
+6ing
+4ime
+7d
+7s
+6ing
+4obber
+9ed
+9ing
+9s
+4ubber
+9ed
+9ing
+9s
+3mear
+7ed
+8r
+9s
+7ing
+7s
+4ile
+7d
+7s
+6ing
+5rch
+8ed
+9s
+8ing
+4oke
+7d
+7s
+6ing
+5oth
+8ed
+8ing
+8s
+4udge
+8d
+8s
+7ing
+5t
+6ch
+8ed
+9s
+8ing
+6s
+6ted
+7ing
+3now
+6ed
+6ing
+6s
+3ognio
+8s
+4in
+6s
+4m
+5ed
+5ing
+5s
+4nian
+8s
+4othe
+8d
+8s
+7ing
+4rt
+6ed
+6ing
+6s
+4t
+5s
+5ted
+8ly
+8ness
+9esses
+6ing
+4ught
+5led
+3pake
+5ngle
+9d
+9s
+8ing
+5t
+6e
+6ter
+9ed
+9ing
+9s
+4eak
+7ing
+7s
+5ckle
+9d
+9s
+8ing
+6tacled
+5d
+5ed
+7ing
+7s
+4ice
+7d
+7s
+6ing
+5t
+6s
+6ting
+4oke
+7n
+5rt
+7ed
+7ing
+7s
+5t
+6s
+6ted
+9ness
+9nesses
+7ing
+5use
+8d
+8s
+7ing
+6t
+7ed
+7ing
+7s
+4read
+8ing
+8s
+6nt
+5inkle
+9ed
+9es
+9ing
+3t
+4ad
+6de
+5in
+7ed
+7ing
+7s
+5r
+6red
+7ing
+6s
+4ead
+7ed
+7ing
+7s
+5d
+4i
+5alise
+9ed
+9es
+9ing
+9m
+9ms
+8ties
+8ze
+9ed
+9es
+9ing
+7ly
+7s
+6ries
+7y
+5ck
+7ing
+7s
+5ll
+7ed
+7ing
+7s
+5ng
+5r
+6red
+7ing
+6s
+5s
+4orm
+7ed
+7ing
+7s
+5w
+6al
+8s
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4raddle
+9ed
+9es
+9ing
+6ught
+5eak
+8ed
+8ing
+8s
+6w
+7ed
+7ing
+7n
+7s
+5id
+7able
+7den
+7e
+8s
+7ing
+5ode
+6w
+7ed
+7ing
+7n
+7s
+4s
+5eller
+9rdom
+9rdoms
+9rs
+8ing
+4uck
+5d
+6ded
+7ing
+6s
+3uited
+4ng
+3warm
+7ed
+7ing
+7s
+2t
+3a
+4carotene
+9enes
+5ism
+8s
+5yanin
+9ns
+4ine
+7s
+4ke
+6n
+6s
+5ing
+4s
+4topic
+5ron
+8s
+5ter
+8ed
+8ing
+8s
+4xed
+3cha
+3e
+4d
+4em
+6e
+7d
+7s
+6ing
+6s
+4l
+5nut
+8s
+5s
+4s
+3h
+4ank
+7ed
+7ing
+8t
+9s
+7s
+4el
+6s
+5sda
+8s
+4ink
+7ing
+7s
+4orn
+7ed
+7ing
+7s
+5ught
+4rall
+8ed
+8ing
+8s
+4s
+4umb
+7ed
+7ing
+7s
+6p
+7ed
+7ing
+7s
+4wack
+8ed
+8ing
+8s
+3id
+5e
+6d
+6s
+5ing
+4ght
+4me
+6d
+6s
+5ing
+4ng
+4se
+6s
+4tle
+7d
+7s
+6ing
+3oil
+6ed
+6ing
+6s
+4ken
+7ed
+7ing
+7s
+4n
+5ies
+5s
+5y
+4ok
+4ss
+6ed
+7s
+6ing
+3ray
+6al
+8s
+6ed
+7r
+8s
+6ing
+6s
+4ead
+7ing
+7s
+4im
+6med
+7ing
+6s
+4od
+6den
+5th
+7al
+9s
+7ed
+9s
+7ing
+7ment
+9nts
+7s
+3s
+3ta
+5s
+4ed
+5r
+6ed
+6ing
+9s
+6ment
+9ts
+7ost
+6ness
+9ses
+6s
+4ies
+5ng
+7s
+4ong
+7s
+5r
+6s
+4y
+3ulaceous
+4mbled
+3ween
+7brain
+9ains
+7ities
+9y
+7ness
+9sses
+7s
+7time
+9mes
+7whiles
+4ixt
+2uncled
+3rre
+6s
+2vatron
+8s
+3el
+5ed
+6r
+7s
+5ing
+5led
+7r
+8s
+6ing
+9s
+5ment
+9s
+5s
+4r
+5age
+8s
+5s
+3ies
+3omit
+7ed
+7ing
+7s
+4r
+5s
+3ue
+5s
+3vied
+6s
+4y
+5ing
+3y
+2wail
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+4re
+6d
+6s
+5ing
+3earied
+8s
+6y
+7ing
+4ep
+6ing
+6s
+4ltered
+4nt
+4pt
+4t
+5s
+5ted
+6ing
+3hiskered
+4oring
+3ig
+5ged
+6ing
+5s
+4lder
+8ed
+9dly
+9dness
+8ing
+9ngly
+8ment
+9ents
+8s
+4nged
+4tch
+7ed
+8r
+9ies
+9s
+9y
+8s
+7ing
+9gly
+7ment
+9nts
+3orm
+6ed
+6ing
+6s
+5ried
+8s
+6y
+7ing
+3rap
+6ped
+7ing
+6s
+6t
+5y
+6ed
+7r
+8s
+6ing
+6s
+2y
+3lic
+6s
+5k
+6s
+3ond
+6s
+3s
+2z
+3ant
+6s
+4zz
+6es
+3el
+5s
+4s
+3il
+5s
+4que
+7s
+3oar
+6dic
+6s
+4nian
+8s
+3zant
+7s
+5zz
+7es
+4le
+6d
+6s
+5ing
+1hagee
+6s
+3i
+4s
+3jan
+6s
+4ee
+6s
+4i
+5a
+5s
+3kta
+6s
+5i
+6s
+3ng
+5ra
+7s
+5s
+3ral
+6s
+3t
+3van
+6s
+3wan
+6s
+2eestie
+8s
+6y
+3l
+4puri
+8s
+4s
+2ikhu
+6s
+4khuni
+9s
+3ndi
+6s
+3shti
+7s
+4tee
+7s
+5i
+6e
+7s
+6s
+2oona
+6s
+4t
+5s
+2una
+5s
+3t
+4s
+1i
+2acetyl
+8s
+4h
+5es
+3li
+5es
+5s
+4y
+5s
+3nnual
+8ly
+8s
+6late
+3s
+4ed
+6ly
+5s
+4ing
+7s
+4ness
+8es
+4sed
+7ly
+6s
+5ing
+3tches
+4hlete
+9s
+6on
+8s
+3uricular
+9ate
+3xal
+4ial
+7ly
+2b
+3acious
+4sic
+4tion
+8s
+3b
+4ed
+5r
+6ies
+6s
+6y
+4ing
+4le
+6s
+4s
+3cock
+7s
+3elot
+7s
+3ful
+6s
+3le
+5s
+6s
+4ical
+8ly
+6ism
+9s
+8t
+9s
+5ke
+5ographer
+9phers
+9phic
+9phical
+9phies
+9phy
+6later
+9ers
+9ries
+9rist
+9rists
+9rous
+9ry
+7ogical
+9ies
+9ist
+9ists
+9y
+6mancies
+9cy
+9e
+9es
+9ia
+9iac
+9iacal
+9iacs
+9ias
+6pegic
+9ies
+9ist
+9ists
+9y
+7hagist
+9gists
+8il
+9le
+9les
+9lic
+9lies
+9lism
+9lisms
+9list
+9listic
+9lists
+9ls
+9ly
+8obia
+9bias
+7ole
+9es
+9ic
+9ical
+9ies
+9ist
+9ists
+9y
+6theca
+9cae
+9cal
+9caries
+9cary
+9cas
+9rapies
+9rapy
+7ic
+9s
+8st
+9ts
+5st
+7s
+3s
+3ulous
+8ly
+8ness
+9esses
+2cameral
+9ism
+9isms
+9ist
+9ists
+4psular
+4rb
+6onate
+9tes
+6s
+5pellary
+4udal
+3cies
+4y
+3e
+4ntenaries
+9ry
+8nial
+9ials
+6ric
+4p
+5halous
+5s
+6es
+4s
+3hir
+6s
+4loride
+9es
+4ord
+4romate
+9ed
+9es
+7e
+3ipital
+3ker
+6ed
+7r
+8s
+6ing
+9s
+6s
+4ie
+6s
+3oastal
+4llateral
+5or
+7ed
+7s
+6ur
+8ed
+8s
+4mponent
+4ncave
+8ities
+9ty
+5ditional
+9onals
+5vex
+8ities
+9ty
+4rn
+6ate
+6e
+7s
+6s
+6uate
+5porate
+3ron
+6s
+3ultural
+9lism
+9lisms
+4spid
+8ate
+9tes
+8s
+3ycle
+7d
+7r
+8s
+7s
+6ic
+8al
+7ng
+7st
+9s
+2d
+3arka
+7s
+6ee
+8s
+3dabilities
+9ty
+6le
+8ness
+9esses
+7y
+4en
+5r
+6s
+4ies
+5ng
+7s
+4y
+3e
+4d
+4nt
+6al
+8s
+7te
+9d
+6s
+4r
+5s
+4s
+4t
+5s
+3i
+4alectal
+9alism
+9alisms
+4ng
+6s
+4rectional
+9onally
+4s
+3on
+5s
+5ville
+9es
+3s
+2eld
+5ed
+5ier
+7st
+6ng
+5s
+5y
+3n
+4nale
+8s
+5ia
+7l
+8ly
+8s
+6um
+8s
+4seance
+9es
+3r
+4keller
+9rs
+4s
+3stings
+2face
+6s
+5ial
+8ly
+4rious
+9ly
+3f
+4ed
+5r
+6s
+4ies
+5n
+6g
+6s
+4o
+5s
+4s
+4y
+3id
+5ities
+7y
+5ly
+4lar
+7ly
+3lagellate
+4ex
+3ocal
+7ed
+7s
+4ld
+5iate
+6olate
+4rate
+5ked
+5m
+6ed
+3tah
+6s
+4er
+6s
+3unctional
+4rcate
+9d
+9s
+8ing
+9on
+9ons
+2g
+3a
+4e
+4mies
+6st
+8s
+5ous
+8ly
+5y
+4rade
+8s
+5oon
+8s
+5reau
+9s
+3eminal
+7ies
+7y
+4ner
+7ic
+7s
+4ye
+6s
+3feet
+4oot
+7ed
+7ing
+7s
+3g
+4ed
+5r
+5st
+5ty
+4ie
+6s
+5n
+6g
+7s
+6s
+5sh
+5ty
+4on
+6s
+4s
+4y
+3ha
+5s
+4ead
+7ed
+9ly
+9ness
+9nesses
+7s
+6rted
+9dly
+9dness
+4orn
+7s
+4t
+5ed
+5ing
+5s
+3ly
+3mouth
+8ed
+8s
+3ness
+7es
+4onia
+8ceous
+8s
+3os
+5es
+4t
+5ed
+7ly
+5ries
+6y
+5s
+3s
+4tick
+3time
+3uanide
+9s
+3wig
+6s
+2hourly
+2jection
+9s
+7ve
+3ou
+5s
+5terie
+9es
+5x
+3ugate
+5ous
+3woner
+8s
+2ke
+4d
+4r
+5s
+4s
+4way
+7s
+3ie
+5s
+4ng
+6s
+5i
+6ed
+6s
+3kie
+6s
+2labial
+8s
+7te
+4nder
+8s
+4teral
+9ism
+9isms
+9ly
+4yer
+7s
+3berries
+7y
+4ies
+4o
+5a
+6s
+5es
+5s
+4y
+3dungsroman
+9omane
+9omans
+3e
+4ction
+9s
+4d
+4s
+5tone
+9s
+4vel
+7s
+3ge
+5d
+5s
+5water
+9rs
+4ier
+6st
+5ng
+4y
+3harzia
+9l
+9s
+9ses
+9sis
+8oses
+9sis
+3ian
+6s
+5ries
+6y
+4mbi
+7ng
+9s
+7s
+4near
+5g
+6ual
+9ism
+9isms
+9ly
+9s
+7ist
+9ts
+4ous
+7ly
+7ness
+9sses
+4rubin
+9s
+4teral
+4verdin
+9ns
+3k
+4ed
+5r
+6s
+4ing
+4s
+3l
+4able
+6ong
+9s
+4board
+9ed
+9ing
+9s
+6ok
+8s
+5ug
+7s
+4ed
+5r
+6s
+5t
+6ed
+7e
+8s
+7r
+8s
+6ing
+6s
+4fish
+8es
+5old
+8s
+4head
+8s
+5ook
+8s
+4iard
+8s
+5e
+6s
+5ng
+7s
+8gate
+9ates
+5on
+7aire
+9res
+7s
+7th
+9s
+4man
+5en
+4on
+6s
+5w
+6ed
+6ier
+8st
+7ness
+9sses
+8g
+9s
+6s
+6y
+4poster
+9rs
+8ing
+9ngs
+4s
+5ticker
+9ers
+9ing
+9ings
+4y
+5boy
+8s
+5can
+8s
+6ock
+9s
+5o
+6h
+7s
+6s
+3obar
+6te
+8d
+5ed
+5ular
+4cation
+9ns
+5ular
+8te
+3sted
+7s
+3tong
+7s
+2ma
+4h
+5s
+4nal
+5ous
+5ual
+8ly
+4s
+3bashi
+8s
+4ette
+8s
+4le
+4o
+5es
+3ensal
+4ster
+8s
+6rial
+9lly
+4tal
+7lic
+9cs
+9sm
+9sms
+9st
+9stic
+9sts
+7s
+5hyl
+8s
+3illenaries
+9ry
+8nia
+9ial
+9ials
+9ium
+9iums
+3odal
+7ities
+9y
+4lecular
+9arly
+4nthlies
+8y
+4rph
+7emic
+7s
+2n
+3al
+4ries
+6sm
+8s
+5y
+4te
+6ly
+5ional
+4ural
+8ly
+3d
+4able
+4er
+6ies
+6s
+6y
+4hi
+6s
+4i
+5ng
+7ly
+7ness
+9sses
+7s
+5s
+4le
+6s
+4s
+4weed
+8s
+3e
+4r
+5s
+5vate
+4s
+3g
+4e
+5d
+5ing
+5r
+6s
+5s
+4hi
+6s
+4ies
+5ng
+4le
+6d
+6s
+5ing
+4o
+5es
+5s
+4s
+4y
+3iou
+6s
+4t
+5s
+3k
+4s
+3man
+4en
+3nacle
+8s
+4ed
+4ing
+3ocle
+7s
+5s
+5ular
+9ities
+9ity
+9ly
+9s
+4mial
+8ly
+8s
+6nal
+9s
+4vular
+3s
+3t
+4s
+4urong
+9s
+3uclear
+8te
+9ed
+2o
+3accumulate
+9lated
+9lates
+9lating
+9lation
+5oustics
+5tive
+8ities
+9ty
+4eration
+9ons
+6onautics
+4ssay
+8ed
+8ing
+8s
+5tronautics
+4vailability
+9ble
+3bank
+7s
+4last
+8s
+3catalyst
+9sts
+9tic
+4ellate
+5nologies
+9gy
+7se
+9s
+8is
+7tic
+4hemic
+9al
+9ally
+9als
+8st
+9tries
+9try
+9ts
+5ip
+7s
+4idal
+6e
+7s
+4lastic
+5ean
+5imatic
+9ology
+4oenologies
+9ogy
+8ses
+9is
+8tic
+5mpatible
+7uting
+9ings
+5ntrol
+9ls
+6version
+9sions
+4ycle
+8s
+3data
+4egradable
+9ation
+9ations
+9e
+9ed
+9es
+9ing
+5structible
+4iesel
+9s
+5versities
+9ity
+4ot
+6s
+4ynamic
+9cal
+9cs
+3ecological
+9ically
+9ies
+9ist
+9ists
+9y
+4lectric
+9ical
+9icity
+4nergetic
+9tics
+8ies
+8y
+5gineer
+9ered
+9ering
+9erings
+9ers
+4thanol
+9ls
+6ic
+8al
+8ist
+9sts
+8s
+3fact
+7s
+4eedback
+9cks
+4ilm
+7s
+4lavonoid
+9oids
+4ouler
+9s
+7ing
+9gs
+4uel
+7ed
+7s
+3g
+4as
+6es
+6ses
+4en
+6eses
+8is
+7tic
+9cal
+9cally
+9cs
+6ic
+7es
+6ous
+6s
+6y
+5ochemical
+9micals
+9mistry
+6grapher
+9phers
+9phic
+9phical
+9phies
+9phy
+4raph
+8ed
+9e
+9es
+9r
+9rs
+8ic
+9cal
+9cally
+9es
+9ng
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+8s
+8y
+4s
+3hazard
+9ous
+9s
+4erm
+7s
+3industries
+9ry
+5formatics
+3logic
+8al
+9lly
+9ls
+8s
+7es
+7sm
+9s
+8t
+9ic
+9s
+6y
+4uminescence
+9scent
+4yses
+6is
+5tic
+3magnetics
+5rker
+9s
+5ss
+7es
+5terial
+9als
+6hematical
+9atics
+4e
+5chanical
+9ically
+9ics
+5dical
+8ine
+9nes
+5s
+5teorology
+7r
+8s
+6ric
+9al
+9ally
+9ian
+9ians
+9s
+8es
+7y
+4imetic
+9cs
+6icries
+9y
+5ning
+9s
+4olecular
+9le
+9les
+5rph
+8ic
+8s
+3nic
+6s
+4omic
+8ally
+8s
+7es
+7st
+9s
+6y
+4t
+5ic
+5s
+3parent
+9s
+4esticidal
+9ide
+9ides
+4hilia
+9s
+5or
+7e
+8s
+7s
+5ysical
+9ally
+9ist
+9ists
+9s
+4ic
+6s
+5racies
+8y
+7te
+9s
+4lasm
+8ic
+8s
+7t
+8s
+4oieses
+8is
+5lymer
+9rs
+4rospecting
+9ctings
+4sic
+6ed
+7s
+5y
+6chologies
+9logy
+6ing
+4tic
+3reactor
+9rs
+6gent
+9ts
+5gion
+9al
+9alism
+9alisms
+9alist
+9alists
+9s
+5mediation
+9ations
+4hythm
+9ic
+9ically
+9ics
+9s
+3s
+4afeties
+8y
+5tellite
+9ites
+4cience
+9es
+8tific
+9ist
+9ists
+5ope
+8s
+7ies
+7y
+4ensor
+9s
+4ocial
+9ly
+5lid
+8s
+4phere
+9s
+8ic
+4table
+6tic
+9ally
+9s
+8stical
+9tician
+9tics
+5ratigraphy
+6ome
+9s
+4urgeries
+9y
+4yntheses
+9sis
+9tic
+5stematic
+9atics
+9atist
+9atists
+3ta
+5s
+4ech
+7nical
+8ologies
+9logist
+9logy
+7s
+5lemetric
+9tries
+9try
+5rror
+9s
+4ic
+6al
+8ly
+6s
+5n
+6s
+5te
+7s
+6ic
+4ope
+7s
+5xin
+8s
+4ron
+7s
+6ph
+8s
+4urbation
+9ions
+7ed
+4ype
+7s
+6ic
+3vular
+3weapon
+9s
+2pack
+6s
+4rental
+9lly
+5ietal
+5ous
+5ted
+6isan
+9nism
+9nisms
+9nship
+9nships
+7te
+9ly
+8ion
+9ons
+6y
+3ed
+5al
+7ism
+9ms
+8ties
+9y
+7ly
+5s
+4talous
+3hasic
+4enyl
+8s
+3innaria
+9as
+7te
+9ly
+3lane
+7s
+3od
+5s
+4lar
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+3rism
+7s
+4opellant
+9ants
+3yramid
+9al
+9s
+2quadrate
+9es
+9ic
+9ics
+5rterly
+4intile
+9es
+2racial
+8ism
+9sms
+8ly
+4dial
+6cal
+9s
+4mose
+6us
+3ch
+5bark
+9s
+5ed
+6n
+6s
+5ing
+6r
+7s
+3d
+4bath
+8s
+5rain
+9ed
+9s
+4cage
+8s
+6ll
+8s
+4dog
+7ged
+8ing
+7s
+4ed
+5r
+6s
+4farm
+8s
+5eed
+8s
+4house
+9s
+4ie
+6d
+6ing
+6s
+5ng
+7s
+4life
+6ke
+6me
+8d
+8s
+7ing
+4man
+5en
+4s
+5eed
+8s
+6ye
+8s
+5foot
+9s
+5hot
+8s
+5ong
+8s
+4watch
+9ed
+9er
+9ers
+9es
+9ing
+9ings
+5ing
+8s
+3efringence
+9ences
+9ent
+4me
+6s
+4tta
+7s
+3iani
+7s
+4yani
+8s
+3k
+4en
+4ie
+6r
+6s
+7t
+4s
+3l
+4e
+5d
+5r
+6s
+5s
+4ieman
+7en
+5ng
+7s
+6n
+7s
+4s
+3o
+4s
+5trate
+3r
+4ed
+5tta
+8s
+4ing
+4otch
+4s
+3se
+5s
+4ier
+6st
+4le
+6d
+6s
+5ing
+4y
+3th
+5date
+9s
+7y
+8s
+6om
+8s
+5ed
+5ing
+8s
+5mark
+9s
+5name
+9s
+6ight
+9ts
+5place
+9es
+5rate
+9s
+6ight
+9ts
+6oot
+9s
+5s
+6tone
+9es
+5wort
+9s
+3yani
+7s
+2s
+3cacha
+8s
+4otti
+7o
+4uit
+7s
+7y
+3e
+4ct
+6ed
+6ing
+7on
+9al
+9ally
+9s
+6or
+8s
+6rices
+8x
+6s
+4rial
+7te
+5rate
+4s
+4xual
+8ism
+9sms
+9ties
+9ty
+8ly
+8s
+3h
+4es
+4op
+6bird
+9ds
+6dom
+9s
+6ed
+7ss
+9es
+6ing
+6ric
+9s
+6s
+6weed
+9ds
+3k
+4s
+3mar
+6s
+4illah
+4uth
+7al
+7ic
+8nite
+9ites
+7ous
+7s
+3naga
+7s
+3ociation
+9ons
+9ve
+4m
+5s
+4n
+5s
+5tine
+3phenol
+9s
+5osphonate
+9onates
+3que
+6s
+3sextile
+9es
+4on
+3t
+4able
+8s
+5te
+4er
+6ed
+6s
+4ort
+7s
+5uries
+7y
+4re
+6d
+6s
+5o
+6ic
+6s
+3ulcate
+5fate
+9s
+6ide
+9s
+7te
+9s
+5phate
+9es
+7ide
+9es
+8te
+9es
+3ymmetric
+9ical
+9ically
+9ies
+9y
+2t
+3able
+4rtrate
+9es
+3e
+4able
+4plate
+9s
+4r
+5s
+4s
+5ize
+4wing
+8s
+3ing
+6ly
+6s
+3less
+3map
+6ped
+7ing
+6s
+3o
+4nal
+7ities
+9y
+4s
+4u
+3s
+4er
+6s
+4ier
+6st
+4tock
+8s
+5ream
+9s
+4y
+3t
+4acle
+8s
+4e
+5d
+5n
+5r
+6bark
+9ks
+7rush
+9shes
+6cress
+9sses
+6ed
+7r
+7st
+6ing
+7sh
+6ling
+9gs
+7y
+6n
+7ess
+9ses
+7s
+7ut
+9s
+6root
+9ts
+6s
+7weet
+9etly
+9etness
+9ets
+6weed
+9ds
+7ood
+9ds
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+7s
+4ock
+7s
+5r
+6s
+5ur
+7s
+4s
+4ur
+6s
+4y
+3umed
+6n
+7s
+5inate
+9ed
+9es
+9ing
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ous
+2unique
+8ness
+9esses
+2valence
+9s
+8ies
+8y
+7t
+8s
+5vate
+6e
+7d
+7s
+6ular
+4riant
+9s
+7te
+9s
+3ia
+4nyl
+7s
+4ous
+4um
+3ouac
+7ked
+8ing
+8s
+7s
+3vied
+6s
+4y
+5ing
+2weeklies
+7y
+2yearly
+2z
+3arre
+7ly
+7ness
+9sses
+7rie
+9es
+7s
+6o
+7s
+4zz
+6es
+3cacha
+8s
+3e
+4s
+3naga
+7s
+3onal
+5e
+6s
+3zes
+4ies
+4o
+5s
+4y
+1lab
+4bed
+6r
+7ed
+7ing
+7mouth
+9uths
+7s
+5ing
+8s
+5y
+4s
+3ck
+5amoor
+9rs
+5ball
+9ed
+9ing
+9ings
+9s
+7nd
+9s
+6erried
+9ies
+9y
+9ying
+9yings
+6ird
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+6oard
+9ds
+7dies
+8y
+7y
+8s
+6uck
+9s
+7tt
+9s
+5cap
+8s
+6ock
+9s
+6urrant
+9ants
+5damp
+9s
+5ed
+6n
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6r
+6st
+5face
+9d
+9s
+6in
+8s
+7sh
+9es
+6lies
+7y
+5game
+9s
+6uard
+9ded
+9ding
+9dism
+9disms
+9dly
+9ds
+7m
+8s
+5hander
+9ers
+6ead
+9ed
+9s
+8rt
+9ts
+5ing
+8s
+6sh
+8ly
+5jack
+9ed
+9ing
+9s
+5land
+9s
+6ead
+9s
+7g
+8ged
+9ing
+8s
+6ist
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+6y
+5mail
+9ed
+9er
+9ers
+9ing
+9s
+5ness
+9es
+5out
+8s
+5poll
+9s
+5s
+6mith
+9hing
+9hings
+9hs
+6nake
+9es
+6trap
+5tail
+9s
+6horn
+9ns
+6op
+8ped
+9ing
+8s
+5wash
+9ed
+9es
+9ing
+7ter
+9rs
+6ood
+9s
+3d
+4ded
+6r
+7ed
+7like
+7nose
+9ses
+8ut
+9ts
+7s
+7wort
+9rts
+8rack
+9acks
+7y
+5ing
+4e
+5d
+5less
+6ike
+5r
+6s
+5s
+5work
+9s
+4ier
+6st
+5ng
+7s
+4s
+4y
+3e
+4berries
+8y
+4r
+4s
+5t
+3ff
+5s
+3g
+4ged
+6r
+7s
+5ing
+8s
+4s
+4ue
+6r
+7s
+6s
+6ur
+8s
+3h
+4ed
+4ing
+4s
+3in
+5s
+4se
+4ze
+3m
+4able
+8ness
+9esses
+7y
+4e
+5able
+9ness
+9nesses
+8y
+5d
+5ful
+8ly
+8ness
+9esses
+5less
+9ly
+9ness
+9nesses
+5r
+6s
+5s
+5worthiness
+9hy
+4ing
+4s
+3nch
+6ed
+7r
+8s
+7s
+6ing
+7sseuse
+9euses
+5mange
+9es
+5o
+6ed
+6ing
+6s
+4d
+5ed
+6r
+6st
+5ing
+6sh
+8ed
+9r
+9rs
+9s
+8ing
+8ment
+9ents
+5ly
+5ness
+9es
+5s
+4k
+5ed
+6r
+6st
+6t
+7ed
+7flower
+9owers
+7ing
+9gs
+7like
+7s
+7weed
+9eds
+7y
+5ing
+8s
+5ly
+5ness
+9es
+5s
+4quet
+8s
+8te
+9es
+3re
+5d
+5s
+4ing
+4ney
+7ed
+7ing
+7s
+4t
+5ed
+5ing
+5s
+3se
+4h
+5es
+5ier
+7st
+5y
+4pheme
+9d
+9r
+9rs
+9s
+8ies
+9ng
+8ous
+9usly
+9usness
+8y
+4t
+5ed
+6ma
+8l
+8s
+8ta
+9ic
+7ic
+6r
+7s
+5ie
+7r
+7s
+8t
+6ng
+8s
+5ment
+9s
+5ochyle
+9les
+7oel
+9le
+9les
+9lic
+9ls
+7yst
+9ts
+6derm
+9mic
+9ms
+7isc
+9cs
+6ff
+8s
+6geneses
+9esis
+9etic
+9ic
+6id
+8s
+6ma
+8s
+8ta
+7ere
+9es
+9ic
+7ycoses
+9osis
+6por
+9al
+9e
+9es
+9ic
+9s
+6sphere
+9eres
+8ore
+9res
+5s
+5ula
+8e
+8r
+8s
+8tion
+9ions
+5y
+3t
+4ancies
+7y
+6t
+7ly
+4e
+5r
+5st
+4her
+7ed
+8r
+9s
+7ing
+7s
+8kite
+9ites
+4s
+4t
+5ant
+5ed
+6r
+7ed
+7ing
+7s
+5ing
+5s
+3ubok
+7s
+4d
+5ed
+5ing
+5s
+3w
+4ed
+4ing
+4n
+4ort
+7s
+4s
+3xploitation
+9ations
+3y
+4s
+3zar
+6s
+4e
+5d
+5r
+6ed
+6s
+5s
+4ing
+7ly
+4on
+6ed
+7r
+8s
+6ing
+9s
+6ries
+7y
+6s
+2each
+6able
+6ed
+7r
+8ies
+9te
+9tes
+8s
+8y
+7s
+6ing
+9s
+4k
+5er
+6st
+5ish
+5ly
+5ness
+9es
+5s
+5y
+4r
+5ed
+6r
+6st
+6yed
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5s
+5y
+4t
+5ed
+6r
+7s
+5ing
+8s
+5s
+3b
+4bier
+7st
+6ng
+8s
+5y
+4s
+3d
+3e
+4d
+5er
+7s
+5ing
+8s
+5s
+4p
+5ed
+6r
+7s
+5ing
+5s
+4s
+3llum
+7s
+3mish
+7ed
+8r
+9s
+8s
+7ing
+7ment
+9nts
+3nch
+6ed
+7r
+8s
+7s
+6ing
+4d
+5e
+6d
+6r
+7s
+6s
+5ing
+8s
+5s
+4nies
+6oid
+9s
+5orrhea
+9eas
+9oea
+9oeas
+5y
+4t
+3omycin
+9s
+3pharism
+9ms
+8tic
+9is
+9ises
+7oplast
+9lasts
+9lasty
+8spasm
+9pasms
+3rt
+5s
+3sbok
+7s
+5uck
+8s
+4s
+5ed
+7er
+8st
+7ly
+7ness
+9sses
+6r
+7s
+6s
+5ing
+8s
+4t
+3t
+4her
+7anskate
+9skates
+8tion
+9ions
+7ed
+8r
+9s
+7ing
+9gs
+7s
+8kate
+9ates
+4s
+4ted
+5ing
+3uatre
+3w
+4art
+7s
+4its
+7es
+3y
+4s
+2ight
+6ed
+7r
+8s
+6ies
+7ng
+9ly
+9s
+6s
+6y
+3ksem
+3mbing
+8s
+4ey
+4p
+5ish
+8ly
+8ness
+9esses
+5s
+4y
+3n
+4d
+5age
+8s
+5ed
+6r
+7s
+6st
+5fish
+9es
+6old
+9ed
+9ing
+9s
+5gut
+8s
+5ing
+8ly
+8s
+5less
+6y
+5ness
+9es
+5s
+6ide
+9d
+9s
+8ing
+7ght
+9ts
+6torey
+9eys
+9ies
+9y
+5worm
+9s
+4g
+5er
+6st
+5ier
+7st
+6ng
+5lish
+9es
+5s
+5y
+4i
+5s
+4k
+5ard
+8s
+5ed
+6r
+7ed
+7ing
+7s
+5ing
+5s
+4ned
+5ing
+4s
+4tz
+6e
+7s
+4y
+3p
+4ped
+5ing
+4s
+4vert
+8s
+3ss
+5ed
+6s
+5ful
+8ly
+8ness
+9esses
+5ing
+5less
+4t
+5er
+7ed
+7ier
+9st
+8ng
+9gly
+7s
+7y
+3t
+4e
+5s
+4he
+6ful
+6ly
+6ness
+9ses
+6r
+7ed
+7ing
+7s
+6some
+9ely
+9eness
+7t
+4s
+4ted
+6r
+7s
+5ing
+4z
+5ed
+6r
+7s
+6s
+5ing
+5krieg
+9gs
+3ve
+3zzard
+8ly
+8s
+8y
+2oat
+5ed
+7ness
+9sses
+6r
+7s
+5ing
+8s
+5s
+5ware
+9s
+3b
+4bed
+5ier
+7st
+6ng
+5y
+4s
+3c
+4k
+5able
+6de
+8d
+8r
+9s
+8s
+7ing
+6ge
+8s
+5board
+9ds
+6ust
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+5ed
+6r
+7s
+5head
+9ed
+9edly
+9edness
+9s
+6ole
+9s
+7use
+9es
+5ie
+7r
+7s
+8t
+6ness
+9ses
+7g
+8s
+6sh
+8ly
+8ness
+9esses
+5s
+6hip
+9s
+5work
+9s
+5y
+4s
+3g
+4ged
+6r
+7ati
+7s
+5ing
+8s
+4osphere
+9res
+4ring
+8s
+5oll
+8s
+4s
+5tream
+9ms
+3kart
+7ing
+9gs
+7s
+4e
+5dom
+8s
+5ish
+8ness
+9esses
+5s
+5y
+4ier
+6st
+5sh
+7ness
+9sses
+3ncket
+4d
+5e
+6ness
+9ses
+6r
+6s
+7t
+5ine
+8d
+8s
+7g
+8s
+7ing
+6sh
+5ness
+9es
+5s
+3od
+5bath
+9s
+5curdling
+9lingly
+5ed
+5fin
+8s
+5guilt
+9tiness
+9ts
+9ty
+5hound
+9ds
+5ied
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+8s
+5less
+9ly
+9ness
+9nesses
+7tter
+9ers
+9ing
+9ings
+6ike
+7ne
+9s
+6ust
+9s
+5mobile
+9les
+5red
+6oot
+9s
+5s
+6hed
+9s
+7ot
+6prent
+6tain
+9ned
+9ns
+7ock
+9ks
+8ne
+9es
+7ream
+9ams
+6ucker
+9ers
+9ing
+5thirstier
+9stiest
+9stily
+9sty
+5wood
+9s
+7rm
+9s
+8t
+9s
+5ying
+4ey
+4ie
+4k
+5s
+4m
+5ed
+6r
+7ies
+7s
+7y
+5ier
+7st
+6ng
+5less
+5s
+5y
+4p
+5ed
+6r
+7s
+5ing
+5s
+4sme
+7d
+7s
+6ing
+4tered
+3quiste
+9s
+3re
+5s
+3ssom
+7ed
+7ing
+9gs
+7less
+7s
+7y
+3t
+4ch
+6ed
+7s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9s
+6y
+4less
+4s
+4ted
+6r
+7s
+6sque
+9es
+5ier
+7st
+6ng
+8s
+5o
+5y
+3ubok
+7s
+4se
+6d
+6s
+5ier
+7st
+6ly
+6ng
+5on
+7s
+5y
+3viate
+8d
+8s
+7ing
+8on
+9ns
+3w
+4back
+8s
+6ll
+8s
+5y
+6s
+4down
+8s
+4ed
+5r
+6s
+4fish
+8es
+5lies
+6y
+4gun
+7s
+4hard
+8s
+5ole
+8s
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+7s
+4lamp
+8s
+4n
+4off
+7s
+5ut
+7s
+4pipe
+8s
+4s
+5e
+6d
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+5y
+4torch
+9ed
+9es
+9ing
+5ube
+8s
+4up
+6s
+4y
+4ze
+6d
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+5y
+2ub
+4bed
+6r
+7ed
+8r
+9s
+7ier
+9st
+8ng
+7s
+7y
+5ing
+4s
+3cher
+7s
+3de
+5s
+4ge
+6d
+6on
+8ed
+9r
+9rs
+8ing
+8s
+6r
+7s
+6s
+5ing
+4ie
+6r
+6st
+4y
+3e
+4back
+8s
+6ll
+8s
+5eard
+9s
+7t
+8s
+6ll
+8s
+6rries
+8y
+5ill
+8s
+6rd
+8s
+5lood
+9s
+5onnet
+9ts
+6ok
+8s
+6ttle
+9es
+5reast
+9ts
+5uck
+8s
+6sh
+8es
+4cap
+7s
+5oat
+8s
+5urls
+4d
+4fin
+7s
+6sh
+8es
+4gill
+8s
+5own
+8s
+5rass
+9es
+5um
+7s
+4head
+8s
+4ing
+7s
+5sh
+7ness
+9sses
+4jack
+8et
+9ts
+8ing
+9ngs
+8s
+6y
+7s
+5eans
+4line
+8r
+9s
+8s
+5y
+4ness
+8es
+5ose
+8d
+8s
+4point
+9s
+5rint
+9ed
+9ing
+9s
+4r
+4s
+5hift
+9ed
+9s
+5ier
+7st
+5man
+6en
+5narfing
+9ings
+5t
+6em
+8s
+6ocking
+9ings
+7ne
+9s
+5y
+4t
+5hroat
+9ts
+5ick
+8s
+6t
+7s
+5ongue
+9es
+5s
+5te
+7s
+4weed
+8s
+5ing
+8s
+5ood
+8s
+4y
+5s
+3ff
+5able
+5ed
+6r
+7s
+6st
+5ing
+5ly
+5ness
+9es
+5s
+3ggier
+7st
+5y
+3id
+5ier
+7st
+5s
+5y
+4er
+5st
+4ng
+6s
+4sh
+6ness
+9ses
+3me
+5d
+5s
+4ing
+3nder
+7buss
+9sses
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7s
+4ge
+6d
+6r
+7s
+6s
+5ing
+4k
+5ed
+6r
+7s
+5ing
+5s
+4t
+5ed
+6r
+6st
+5head
+9s
+5ing
+6sh
+5ly
+5ness
+9es
+5s
+3r
+4b
+5ed
+5ing
+6st
+8s
+5s
+4red
+7ly
+7ness
+9sses
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+5y
+4s
+4t
+5ed
+6r
+7s
+5ing
+8s
+5s
+3sh
+5ed
+6r
+7s
+6s
+6t
+7s
+5ful
+5ing
+8ly
+8s
+5less
+9ly
+4ter
+7ed
+8r
+9s
+7ier
+9st
+8ng
+9gly
+9gs
+7ous
+9sly
+7s
+7y
+5rous
+3twurst
+9s
+2ype
+5s
+1o
+2a
+3b
+4s
+3k
+4ed
+4ing
+4s
+3r
+4d
+5able
+5ed
+6r
+7s
+5ing
+8house
+9ouses
+8s
+5like
+5man
+6en
+5room
+9s
+5s
+6ailing
+9ings
+9or
+9ors
+5walk
+9s
+4fish
+8es
+4hound
+9s
+4ish
+7ly
+7ness
+9sses
+4s
+4t
+5s
+3s
+4t
+5ed
+6r
+7s
+5ful
+8ly
+8ness
+9esses
+5ing
+8ly
+8s
+5less
+5s
+3t
+4able
+4bill
+8s
+5uilder
+9ers
+9ing
+9ings
+4ed
+5l
+6s
+5r
+6s
+4ful
+7s
+4hook
+8s
+6use
+9s
+4ie
+6s
+5ng
+7s
+4lift
+8ed
+8ing
+8s
+6ke
+5oad
+8s
+4man
+5en
+4neck
+8s
+4s
+5man
+6en
+5wain
+9s
+4tail
+8s
+4yard
+8s
+2b
+3a
+4c
+5s
+4k
+5s
+4s
+3bed
+5jaan
+9s
+5r
+6ies
+6s
+6y
+4ies
+5n
+6et
+8s
+6g
+6s
+5sh
+5tt
+7ed
+7ing
+7s
+4le
+6d
+6head
+9ds
+6s
+5ier
+7st
+6ng
+5y
+4y
+5sock
+9s
+7x
+8er
+9rs
+3cat
+6s
+3eche
+7s
+3float
+8s
+3let
+6s
+3ol
+5ink
+8s
+5led
+6ing
+5s
+4tie
+7s
+4wler
+8s
+3s
+4led
+7ded
+9r
+9rs
+8ing
+9ngs
+7s
+6igh
+9ed
+9ing
+9s
+4tay
+7s
+3tail
+7ed
+7ing
+7s
+3weight
+9s
+4heel
+8s
+5ite
+8s
+4ig
+6s
+2caccio
+8s
+4ge
+6s
+3ca
+5s
+4e
+5s
+4i
+5a
+6s
+5e
+6s
+5s
+4oncini
+3he
+5s
+3k
+4ed
+6y
+4ing
+4s
+3oncini
+2d
+3ach
+6s
+5ious
+9ly
+3dhisattva
+9tvas
+4le
+6s
+3e
+4d
+4ful
+4ga
+6s
+5uero
+9s
+4ment
+8s
+4s
+3ge
+5d
+5r
+6s
+5s
+4ie
+6r
+6s
+7t
+5ng
+3hi
+5sattva
+9vas
+4ran
+7s
+3ice
+6s
+4ed
+5s
+4kin
+7s
+4less
+5y
+4ng
+6ly
+6s
+3kin
+6s
+3le
+5s
+3rag
+6s
+3s
+3y
+4board
+9ed
+9ing
+9ings
+9s
+5uilder
+9ers
+9ing
+9ings
+4check
+9ed
+9ing
+9s
+4guard
+9ed
+9ing
+9s
+4ing
+4line
+8s
+4shell
+9s
+5uit
+8s
+6rf
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+4work
+8er
+9rs
+8s
+2ehmite
+8s
+3p
+4s
+3rbul
+7l
+8s
+7s
+4emusiek
+9eks
+5wors
+9es
+4tjie
+8s
+3t
+4s
+3uf
+2ff
+4ed
+4in
+6g
+6s
+4o
+5la
+7s
+5s
+4s
+2g
+3an
+5s
+4rt
+6ed
+6ing
+6s
+3bean
+7s
+3ey
+5ed
+5ing
+6sm
+8s
+5man
+6en
+5s
+3gard
+7s
+6t
+7s
+4ed
+5r
+6s
+4ier
+6st
+5ness
+9es
+6g
+5sh
+4le
+6d
+6r
+7s
+6s
+5ing
+4y
+3ie
+5d
+5ing
+5s
+3land
+7s
+4e
+5d
+5s
+4ing
+3man
+4en
+3oak
+6s
+4ng
+6s
+3s
+3trotter
+9rs
+8ing
+9ngs
+3us
+5ly
+5ness
+9es
+3wood
+7s
+3y
+4ism
+7s
+4man
+5en
+2h
+3ea
+5s
+4mia
+7n
+8ism
+9sms
+8s
+7s
+3o
+4s
+3rium
+7s
+3s
+3unk
+6s
+2i
+3l
+4able
+4ed
+5r
+6ies
+6maker
+9ers
+6plate
+9ted
+9tes
+9ting
+6s
+7uit
+9ts
+6y
+4ing
+7ly
+7s
+4off
+7s
+5ver
+8s
+4s
+3ng
+5ed
+5ing
+5s
+4k
+5ed
+5ing
+5s
+3s
+4erie
+8s
+4terous
+9sly
+9sness
+3te
+5s
+2k
+3e
+4d
+4h
+4s
+3ing
+3makierie
+9ies
+3o
+4s
+3s
+2la
+4r
+4s
+5es
+3d
+4en
+6ed
+6ing
+6s
+5r
+5st
+4face
+8d
+8s
+7ing
+4ly
+4ness
+8es
+4s
+3e
+4ction
+9s
+4ro
+6s
+4s
+4te
+6s
+5i
+5us
+7es
+3ide
+6s
+4ne
+6s
+4var
+7es
+7s
+5ia
+7no
+9s
+7s
+4x
+5ed
+6s
+5ing
+3l
+4ard
+7s
+4ed
+5n
+5trie
+9s
+4ing
+5x
+6ed
+7s
+6ing
+4s
+4worm
+8s
+3o
+4gna
+7s
+6ese
+9s
+5raph
+9s
+4meter
+9s
+7ric
+9cally
+9es
+8y
+4ney
+7s
+4s
+3shevik
+9i
+9s
+8sm
+9ms
+8ze
+9ed
+9es
+9ing
+5ie
+7r
+7s
+8t
+5y
+4on
+6s
+4ter
+7ed
+8r
+9s
+7ing
+9gs
+7s
+3t
+4ed
+5r
+6s
+4head
+8s
+5ole
+8s
+4ing
+7s
+4less
+5ike
+4onia
+8s
+4rope
+8s
+4s
+3us
+5es
+2ma
+4s
+3b
+4able
+5caceous
+5rd
+7e
+8d
+8r
+9s
+8s
+7ier
+9rs
+8ng
+7ment
+9nts
+7on
+9s
+7s
+5sine
+9s
+6t
+7ed
+8r
+9s
+7ic
+9ally
+8ng
+7s
+5x
+6es
+5zine
+9s
+4e
+5d
+5r
+6s
+5s
+6in
+8s
+4ilate
+9d
+9s
+8ing
+9on
+9ons
+5nate
+9d
+9s
+8ing
+9on
+9ons
+6g
+7s
+4let
+7s
+5oad
+8s
+4o
+5ra
+7s
+5s
+4proof
+9ed
+9ing
+9s
+4s
+5hell
+9s
+5ight
+9s
+6te
+8s
+4ycid
+8s
+6oid
+5x
+6es
+3mie
+6s
+2n
+3a
+4ci
+6s
+4mani
+7o
+5ia
+7s
+8es
+8is
+4nza
+7s
+4ssus
+8es
+5us
+7es
+3bon
+6niere
+9res
+6s
+3ce
+5s
+3d
+4able
+5ger
+8s
+7s
+4ed
+5r
+6s
+4holder
+9rs
+4ing
+7s
+4less
+4maid
+8s
+6n
+7ship
+9ips
+5en
+4s
+5ervant
+9nts
+5man
+6en
+5tone
+9s
+5woman
+8en
+4uc
+6s
+4woman
+7en
+3e
+4black
+9s
+4d
+4fish
+8es
+8ing
+9ngs
+4head
+8ed
+9dness
+8s
+4less
+4meal
+8s
+4s
+5et
+7s
+7ter
+9rs
+5haker
+9rs
+4tired
+4y
+5ard
+8s
+5er
+6st
+3fire
+7s
+3g
+4ed
+4ing
+4o
+5es
+5ist
+8s
+5s
+4race
+8s
+4s
+3ham
+6s
+4omie
+8s
+6mie
+9s
+6ous
+3iato
+7s
+4bell
+8s
+4e
+5r
+5st
+4face
+8s
+4lasse
+9s
+4ness
+8es
+5g
+6s
+4sm
+6s
+5t
+6s
+4ta
+6s
+5o
+6es
+6s
+3jour
+3k
+4buster
+9rs
+4ed
+5rs
+4ing
+7s
+4s
+3ne
+5s
+5t
+6ed
+6ing
+6s
+4ibell
+9s
+5e
+6r
+6s
+7t
+5lasse
+9es
+6y
+5ness
+9es
+4ock
+7s
+4y
+5clabber
+9bers
+3obo
+6s
+3sai
+4ela
+7s
+6la
+8s
+4oir
+4pell
+8s
+5iel
+8s
+3tebok
+8s
+3us
+5es
+3xie
+6s
+3y
+3za
+4e
+5r
+5s
+2o
+3ai
+5s
+4y
+5s
+3bed
+4head
+8s
+4ialla
+9s
+5e
+6s
+5ng
+5rd
+7s
+5sh
+4oisie
+9s
+5o
+6k
+7s
+6s
+4y
+5ish
+7m
+8s
+3coo
+6s
+3die
+6d
+6s
+4le
+6d
+6r
+7s
+6s
+5ing
+4y
+5ing
+3ed
+3fhead
+8s
+4ier
+6st
+4y
+3galoo
+8ed
+8ing
+8s
+4er
+6man
+7en
+6s
+5y
+6ed
+6ing
+6man
+7en
+6s
+4ie
+6d
+6ing
+6man
+7en
+6s
+4y
+5ing
+5man
+6en
+3h
+4ai
+6s
+4ed
+4ing
+4oo
+6ed
+6ing
+6s
+4s
+3ing
+3jum
+6s
+3k
+4able
+4binder
+9ries
+9rs
+9ry
+8ing
+9ngs
+4case
+8s
+5rossing
+9ings
+4ed
+5nd
+7s
+5r
+6s
+4ful
+7s
+4ie
+6r
+6s
+7t
+5ng
+7s
+5sh
+7ly
+7ness
+9sses
+4keeper
+9rs
+8ing
+9ngs
+4land
+8s
+5ess
+6t
+7s
+5ice
+6ght
+9s
+5ore
+8s
+6use
+4maker
+9s
+7ing
+9gs
+6n
+6rk
+8ed
+9r
+9rs
+8ing
+8s
+5en
+5obile
+9es
+4oo
+6s
+4plate
+9s
+4rack
+8s
+5est
+8s
+4s
+5eller
+9rs
+8ing
+9ngs
+5helf
+8ves
+6op
+8s
+5ie
+7r
+7st
+5tall
+9s
+7nd
+9s
+6ore
+9s
+5y
+4work
+8s
+7m
+8s
+4y
+3l
+4ed
+4ing
+4s
+3m
+4box
+7es
+4ed
+5r
+6ang
+9ed
+9ing
+9s
+6s
+4ier
+6st
+5ng
+7ly
+7s
+4kin
+7s
+4let
+7s
+4s
+5lang
+9s
+4town
+8s
+4y
+3n
+4dock
+8s
+6ggle
+9ed
+9er
+9ers
+9es
+9ing
+4er
+6s
+4g
+5a
+6ries
+7y
+6s
+5s
+4ies
+4less
+4s
+3r
+4d
+5e
+6s
+5s
+4ish
+7ly
+7ness
+9sses
+4ka
+6s
+4s
+4tree
+8s
+3s
+4e
+5d
+5s
+4ing
+4t
+5ed
+6r
+7ish
+9m
+9ms
+7s
+5ing
+5s
+3t
+4able
+4black
+9s
+4cut
+4ed
+5e
+6s
+5ries
+6y
+4h
+5ose
+5s
+4ie
+6s
+5kin
+8s
+5ng
+4jack
+8s
+4lace
+8s
+6st
+8s
+5eg
+7ged
+9r
+9rs
+8ing
+9ngs
+7s
+6ss
+8ly
+8ness
+9esses
+5ick
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+5oader
+9rs
+4maker
+9s
+7ing
+9gs
+4s
+5trap
+9ped
+9ping
+9s
+4y
+5licious
+3ze
+5d
+5r
+6s
+5s
+5y
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4y
+2p
+3eep
+6s
+3ped
+5r
+6s
+4ing
+3s
+2r
+3a
+4ces
+5hio
+8s
+5ic
+6te
+8s
+4ge
+6s
+5inaceous
+4k
+5s
+4l
+5s
+4ne
+6s
+4s
+4te
+6d
+6s
+5ing
+4x
+5es
+4zon
+7s
+3borygmal
+9i
+9ic
+9us
+3d
+4ar
+6s
+4e
+5aux
+5l
+6lo
+8s
+6s
+5r
+6eau
+9x
+7d
+7r
+8s
+6ing
+6land
+9ds
+7ess
+7ine
+9es
+6s
+5s
+4raging
+9gs
+4s
+4ure
+7s
+3e
+4al
+6is
+5s
+6es
+4cole
+8s
+4d
+5om
+7s
+4e
+5n
+6s
+5s
+4hole
+8s
+4l
+4r
+5s
+4s
+5cope
+9s
+5ome
+3ghetto
+9s
+4o
+5s
+3ic
+4de
+6s
+4ng
+6ly
+6ness
+9ses
+6s
+3k
+4ed
+4ing
+4s
+3lotti
+3m
+4ed
+4ing
+4s
+3n
+4a
+4e
+5ol
+7s
+4ite
+7s
+6ic
+4yl
+6s
+3ohydride
+9des
+4n
+5ia
+7s
+6c
+5s
+4silicate
+9ates
+4ugh
+7s
+3rel
+6ia
+8s
+6l
+4ow
+6ed
+7r
+8s
+6ing
+9s
+6s
+3s
+4ch
+6es
+6t
+7s
+4hch
+7es
+5t
+6s
+4ic
+6s
+4tal
+7l
+8s
+7s
+3t
+4ier
+6st
+4s
+5ch
+7es
+4y
+4z
+5es
+3zoi
+6s
+2s
+3beraad
+9s
+4ok
+6s
+3cage
+7s
+4hbok
+8s
+5e
+6s
+5vark
+9s
+6eld
+9s
+3h
+4bok
+7s
+4es
+4ta
+5er
+4vark
+8s
+3ie
+5s
+3k
+4age
+7s
+4er
+5t
+6s
+4ier
+6st
+5ness
+9es
+4s
+4y
+3om
+5ed
+5ier
+7st
+6ng
+5s
+5y
+4n
+5ic
+5s
+3que
+6s
+6t
+7s
+3s
+4boy
+7s
+4dom
+7s
+4ed
+5r
+5s
+6t
+5t
+6s
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+5sm
+7s
+4y
+5boots
+3tangi
+8s
+4hoon
+8s
+4on
+6s
+4ryx
+7es
+3un
+5s
+2t
+3a
+4nic
+7a
+8l
+9ly
+9s
+8s
+7s
+6es
+6se
+8d
+8r
+9s
+8s
+7ing
+7t
+8s
+6ze
+8d
+8r
+9s
+8s
+7ing
+5omancies
+9cy
+5y
+4rgo
+7es
+7s
+4s
+3ch
+5ed
+7ly
+6r
+7ies
+7s
+7y
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5y
+3e
+4l
+5s
+4s
+3flies
+5y
+3h
+4an
+6s
+4er
+6ation
+9ons
+6ed
+6ing
+6s
+7ome
+4ie
+6s
+4ole
+7s
+4ria
+6um
+8s
+4y
+5man
+6en
+3net
+6s
+3one
+6e
+5nee
+3ryoid
+8al
+6se
+5tis
+8es
+3s
+3t
+4arga
+8s
+4e
+5d
+5ga
+7s
+5s
+4ies
+5ne
+7s
+6g
+4le
+6brush
+9shes
+6d
+6ful
+9s
+6neck
+9ked
+9king
+9ks
+7ose
+9es
+6r
+7s
+6s
+5ing
+8s
+4om
+6ed
+7r
+8s
+6ing
+9s
+6land
+9ds
+7ess
+9sly
+9sness
+6most
+6ness
+9ses
+6ries
+7y
+6s
+7et
+5ny
+4s
+4y
+3ulin
+7al
+7s
+7um
+9s
+8s
+9es
+6sm
+8s
+2ubou
+6s
+3che
+6e
+7s
+6s
+4le
+6e
+7s
+6s
+3derie
+8s
+4in
+6s
+4oir
+7s
+3ffant
+8s
+5e
+6s
+3gainvilia
+9lias
+9llaea
+9llaeas
+9llea
+9lleas
+4e
+5d
+5s
+5t
+6s
+4h
+5ed
+5less
+5pot
+8s
+5s
+5t
+6en
+6s
+4ie
+6s
+5ng
+3illabaisse
+9isses
+6i
+7s
+6on
+8s
+7tte
+9es
+3k
+4s
+3lder
+7ed
+8r
+9s
+7ing
+9gs
+7s
+7y
+4e
+5s
+5vard
+9ier
+9iers
+9s
+6ersement
+9ements
+4le
+6s
+6work
+9ks
+4t
+5ed
+6r
+7s
+5ing
+8s
+5s
+3n
+4ce
+6d
+7own
+9ns
+6r
+7s
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+5y
+4d
+5able
+6ries
+7y
+5ed
+7ness
+9sses
+6n
+6r
+7ish
+7s
+5ing
+5less
+9ly
+9ness
+9nesses
+5ness
+9es
+5s
+4ed
+4ing
+4s
+4teous
+9ly
+9ness
+9nesses
+5ied
+7s
+6ful
+9ly
+9ness
+9nesses
+5ree
+8s
+5y
+6hed
+9s
+3quet
+7iere
+9res
+7s
+3rasque
+9s
+4bon
+7ism
+9ms
+7s
+4d
+5er
+7s
+5on
+7s
+5s
+4g
+5eois
+9e
+9es
+9ie
+9ies
+9ified
+9ifies
+9ify
+9ifying
+7n
+8ed
+8ing
+8s
+5s
+5uignon
+9onne
+4kha
+7s
+4law
+7s
+4n
+5e
+6s
+5s
+4ree
+7s
+5ide
+8s
+4se
+6s
+5ier
+8s
+6n
+7s
+4tree
+8s
+3se
+5d
+5s
+4ier
+6st
+5ng
+7ken
+9ns
+4ouki
+8a
+8s
+4trophedon
+9edonic
+9edons
+4y
+3t
+4ade
+7s
+4ique
+8s
+8y
+4on
+6ne
+8e
+7iere
+9res
+6s
+4s
+3vardia
+9s
+4ier
+7s
+3zouki
+8a
+8s
+2vate
+6s
+3id
+5s
+4ne
+6ly
+6s
+5ities
+7y
+3ver
+6s
+2w
+3at
+5s
+3bent
+3dlerisation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+3ed
+4l
+5ed
+5ing
+5led
+7ss
+6ing
+5s
+4r
+5bird
+9s
+5ed
+5ies
+6ng
+5s
+5woman
+8en
+5y
+4s
+4t
+5s
+3fin
+6s
+4ront
+3get
+6s
+3head
+7s
+4unter
+9s
+3ie
+4ng
+6ly
+6s
+3knot
+7s
+3l
+4der
+7s
+4ed
+5g
+6ged
+6s
+5r
+6s
+5ss
+4ful
+7s
+4ike
+5ne
+7s
+6g
+7s
+4like
+4s
+3man
+4en
+3ne
+5d
+5s
+4ing
+3pot
+6s
+3r
+4s
+3s
+4aw
+6s
+4e
+5d
+5r
+6s
+5s
+5y
+6s
+4hot
+7s
+4ie
+6s
+5ng
+4prit
+8s
+4tring
+9ed
+9ing
+9s
+6ung
+3wow
+6ed
+6ing
+6s
+3yang
+7s
+4er
+6s
+2x
+3ball
+7s
+4erries
+7y
+4oard
+8s
+3car
+6s
+3ed
+4n
+4r
+5cise
+9s
+5s
+4s
+3fish
+7es
+4ul
+6s
+3haul
+7ed
+7ing
+7s
+3ier
+5st
+4ly
+4ness
+8es
+5g
+6s
+3keeper
+9s
+3like
+3plot
+7s
+3room
+7s
+3thorn
+8s
+4ies
+4y
+3wallah
+9s
+4ood
+7s
+3y
+2y
+3ar
+5d
+6s
+5ism
+8s
+5s
+4u
+5x
+3chick
+8s
+6k
+7s
+4ott
+7ed
+8r
+9s
+7ing
+7s
+3ed
+3f
+4riend
+9s
+4s
+3g
+4s
+3hood
+7s
+3ing
+4sh
+6ly
+6ness
+9ses
+3kie
+6s
+3la
+5s
+3o
+4s
+3s
+4enberries
+9ry
+4horts
+4ier
+6st
+4y
+2zo
+4s
+3zetti
+7o
+1ra
+3ai
+5ed
+5ing
+5s
+5vleis
+9ses
+4ta
+6s
+7es
+3bble
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+3ccate
+5ia
+6o
+4e
+5d
+5let
+8s
+5r
+6o
+7s
+6s
+5s
+4h
+5ah
+7s
+5es
+6t
+7s
+5ia
+7l
+8s
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6ocephalic
+7pod
+9ds
+7saurus
+9uruses
+6stochrone
+6um
+5ot
+5s
+5yaxes
+8is
+6cephal
+9halic
+9halics
+9halies
+9halism
+9halous
+9hals
+9haly
+8rous
+6dactyl
+9tylic
+9tylies
+9tylism
+9tylous
+9tyly
+7iagonal
+9gonals
+7ome
+9es
+6graphies
+9phy
+6logies
+9ous
+9y
+6odont
+6pinakoid
+9akoids
+7rism
+9sms
+7terism
+9risms
+9rous
+6therapies
+9rapy
+6ural
+9n
+9ns
+8ous
+4ing
+7ly
+7s
+5ola
+8s
+7e
+8s
+4k
+5en
+7s
+6t
+7ed
+7ing
+9gs
+7s
+5ish
+8ness
+9esses
+5s
+4onid
+8s
+4t
+5eal
+7te
+9s
+6d
+6olate
+8e
+9s
+5less
+7t
+8s
+5s
+3d
+4awl
+7s
+4ded
+5ing
+4oon
+7s
+4s
+4ycardia
+9iac
+9ias
+5kinesia
+9sias
+8in
+9ns
+5peptic
+9ics
+5seism
+9ms
+3e
+4heid
+8s
+4s
+3g
+4adisme
+9es
+4gadocio
+9ios
+9ious
+6rt
+8ism
+9sms
+8ly
+8s
+5ed
+6r
+7s
+6st
+5ier
+7st
+6ng
+8ly
+8s
+5y
+4ly
+4s
+3hma
+6n
+7i
+8s
+9m
+9ms
+9t
+9ts
+7s
+6s
+5in
+7ism
+9ms
+9t
+9ts
+7s
+3id
+5e
+6d
+6r
+7s
+6st
+5ing
+8s
+5s
+4l
+5ed
+5ing
+5le
+7d
+7r
+8s
+7s
+7writer
+9iters
+6ing
+7st
+9s
+5s
+4n
+5box
+8es
+5case
+9s
+6hild
+9dren
+5dead
+5ed
+5fart
+9s
+6ood
+9s
+5iac
+8s
+6er
+7st
+6ly
+6ness
+9ses
+7g
+6sh
+5less
+9ly
+9ness
+9nesses
+5pan
+8s
+6ower
+9rs
+5s
+6ick
+9ly
+9ness
+9nesses
+6tem
+9s
+7orm
+9med
+9mer
+9mers
+9ming
+9mings
+9ms
+5teaser
+9ers
+5wash
+9ed
+9er
+9ers
+9es
+9ing
+9ings
+7ve
+9s
+5y
+4rd
+6ed
+6ing
+6s
+4se
+6d
+6s
+5ing
+4ze
+6s
+3k
+4e
+5age
+8s
+5d
+5less
+5man
+6en
+5s
+6man
+7en
+4ier
+6st
+5ng
+4s
+4y
+3less
+3mble
+7d
+7s
+6ier
+8st
+7ng
+9s
+6y
+4e
+5s
+3n
+4card
+8s
+5h
+6ed
+7r
+8ies
+8s
+8y
+7s
+6ia
+8e
+8l
+8te
+7er
+8st
+7ng
+9s
+7opod
+9ods
+8stegal
+6less
+8t
+9s
+7ike
+8ne
+9es
+6y
+4d
+5ade
+8s
+5ed
+6r
+7ed
+7ing
+7s
+5ied
+7s
+6ng
+8s
+6se
+8s
+7h
+8ed
+9r
+9rs
+9s
+8ing
+5less
+6ing
+9s
+5reth
+9s
+5s
+5y
+6ing
+4e
+5s
+4fulness
+9sses
+4gle
+7d
+7s
+6ing
+9s
+4k
+5ed
+5ier
+7st
+6ng
+5s
+5ursine
+9nes
+5y
+4le
+6s
+4ned
+6r
+7s
+5ier
+7st
+6gan
+9s
+6ng
+5y
+4s
+5le
+7s
+4t
+5ail
+8s
+5le
+7s
+5s
+3s
+4co
+6s
+4ero
+7s
+5s
+4h
+5ed
+6r
+6s
+7t
+5ier
+7st
+6ness
+9ses
+7g
+5ly
+5ness
+9es
+5y
+4ier
+7s
+5l
+6ein
+9s
+6in
+8s
+6s
+4s
+5age
+8s
+6rd
+8s
+7t
+8s
+5bound
+5ed
+6rie
+9s
+6s
+6t
+7s
+5founder
+9ders
+9ding
+9dings
+5ica
+8ceous
+8s
+6e
+7r
+8e
+9s
+7s
+8t
+6ly
+6ness
+9ses
+7g
+6sh
+5ware
+9s
+5y
+4t
+5ing
+5s
+3t
+4chet
+8s
+4ling
+8s
+4pack
+8er
+9rs
+8s
+4s
+4tice
+8d
+8s
+7ing
+9gs
+6er
+7st
+6ness
+9ses
+6sh
+8ed
+9s
+8ing
+9ngs
+5le
+7d
+7s
+6ing
+9s
+5y
+4wurst
+9s
+3unch
+7ed
+8s
+7ing
+5ite
+8s
+5schweiger
+9eigers
+3va
+5do
+7ed
+8s
+7ing
+7s
+5s
+4e
+5d
+5ly
+5ness
+9es
+5r
+6ies
+6s
+6y
+5s
+6t
+4i
+5ng
+5ssimo
+4o
+5ed
+6s
+5ing
+5s
+4ura
+7s
+6e
+3w
+4er
+5st
+4l
+5ed
+6r
+7s
+5ie
+7r
+7st
+6ng
+8s
+5s
+5y
+4n
+5ed
+5ier
+7st
+6ly
+6ness
+9ses
+5s
+5y
+4s
+3xies
+4y
+3y
+4ed
+5r
+6s
+4ing
+4s
+3za
+5s
+4e
+5d
+5less
+5n
+6ed
+6ing
+6ly
+6ness
+9ses
+6ries
+7y
+6s
+5r
+6s
+5s
+4ier
+7ies
+7s
+7y
+5l
+6ein
+9s
+6in
+8s
+6s
+6wood
+9ds
+5ng
+2each
+6ed
+7r
+8s
+7s
+6ing
+4d
+5basket
+9ets
+6erries
+9y
+6oard
+9ded
+9ding
+9ds
+7x
+8es
+5crumb
+9bed
+9bing
+9bs
+5ed
+5fruit
+9ts
+5head
+9s
+5ier
+7st
+6ng
+5less
+6ine
+9s
+5nut
+8s
+5room
+9s
+8t
+9s
+5s
+6tick
+9ks
+7uff
+9fs
+5th
+7s
+7ways
+8ise
+5winner
+9ers
+9ing
+9ings
+5y
+4k
+5able
+9ness
+9nesses
+9s
+6ge
+8s
+6way
+9s
+5back
+6eat
+9s
+6one
+5dance
+9ed
+9er
+9ers
+9es
+9ing
+9ings
+6own
+9s
+5er
+7s
+6ven
+9s
+5fast
+9ed
+9er
+9ers
+9ing
+9s
+6ront
+9ts
+5ing
+8s
+5neck
+5off
+8s
+6ut
+8s
+5point
+9ts
+5s
+6away
+5through
+9ughs
+6ime
+9s
+5up
+7s
+5wall
+9s
+7ter
+9rs
+4m
+5ed
+5ing
+5s
+4re
+6s
+4skit
+8s
+5t
+6bone
+9es
+6ed
+6fed
+8ed
+9ding
+9dings
+9ds
+6ing
+6pin
+9s
+7late
+9tes
+8ough
+9ughs
+6rail
+9ls
+6stroke
+9oker
+9okers
+9okes
+7ummer
+9mers
+6work
+9ks
+4th
+6abilities
+9lity
+8le
+7lyse
+9sed
+9ser
+9sers
+9ses
+9sing
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+7rian
+9anism
+9anisms
+9ans
+6e
+7d
+7r
+8s
+7s
+6ful
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9s
+6less
+9sly
+9sness
+6s
+6taking
+9ingly
+6y
+3ccia
+7l
+7s
+7te
+9d
+9s
+8ing
+9on
+9ons
+4ham
+7s
+6n
+7s
+3d
+4e
+5d
+5s
+4ie
+6s
+5ng
+4ren
+7s
+5in
+7s
+4s
+3e
+4ch
+6block
+9cks
+6cloth
+9ths
+9ut
+9uts
+6ed
+7s
+6ing
+9s
+6less
+7oader
+9ders
+4d
+5er
+7s
+5ing
+8s
+5s
+4ks
+4m
+4nge
+7d
+7s
+6ing
+4r
+5ed
+5ing
+5s
+4s
+5e
+6s
+5t
+6s
+4ze
+6d
+6less
+6s
+6way
+9s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5y
+3gma
+6ta
+7e
+7ic
+3hon
+6s
+3i
+4d
+5s
+4ing
+4nge
+7d
+7s
+6ing
+4s
+5t
+6s
+3kkies
+5y
+3loque
+8s
+3me
+4sstrahlung
+9hlungs
+3n
+4ne
+6s
+5ing
+4s
+4t
+5er
+6st
+5s
+3r
+4e
+5s
+4s
+3saola
+8s
+4summer
+9rs
+3tasche
+9s
+4esse
+8s
+4hren
+4on
+6s
+4tice
+8d
+8s
+7ing
+3unnerite
+9tes
+3ve
+5s
+5t
+6cies
+7y
+6e
+7d
+6ing
+6s
+6ted
+7ing
+4iaries
+7y
+6te
+8s
+5er
+7s
+5pennate
+5s
+6es
+5ties
+6y
+3w
+4age
+7s
+4ed
+5r
+6ies
+6s
+6y
+4ing
+7s
+5s
+6es
+4master
+9rs
+4pub
+7s
+4s
+5ki
+7es
+7s
+5ter
+8s
+3y
+4ed
+4ing
+4s
+2iar
+5d
+6s
+5ed
+5root
+9s
+5s
+5wood
+9s
+5y
+3bable
+4e
+5able
+5d
+5e
+6s
+5r
+6ies
+6s
+6y
+5s
+4ing
+3cabrac
+9s
+4ht
+6er
+7st
+4k
+5bat
+8s
+5clay
+9s
+5earth
+9hs
+6d
+6n
+5field
+9der
+9ders
+9ds
+5ie
+7r
+7s
+8t
+6ng
+8s
+5kiln
+9s
+5layer
+9rs
+8ing
+9ngs
+6e
+7s
+6ike
+5maker
+9rs
+8ing
+9ngs
+5s
+5wall
+9s
+6ork
+9s
+5y
+6ard
+9s
+4olage
+9s
+6e
+7s
+3dal
+6ly
+6s
+4e
+5cake
+9s
+5d
+5groom
+9ms
+5maid
+9en
+9ens
+9s
+7n
+6en
+5s
+6maid
+9ds
+8n
+7en
+5wealth
+9ths
+7ll
+9s
+4gable
+5e
+6able
+6board
+9rds
+6d
+6head
+9ds
+6less
+6s
+6work
+9ks
+5ing
+8s
+4ie
+6s
+5ng
+4le
+6d
+6r
+7s
+6s
+6way
+9s
+7ise
+5ing
+4oon
+7s
+3e
+4f
+5case
+9s
+5ed
+6r
+7s
+6st
+5ing
+8s
+5less
+6y
+5ness
+9es
+5s
+4r
+5ed
+5ier
+7st
+5root
+9s
+5s
+5wood
+9s
+5y
+4s
+3g
+4ade
+7d
+7s
+6ier
+9s
+7ng
+5low
+8s
+5nd
+7age
+9es
+7ine
+9es
+7ries
+8y
+7s
+6tine
+9es
+4ht
+6en
+8ed
+9r
+9rs
+8ing
+8s
+7r
+7st
+6ish
+6ly
+6ness
+9ses
+6s
+7ome
+6work
+9ks
+4s
+4ue
+6d
+6s
+5ing
+8s
+3k
+4i
+5s
+4s
+3ll
+5er
+6st
+5iance
+9es
+9ies
+9y
+8t
+9e
+9ed
+9ine
+9ines
+9ing
+9ly
+9ness
+9nesses
+9s
+5o
+6s
+5s
+3m
+4ful
+7l
+8ness
+9esses
+8y
+7ness
+9sses
+4ing
+7s
+4less
+4med
+6r
+7s
+5ing
+4s
+5tone
+9s
+8y
+3n
+4ded
+5isi
+8s
+5le
+7d
+7s
+4e
+5d
+5less
+6ling
+9gs
+5r
+6s
+5s
+4g
+5down
+9s
+5er
+7s
+5ing
+8s
+5s
+4ier
+6s
+7t
+5ness
+9es
+6g
+5sh
+4jal
+7s
+6rries
+8y
+4k
+5man
+8ship
+9hips
+6en
+5s
+6manship
+9ships
+4nies
+5y
+4s
+4y
+3o
+4che
+7s
+4lette
+9s
+4nies
+5y
+4s
+3quet
+7s
+7te
+9d
+9s
+8ing
+3s
+4ance
+8s
+6t
+4e
+5s
+4k
+5ed
+6n
+7ed
+7ing
+7s
+6r
+6st
+6t
+7s
+5ier
+7st
+6ng
+6sh
+5ly
+5ness
+9es
+5s
+5y
+4ling
+8s
+4s
+5es
+4tle
+7cone
+9nes
+7d
+7like
+7s
+7tail
+9ils
+6ier
+8st
+7ness
+9sses
+8g
+6y
+5ol
+7s
+4ure
+7s
+3t
+4annia
+9s
+4ches
+4h
+5s
+4s
+5chka
+9s
+5ka
+7s
+4t
+5ania
+9s
+5le
+7d
+7ly
+7ness
+9sses
+7r
+7s
+8t
+6ing
+6y
+5s
+4zka
+7s
+5ska
+8s
+3ze
+5s
+2o
+3ach
+6ed
+7r
+8s
+7s
+6ing
+4d
+5ax
+7e
+8s
+5band
+9s
+6ean
+9s
+6ill
+9s
+6rim
+9s
+7ush
+5cast
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+6loth
+9hs
+5en
+7ed
+8r
+9s
+7ing
+7s
+6r
+6st
+5ish
+5leaf
+8ves
+6ine
+9s
+6oom
+9s
+6y
+5ness
+9es
+5piece
+9es
+5s
+6cale
+6heet
+9ts
+6ide
+9d
+9s
+8ing
+6word
+9ds
+5tail
+9s
+5way
+8s
+6ise
+3bdingnagian
+3cade
+7d
+7s
+6ing
+5ge
+7s
+5rd
+7s
+5tel
+8le
+9es
+8s
+4coli
+8ni
+9is
+8s
+4h
+5an
+7s
+5e
+6d
+6s
+6tte
+9s
+5ing
+5o
+6s
+5s
+5ure
+8s
+4k
+5age
+8s
+5ed
+6t
+7s
+5it
+5ram
+8s
+5s
+4oli
+7s
+3d
+4ded
+5ing
+5le
+7d
+7s
+6ing
+4ekin
+8s
+4kin
+7s
+4s
+3ekies
+3g
+4an
+6s
+4ged
+5ing
+4h
+5s
+4s
+4ue
+6ish
+6ries
+7y
+6s
+5ish
+3ider
+7ed
+8r
+9s
+7ies
+8ng
+9gs
+7s
+7y
+4l
+5ed
+6r
+7s
+5ing
+5s
+3kage
+7s
+4e
+5d
+5n
+6hearted
+9rtedly
+6ly
+6ness
+9ses
+5r
+6age
+9s
+6ed
+6ies
+7ng
+9s
+6s
+6y
+5s
+4ing
+7s
+3lga
+6s
+4lies
+5y
+3mal
+6s
+5te
+7d
+7s
+6ing
+4e
+5grass
+9ses
+5lain
+9s
+6ia
+8ceous
+8d
+9s
+8s
+7n
+8s
+5osin
+9s
+5s
+4hidroses
+9sis
+4ic
+5d
+6e
+7s
+6ic
+6roses
+9is
+6s
+5n
+6ate
+9d
+9s
+8ing
+9on
+9ons
+6e
+7s
+6ism
+9s
+6s
+5se
+7d
+7s
+6ing
+6m
+7s
+5ze
+7d
+7s
+6ing
+4mer
+7s
+4o
+5criptine
+9tines
+5form
+9s
+5s
+5uracil
+9ils
+3nc
+5hi
+7a
+8l
+9ly
+7ectases
+9tasis
+7olar
+9e
+9es
+9itis
+9itises
+7tes
+8ic
+9cs
+9des
+9s
+9ses
+7um
+6o
+7dilator
+9lators
+7genic
+8raphies
+9aphy
+7s
+8cope
+9opes
+9opic
+9opical
+9opies
+9opist
+9opists
+9opy
+8pasm
+9asms
+9astic
+6us
+5o
+6buster
+9ters
+6s
+5s
+4d
+5s
+5yron
+9s
+4tobyte
+9es
+6saur
+9rs
+9rus
+9ruses
+4ze
+6d
+6n
+6r
+7s
+6s
+5ier
+7st
+6fied
+9s
+7y
+8ing
+6ng
+8s
+6te
+8s
+5y
+3o
+4ch
+6ed
+7s
+6ing
+4d
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+8s
+5less
+5mare
+9s
+5s
+5y
+4k
+5able
+5ed
+5ie
+7s
+6ng
+6te
+8s
+5let
+8s
+6ike
+7me
+9s
+5s
+5weed
+9s
+4l
+5s
+4m
+5ball
+9er
+9ers
+9s
+5corn
+9s
+5ed
+5ier
+7st
+6ng
+5rape
+9s
+5s
+6taff
+9fs
+7ick
+9ks
+5y
+4s
+5e
+6s
+3s
+4e
+5s
+4ier
+6st
+4y
+3th
+5el
+7s
+6r
+7ed
+7hood
+9ods
+7ing
+7like
+9ness
+9nesses
+8y
+7s
+5ier
+7st
+5s
+5y
+3ugh
+6am
+8s
+6s
+6t
+7a
+8s
+9es
+4haha
+8s
+4ze
+6s
+3w
+4allia
+9s
+4band
+8s
+5eat
+8en
+9r
+9rs
+8ing
+9ngs
+8s
+4ed
+4less
+4n
+5ed
+6r
+6st
+5field
+9ds
+5ie
+7r
+7s
+8t
+6ng
+8s
+6sh
+5ness
+9es
+6ose
+9d
+9r
+9rs
+9s
+8ing
+5out
+8s
+5s
+6hirt
+9ts
+6tone
+9es
+5tail
+5y
+4ridge
+9s
+4s
+5able
+9s
+5e
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5t
+6s
+5y
+2r
+3r
+2u
+3cella
+8e
+8s
+7oses
+9is
+4hid
+7s
+4in
+6e
+7s
+6s
+5te
+7s
+4kle
+3gh
+5s
+4mansia
+9as
+3haha
+7s
+3ilzie
+8s
+4n
+5s
+4se
+6d
+6r
+7s
+6s
+5ing
+8s
+4t
+5ed
+6r
+7s
+5ing
+5s
+3le
+5s
+4ot
+6s
+4yie
+7s
+4zie
+7s
+3mal
+4bies
+5y
+4e
+5s
+4magem
+9s
+5er
+7s
+4ous
+3nch
+6ed
+7r
+8s
+7s
+6ing
+4et
+6s
+6te
+8s
+4g
+4izem
+8s
+4t
+5ed
+5ing
+5s
+3s
+4chetta
+9as
+9e
+4h
+5abilities
+9ity
+5back
+9s
+5ed
+6r
+7s
+6s
+5fire
+9s
+5ier
+7st
+6ng
+8s
+5land
+9s
+6ess
+6ike
+5mark
+9s
+5off
+8s
+5up
+7s
+5wheel
+9ls
+6ood
+9s
+7rk
+9s
+5y
+4k
+5er
+6st
+4que
+7ly
+7ness
+9sses
+7r
+8ie
+9es
+7st
+4sels
+6n
+4t
+5ing
+5s
+3t
+4al
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+4e
+5d
+5like
+6y
+5ness
+9es
+5r
+6s
+5s
+4ified
+8s
+6y
+7ing
+5ng
+7s
+5sh
+7ly
+7ness
+9sses
+6m
+7s
+4s
+3x
+4ed
+5s
+4ing
+5sm
+7s
+2yological
+8es
+8st
+9ts
+7y
+4nies
+5y
+4phyllum
+9ums
+7te
+9s
+8ic
+4zoan
+8s
+1uat
+4s
+3ze
+5s
+2b
+3a
+4l
+5e
+6s
+5ine
+6s
+7es
+5s
+4s
+3ba
+5s
+4ies
+4le
+6d
+6gum
+9s
+6head
+9ded
+9ds
+6r
+7s
+6s
+5ier
+7s
+8t
+6ng
+5y
+4y
+3inga
+7s
+3kes
+4is
+3o
+4ed
+5s
+4nic
+5ocele
+9es
+3s
+3u
+4kle
+7s
+4s
+2cardo
+7s
+4tini
+3cal
+6ly
+5neer
+9ed
+9ing
+9ings
+9ish
+9s
+6ier
+9ed
+9ing
+9s
+4ina
+7s
+7tor
+9rs
+9ry
+3ellas
+8es
+4ntaur
+9s
+3hu
+5s
+3k
+4aroo
+8s
+5yro
+8s
+4bean
+8s
+5oard
+9s
+5rush
+9es
+4ed
+5en
+7s
+5r
+6oo
+8s
+6s
+5t
+6ed
+6ful
+9s
+6ing
+9s
+6s
+7ful
+5ye
+7s
+4horn
+8s
+6und
+9s
+4ie
+6s
+5ng
+7s
+5sh
+7ly
+4jumper
+9rs
+8ing
+9ngs
+4le
+6d
+6r
+7ed
+7ing
+7s
+6s
+5ing
+8s
+4o
+5es
+5s
+4ra
+6ke
+8s
+6m
+7ed
+7ing
+7s
+6s
+4s
+5aw
+7s
+5hee
+8s
+6ish
+9ed
+9es
+9ing
+6ot
+8s
+5kin
+8ned
+8s
+5om
+4tail
+8s
+5eeth
+5horn
+9s
+5ooth
+9ed
+4u
+5s
+4wheat
+9s
+4yball
+9s
+5tube
+9s
+3olic
+7al
+9ly
+7s
+2d
+3a
+4s
+3ded
+5r
+6s
+4ha
+6s
+4ied
+6r
+6s
+7t
+5ng
+7s
+4le
+6d
+6ia
+8s
+6s
+5ing
+4y
+5ing
+3ge
+5d
+5r
+6ee
+6igar
+9rs
+6o
+7s
+7w
+8s
+6s
+5s
+5t
+6ary
+6ed
+7er
+9s
+7r
+8s
+6ing
+6s
+4ie
+6s
+5ng
+3i
+4s
+3less
+4ike
+3mash
+7es
+3o
+4s
+3s
+3worm
+7s
+2ff
+4a
+5ble
+5lo
+7berries
+9rry
+7ed
+8s
+7fish
+9shes
+7ing
+7s
+4e
+5d
+5l
+5r
+6ed
+6ing
+6s
+5st
+5t
+6ed
+7r
+8s
+6ing
+9s
+6s
+4i
+5er
+6st
+5ng
+7s
+4lehead
+9ds
+4o
+5on
+7eries
+9y
+7ish
+7s
+5s
+4s
+4y
+3o
+4s
+4talin
+9s
+5enine
+9es
+3tie
+6s
+4y
+2g
+3aboo
+7s
+3bane
+7s
+4ear
+7s
+3eye
+6s
+3gan
+6e
+7s
+6s
+4ed
+4ier
+6s
+7t
+5n
+6ess
+9es
+6g
+7s
+6s
+4y
+3house
+8s
+3le
+5d
+5r
+6s
+5s
+5t
+6s
+5weed
+9s
+4ing
+4oss
+7es
+3ong
+6s
+4ut
+6s
+3s
+4eed
+7s
+4ha
+6s
+3wort
+7s
+2hl
+4s
+4work
+8s
+3r
+4s
+5tone
+9s
+3und
+6s
+2ibui
+6s
+3k
+4s
+3ld
+5able
+5down
+9s
+5ed
+6r
+7s
+5ing
+8s
+5s
+5up
+7s
+4t
+3rdlier
+8st
+6y
+3st
+5ed
+5ing
+5s
+2ke
+4s
+3shee
+7s
+5i
+6s
+2lb
+4ar
+4ed
+5l
+6s
+4iferous
+5l
+6s
+5ng
+4let
+7s
+4osities
+8y
+5us
+7ly
+7ness
+9sses
+4s
+4ul
+6s
+3ge
+5d
+5r
+6s
+5s
+4hur
+7s
+4ier
+6st
+5ne
+7s
+8s
+9es
+6g
+7ly
+4ur
+6s
+4y
+3imia
+7c
+7s
+6c
+7s
+6es
+5us
+7es
+5y
+3k
+4age
+7s
+4ed
+5r
+6s
+4head
+8s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4s
+4y
+3l
+4a
+5ce
+7s
+5e
+5ries
+6y
+5te
+4baiting
+9ngs
+6rs
+6t
+7s
+5rier
+9s
+4dog
+7ged
+9r
+9rs
+8ing
+9ngs
+7s
+6ze
+8d
+8r
+9s
+8s
+7ing
+5ust
+8s
+4ed
+5r
+6ed
+6ing
+6s
+5t
+6ed
+6in
+8ed
+8g
+8ing
+8s
+6proof
+9ofed
+9ofing
+9ofs
+6rie
+9s
+6s
+6wood
+9ds
+4fight
+9er
+9ers
+9ing
+9ings
+9s
+6nch
+9es
+5rog
+8s
+4gine
+8s
+4head
+8ed
+9dly
+9dness
+8s
+5orn
+8s
+4ied
+6r
+6s
+7t
+5ng
+7s
+5on
+7ist
+9ts
+7s
+5sh
+7ly
+7ness
+9sses
+4mastiff
+9ffs
+4neck
+8ed
+8s
+5ose
+8s
+4ock
+7ed
+7ies
+8ng
+7s
+7y
+5sa
+5us
+4pen
+7s
+5out
+8s
+4ring
+8s
+5oarer
+9rs
+5ush
+8es
+4s
+5hat
+6ot
+8s
+5nake
+9s
+4terrier
+9ers
+4waddie
+9es
+8y
+5eed
+8s
+5hack
+9ed
+9ing
+9s
+6ip
+8ped
+9ing
+8s
+4y
+5boy
+8s
+5cide
+9s
+5ing
+6sm
+8s
+5rag
+8ged
+9ing
+8s
+3nbuln
+8s
+3rush
+7es
+7y
+3se
+5s
+3waddee
+9s
+7ies
+7y
+5rk
+7ed
+7ing
+7s
+2malo
+6ti
+8s
+3bag
+6s
+5iliff
+9fs
+5ze
+7d
+7s
+6ing
+4ershoot
+9ots
+4le
+6bee
+9s
+8rries
+9ry
+6d
+7om
+9s
+6r
+7s
+6s
+5ing
+8ly
+8s
+4o
+5at
+7s
+5s
+3elia
+7s
+3f
+4luff
+8s
+4reezer
+9rs
+4s
+4uzzle
+9d
+9s
+8ing
+3kin
+6s
+3malo
+7s
+7ti
+9s
+5ree
+8s
+4ed
+5l
+6s
+5r
+6s
+5st
+4ing
+4le
+6d
+6s
+5ing
+4ock
+7s
+3p
+4ed
+5r
+6ed
+6ing
+6s
+4h
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4kin
+7ish
+7ly
+7s
+4ologies
+8y
+4s
+5adaisy
+4tious
+9ly
+9ness
+9nesses
+4y
+3s
+4ter
+7s
+4ucker
+9s
+7ing
+9gs
+2n
+3a
+4s
+3ce
+5d
+5s
+4h
+5berries
+9y
+5ed
+6s
+5grass
+9ses
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5y
+4ing
+4o
+5ed
+5ing
+5mbe
+8s
+5s
+3d
+4e
+5d
+4h
+5s
+4ied
+6s
+5ng
+5st
+7s
+4le
+6d
+6r
+7s
+6s
+5ing
+8s
+4obust
+9s
+5ok
+7s
+4s
+4t
+5s
+4u
+5s
+4wall
+8s
+4y
+5ing
+3fight
+8s
+3g
+4aloid
+9s
+7w
+8s
+4ed
+5e
+6s
+5r
+6s
+5y
+6s
+4holes
+4ie
+6s
+5ng
+4le
+6d
+6r
+7s
+6s
+7ome
+5ing
+8ly
+8s
+4s
+4wall
+8s
+4y
+3ia
+5s
+4on
+6s
+3je
+5e
+6s
+5s
+4ie
+6s
+4y
+3k
+4ed
+5r
+6ed
+6ing
+6s
+4house
+9s
+4ing
+4mate
+8s
+4o
+5ed
+5ing
+5s
+4s
+4um
+6s
+3n
+4et
+6s
+4ia
+6s
+5es
+4s
+4y
+3odont
+3raku
+7s
+3s
+4en
+6s
+3t
+4al
+6s
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7s
+4line
+8s
+4s
+4y
+3ya
+5s
+4ip
+6s
+2oy
+4age
+7s
+5nce
+8s
+7ies
+7y
+6t
+7ly
+7ness
+9sses
+4ed
+4ing
+4s
+2pivacaine
+9nes
+3kes
+4is
+4us
+3lever
+8s
+3pie
+6s
+4y
+3renorphine
+9hines
+5stid
+9s
+4opion
+9s
+2qsha
+6s
+2r
+3a
+4n
+5s
+4s
+3b
+4le
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5y
+4ot
+6s
+4s
+3d
+4ash
+7es
+4en
+6ed
+7r
+8s
+6ing
+6ous
+6s
+7ome
+4ie
+6s
+5zzo
+8s
+4ock
+7s
+4s
+3eau
+6cracies
+9cy
+9t
+9tese
+9teses
+9tic
+9tise
+9tised
+9tises
+9tising
+9tism
+9tisms
+9tist
+9tists
+9tize
+9tized
+9tizes
+9tizing
+9ts
+6s
+6x
+4t
+5s
+5te
+7s
+3g
+4age
+7s
+5net
+8s
+4ee
+6s
+5on
+7ed
+7ing
+7s
+5r
+6s
+5ss
+7es
+4h
+5al
+5er
+7s
+5s
+5ul
+7s
+4lar
+7ed
+7ies
+8ng
+8ous
+9usly
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7proof
+7s
+7y
+5e
+6d
+6s
+5ing
+4omaster
+9ers
+5net
+8s
+5o
+6s
+5ut
+7s
+4rave
+8s
+4s
+4undies
+7y
+3hel
+6s
+3ial
+6s
+4ed
+5r
+6s
+5s
+4n
+5ist
+8s
+5s
+4ti
+6s
+3k
+4a
+5s
+4e
+5d
+5r
+6s
+5s
+4ha
+6s
+4ing
+5te
+7s
+4s
+3l
+4adero
+9s
+5p
+6s
+4ed
+5r
+6s
+5sk
+7s
+6que
+9d
+9ly
+9r
+9rs
+9s
+8ing
+5tta
+8s
+5y
+6cue
+9s
+6ed
+6ing
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4s
+4y
+3n
+4able
+8s
+4ed
+5r
+6s
+5t
+6s
+6tise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+4ie
+6s
+5ng
+7ly
+7s
+5sh
+7able
+7ed
+8r
+9s
+8s
+7ing
+9gs
+7ment
+9nts
+4oose
+8d
+8s
+5us
+7e
+8d
+8s
+6t
+7s
+4s
+5ide
+8s
+4t
+3oo
+5s
+3p
+4ed
+5e
+6s
+4ing
+4s
+3qa
+5s
+3r
+4amundi
+9is
+6ys
+8es
+5wang
+9s
+4ed
+5l
+6l
+7s
+6s
+5r
+6s
+4hel
+7s
+4ier
+6st
+5ng
+5to
+7s
+4o
+5s
+5w
+6ed
+7r
+8s
+6ing
+6s
+7town
+9wns
+4s
+5tone
+9s
+4y
+3s
+4a
+5e
+5l
+5r
+6ial
+7es
+6s
+7hip
+9ps
+6y
+5s
+5te
+4e
+5ed
+7s
+5ra
+7ceous
+5s
+4icon
+8s
+6ulate
+5form
+5tis
+8es
+4t
+5ed
+6n
+6r
+7s
+5ing
+5one
+8s
+5s
+3then
+7ed
+7ing
+7s
+8ome
+4on
+6s
+3weed
+7s
+3y
+4ing
+2s
+3bar
+6s
+4ies
+4oy
+6s
+4y
+3ed
+4ra
+6s
+4s
+3girl
+7s
+3h
+4babies
+7y
+6shing
+9ngs
+5uck
+8s
+4craft
+9s
+4ed
+5l
+6ed
+7r
+8s
+6ing
+6led
+8r
+9s
+7ing
+9gs
+6man
+7en
+6s
+6woman
+9en
+5r
+6s
+5s
+4fire
+8s
+5lies
+6y
+4goat
+8s
+4hammer
+9rs
+4ido
+7s
+5e
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+4land
+8s
+5ess
+5ike
+4man
+7ship
+9ips
+6ster
+9rs
+5eat
+8s
+6n
+4pig
+7s
+4ranger
+9rs
+8ing
+9ngs
+4tit
+7s
+4veld
+8s
+4wa
+6h
+7s
+6lk
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+6s
+5hack
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+5oman
+7en
+4y
+3ied
+5r
+5s
+6t
+4ly
+4ness
+8es
+8like
+8man
+9en
+8people
+9erson
+9ersons
+8woman
+9omen
+8y
+5g
+6s
+3k
+4ed
+5r
+6s
+5t
+6s
+4in
+6ed
+6g
+7s
+6s
+4s
+4y
+3load
+7s
+3man
+4en
+3s
+4ed
+5s
+4ing
+7s
+4u
+5s
+3t
+4ard
+7s
+4ed
+5e
+6s
+5r
+6s
+4i
+5c
+6ate
+9d
+9s
+8ing
+6s
+5er
+7s
+6st
+5ness
+9es
+6g
+7s
+5s
+4le
+6d
+6r
+7s
+6s
+5ine
+8s
+7g
+8ly
+4s
+3ulfan
+8s
+4uti
+7s
+3y
+4bodied
+9s
+7y
+8ing
+9ngs
+4ing
+4ness
+8es
+4work
+8s
+2t
+3adiene
+9s
+4ne
+6s
+5oic
+6l
+7s
+6ne
+8s
+3ch
+5er
+7bird
+9rds
+7ed
+8r
+9s
+7ies
+8ng
+9gs
+7ly
+7s
+7y
+6s
+7t
+5ing
+8s
+5ness
+9es
+3e
+4ne
+6dioic
+6s
+4o
+5nine
+9s
+5s
+4s
+3le
+5d
+5r
+6age
+9s
+6ed
+6ies
+7ng
+6s
+7hip
+9ps
+6y
+5s
+4ing
+3ment
+7s
+3s
+4udan
+8s
+3tals
+4e
+5d
+5r
+6ball
+9ls
+7ur
+9s
+6cup
+9s
+6dock
+9ks
+6ed
+6fat
+9s
+7ingered
+9gers
+8sh
+9hes
+7lied
+9es
+8y
+9er
+9ers
+9ing
+6ier
+8s
+9t
+7ne
+9s
+9ss
+9sses
+8g
+6less
+6milk
+9ks
+6nut
+9s
+6s
+7cotch
+9tches
+6weed
+9ds
+7ort
+9ts
+6y
+5s
+4head
+8s
+4ies
+5ng
+6ski
+9es
+9s
+8y
+4le
+6d
+6s
+5ing
+4ock
+7ed
+7ing
+7s
+5n
+6ball
+9ls
+7ush
+9hes
+6ed
+7r
+8s
+6held
+7old
+9ding
+9ds
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8ok
+9ked
+9king
+9ks
+6ing
+6less
+6mould
+9lds
+6s
+6wood
+9ds
+6y
+4ress
+8ed
+9s
+8ing
+4s
+5tock
+9s
+4y
+5man
+6en
+3ut
+5s
+3yl
+5ate
+8d
+8s
+7ing
+8on
+9ns
+5ene
+8s
+5s
+4raceous
+6l
+7dehyde
+9hydes
+7s
+6te
+8s
+5ic
+6n
+7s
+5ophenone
+9nones
+6us
+5yl
+7s
+2vette
+7s
+2xom
+5er
+6st
+5ly
+5ness
+9es
+2y
+3able
+7s
+3back
+7s
+3er
+5s
+3ing
+6s
+3off
+6s
+4ut
+6s
+3s
+2zkashi
+8s
+3uki
+6a
+6s
+3z
+4ard
+7s
+4bait
+8s
+4cut
+7s
+4ed
+5r
+6s
+5s
+4ier
+6st
+5ng
+7ly
+7s
+4kill
+8er
+9rs
+8s
+4wig
+7s
+5ord
+8s
+4y
+1wana
+5s
+3zi
+5s
+1y
+2catch
+7es
+3oket
+7s
+2de
+4d
+4s
+3ing
+2e
+3law
+6s
+3s
+2gone
+6s
+2ke
+4d
+4s
+3ing
+2lander
+8s
+5e
+6s
+4w
+5s
+3ine
+6d
+6r
+7s
+6s
+5ing
+4ve
+2name
+6s
+3empt
+2pass
+6ed
+7s
+6ing
+5t
+4th
+6s
+3lace
+7s
+5y
+6s
+3roduct
+9s
+2re
+4man
+5en
+4s
+4woman
+7en
+3l
+4ady
+5kin
+5w
+6s
+4ed
+4ing
+4s
+3nie
+6s
+3oad
+6s
+4om
+6s
+2s
+3saceous
+5l
+4i
+5ne
+6oses
+8is
+4oid
+4us
+6es
+3tander
+9s
+4reet
+8s
+2talk
+6s
+3e
+4s
+3ownite
+9s
+2way
+5s
+3oner
+7s
+4rd
+6s
+5k
+6s
+2zant
+6ine
+6s
+0caa
+3ed
+3ing
+3s
+3tinga
+8s
+2b
+3a
+4l
+5a
+6s
+5etta
+9s
+8e
+5ism
+8s
+7t
+8ic
+9cal
+8s
+5led
+7r
+8o
+9s
+8s
+6ine
+8g
+5s
+4na
+6s
+4ret
+7s
+4s
+3bage
+7d
+7s
+7town
+9wns
+7worm
+9rms
+7y
+6ing
+6y
+5la
+7h
+8s
+7s
+6ism
+9s
+8t
+9ic
+9ical
+9s
+4ed
+4ie
+6s
+5ng
+4y
+3driver
+9s
+3er
+5net
+8s
+5s
+4stro
+8s
+4zon
+7e
+8s
+7s
+3ildo
+7s
+4n
+5ed
+6t
+7maker
+9kers
+9king
+9kings
+7ries
+8y
+7s
+7work
+9rks
+5ing
+5mate
+9s
+5s
+3le
+5cast
+9ed
+9ing
+9s
+5d
+5gram
+9s
+5r
+6s
+5s
+5t
+6s
+5vision
+9ons
+5way
+8s
+4ing
+7s
+3man
+4en
+3ob
+5bed
+6ing
+5s
+4c
+5eer
+8s
+5hed
+6on
+8s
+5s
+4mba
+7s
+4odle
+8s
+5se
+7s
+4shed
+4tage
+8s
+4ver
+3re
+5sta
+8s
+7o
+8s
+5tta
+8s
+4ie
+6s
+5lla
+8s
+5o
+6le
+8s
+8t
+9s
+6s
+5t
+6s
+3s
+4tand
+8s
+2ca
+4fogo
+8s
+5uego
+9s
+4o
+5s
+4s
+3ciatora
+9e
+3haca
+7s
+5emia
+9s
+8c
+5lot
+8s
+4e
+5ctic
+9al
+5d
+5pot
+8s
+5s
+5t
+6ed
+6ing
+6s
+5xia
+8s
+7c
+7es
+6y
+4ing
+6nate
+9ed
+9es
+9ing
+9ion
+9ions
+9ory
+4olong
+9s
+7t
+8s
+5u
+6s
+4ucha
+8s
+3ique
+7s
+6ism
+9s
+3k
+4ermander
+9ders
+4ier
+6st
+4le
+6berries
+9ry
+6d
+6r
+7s
+6s
+5ing
+4s
+4y
+3odaemon
+9ns
+5emon
+9ic
+9s
+5oxies
+7y
+5yl
+7ic
+7s
+4epies
+7stic
+6y
+5thes
+7ic
+4gastric
+5enic
+9s
+5rapher
+9ers
+9ic
+9ical
+9ies
+9y
+4let
+7s
+5ogies
+7y
+4mistle
+9es
+6xl
+8e
+9s
+8s
+4nym
+7ies
+7s
+7y
+4on
+6s
+4phonic
+9cal
+9cally
+9es
+9ous
+8ous
+9usly
+8y
+4topia
+9n
+9s
+5rophies
+9y
+3taceous
+4i
+5form
+4oblastes
+9tis
+5id
+4us
+6es
+3umen
+5ina
+8l
+9s
+7ous
+2d
+3aga
+6s
+5i
+6s
+4ster
+8s
+6ral
+9ly
+7e
+8s
+4ver
+7ic
+8ne
+9es
+7ous
+9sly
+9sness
+7s
+3dice
+7s
+5e
+6d
+6s
+5s
+6ed
+7s
+6flies
+8y
+6h
+7ly
+7ness
+9sses
+6worm
+9ms
+4y
+5ing
+5ss
+7es
+3e
+4au
+6x
+4e
+5s
+4lle
+7s
+4nce
+7d
+7s
+6ies
+7ng
+6y
+5t
+6ial
+5za
+7s
+4s
+4t
+5s
+6hip
+9s
+3ge
+5d
+5r
+6s
+5s
+4ier
+6st
+5ng
+4y
+3i
+4e
+5s
+4s
+3mic
+5um
+7s
+3rans
+7es
+4e
+5s
+3s
+3uac
+6s
+4cean
+6i
+6us
+5ities
+7y
+5ous
+2eca
+5l
+6ly
+4ilian
+9s
+5tis
+8es
+4um
+3nogeneses
+9sis
+9tic
+3oma
+6s
+3rule
+7an
+3salpinoid
+5r
+6ean
+9s
+6ian
+9s
+7sm
+9s
+6opapism
+9pisms
+6s
+4e
+4ious
+5um
+7s
+4pitose
+9ely
+4tus
+7es
+4ura
+7e
+7l
+7s
+6ic
+2fard
+6s
+3e
+4s
+4teria
+9s
+5iere
+9s
+5oria
+8um
+9ms
+3f
+4ein
+7ated
+9ing
+7e
+8s
+7ic
+8sm
+9ms
+7s
+6sm
+8s
+4ila
+7s
+4s
+3ila
+6s
+3tan
+6ed
+6s
+2g
+3aner
+7s
+3e
+4d
+4ful
+7s
+4like
+6ng
+8s
+4r
+5s
+4s
+4work
+8s
+4y
+5ness
+9es
+3ier
+5st
+4ly
+4ness
+8es
+5g
+3mag
+6ged
+7ing
+6s
+3ot
+5s
+4ul
+6e
+7s
+6s
+3s
+3y
+4ness
+8es
+2hier
+6s
+3oot
+6s
+4w
+5s
+2id
+4s
+3llach
+8s
+5e
+6ach
+9s
+6s
+5iach
+9s
+3mac
+6am
+8s
+6s
+5n
+6s
+3n
+4ogeneses
+9sis
+9tic
+4s
+3que
+6s
+3rd
+5s
+4n
+5ed
+5gorm
+9s
+5ier
+7st
+5s
+5y
+3sson
+7s
+3tiff
+7s
+5ve
+7s
+2japut
+7s
+3eput
+7s
+3ole
+6d
+6ment
+9ts
+6r
+7ies
+7s
+7y
+6s
+5ing
+8ly
+4n
+5es
+3un
+4put
+7s
+2ke
+4d
+4s
+4walk
+8ed
+9r
+9rs
+8ing
+8s
+4y
+3ier
+5st
+4ness
+8es
+5g
+6s
+3y
+2labash
+8es
+6za
+8s
+5ogus
+9es
+6ose
+9s
+5rese
+9s
+4dium
+8s
+4loo
+7s
+5u
+6s
+4manco
+9es
+9s
+7der
+9rs
+6r
+7i
+8es
+8s
+7s
+7y
+6ta
+8s
+5i
+6ne
+8d
+8s
+7ing
+7t
+8s
+6te
+8s
+7ies
+7ous
+9sly
+9sness
+7y
+5ondin
+9ns
+5us
+4ndo
+6ria
+9s
+5the
+8s
+4sh
+6es
+4thea
+8s
+6i
+6os
+6us
+4vance
+9s
+5erite
+9es
+3canea
+8l
+8n
+7i
+7um
+8s
+5r
+6ate
+6eous
+9sly
+6ia
+7ferous
+8orm
+7ne
+6s
+4eamenta
+9tum
+6te
+8d
+8s
+7ing
+5d
+6onies
+9o
+9os
+8y
+5iform
+5olaria
+9ias
+8te
+5s
+4ic
+6ole
+9s
+8ous
+5ferol
+9ls
+9us
+6ic
+8ation
+9tions
+7ed
+8s
+6ugal
+8e
+9s
+8ous
+6y
+7ing
+5gerous
+5mine
+9d
+9s
+8ing
+5nable
+7tion
+9ons
+6e
+7d
+7s
+6ing
+6oses
+8is
+5te
+7s
+6ic
+6onin
+9ns
+5um
+7s
+4rete
+8s
+4sinter
+9rs
+5par
+8s
+4tufa
+8s
+7f
+8s
+4ulabilities
+9lity
+8le
+9y
+7r
+8y
+7te
+9d
+9dly
+9dness
+9s
+8ing
+9ngly
+9on
+9onal
+9ons
+9ve
+8or
+9rs
+6i
+6ose
+7us
+6us
+8es
+3daria
+7um
+4era
+7s
+4ron
+7s
+3eche
+7s
+4facient
+9nts
+7tion
+9ons
+9ve
+8or
+9ries
+9rs
+9ry
+5ied
+7s
+5y
+6ing
+4mbour
+9s
+4ndal
+7r
+8ed
+9r
+9rs
+8ing
+9sation
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+6er
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+6rer
+9s
+7ic
+9al
+8es
+7y
+6s
+6ula
+9s
+5ture
+9s
+4sa
+6s
+5cence
+9es
+8t
+3f
+4dozer
+9s
+4less
+5ick
+8s
+6ke
+4s
+5kin
+8s
+3iatour
+9s
+4ber
+7ed
+7s
+5rate
+9d
+9r
+9rs
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6e
+7d
+7s
+4ces
+5he
+7s
+5le
+7s
+5o
+6es
+6s
+5ular
+4d
+5ities
+7y
+4f
+5ate
+8s
+5ont
+8s
+6rnium
+9ums
+5s
+4ginosities
+9ity
+8us
+5o
+6es
+6s
+4ma
+6s
+5ocho
+9s
+4ologies
+8y
+4pash
+8es
+5ee
+7s
+6r
+7ed
+7ing
+7s
+5h
+6al
+7te
+9s
+6s
+4saya
+8s
+5thenic
+9ics
+4ver
+7s
+4x
+3k
+4ed
+5r
+6s
+4in
+6g
+7s
+6s
+4s
+3l
+4a
+5ble
+5ides
+6s
+5loo
+8s
+5n
+6s
+6t
+7s
+5s
+4back
+8s
+5oard
+9s
+6y
+7s
+4ed
+5e
+6s
+5r
+6s
+5t
+6s
+4iature
+9es
+5d
+6ities
+8y
+5gram
+9me
+9mes
+9s
+8pher
+9hers
+9hic
+9hical
+9hies
+9hist
+9hists
+9hy
+5ng
+7s
+5ope
+8s
+7sis
+5pash
+9es
+6ee
+8s
+7r
+8ed
+8ing
+8s
+6ygean
+8ian
+8ous
+5stemon
+9ons
+7henic
+9nics
+5thump
+9pian
+9ps
+4op
+6s
+5se
+7s
+6ities
+8y
+5us
+7ed
+8s
+7ing
+7ly
+7ness
+9sses
+5w
+6er
+7st
+6ness
+9ses
+6s
+4s
+4time
+8s
+4una
+7s
+5s
+6ed
+7s
+6ing
+3m
+4ant
+7s
+5tive
+9s
+4ed
+5r
+5st
+4ier
+6st
+5ng
+7ly
+7s
+4ly
+4ness
+8es
+4odulin
+9ns
+4s
+5tane
+9s
+6one
+9s
+4y
+3o
+4mel
+7s
+4rescence
+9nces
+9nt
+5ic
+7ally
+7ities
+9y
+7s
+6e
+7s
+6fic
+9ally
+9ation
+9ations
+8er
+9rs
+6meter
+9ers
+9ric
+9rical
+9ries
+9ry
+6se
+8d
+8s
+7ing
+7t
+8s
+6ze
+8d
+8s
+7ing
+5y
+4s
+4tte
+7s
+5ype
+8s
+7ist
+9ts
+4yer
+7s
+3p
+4a
+5c
+6k
+7s
+6s
+5in
+7s
+5s
+4s
+3que
+6d
+6s
+5ing
+3tha
+6s
+5rop
+8s
+4rap
+7s
+5op
+7s
+3umba
+7s
+5et
+7s
+5niable
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+9ory
+7es
+7ous
+9sly
+6y
+4tron
+8s
+3vados
+8es
+5ria
+8l
+8n
+8s
+7es
+7um
+9s
+6y
+4e
+5d
+5r
+6ed
+6ing
+6s
+5s
+4ing
+5ties
+3x
+4es
+3ycanthemies
+9emy
+9us
+9uses
+6te
+5eal
+6s
+5iform
+6nal
+7e
+5le
+7d
+7s
+5oid
+8eous
+5ular
+8te
+7e
+8s
+7i
+7us
+4pso
+7es
+7nian
+9ans
+7s
+5ter
+8a
+9s
+8s
+6ra
+8s
+8te
+7ogen
+9ens
+4x
+5es
+3zone
+7s
+6i
+2m
+3a
+4ieu
+7x
+5l
+6ed
+6s
+4n
+5achd
+9s
+5s
+4raderie
+9ies
+5illa
+9s
+5on
+7s
+4s
+5es
+5h
+6es
+5s
+6es
+3ber
+6ed
+6ing
+9s
+6s
+4ia
+6l
+5form
+5sm
+7s
+6t
+7ries
+8y
+7s
+5um
+7s
+4oge
+7s
+6ia
+8s
+5ose
+8s
+4rel
+7s
+5ic
+7s
+3corder
+9s
+3e
+4l
+5back
+9s
+5eer
+8s
+6on
+8s
+7pard
+9rds
+5hair
+9s
+5ia
+7s
+6d
+7s
+6ne
+8s
+6sh
+5lia
+8s
+7ke
+5oid
+8s
+6pard
+9ds
+6t
+7s
+5ries
+6y
+5s
+4o
+5ed
+5ing
+5s
+4ra
+6e
+6l
+6man
+7en
+6person
+9sons
+6s
+6ted
+7ion
+9ns
+6woman
+9en
+8rk
+9ks
+5lengo
+9os
+6ingo
+9os
+4s
+5e
+6s
+3iknickers
+9s
+4on
+6s
+4s
+5a
+6de
+8s
+7o
+8es
+8s
+6s
+5e
+6s
+5ia
+7s
+5ole
+8s
+3let
+6s
+3med
+4ie
+6s
+5ng
+3o
+4gie
+7s
+4mile
+8s
+4odi
+7s
+4rra
+7s
+6ist
+9a
+9i
+9s
+4s
+4te
+6s
+4uflage
+9eable
+9ed
+9es
+9ic
+9ing
+7et
+9s
+8ur
+9rs
+3p
+4agna
+8s
+7e
+5ign
+8ed
+9r
+9rs
+8ing
+8s
+5na
+7s
+6ero
+9s
+6iform
+7le
+9s
+8i
+7st
+9s
+6ologer
+9gers
+9gical
+9gies
+9gist
+9gists
+9gy
+6ula
+9ceous
+9r
+9s
+9te
+4craft
+9s
+4eachy
+6dor
+9s
+5d
+5r
+6ies
+6s
+6y
+5sino
+9s
+6t
+7ral
+8ian
+4fire
+8s
+4ground
+9ds
+4hane
+8s
+5ene
+8s
+5ine
+8s
+6re
+8s
+5ol
+7s
+6ne
+8s
+6r
+7aceous
+8te
+9ed
+9es
+9ing
+7ic
+7s
+4i
+5er
+6st
+5ly
+5metries
+9y
+5ness
+9es
+6g
+7s
+5on
+7s
+4le
+6d
+6s
+5ing
+5y
+4ness
+8es
+4o
+5deid
+9s
+8form
+5ng
+7s
+5ree
+8s
+5s
+5ut
+7s
+4s
+5hirt
+9s
+5ite
+8s
+5tool
+9s
+4us
+6ed
+7s
+6ing
+4y
+5lobacter
+9cters
+7tropous
+3s
+4haft
+8s
+5o
+6ch
+4tairy
+6ne
+8s
+5eary
+6erie
+5one
+8s
+3us
+5es
+3wood
+7s
+2n
+3ada
+6s
+4igre
+8s
+5lle
+8s
+4kin
+7s
+4l
+5boat
+9s
+5ed
+5icular
+9ate
+9ated
+9i
+9us
+6ng
+6sation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5led
+7r
+8s
+6ing
+5s
+4pe
+6s
+4rd
+6s
+5ied
+7s
+5y
+6ing
+4sta
+7s
+6er
+8s
+3bank
+7s
+3can
+6s
+4el
+6able
+7tion
+9ons
+6bot
+9s
+6ed
+7er
+9ed
+9ing
+9s
+7r
+8s
+6ier
+9ed
+9ing
+9s
+7ng
+6lable
+8rial
+9ian
+9iate
+9iates
+8te
+9ed
+9ion
+9ions
+7ed
+8r
+9s
+7i
+8ng
+7ous
+6s
+5r
+6ate
+9d
+9s
+8ing
+9on
+9ons
+6ed
+6ophobia
+9obias
+7us
+9ly
+6phobia
+9bias
+6s
+4ha
+6s
+4ionero
+9os
+4riform
+6ne
+6zans
+5oid
+8s
+3dela
+7bra
+9as
+9um
+9ums
+7s
+6illa
+9as
+5nt
+5scence
+9ces
+9t
+9tly
+4id
+6a
+7cies
+8y
+7l
+7s
+7te
+9s
+9ship
+9ships
+8ure
+9res
+6er
+7st
+6iases
+9is
+6ly
+6ness
+9ses
+6s
+5e
+6d
+6s
+5ru
+7s
+4le
+6berries
+9ry
+6d
+6fish
+9hes
+6holder
+9ders
+6light
+9hted
+9hter
+9hters
+9hts
+8t
+6nut
+9s
+6pin
+9s
+7ower
+9ers
+6r
+7s
+6s
+7nuffer
+9ffers
+7tick
+9cks
+6wick
+9ks
+7ood
+9ds
+5ing
+4ock
+7s
+5r
+6s
+5ur
+7s
+4y
+5floss
+9ses
+5gram
+9s
+5ing
+5man
+6en
+5tuft
+9s
+3e
+4brake
+9s
+4d
+4fruit
+9s
+4grub
+8s
+4h
+5s
+4lla
+7s
+6ini
+4phor
+8a
+9s
+8e
+9s
+8s
+8us
+9ses
+4r
+5s
+4s
+5cence
+9es
+8t
+4ware
+8s
+3field
+8s
+4ul
+6s
+3g
+4le
+6d
+6s
+5ing
+4s
+4ue
+6s
+3icular
+4d
+5s
+4er
+5st
+4kin
+7s
+4ne
+6s
+5g
+6s
+5ities
+7y
+4stel
+8s
+7r
+8ed
+8ing
+9sation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+4ties
+3ker
+6ed
+8ly
+8ness
+9esses
+6ing
+6ous
+6s
+6worm
+9ms
+6y
+4le
+6s
+3n
+4a
+5bic
+7n
+8oid
+9ids
+9l
+9ls
+8s
+7s
+8es
+5ch
+7s
+5e
+5s
+4ed
+5l
+6lini
+7oni
+6on
+8i
+8s
+6s
+6ure
+9s
+5r
+6ies
+6s
+6y
+4ibal
+8isation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9stic
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+5e
+6r
+6st
+5kin
+8s
+5ly
+5ness
+9es
+6g
+7s
+5ster
+9s
+4oli
+7s
+5n
+6ade
+9d
+9s
+8ing
+6ball
+9led
+9ling
+9ls
+6ed
+7er
+9s
+6ier
+9s
+7ng
+6ries
+7y
+6s
+5t
+4s
+4ula
+7e
+7r
+7s
+7te
+9d
+9s
+8ing
+9on
+9ons
+4y
+3oe
+5able
+5d
+5ing
+8s
+6st
+8s
+5r
+6s
+5s
+5wood
+9s
+4la
+6s
+4n
+5ess
+8es
+5ic
+7al
+9ly
+9s
+8te
+9es
+7ities
+9y
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7t
+8ic
+8s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5ries
+6y
+5s
+4odle
+8d
+8r
+9s
+8s
+7ing
+4philia
+9as
+9st
+9sts
+6obia
+9as
+5ic
+6ed
+7s
+5y
+6ing
+4rous
+8ly
+8ness
+9esses
+3s
+4ful
+4o
+5s
+4t
+5ick
+8s
+3t
+4abank
+9s
+6ile
+9s
+5l
+6a
+7s
+6oup
+9e
+9es
+9s
+6s
+5nkerous
+9ously
+5r
+6s
+5ta
+7s
+6e
+7s
+6rice
+9es
+9i
+4dog
+7s
+4ed
+5en
+7s
+5r
+6buries
+9y
+9ys
+6ed
+6ing
+6s
+5st
+4hal
+6ri
+8d
+9al
+9es
+9ian
+9ic
+9in
+9ins
+9s
+8s
+7us
+6xanthin
+9thine
+9thines
+9thins
+5i
+6tis
+9es
+5ook
+8s
+5us
+4ic
+6le
+8s
+6o
+7ed
+7ing
+7s
+7y
+8ed
+8ing
+8s
+6um
+8s
+5er
+6st
+5lena
+9s
+7ver
+9red
+9ring
+9rs
+6late
+9ed
+9es
+9ing
+9ion
+9ions
+9ory
+6y
+5na
+7s
+6ess
+9es
+6g
+7ly
+7s
+5on
+7s
+4le
+6d
+6s
+6t
+7s
+5ing
+4o
+5n
+6al
+6ed
+6ing
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ment
+9ts
+6s
+5r
+6ial
+7s
+6s
+5s
+4raip
+8s
+6p
+7s
+5ed
+7s
+6f
+7s
+5ip
+7s
+4s
+4us
+4y
+3ula
+6e
+6r
+6s
+6te
+8d
+8s
+7ing
+8on
+9ns
+3vas
+6back
+9ks
+6ed
+7r
+8s
+7s
+6ing
+6like
+6s
+7ed
+8r
+9s
+8s
+7ing
+9gs
+3y
+4on
+6eer
+9s
+6ing
+9s
+6s
+3zona
+7s
+6e
+7s
+7t
+8s
+8ta
+9as
+9e
+6i
+2outchouc
+9cs
+2p
+3a
+4bilities
+9y
+5le
+7ness
+9sses
+7r
+7st
+6y
+4cious
+9ly
+9ness
+9nesses
+6tance
+9ces
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+7ies
+8ve
+9ely
+7or
+9s
+7y
+4rison
+9ed
+9ing
+9s
+4s
+3e
+4d
+4lan
+7s
+5et
+7s
+5in
+7e
+8s
+7s
+5let
+8s
+6ine
+9s
+8i
+6meister
+9sters
+4r
+5caillie
+9lies
+9zie
+9zies
+5ed
+6r
+7s
+5ing
+8ly
+5noited
+9ie
+9ies
+9y
+5s
+4s
+5kin
+8s
+4work
+8s
+4x
+5es
+3ful
+6s
+3h
+4s
+3i
+4as
+6es
+4llaceous
+7ire
+9es
+7ries
+9ties
+9ty
+8y
+6itia
+9um
+9ums
+4ng
+4ta
+6l
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7s
+6n
+7i
+7o
+8s
+7s
+6te
+8d
+7ion
+9ns
+8ve
+6yn
+8s
+5ella
+8um
+5ol
+7ian
+8ne
+7s
+5ula
+8nt
+9ts
+8r
+9ies
+9ly
+9s
+9y
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+9ory
+7um
+4z
+5es
+3le
+5s
+6s
+5t
+6s
+4in
+6s
+3maker
+8s
+3nomancies
+9y
+3o
+4cchia
+9s
+4dastro
+9os
+4eira
+8s
+4n
+5ata
+8s
+5ier
+8e
+9s
+8s
+6se
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5s
+4ral
+7s
+4s
+4t
+5asto
+9s
+5e
+6s
+5s
+5ted
+6ing
+4uch
+7es
+3paridaceous
+4ed
+5lletti
+5r
+6noities
+9ty
+6s
+4ing
+7s
+4uccini
+9o
+9os
+3rate
+7s
+4eolate
+4ic
+6ci
+8o
+9s
+9so
+6e
+7s
+6ious
+9sly
+9sness
+5d
+6s
+5fication
+9tions
+7ed
+8s
+7g
+8s
+6oil
+9s
+7le
+9s
+8iaceous
+7rm
+6y
+7ing
+5ne
+5ole
+8d
+8s
+7ing
+5s
+4oate
+8s
+5ck
+7s
+5ic
+5lactam
+9ams
+4ylate
+9s
+6ic
+3s
+4aicin
+9s
+4icin
+8s
+6um
+8s
+5d
+6al
+6s
+5zable
+7l
+8s
+6e
+7d
+7s
+6ing
+4omer
+8e
+9s
+8s
+4tan
+7s
+5one
+8s
+4ular
+8y
+7te
+9d
+8ion
+9ons
+6e
+7d
+7s
+6ing
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+3tain
+7cies
+8y
+7ed
+7ing
+7ries
+8y
+7s
+8hip
+9ips
+5n
+6s
+4ion
+7ed
+7ing
+7less
+7s
+6us
+8ly
+8ness
+9esses
+5vance
+9es
+7te
+9d
+9s
+8ing
+9ngly
+9on
+9ons
+8or
+9rs
+7unce
+9ces
+6e
+7d
+7s
+6ing
+7ties
+8y
+4opril
+9s
+5r
+6s
+4ure
+7d
+7r
+8s
+7s
+6ing
+3uccio
+8s
+5he
+7d
+7s
+6in
+8s
+4era
+7s
+4l
+5s
+4t
+3ybara
+8s
+2r
+3abao
+7s
+5id
+7s
+6n
+7e
+8er
+9rs
+8r
+9o
+9os
+9s
+8s
+7ier
+9re
+9ri
+9rs
+7s
+4cal
+7s
+6ra
+8s
+5k
+6s
+5ol
+7e
+8d
+8r
+9s
+8s
+7ing
+7led
+8ing
+7s
+5t
+6s
+5ul
+7s
+4fe
+6s
+4gana
+8s
+5een
+8an
+9ns
+8s
+4mba
+6ola
+9s
+8e
+9d
+9s
+8ing
+5el
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7led
+8ing
+7s
+4ngid
+8s
+6oid
+9s
+5na
+7s
+4p
+5ace
+8d
+8s
+7ial
+6x
+7es
+5s
+4ssow
+8s
+4t
+5e
+6s
+5s
+4una
+7s
+4van
+7ce
+9s
+7ed
+8er
+9rs
+8r
+9s
+8tte
+9tes
+7ing
+9gs
+7ned
+9r
+9rs
+8ing
+9ngs
+7s
+8arai
+9rais
+9ries
+9ry
+8erai
+9rais
+5el
+7le
+9s
+7s
+4way
+7s
+3b
+4achol
+9s
+5mate
+9s
+7zepine
+9pines
+6ic
+7de
+9s
+8ine
+9nes
+7no
+6oyl
+9s
+6yl
+8s
+5nion
+9s
+5rn
+7s
+6yl
+8s
+5zole
+9s
+4een
+7s
+5ne
+7s
+4ide
+7s
+5es
+5mazole
+9les
+5ne
+7er
+9s
+7s
+6ier
+9s
+6ol
+8s
+4o
+5cyclic
+5hydrase
+9ases
+9ate
+9ates
+5lated
+6ic
+8s
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+5n
+6aceous
+7de
+9s
+8o
+9ed
+9es
+9ing
+9s
+7ra
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9te
+9tes
+6ette
+9es
+6ic
+7ferous
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7um
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6less
+6nade
+9es
+6ous
+6s
+6yl
+8ate
+9ted
+9tes
+9ting
+9tion
+9tions
+8ic
+8s
+5ra
+7s
+5s
+5xyl
+8ase
+9ses
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+8ic
+8s
+5y
+6ed
+6s
+4s
+4uncle
+9d
+9s
+7ular
+5rate
+9d
+9s
+8ing
+9on
+9ons
+6et
+8ed
+9r
+9rs
+8ing
+9on
+9ons
+8or
+9rs
+8s
+8ted
+9er
+9ers
+9ing
+9or
+9ors
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+4y
+5lamine
+9nes
+3cajou
+8s
+5ke
+7s
+5net
+8s
+5se
+7d
+7s
+6ing
+6s
+7ed
+8s
+7ing
+4el
+6s
+5ral
+4inogen
+9neses
+9nesis
+9nic
+9nicity
+9ns
+7id
+9s
+7logical
+9gies
+9gist
+9gists
+9gy
+7ma
+9s
+9ta
+9toid
+9toses
+9tosis
+9tous
+7sarcoma
+9rcomas
+8es
+8is
+3d
+4amine
+9s
+6om
+8s
+7n
+8s
+6um
+8s
+5n
+4board
+9s
+9y
+4case
+8s
+4ecu
+7e
+8s
+7s
+5d
+5r
+6s
+4holder
+9rs
+4i
+5a
+6c
+7al
+7s
+6e
+6lgia
+9as
+9c
+9es
+8y
+6s
+5e
+6s
+5gan
+8ed
+8s
+5nal
+8ate
+9tes
+9tial
+8itial
+9ties
+9ty
+8ly
+8s
+9hip
+9hips
+6g
+7s
+5o
+6centeses
+9tesis
+6genic
+7ram
+9ms
+9ph
+9pher
+9phers
+9phic
+9phical
+9phies
+9phs
+9phy
+6id
+8s
+6logical
+9ies
+9ist
+9ists
+9y
+6megalies
+9aly
+7otor
+7yopathy
+6pathies
+9hy
+7legia
+9gias
+7ulmonary
+6s
+6thoracic
+7onic
+9ics
+6vascular
+5s
+5tic
+7s
+8es
+4on
+6s
+5on
+7s
+5phagi
+9us
+4phone
+9s
+5layer
+9rs
+5unch
+9es
+4s
+5harp
+9er
+9ers
+9ing
+9ings
+9s
+4uaceous
+5us
+7es
+4y
+3e
+4d
+4en
+6age
+9s
+6ed
+7r
+8s
+6ing
+6s
+5r
+6ed
+7r
+8s
+6ing
+7sm
+9s
+8t
+9s
+6s
+4free
+8ness
+9esses
+5ul
+7ler
+9st
+8y
+7ness
+9sses
+4giver
+9s
+7ing
+9gs
+4less
+8ly
+8ness
+9esses
+5ine
+8s
+4me
+6s
+4r
+5s
+4s
+5s
+6ed
+7r
+8s
+7s
+6ing
+9ly
+9s
+7ve
+9ly
+4t
+5ake
+8n
+8r
+9s
+8s
+7ing
+9gs
+5ook
+5s
+4ware
+8s
+5orker
+9rs
+7n
+4x
+3fare
+7s
+5x
+6es
+4ox
+6es
+4uffle
+9d
+9s
+8ing
+5l
+6s
+3geese
+4o
+5ed
+6s
+5ing
+5ose
+5s
+3hop
+6ped
+7ing
+6s
+3iacou
+8s
+5ma
+7s
+4be
+6s
+5ou
+7s
+4catura
+9al
+9as
+9e
+9ed
+9es
+9ing
+9ist
+9ists
+5es
+4ed
+5re
+7s
+5s
+4llon
+8ed
+8ing
+9st
+9sts
+8ned
+9eur
+9eurs
+9ing
+8s
+4na
+6e
+6l
+6s
+6te
+8d
+5g
+6ly
+6s
+4oca
+7s
+5genic
+5le
+7s
+5se
+6ities
+8y
+5us
+7ness
+9sses
+4tas
+7es
+6tes
+3jack
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6ou
+8s
+3k
+4ed
+4ing
+4s
+3l
+4e
+5s
+6s
+4in
+6e
+7s
+6g
+7s
+6s
+5sh
+4oad
+7s
+5ck
+7s
+5t
+6s
+4s
+3magnole
+9es
+5ker
+8s
+5n
+4elite
+9s
+5n
+4inative
+9ves
+6e
+7s
+3n
+4age
+7s
+5huba
+9s
+5l
+6ise
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7ties
+8y
+7ze
+9d
+9s
+8ing
+6led
+7ing
+8te
+9es
+7y
+6s
+5ptious
+5roli
+9s
+5ssial
+9ls
+5tion
+9ed
+9s
+5uba
+8s
+4elian
+9s
+5ous
+5t
+6s
+5y
+6ed
+6ing
+6s
+4ie
+6d
+6r
+6s
+7t
+5fex
+8es
+6ication
+9tions
+8ial
+7ed
+8s
+6y
+7ing
+5tine
+9s
+5val
+8esque
+8s
+6ora
+8e
+9s
+8ies
+8ous
+9usly
+9usness
+8y
+4osaur
+9s
+6e
+6ities
+8y
+5tite
+9s
+4s
+4y
+5ing
+5x
+6es
+3oach
+7es
+4b
+5s
+4ch
+6e
+7s
+4l
+5ed
+6r
+7s
+5i
+6ng
+8s
+5led
+7r
+8s
+6ing
+9s
+5s
+5us
+7es
+4m
+5ed
+6l
+7led
+8ing
+7s
+5ing
+5s
+4n
+5s
+4tene
+8s
+7oid
+9ds
+5id
+7al
+7s
+6n
+7oid
+9ds
+7s
+4usal
+8s
+6e
+7d
+7l
+8s
+7r
+8s
+7s
+6ing
+9ly
+9s
+3p
+4accio
+9s
+5l
+6e
+7s
+6ia
+6s
+4ed
+5l
+6lary
+8te
+9es
+6s
+5ntaria
+9ias
+7er
+9ed
+9ing
+9s
+7ries
+8y
+5r
+6s
+5t
+6bag
+9ged
+9ger
+9geries
+9gers
+9gery
+9ging
+9s
+6ed
+6ing
+9s
+6monger
+9gers
+6s
+6weed
+9ds
+4hologies
+9y
+6ne
+8s
+4i
+5ng
+7ly
+7s
+4ogonia
+9al
+9um
+5logical
+9es
+9st
+9sts
+8y
+5metacarpi
+9carpus
+5ol
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5phagous
+7ore
+9es
+5rt
+7s
+5spore
+9es
+4s
+4us
+3r
+4ack
+7s
+6t
+7s
+5geen
+9an
+9ans
+9in
+9ins
+9s
+6heen
+9nan
+9nans
+9nin
+9nins
+9ns
+5t
+6s
+5way
+8s
+4ect
+7s
+5four
+9s
+5l
+6l
+7s
+6s
+4iage
+8able
+8s
+8way
+9ays
+5ck
+5ed
+6r
+7s
+6s
+5ole
+8s
+6n
+7s
+5tch
+8es
+5witchet
+9hets
+4och
+7es
+5m
+6ed
+6ing
+6s
+5n
+6ade
+9s
+5t
+6ier
+8st
+7n
+8s
+6s
+6top
+9ped
+9s
+6y
+5usel
+9s
+4s
+4y
+5all
+8s
+5back
+9s
+5cot
+8s
+5forward
+9ards
+5ing
+5on
+7s
+6ut
+8s
+6ver
+9s
+5tale
+9s
+3s
+4e
+5s
+5y
+6s
+4hare
+8d
+8s
+7ing
+9gs
+4ick
+7ness
+9sses
+3t
+4a
+5ble
+5ge
+7s
+5s
+4e
+5d
+5l
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+5r
+6s
+5s
+4ful
+7s
+4hamine
+9es
+5orse
+9s
+4ilage
+9s
+8inous
+5ng
+4load
+8s
+4ogram
+9s
+8pher
+9hers
+9hic
+9hical
+9hies
+9hy
+5logical
+9es
+8y
+5mancies
+9y
+5n
+6age
+9s
+6ed
+6ing
+6nage
+9es
+6s
+5on
+7ed
+7ing
+9gs
+8sh
+9hly
+9t
+9ts
+7like
+7s
+7y
+5p
+6hile
+9es
+9ic
+9ies
+9ist
+9ists
+9y
+6per
+9s
+5uch
+8e
+9s
+4ridge
+9s
+5oad
+8s
+4s
+4ularies
+8y
+4way
+7s
+5heel
+9ed
+9er
+9ers
+9ing
+9s
+5right
+9ts
+3ucage
+8s
+6te
+8s
+4ncle
+8s
+6ular
+9te
+9ted
+8ous
+3vacrol
+9s
+4e
+5d
+5l
+6s
+5n
+5r
+6ies
+6s
+6y
+5s
+4ies
+5ng
+7s
+4y
+3wash
+7es
+3yatic
+7d
+8al
+8ean
+9s
+8ic
+8s
+4opses
+7ides
+8s
+6teris
+9ises
+5tin
+8s
+2sa
+4ba
+6s
+4s
+4va
+6s
+3bah
+6s
+3cabel
+8s
+6le
+8s
+5de
+7d
+7s
+6ing
+6ura
+9s
+5ra
+7s
+6illa
+9as
+4hrom
+8s
+4o
+5s
+3e
+4ase
+7s
+5te
+7d
+7s
+6ing
+7on
+9s
+4bearer
+9rs
+5ook
+8s
+6und
+4d
+4fied
+7s
+5y
+6ing
+4ic
+5n
+6ate
+9s
+6ogen
+9ns
+6s
+4load
+8s
+4maker
+9s
+6n
+6te
+8d
+8s
+5en
+7t
+8ed
+8s
+5ix
+7es
+4ose
+7s
+5us
+4rn
+6e
+7s
+6s
+4s
+4tte
+7s
+4vac
+7ed
+7ing
+7s
+4work
+8er
+9rs
+8s
+7m
+8s
+3h
+4able
+5w
+6s
+4back
+8s
+5ook
+8s
+6x
+7es
+4ed
+5s
+5w
+6s
+4ier
+7ed
+8r
+9s
+7ing
+9gs
+7ment
+9nts
+7s
+5ng
+4less
+4mere
+8s
+4oo
+6s
+4point
+9s
+3imere
+8s
+5ire
+8s
+4ng
+6head
+9ds
+6s
+5i
+5o
+6s
+4ta
+6s
+3k
+4ed
+5t
+6ed
+6ing
+6s
+4ier
+6st
+5ng
+4s
+5tand
+9s
+4y
+3pase
+7s
+3que
+6d
+6s
+3saba
+7s
+5reep
+9s
+5ta
+7s
+6ion
+9s
+5va
+7s
+4ena
+7s
+6e
+7s
+5role
+9d
+9s
+8ing
+5tte
+8s
+4ia
+6s
+5mere
+9s
+5na
+7s
+6e
+7s
+6gle
+9s
+6o
+7s
+5opeium
+9ums
+5s
+6es
+5terite
+9tes
+4ock
+7ed
+7s
+5lette
+9es
+5nade
+9s
+6e
+7s
+5ulet
+9s
+5waries
+8y
+4pir
+7s
+4umunar
+9rs
+3t
+4abilities
+9ty
+6le
+5net
+8s
+6ospermine
+5way
+8s
+4e
+5d
+5ism
+8s
+5less
+6la
+8n
+9s
+8ted
+9ion
+9ions
+7um
+9s
+5r
+6s
+5s
+4igate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+9ry
+5ng
+7s
+4le
+6d
+6s
+5ing
+4ock
+7s
+5ff
+7s
+5r
+6eum
+9s
+6ies
+6s
+6y
+4ral
+6metation
+9ations
+6te
+8d
+8r
+9s
+8s
+7i
+8ng
+8on
+9ns
+7o
+8r
+9s
+9y
+8s
+4s
+3ual
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+6ness
+9ses
+6s
+6ties
+7y
+5rina
+9s
+4ist
+7ic
+9al
+9ally
+7ries
+8y
+7s
+4s
+2t
+3abases
+7is
+6tic
+5olic
+9ally
+8se
+9ed
+9es
+9ing
+9m
+9ms
+8te
+9es
+8ze
+9ed
+9es
+9ing
+4caustic
+9ics
+5hreses
+9is
+9tic
+9tical
+5lases
+8is
+8m
+9ic
+9s
+8tic
+6inal
+6ysm
+9al
+9ic
+9ically
+9s
+5omb
+8s
+6ustics
+5umbal
+4dioptric
+9rical
+5romous
+4falco
+9es
+7que
+9es
+4lase
+8s
+6tic
+5ectic
+9cs
+6psies
+8y
+7tic
+9cally
+9cs
+6xes
+7is
+5lactic
+9ically
+9ics
+5o
+6es
+6g
+7ed
+8r
+9s
+7ic
+8ng
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7s
+7ue
+9d
+9r
+9rs
+9s
+8ing
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+6s
+5pa
+7s
+5yse
+8d
+8r
+9s
+8s
+7ing
+8s
+7t
+8s
+6tic
+9al
+9ally
+6ze
+8d
+8r
+9s
+8s
+7ing
+4maran
+9s
+5enia
+9l
+5ite
+8s
+5ount
+9ain
+9ains
+9s
+4nanche
+9es
+4pan
+7s
+5honic
+9cs
+7r
+8a
+9s
+8eses
+9sis
+9tic
+8ic
+9cally
+8s
+6ract
+9tic
+9ts
+6yll
+9ary
+9s
+7sical
+5lasia
+9as
+8m
+9s
+8tic
+6ectic
+7xies
+8y
+5ult
+8ed
+8ic
+9er
+9ers
+9ng
+8s
+4ract
+8ous
+8s
+5hine
+5rh
+7al
+9ly
+7ine
+9es
+7ous
+7s
+4sta
+7s
+8es
+8is
+6rophe
+9hes
+9hic
+9hism
+9hisms
+9hist
+9hists
+4tonia
+9s
+8c
+9ally
+9s
+8es
+7y
+4wba
+7s
+3bird
+7s
+4oat
+7s
+4rier
+8s
+3call
+7ed
+8r
+9s
+7ing
+7s
+4h
+5able
+6ll
+8s
+5cries
+7y
+5ed
+6n
+6r
+7s
+6s
+5flies
+7y
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5ment
+9s
+5pennies
+9y
+6hrase
+9ses
+6ole
+9s
+8l
+9s
+5t
+5up
+7s
+5water
+6eed
+9s
+7ight
+6ord
+9s
+5y
+4law
+7s
+4on
+6s
+3e
+4cheses
+8is
+7tic
+9cal
+9cally
+9cs
+6in
+8s
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+8m
+9al
+9s
+8t
+9ic
+9ical
+9ically
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+6ol
+8amine
+9mines
+8s
+6u
+7men
+9nal
+9nate
+9nates
+9nical
+9nism
+9nisms
+9ns
+9nship
+9nships
+7s
+4gorematic
+7ial
+9lly
+8c
+9al
+9ally
+9alness
+8es
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9t
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7y
+4log
+7s
+4na
+6ccio
+9os
+6e
+6ne
+8s
+6rian
+8es
+7y
+6s
+6te
+8d
+8s
+7ing
+8on
+9ns
+5oid
+8s
+5ulate
+4r
+5an
+7s
+5corner
+9ered
+5ed
+6r
+7s
+6ss
+8es
+5ing
+8s
+5pillar
+9ars
+5s
+5waul
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+4s
+3face
+7s
+6ing
+9s
+5ll
+7s
+4ight
+8s
+5sh
+7es
+4lap
+7s
+3gut
+6s
+3harise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6ses
+7is
+6tic
+9al
+9ally
+9s
+4ead
+7s
+5ct
+7ed
+7ic
+8ng
+7s
+5dra
+8e
+8l
+9s
+8s
+8tic
+5psin
+9s
+6tic
+5ter
+8isation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+6ometer
+9ters
+6us
+8es
+5xes
+6is
+4isma
+8s
+4odal
+8ly
+6e
+7s
+6ic
+8al
+9lly
+6ograph
+9apher
+9aphers
+9aphies
+9aphs
+9aphy
+5le
+7s
+6ic
+8ally
+9te
+9tes
+8isation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8oi
+9n
+9ns
+9s
+9ses
+8s
+6yte
+9s
+5od
+7s
+5use
+8s
+3ion
+6ic
+8ally
+6s
+3jang
+7s
+3kin
+6ate
+6s
+3like
+5n
+6g
+7s
+6s
+3mint
+7s
+3nap
+6er
+8s
+6ped
+8r
+9s
+7ing
+6s
+4ep
+6s
+4ip
+6s
+3olyte
+8s
+4ptric
+9al
+9s
+3rigged
+3s
+4kin
+7s
+4paw
+7s
+4uit
+7s
+5p
+6s
+3tabu
+7s
+5il
+7s
+5lo
+7es
+7s
+4ed
+5ries
+6y
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+5sh
+7ly
+7ness
+9sses
+4le
+6man
+7en
+6ya
+8s
+4y
+3walk
+7s
+4orks
+6m
+7s
+2uchemar
+9s
+4us
+6ed
+7s
+6ing
+6sed
+8s
+7ing
+3da
+5d
+5e
+5l
+6ly
+5te
+7d
+7s
+6ion
+9s
+4ex
+6es
+4ices
+6le
+8s
+5llismo
+9mos
+7o
+8s
+4le
+6d
+6s
+5ing
+4ron
+7s
+3f
+3ght
+3k
+4er
+6s
+4s
+3l
+4d
+5er
+6st
+5rife
+6on
+8s
+5s
+4es
+6cent
+4icle
+8s
+6olous
+6ulate
+8i
+8us
+9ses
+5flories
+9ous
+9y
+8wer
+9eret
+9erets
+9ers
+6orm
+5genous
+5nary
+6e
+5s
+4k
+5ed
+6r
+7s
+5ing
+8s
+5s
+4ome
+7s
+4s
+3m
+4ed
+4ing
+4s
+5tane
+9s
+6one
+9s
+3p
+4s
+3sa
+5bilities
+9ty
+6le
+5e
+5l
+6gia
+9s
+8c
+6ities
+8y
+6ly
+6s
+5tion
+9al
+9ism
+9isms
+9ist
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+9s
+4e
+5d
+5less
+9ly
+9ness
+9nesses
+5n
+5r
+6ie
+8s
+6s
+5s
+5way
+8ed
+8ing
+8s
+5y
+6ed
+6s
+4ing
+4tic
+7al
+9ly
+7ities
+9y
+7ness
+9sses
+7s
+3tel
+6ous
+6s
+5r
+6ant
+9s
+6ies
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+6y
+4ion
+7ary
+7ed
+8r
+9s
+7ing
+7ries
+8y
+7s
+6us
+8ly
+8ness
+9esses
+3ves
+2va
+4lcade
+9d
+9s
+8ing
+5ero
+8s
+6tti
+5ier
+8ed
+8ing
+9sh
+9sm
+9sms
+8ly
+8s
+5la
+7s
+6etti
+6ies
+6y
+5ries
+6y
+7man
+8en
+4s
+5s
+6es
+4tina
+8s
+7e
+3e
+4at
+6ed
+6ing
+6or
+8s
+6s
+4d
+4fish
+8es
+4l
+5ike
+5s
+4man
+5en
+4ndish
+9es
+4r
+5n
+6ed
+6icolous
+7ng
+6ous
+9ly
+6s
+6ulous
+5s
+4s
+5son
+8s
+4tti
+6o
+7s
+3iar
+6e
+7s
+6ie
+8s
+6s
+4corn
+8s
+4e
+5r
+6s
+5s
+4l
+5ed
+6r
+7s
+5ing
+5lation
+9ons
+6ed
+7r
+8s
+6ing
+9s
+5s
+4ng
+6s
+4tary
+6te
+8d
+8s
+7ing
+8on
+9ns
+5ied
+7s
+5y
+3ort
+6ed
+7r
+8s
+6ing
+6s
+3y
+2w
+3ed
+3ing
+6s
+3ker
+6s
+4s
+3s
+2xon
+5s
+2y
+3enne
+7d
+7s
+3man
+6s
+3s
+3use
+6s
+2z
+3ique
+7s
+1eanothus
+9es
+3s
+4e
+5d
+5fire
+9s
+5less
+9ly
+9ness
+9nesses
+5s
+4ing
+7s
+3ze
+5d
+5s
+4ing
+2badilla
+9s
+3id
+5s
+3oid
+6s
+2ca
+4l
+5ly
+3ils
+4ties
+6s
+7es
+5y
+3ropia
+8s
+7n
+8s
+3um
+4tiencies
+9y
+2dar
+5bird
+9s
+5ed
+5n
+5s
+5wood
+9s
+5y
+3e
+4d
+4r
+5s
+4s
+3i
+4lla
+7s
+4ng
+4s
+3rate
+7s
+4elaceous
+4ine
+3ula
+6s
+2e
+3s
+2iba
+5s
+3l
+4ed
+5r
+6s
+4i
+5dh
+7s
+5ng
+7ed
+7s
+5s
+4ometer
+9rs
+4s
+3nture
+8s
+2l
+3adon
+7s
+4ndine
+9s
+3eb
+5rant
+9s
+7te
+9d
+9dness
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+6ities
+8y
+5s
+5utante
+9tes
+4coxib
+9s
+4riac
+8s
+6es
+6ties
+7y
+5y
+4sta
+7s
+6e
+7s
+6ial
+9ly
+9s
+7ne
+9s
+7te
+9s
+3iac
+6s
+4bacies
+7y
+6tarian
+7e
+8s
+7ic
+3l
+4a
+5e
+5r
+6age
+9s
+6ed
+7r
+8s
+7t
+8s
+8te
+9es
+6ing
+7st
+9s
+6man
+7en
+6ous
+6s
+6way
+9s
+4block
+9s
+4ed
+5ntani
+9is
+4i
+5ferous
+5ng
+5st
+7s
+4mate
+8s
+4o
+5biose
+9es
+5idin
+9s
+5phane
+9es
+5s
+6e
+7s
+4phone
+9s
+4s
+4ular
+8ities
+9ty
+8s
+7se
+9s
+7ted
+6e
+7s
+6iferous
+7te
+9s
+8ides
+9s
+9ses
+6oid
+9s
+7lytic
+7se
+9s
+8ic
+9cs
+7us
+3om
+5ata
+5ic
+5s
+4sia
+7s
+4tex
+7es
+3s
+4itude
+9s
+3t
+4s
+2mbali
+7st
+9s
+6o
+7s
+4ra
+6s
+3ent
+6a
+7tion
+9ons
+8ory
+6ed
+7r
+8s
+6ing
+7te
+9s
+8ious
+6s
+6um
+8s
+4teries
+7y
+3itare
+8s
+2nacle
+7s
+3dre
+3estheses
+9ia
+9ias
+9is
+8tic
+3obite
+8s
+7ic
+9al
+4geneses
+9is
+8tic
+9ically
+4species
+4taph
+8ic
+8s
+5e
+6s
+4zoic
+3s
+4e
+5d
+5r
+6s
+5s
+4ing
+4or
+6able
+6ed
+6ial
+8n
+7ng
+7ous
+9sly
+9sness
+6s
+7hip
+9ps
+4ual
+5rabilities
+9lity
+8le
+9eness
+9y
+6e
+7d
+7r
+8s
+7s
+6ing
+5s
+6ed
+7s
+6ing
+3t
+4age
+7s
+5i
+5l
+6s
+5re
+7s
+5s
+5ur
+7ea
+9s
+7ian
+8c
+8es
+7s
+7y
+5vo
+7s
+4enarian
+9anism
+9anisms
+9ans
+9es
+8y
+6ier
+9s
+6nial
+9lly
+9ls
+5r
+6board
+9rds
+6ed
+8ness
+9esses
+6fold
+9ds
+6ing
+9s
+6less
+7ine
+9es
+6piece
+9ces
+6s
+5ses
+6imal
+9lly
+9ls
+8i
+8o
+9s
+7s
+4iare
+8s
+5grade
+9es
+8m
+9me
+9mes
+9s
+5le
+7s
+6iter
+9rs
+8re
+9es
+6lion
+9ns
+9nth
+9nths
+5me
+7s
+7ter
+9rs
+8re
+9es
+9ic
+6o
+7rgan
+9ans
+7s
+5nel
+8l
+9s
+8s
+5pede
+9s
+6oise
+9es
+4ner
+7s
+4o
+5ist
+8s
+5nate
+6el
+8l
+9s
+8s
+7s
+6ist
+9s
+5s
+4ra
+6l
+7er
+8st
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7ly
+7s
+5e
+6board
+9rds
+6d
+6fold
+9ds
+6ing
+9s
+6line
+9es
+6piece
+9ces
+6s
+5ic
+7al
+9ly
+9ness
+9nesses
+7ities
+9y
+6es
+6fugal
+9alise
+9alised
+9alises
+9alize
+9alized
+9alizes
+9ally
+9als
+9ation
+9ations
+9e
+9ed
+9ence
+9ences
+9es
+9ing
+6ng
+8s
+6ole
+9s
+6petal
+9alism
+9alisms
+9ally
+6sm
+8s
+7t
+8s
+5obaric
+6clinal
+6de
+8s
+6id
+8al
+8s
+6lecithal
+6mere
+9es
+9ic
+6some
+9es
+9ic
+7phere
+9eres
+7ymmetric
+5um
+7s
+5y
+4s
+4u
+5m
+6s
+6vir
+9ate
+9ates
+9i
+5ple
+8d
+8s
+7icate
+9ated
+9ates
+9ating
+9ation
+9ations
+8ng
+5rial
+8tion
+9ions
+9or
+9ors
+7es
+7on
+9s
+6y
+2orl
+5ish
+5s
+2p
+3aceous
+4ge
+6s
+3e
+4s
+3halad
+7gra
+9as
+7lgia
+9ias
+9ic
+7te
+6exin
+9ns
+6ic
+8ally
+8s
+7n
+8s
+7sation
+9tions
+7tis
+9ses
+7zation
+9tions
+6ocele
+9les
+8hordate
+7meter
+9ters
+9tric
+9tries
+9try
+7pod
+9dan
+9dans
+9dic
+9dous
+9ds
+7ridine
+9dines
+7sporin
+9orins
+7thin
+9ins
+9oraces
+9oracic
+9orax
+9oraxes
+8omies
+9my
+7us
+4eid
+7s
+3s
+2raceous
+4mal
+7s
+5ic
+7ist
+9ts
+7s
+6de
+8s
+6st
+8s
+5ographies
+9phy
+4rgyrite
+9tes
+4sin
+7s
+5tes
+6ium
+9s
+4te
+6d
+6s
+5in
+7s
+6tis
+9es
+5odus
+9es
+6id
+6psian
+9ans
+9d
+9ds
+3berean
+6ian
+3cal
+5ria
+8e
+8l
+8n
+9s
+8s
+4i
+5s
+6es
+4opid
+8s
+7thecid
+9ecids
+9ecoid
+9ecoids
+4us
+3e
+4al
+6ist
+9s
+6s
+4bella
+9r
+8ic
+8ous
+8um
+9ms
+5ra
+7l
+8ism
+9sms
+9st
+9sts
+8ly
+8s
+7te
+9d
+9s
+8ing
+9on
+9ons
+6ic
+7form
+7tis
+9ses
+6oid
+7side
+9des
+8pinal
+7tonia
+9nias
+9nic
+7vascular
+6um
+8s
+4cloth
+9s
+4d
+4ment
+8s
+5onial
+9lism
+9lisms
+9list
+9lists
+9lly
+9ls
+8es
+8ous
+9usly
+9usness
+7y
+4ous
+4s
+5in
+7e
+8s
+7s
+4us
+6es
+3ge
+5s
+3ia
+5s
+4c
+4ferous
+4ng
+4ph
+6s
+4se
+6s
+4te
+6s
+4um
+6s
+3met
+6s
+3ne
+5d
+5s
+4ing
+4uous
+3o
+4graph
+9ic
+9ical
+9ies
+9ist
+9ists
+9s
+9y
+4mancies
+8y
+4on
+6s
+4plastic
+9ics
+4s
+4tic
+5ype
+8s
+4us
+3rado
+7s
+4ial
+5s
+6es
+3t
+4ain
+7er
+8st
+7ly
+7ties
+8y
+4es
+4ie
+5fiable
+9ly
+7cate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tories
+9tory
+7ed
+8r
+9s
+8s
+6y
+7ing
+5orari
+9is
+5tude
+9s
+4s
+4y
+3ule
+6an
+8s
+6in
+8s
+6ous
+5oplasmin
+9smins
+4men
+7s
+5inous
+4se
+6s
+5ite
+8s
+5site
+9s
+3velas
+8es
+7t
+8s
+5za
+7s
+4ical
+6es
+6ites
+8ides
+9s
+9ses
+6ographies
+9aphy
+6um
+8s
+5d
+6s
+5ne
+5x
+6es
+2sarean
+8s
+6vich
+9hes
+8tch
+9ches
+7na
+9s
+6wich
+9hes
+8tch
+9ches
+5ian
+8s
+3ious
+4um
+6s
+3pitose
+9ly
+3s
+4ation
+9s
+4e
+5d
+5r
+6s
+5s
+4ing
+5on
+7aries
+9y
+7s
+4pit
+7s
+5ool
+8s
+3ta
+5s
+4i
+4ode
+7s
+5i
+6d
+7ean
+9ns
+7s
+5s
+6es
+4ui
+6s
+5s
+6es
+3ura
+6e
+6l
+6s
+5e
+6s
+2tacean
+8s
+6ous
+4ne
+6s
+3e
+4osaurus
+9uses
+4rach
+8s
+4s
+3ological
+8es
+8st
+9ts
+7y
+3rimide
+9s
+3uximab
+9s
+3yl
+5s
+4wall
+8s
+2vadilla
+9s
+4pcici
+3iche
+7s
+4tamic
+2ylanite
+9s
+4onite
+9s
+2zve
+5s
+1h
+2a
+3bazite
+9s
+4lis
+4ouk
+7s
+4uk
+6s
+3ce
+5d
+5s
+4hka
+7s
+4ing
+4k
+5ed
+5ing
+5s
+4ma
+6s
+4o
+5es
+5nine
+9s
+6ne
+8s
+5s
+3d
+4ar
+6im
+6s
+4dar
+7s
+5or
+7s
+4less
+4o
+5r
+6s
+5s
+4ri
+4s
+3ebol
+7s
+4nomeles
+9eses
+4ta
+6e
+6l
+5iferous
+5odon
+9s
+6gnath
+9ths
+6pod
+9s
+3fe
+5d
+5r
+6s
+5s
+4f
+5ed
+6r
+7ed
+8r
+9s
+7ies
+8ng
+7s
+7y
+5ier
+7st
+6nch
+9es
+7g
+8ly
+8s
+5ron
+8s
+5s
+5y
+4ing
+4t
+5s
+3gan
+6s
+4rin
+7ed
+7ing
+7ned
+8ing
+7s
+3i
+4n
+5brake
+9es
+5e
+6d
+6s
+5fall
+9s
+5ing
+5less
+7t
+8s
+5man
+6en
+5plate
+9es
+5s
+6aw
+8ed
+8ing
+8s
+6hot
+9s
+6titch
+9ches
+5wheel
+9ls
+6ork
+9s
+4r
+5borne
+7und
+5days
+5ed
+5ing
+5lift
+9s
+5man
+8ed
+8ing
+8ned
+9ing
+8s
+9hip
+9hips
+6en
+5person
+9ons
+5s
+5woman
+8en
+4s
+5e
+6less
+6s
+3kalaka
+9s
+4ra
+6s
+3l
+4ah
+6s
+5n
+6s
+5za
+7e
+7l
+7s
+6ia
+7on
+9s
+6ogamic
+9mies
+9my
+4canthite
+9ites
+5edonic
+9ies
+9y
+9yx
+9yxes
+5id
+7s
+5ocite
+9es
+6gen
+9ide
+9ides
+9s
+7rapher
+9phers
+9phic
+9phical
+9phies
+9phist
+9phists
+9phy
+6lithic
+6pyrite
+9ites
+4der
+7s
+5ron
+8s
+4eh
+6s
+5t
+6s
+4ice
+7d
+7s
+6othere
+9eres
+4k
+5board
+9ds
+5ed
+5face
+9s
+5ier
+7st
+6ness
+9ses
+7g
+5like
+5pit
+8s
+5s
+6tone
+9es
+5y
+4la
+6h
+7s
+6n
+7s
+6s
+5enge
+9able
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+5ie
+7s
+6s
+7es
+5ot
+7h
+5y
+4one
+7s
+6ic
+5t
+6h
+4s
+4umeau
+9s
+9x
+5pa
+7s
+5tz
+7es
+7im
+4ybean
+8te
+9es
+6ite
+9s
+3m
+4ade
+7s
+5eleon
+9ns
+6phyte
+9tes
+4ber
+7ed
+8r
+9s
+7hand
+9nds
+7ing
+9gs
+7lain
+9ins
+9inship
+7maid
+9ids
+7pot
+9ts
+7s
+5ranle
+9es
+7y
+8s
+6e
+4eleon
+9ic
+9like
+9s
+6ot
+8s
+5tz
+7es
+4fer
+7ed
+8r
+9s
+7ing
+7s
+5rain
+9s
+6on
+8s
+4isa
+7l
+8s
+7s
+6e
+7s
+6o
+7s
+4let
+7s
+4mied
+7s
+5y
+6ing
+4ois
+7ed
+8s
+7ing
+6x
+5mile
+9s
+4p
+5ac
+7a
+8s
+7s
+6gne
+9s
+6ign
+9s
+6k
+7s
+6rt
+8s
+5ed
+6r
+7s
+7ties
+8ous
+8y
+5ier
+7st
+6gnon
+9ns
+6ng
+6on
+8ed
+9ss
+9sses
+8ing
+8s
+9hip
+9hips
+5leve
+9s
+5s
+5y
+4s
+3na
+5s
+4ce
+6d
+6ful
+6l
+7ess
+7leries
+9ry
+8or
+9ries
+9rs
+9rship
+9rships
+9ry
+7s
+6r
+7ies
+7s
+7y
+6s
+6y
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5re
+7s
+6oid
+9al
+9s
+7us
+5y
+4delier
+9red
+9rs
+7le
+9d
+9s
+8ing
+5ler
+8ies
+9ng
+9ngs
+8ly
+8s
+8y
+4fron
+8s
+4g
+5a
+5e
+6abilities
+9lity
+8le
+9eness
+9y
+6d
+6ful
+9ly
+9ness
+9nesses
+6less
+9sly
+9sness
+7ing
+9gs
+6over
+9rs
+6r
+7ound
+9nds
+7s
+6s
+6up
+8s
+5ing
+5s
+4k
+5s
+4nel
+7ed
+8r
+9s
+7ing
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7led
+9r
+9rs
+8ing
+7s
+6r
+7s
+4oyo
+7s
+6u
+7s
+4son
+7ette
+9tes
+7nier
+9ers
+7s
+4t
+5able
+6ge
+8s
+6relle
+9les
+5ecler
+9rs
+6d
+6r
+7elle
+9les
+7s
+6use
+9s
+6y
+7s
+5icleer
+9ers
+6e
+7s
+6lly
+6ng
+8ly
+8s
+5or
+7s
+5ress
+9es
+6ies
+6y
+5s
+5y
+4ukiah
+9s
+3o
+4logies
+8st
+9ts
+7y
+4rdic
+4s
+5es
+4tic
+7ally
+3p
+4arajos
+6ejos
+6ral
+9s
+5ti
+7es
+7s
+6ti
+8es
+8s
+4book
+8s
+4e
+5au
+7s
+7x
+5l
+6ess
+6ries
+7y
+6s
+5ron
+8age
+9ges
+8e
+9d
+9s
+8ing
+8s
+5s
+6s
+7es
+4fallen
+4iter
+8s
+4ka
+6s
+4lain
+8cies
+9y
+8ries
+9y
+8s
+9hip
+9hips
+5ess
+6t
+7ed
+7s
+4man
+7ship
+9ips
+5en
+4pal
+7s
+6ti
+8s
+5ed
+6ss
+8es
+5ie
+7r
+7s
+8t
+6ng
+5y
+4rassi
+9es
+9s
+4s
+5tick
+9s
+4t
+5alisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5er
+7al
+7ed
+7house
+9uses
+7ing
+7s
+5rel
+8s
+3queta
+8s
+3r
+4a
+5banc
+9s
+5cid
+8s
+7n
+8oid
+8s
+6t
+7er
+9ed
+9ful
+9ies
+9ing
+9isable
+9ise
+9ised
+9iser
+9isers
+9ises
+9ising
+9ism
+9isms
+9istic
+9istics
+9izable
+9ize
+9ized
+9izer
+9izers
+9izes
+9izing
+9less
+9ology
+9s
+9y
+7s
+5de
+7s
+5nga
+8s
+7o
+8s
+5s
+6es
+4broil
+9ed
+9er
+9ers
+9ing
+9s
+4coal
+8ed
+8ing
+8s
+8y
+5uterie
+9ies
+4d
+5onnay
+9ys
+5s
+4e
+5d
+5s
+5t
+6s
+4ge
+6abilities
+9lity
+8le
+9eness
+9y
+6back
+9ks
+6d
+6ful
+6hand
+9ds
+6less
+6r
+7s
+6s
+7heet
+9ets
+5ing
+5rill
+9ed
+9ing
+9s
+4idee
+8s
+5er
+6st
+5ly
+5ness
+9es
+6g
+5ot
+7ed
+8er
+9red
+9ring
+9rs
+7ing
+7s
+5sm
+7a
+8s
+8ta
+9ic
+9ics
+7s
+5table
+9eness
+9y
+6ies
+6y
+5vari
+9ed
+9ing
+9s
+4k
+5a
+6s
+5ed
+5ha
+7s
+5ing
+5s
+4ladies
+7y
+6tan
+9ic
+9ical
+9ism
+9isms
+9istic
+9ries
+9ry
+9s
+5eston
+9ned
+9ning
+9ns
+6y
+7s
+5ie
+7r
+7s
+5ock
+8s
+6tte
+9s
+4m
+5ed
+6r
+7s
+6use
+9s
+5ful
+5ing
+8er
+9st
+8ly
+5less
+9ly
+5onia
+8um
+5s
+4neco
+8s
+6l
+7s
+4oset
+8h
+9s
+8s
+4pai
+7s
+5ie
+7s
+5oy
+7s
+4qui
+7d
+7s
+4r
+5ed
+5ier
+7st
+6ng
+5o
+6s
+5s
+5y
+4s
+4t
+5a
+6ble
+6ceous
+6s
+5ed
+6r
+7ed
+8r
+9s
+7ing
+7parties
+9rty
+7s
+5house
+9es
+5ing
+6sm
+8s
+7t
+8s
+5less
+5ographer
+9phers
+9phic
+9phical
+9phies
+9phy
+5reuse
+9es
+5s
+5ularies
+9y
+4ver
+7s
+4woman
+7en
+4y
+3s
+4e
+5able
+5d
+5port
+9s
+5r
+6s
+5s
+4ing
+7s
+4m
+5al
+5ed
+5ic
+6er
+7st
+5ogamic
+9ies
+9ous
+9y
+5s
+5y
+4se
+6d
+6ed
+6ing
+6pot
+9s
+6s
+6ur
+8s
+5is
+4te
+6ly
+6n
+7ed
+8r
+9s
+8ss
+9ses
+7ing
+9gly
+7ment
+9nts
+7s
+6r
+6st
+5isable
+7e
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+6ties
+7y
+4uble
+8s
+3t
+4bot
+7s
+4chka
+8s
+7e
+8s
+4eau
+7briand
+9iands
+7s
+7x
+5lain
+9e
+9es
+9s
+4line
+8s
+4on
+6s
+5yance
+9es
+9ies
+9y
+8t
+9s
+4room
+8s
+4s
+4ta
+6s
+5ed
+6l
+7s
+6r
+7ati
+7box
+9xes
+7ed
+8r
+9s
+7ing
+9gs
+7s
+7y
+5i
+6er
+7s
+8t
+6ly
+6ness
+9ses
+7g
+6s
+5y
+3udfroid
+9ds
+4fe
+6d
+6r
+7s
+6s
+5f
+6ed
+7r
+8s
+7ur
+9ed
+9ing
+9s
+8se
+9ed
+9es
+9ing
+6ing
+6s
+5ing
+4lmoogra
+9ras
+6ugra
+9as
+4mer
+7s
+4nce
+7d
+7s
+6ing
+5ge
+7d
+7s
+6ing
+5t
+6ed
+7r
+8s
+6ing
+6ress
+9ses
+7ies
+7y
+6s
+4sses
+6ure
+9s
+4tauqua
+9as
+4vin
+7ism
+9ms
+9t
+9tic
+9ts
+7s
+3v
+4e
+5nder
+9s
+5tte
+8s
+4ish
+4s
+4tastic
+4vier
+7st
+5y
+3w
+4bacon
+9s
+4dron
+8s
+4ed
+5r
+6s
+4ing
+4k
+5s
+4s
+3y
+4a
+5s
+4ote
+7s
+4root
+8s
+4s
+3zan
+6im
+6s
+4zan
+7im
+7s
+5en
+7im
+7s
+2e
+3ap
+5ed
+6n
+7ed
+8r
+9s
+7ing
+7s
+6r
+6st
+5ie
+7s
+6ng
+6sh
+8ly
+5jack
+9s
+5ly
+5ness
+9es
+5o
+6s
+5s
+6kate
+9es
+5y
+4t
+5able
+5ed
+6r
+7ies
+7s
+7y
+5ing
+8ly
+8s
+5s
+3bec
+6s
+3chako
+8es
+8s
+6quo
+9s
+5ia
+7s
+4k
+5able
+5book
+9s
+5clerk
+9ks
+5ed
+6r
+7berries
+9rry
+8loom
+9ooms
+8oard
+9ards
+7ed
+7ing
+7s
+5ier
+7st
+6ng
+5laton
+9ns
+6ess
+6ist
+9ed
+9ing
+9s
+5mark
+9ed
+9ing
+9s
+7te
+9d
+9s
+8ing
+5off
+8s
+6ut
+8s
+5point
+9ts
+5rail
+9s
+6ein
+9s
+6oom
+9s
+7w
+8ed
+8ing
+8s
+5s
+6um
+8s
+5up
+7s
+5weigher
+9hers
+5y
+3ddar
+7s
+7y
+5ite
+8s
+4er
+6s
+4ite
+7s
+3echako
+9es
+9s
+7lko
+9oes
+9os
+4k
+5bone
+9s
+5ed
+5ful
+8s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5less
+5piece
+9es
+6ouch
+9hes
+5s
+5teeth
+6ooth
+5y
+4p
+5ed
+6r
+7s
+5ing
+5s
+4r
+5ed
+6r
+7s
+5ful
+8ler
+9est
+9y
+8ness
+9esses
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+6o
+7s
+6shness
+9esses
+5lead
+9er
+9ers
+9ing
+9s
+7d
+7ss
+9ly
+9ness
+9nesses
+6y
+5o
+6s
+5s
+5y
+4se
+6board
+9rds
+7urger
+9gers
+6cake
+9es
+7loth
+9ths
+7utter
+9ters
+6d
+6hopper
+9pers
+6mite
+9es
+7onger
+9gers
+6parer
+9ers
+9ing
+9ings
+7ress
+9sses
+6s
+7teak
+9aks
+6taster
+9ters
+6vat
+9s
+6wire
+9es
+7ood
+9ds
+7ring
+9ngs
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5y
+4tah
+7s
+4wink
+8s
+3f
+4dom
+7s
+4ed
+4fed
+5ing
+4ing
+4s
+3goe
+6s
+3ilitis
+9es
+3ka
+5s
+4ist
+7s
+3la
+5e
+5s
+6hip
+9s
+5table
+6e
+7d
+7s
+6ing
+7on
+9s
+6or
+8s
+4icera
+9e
+9l
+9te
+9tes
+5ferous
+6orm
+5ped
+8s
+4lup
+7s
+4oid
+7al
+7s
+5ne
+7s
+6ian
+9s
+4p
+5ed
+5ing
+5s
+4uviation
+9ions
+3mautotroph
+9rophic
+9rophs
+4iatric
+5c
+6al
+8ly
+8s
+6ked
+7ing
+6s
+5osmoses
+9sis
+9tic
+5se
+7s
+7tte
+9es
+6m
+7s
+6orb
+9ed
+9ing
+9s
+8ption
+9tions
+6t
+7ries
+8y
+7s
+5type
+9s
+8ies
+8y
+4mies
+5y
+4o
+5attractant
+6utotroph
+9trophs
+9trophy
+8roph
+9ophs
+5ceptor
+9ors
+5kine
+9s
+9ses
+9sis
+5lithotroph
+5nasties
+9y
+5psychiatry
+5reception
+9ptions
+9ptive
+9ptor
+9ptors
+5s
+6moses
+9is
+8tic
+6orb
+9ed
+9ing
+9s
+6phere
+9res
+9ric
+6tat
+9s
+6urgeries
+9ery
+9ical
+6yntheses
+9hesis
+9hetic
+5tactic
+9ically
+7xes
+8is
+8onomic
+9nomies
+9nomist
+9nomy
+6herapies
+9apist
+9apists
+9apy
+6ropic
+9ically
+9ism
+9isms
+4paduk
+9s
+4urgic
+9al
+8es
+7y
+3nar
+6s
+4et
+6s
+4ille
+8s
+5x
+6es
+4opod
+8iaceous
+8s
+3ongsam
+9s
+3que
+6book
+9ks
+6r
+7board
+9ards
+7ed
+7ing
+7s
+7wise
+8ork
+9rks
+6s
+5ier
+7st
+6ng
+5y
+3r
+4alite
+9s
+4e
+4imoya
+9s
+8er
+9rs
+5sh
+7able
+7ed
+8r
+9s
+8s
+7ing
+9gly
+7ment
+9nts
+4moula
+9s
+4nozem
+9ic
+9s
+4oot
+7s
+4ried
+7r
+7s
+8t
+5y
+6ing
+6like
+6stone
+9nes
+4sonese
+9es
+4t
+5ier
+7st
+5s
+5y
+4ub
+6ic
+8al
+9lly
+7m
+8ic
+8s
+7n
+8s
+6like
+6s
+5p
+6ed
+6ing
+6s
+4vil
+7s
+5onets
+3shire
+8s
+4il
+6s
+4nut
+7s
+4s
+5board
+9ds
+7xing
+9ngs
+5el
+7s
+6s
+5man
+6en
+5piece
+9es
+5ylite
+9es
+4t
+5ed
+6rfield
+9elds
+5ful
+8s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5nut
+8s
+5s
+5y
+3tah
+6s
+4h
+5s
+4nik
+7s
+4rum
+7s
+3val
+6et
+8s
+6ier
+9s
+4elure
+9s
+5n
+6s
+5rel
+8s
+6il
+8s
+6on
+8s
+6ye
+8s
+5saile
+9es
+5t
+6s
+4ied
+6s
+5lle
+8s
+5n
+6s
+5ot
+7s
+5sance
+9es
+4re
+6s
+6t
+7s
+7te
+9s
+5on
+7ed
+7s
+7y
+6tain
+9ns
+4y
+5ing
+3w
+4able
+4ed
+5r
+6s
+5t
+6s
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+6k
+7s
+4s
+4y
+3z
+2i
+3a
+4ck
+6ed
+6ing
+9s
+6s
+4nti
+7s
+4o
+4rezza
+8e
+5oscurism
+9risms
+9rist
+9rists
+9ro
+9ros
+4s
+5m
+6a
+7l
+7s
+7ta
+8ic
+6i
+7c
+6s
+6us
+5tic
+6olite
+9tes
+4us
+6ed
+7s
+6ing
+3b
+4bed
+5ing
+4ol
+6s
+5uk
+7s
+6que
+9s
+4s
+3c
+4a
+5lote
+9s
+5na
+7s
+6e
+7d
+7r
+8ies
+8s
+8y
+7s
+6ing
+9s
+6o
+7s
+5s
+4cories
+7y
+4er
+5st
+4h
+5a
+6s
+5es
+5i
+6er
+7st
+6s
+4k
+5abiddies
+9dy
+6dee
+9s
+6ree
+9s
+5ee
+7s
+6n
+7ed
+7hearted
+7ing
+7pox
+9xes
+7s
+5ling
+9s
+5ories
+7y
+5pea
+8s
+5s
+5weed
+9s
+4le
+6s
+5y
+4ness
+8es
+4o
+5n
+6s
+5ries
+6y
+5s
+4s
+3d
+4den
+4e
+5d
+5r
+6s
+5s
+4ing
+7ly
+7s
+4lings
+3ef
+5dom
+8s
+5er
+7ies
+7y
+6ss
+8es
+7t
+5less
+6ing
+9s
+6y
+5ries
+6y
+5s
+6hip
+9s
+5tain
+9cies
+9cy
+9ess
+9esses
+9ries
+9ry
+9s
+9ship
+9ships
+4l
+5d
+6s
+5s
+3ffchaff
+9fs
+5on
+7ade
+9es
+7ier
+9rs
+7nier
+9ers
+7s
+7y
+6robe
+9es
+3getai
+8s
+4ga
+6s
+5er
+7s
+4non
+7ed
+7s
+4oe
+6s
+4re
+6s
+3huahua
+9s
+3k
+4ara
+7s
+4hor
+7s
+4or
+6s
+4s
+3lblain
+9ed
+9s
+4d
+5bearing
+9ings
+7d
+8s
+6irth
+9hs
+5care
+9s
+6rowing
+9ings
+5e
+6d
+6r
+7mas
+9ses
+6s
+5hood
+9s
+5ing
+6sh
+8ly
+8ness
+9esses
+5less
+9ness
+9nesses
+6ier
+8st
+7ke
+9ness
+9nesses
+6y
+5minder
+9ers
+5ness
+9es
+5proof
+9fed
+9fing
+9fs
+5ren
+5s
+4e
+5s
+4i
+5ad
+7al
+7ic
+7s
+6gon
+9s
+6hedra
+9ron
+9rons
+6rch
+9ies
+9s
+9y
+6sm
+8s
+7t
+8ic
+8s
+5dog
+8s
+5es
+5s
+4l
+5ada
+8s
+5ed
+6r
+7s
+6st
+5i
+6er
+7s
+8t
+6ly
+6ness
+9ses
+7g
+8ly
+8s
+6s
+5ness
+9es
+5s
+5um
+7s
+5y
+4opod
+8an
+9ns
+8ous
+8s
+4tepin
+9s
+3maera
+8s
+7ic
+8sm
+9ms
+5r
+6s
+4b
+5ley
+8s
+6ies
+6y
+5s
+4e
+5d
+5r
+6a
+7s
+6e
+7s
+6ic
+8al
+9lly
+9lness
+7d
+8s
+7sm
+9s
+6s
+5s
+4ichanga
+9gas
+5nea
+8s
+6g
+4la
+6s
+5ey
+7s
+4ney
+7board
+9ards
+8reast
+9easts
+7ed
+7ing
+7like
+7piece
+9eces
+8ot
+9ts
+7s
+4o
+4p
+5anzee
+9es
+5s
+3n
+4a
+5berries
+9y
+5china
+9as
+5man
+6en
+6pa
+8s
+5r
+6oot
+9s
+6s
+5s
+5ware
+9s
+4bone
+8s
+4capin
+9s
+5h
+6erinchee
+9nchees
+7s
+6ier
+8st
+7lla
+9as
+6y
+5ough
+9s
+4dit
+7s
+4e
+5d
+5s
+6e
+4ing
+4kapin
+9s
+6ra
+8s
+5ed
+6rinchee
+9chees
+5ie
+7r
+7s
+8t
+6ng
+5s
+5y
+4less
+4ned
+5ing
+4o
+5iserie
+9ies
+5ne
+7s
+5ok
+7s
+5s
+5vnik
+9s
+4quapin
+9ns
+4s
+5trap
+9s
+4ts
+6es
+5z
+6es
+6ier
+8st
+6y
+4wag
+7ged
+8ing
+7s
+3onodoxa
+9as
+3p
+4board
+9s
+4muck
+8s
+6nk
+8s
+4ochia
+9s
+5lata
+9s
+5tle
+8s
+4pable
+5ed
+6r
+7ed
+7ing
+7s
+5ie
+7r
+7s
+8t
+6ness
+9ses
+7g
+8s
+5y
+4s
+5et
+7s
+3quichiqui
+9quis
+3ragra
+8s
+7ic
+9al
+5l
+6ities
+8y
+4imoya
+9s
+4k
+5ed
+6r
+6st
+5ing
+5s
+4l
+5ed
+5ing
+5s
+4m
+5ed
+5ing
+5s
+4o
+5gnomies
+9y
+6raph
+9her
+9hers
+9hic
+9hical
+9hies
+9hist
+9hists
+9hs
+9hy
+5logies
+9st
+9sts
+8y
+5mancer
+9ers
+9ies
+9y
+8tic
+9ical
+5nomer
+9rs
+8ic
+9d
+9ds
+9es
+8y
+5podial
+9es
+9st
+9sts
+8y
+6ractic
+9tics
+9tor
+9tors
+6ter
+9an
+9ans
+9ous
+9s
+5s
+4p
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5s
+5y
+4r
+5e
+6d
+6n
+6s
+5ing
+5s
+5up
+7ed
+8r
+9s
+7ing
+7s
+7y
+4t
+5ed
+5ing
+5s
+4u
+5rgeon
+9nly
+9ns
+8ries
+9y
+7ical
+5s
+3s
+4el
+6ed
+7r
+8s
+6ing
+6led
+8r
+9s
+7ing
+9gs
+6s
+3t
+4al
+6s
+5rrone
+9i
+4chat
+8s
+8ted
+9ing
+4in
+6oid
+7us
+6s
+4lin
+7g
+8s
+7s
+4on
+6s
+5san
+8s
+4s
+4tagong
+9gs
+5ed
+6r
+7ed
+7ing
+9gs
+7ling
+9ngs
+7s
+5ier
+7s
+8t
+6ng
+5y
+3v
+4alric
+8es
+7ous
+9sly
+9sness
+7y
+5ree
+8d
+8ing
+8s
+6i
+7ed
+8s
+7ing
+4e
+5d
+5s
+4ied
+6s
+5ng
+4s
+4ved
+5ied
+7s
+6ng
+5y
+6ing
+4y
+5ing
+3yogami
+9s
+3z
+4z
+5ed
+6s
+5ing
+2lamydate
+7eous
+8s
+7ia
+9e
+9l
+9s
+7omonades
+9onas
+8spore
+9pores
+6s
+7es
+3oanthite
+9tes
+5sma
+8s
+8ta
+4racetic
+7ne
+9s
+6l
+7ism
+9ms
+7ose
+9ed
+9es
+7s
+6mbucil
+9cils
+7ine
+9es
+7phenicol
+6rgyrite
+9rites
+6te
+8s
+5dan
+8e
+9s
+8s
+5ella
+9s
+6nchyma
+9ymas
+9ymata
+5hexidine
+9dines
+5ic
+6d
+7ate
+9ed
+9es
+9ing
+7e
+8s
+7ic
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7s
+6meter
+9ers
+9ric
+9ries
+9ry
+6n
+7ate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7e
+8s
+7ise
+9ed
+9es
+9ing
+8ties
+9y
+8ze
+9ed
+9es
+9ing
+7s
+6te
+8s
+7ic
+8sation
+9ations
+8zation
+9ations
+5oacetic
+7rgyrite
+6benzene
+9zenes
+7romide
+9mides
+6cruorin
+9orins
+6dyne
+9es
+6form
+9med
+9mer
+9mers
+9ming
+9mist
+9mists
+9ms
+6hydrin
+9rins
+6meter
+9ers
+9hane
+9hanes
+9ric
+9ries
+9ry
+6phyl
+9ll
+9lloid
+9llous
+9lls
+9ls
+9tum
+9tums
+7icrin
+9rins
+7last
+9stal
+9stic
+9sts
+7rene
+9nes
+6quin
+9ne
+9nes
+9ns
+6ses
+7is
+6thiazide
+9azides
+7ic
+6us
+5picrin
+9ins
+6romazine
+9azines
+8pamide
+9amides
+5thalidone
+9idones
+2oana
+6e
+5ocyte
+9es
+3bdar
+7s
+3c
+4aholic
+9cs
+4cier
+7s
+8t
+5y
+4ho
+6s
+4k
+5ablock
+5ed
+6r
+5ful
+8l
+5ing
+5o
+6s
+5s
+6tone
+9es
+4o
+5holic
+9cs
+5late
+9s
+9y
+8ier
+9ers
+9est
+8y
+5s
+4s
+4taw
+7s
+3de
+3enix
+7es
+3g
+4s
+3ice
+6ful
+6ly
+6ness
+9ses
+6r
+6s
+7t
+4r
+5boy
+8s
+5ed
+5girl
+9s
+5ing
+5like
+5man
+7ster
+9ers
+6en
+5s
+6creen
+9ens
+6talls
+3ke
+5able
+5berries
+9y
+6ore
+9s
+5cherries
+9ry
+6oil
+9s
+5d
+6amp
+9s
+5hold
+9s
+5r
+6s
+5s
+5y
+6s
+4idar
+8s
+5er
+6s
+7t
+5ng
+7ly
+4o
+5s
+4ra
+6s
+5i
+6s
+4y
+3la
+5emia
+9s
+8c
+5gogic
+8ue
+9es
+5ngiogram
+9grams
+9graphy
+5s
+5te
+7s
+4ecalciferol
+6yst
+9ectomy
+9ites
+9itides
+9itis
+9itises
+9okinin
+9ostomy
+9otomy
+9s
+5lith
+9iases
+9iasis
+9s
+5mia
+8s
+5nt
+7s
+5r
+6a
+7ic
+7s
+6ic
+8ally
+8ly
+6oid
+6s
+5stases
+9is
+8tic
+7eric
+9in
+9ins
+9ol
+9olemia
+9ols
+7yramine
+9amines
+4i
+5amb
+8ic
+9cs
+8s
+5c
+5ne
+7rgic
+9ically
+7s
+8terase
+9erases
+5s
+4la
+6s
+5ers
+4o
+5s
+4tries
+6y
+3metz
+7es
+4mie
+7s
+4ophyte
+9es
+4p
+5ed
+6r
+7s
+5ing
+5s
+3n
+4dral
+6e
+7s
+6i
+7chthyan
+9thyans
+7fication
+9ed
+9es
+8y
+9ing
+7n
+8s
+7osomal
+9ome
+9omes
+7te
+9s
+8ic
+9s
+9ses
+6oblast
+9asts
+7crania
+9anium
+9aniums
+7geneses
+9nesis
+7id
+8tin
+9ins
+7ma
+9s
+9ta
+9toses
+9tosis
+9tous
+7phorine
+9orines
+7skeleton
+8tian
+9ians
+6ule
+9s
+7s
+3of
+5ed
+5ing
+5s
+4k
+5ed
+5ie
+7s
+6ng
+5s
+4m
+5s
+4n
+5s
+4se
+6r
+7s
+6s
+6y
+5ier
+7st
+6ng
+5y
+3p
+4fallen
+4house
+9s
+4in
+6e
+7s
+6s
+4logic
+9s
+4ped
+6r
+7ed
+7ing
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5y
+4s
+5ockies
+8y
+5tick
+9s
+3ragi
+7c
+6us
+8es
+5l
+6e
+7s
+6ist
+9s
+6ly
+6s
+4d
+5a
+6e
+6l
+6mesoderm
+9oderms
+6te
+8s
+5ed
+6e
+7s
+5ing
+8s
+5ophone
+9nes
+9nic
+6tomies
+9y
+5s
+5wise
+4e
+5a
+6l
+6s
+6tic
+5d
+5e
+6s
+5gi
+7c
+6raph
+9hed
+9her
+9hers
+9hic
+9hies
+9hing
+9hs
+9hy
+6us
+8es
+5ic
+6form
+5man
+6en
+5odrama
+9mas
+6graph
+9phed
+9pher
+9phers
+9phic
+9phies
+9phing
+9phs
+9phy
+6id
+6logies
+9ist
+9ists
+9y
+5piscopal
+5s
+5us
+7es
+4ia
+6l
+6mb
+8i
+9c
+9cs
+8s
+8us
+9ses
+5c
+5ne
+7s
+6g
+5oallantoic
+9antois
+6carcinoma
+6id
+8s
+6n
+7ic
+7s
+5sation
+9ons
+6es
+6is
+6m
+7s
+6t
+7er
+9s
+7s
+5zation
+9ons
+6o
+7nt
+9ist
+9ists
+9s
+7s
+4ographer
+9hers
+9hic
+9hical
+9hies
+9hy
+5id
+7al
+7itis
+9ises
+7s
+5logical
+9es
+9st
+9sts
+8y
+5pleth
+9hs
+4rie
+7s
+4ten
+7s
+5le
+7d
+7r
+8s
+7s
+6ing
+4us
+6ed
+7s
+6ing
+6master
+9ters
+6sed
+8s
+7ing
+3se
+5n
+5s
+3ta
+4t
+5s
+3u
+4croute
+9es
+4gh
+6s
+4ltries
+7y
+4nter
+8ed
+8ing
+8s
+4se
+6d
+6r
+7s
+6s
+5h
+6es
+5ing
+4t
+5s
+4x
+3w
+4chow
+8s
+4der
+7ed
+7head
+9aded
+9ads
+7ing
+7s
+4ed
+4hound
+9s
+4ing
+4k
+5idar
+9s
+5s
+4ri
+6es
+6s
+5y
+4s
+5e
+6d
+6s
+5ing
+4time
+8s
+2rematist
+9tic
+9tics
+9ts
+4sard
+8s
+5tomathic
+9thical
+9thies
+9thy
+3ism
+6a
+7l
+8s
+7tion
+9ons
+8ories
+9ry
+6on
+8s
+6s
+5om
+7s
+5tcross
+9sses
+6en
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+6ian
+9ia
+9ias
+9s
+7e
+8s
+6om
+8s
+7phanies
+9any
+6y
+3oma
+6ffin
+6key
+9s
+6s
+6te
+8s
+7ic
+9ally
+9ism
+9isms
+9ities
+9ity
+9ness
+9nesses
+9s
+8d
+9s
+8n
+9ic
+9s
+8st
+9ts
+7ogram
+9rams
+9raph
+9raphed
+9rapher
+9raphic
+9raphs
+9raphy
+8id
+8logies
+9ogist
+9ogists
+9ogy
+9yses
+9ysis
+9ytic
+8phore
+9hores
+9horic
+9horous
+9sia
+9sias
+8sphere
+9pheres
+7ype
+9es
+5e
+6d
+6l
+7s
+6ne
+8s
+6s
+5ic
+6de
+8s
+7ia
+8um
+6er
+7st
+6nance
+9ces
+7g
+8s
+6se
+8d
+8s
+7ing
+6te
+8s
+6um
+8s
+6ze
+8d
+8s
+7ing
+5o
+6center
+9ters
+6dynamics
+6gen
+9ic
+9s
+7ram
+9ms
+6mere
+9es
+9ic
+6nema
+9al
+9ata
+9atic
+9ic
+6phil
+9lic
+8obe
+9re
+9res
+9ric
+9rous
+7last
+9sts
+7rotein
+9teins
+6s
+7cope
+9pes
+7omal
+9ally
+9e
+9es
+7phere
+9eres
+9eric
+6therapies
+9rapy
+7ype
+9es
+6us
+6xylograph
+5y
+6l
+7s
+4naxie
+9s
+7y
+5ic
+7al
+9ly
+7ities
+9y
+7le
+9d
+9r
+9rs
+9s
+8ing
+7s
+5obiologic
+9logies
+9logist
+9logy
+6gram
+9mmatic
+9ms
+9ph
+9pher
+9phers
+9phic
+9phies
+9phs
+9phy
+6loger
+9ers
+9ic
+9ical
+9ically
+9ies
+9ise
+9ised
+9ises
+9ising
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+9y
+6meter
+9ers
+9ric
+9rical
+9ries
+9ry
+6n
+7s
+6scope
+9pes
+9pic
+6therapies
+9rapy
+7ron
+9ns
+3ysalid
+9al
+9es
+9s
+8s
+9es
+6nth
+9emum
+9emums
+9s
+6robin
+9ins
+5oberyl
+9yls
+6colla
+9las
+7racies
+9cy
+6lite
+9es
+9ic
+6melid
+9ids
+6phan
+9ns
+8ilite
+9lites
+8yte
+9tes
+7rase
+9ses
+6tile
+9es
+2thonian
+7c
+2ub
+4asco
+8s
+4bier
+7st
+6ly
+6ness
+9ses
+5y
+4s
+3ck
+5awalla
+9las
+5ed
+6r
+7s
+5hole
+9s
+5ie
+7s
+6ng
+5le
+7d
+7head
+9aded
+9ads
+7r
+8s
+7s
+8ome
+6ing
+9ly
+9s
+5s
+5walla
+9as
+5y
+3ddah
+7s
+6r
+7s
+5er
+7s
+5ies
+5y
+3fa
+5s
+4f
+5ed
+6r
+6st
+5ier
+7st
+6ness
+9ses
+7g
+5s
+5y
+3g
+4alug
+8ged
+9ing
+8s
+4ged
+6r
+7s
+5ing
+4s
+3kar
+6s
+4ka
+6r
+7s
+6s
+5er
+7s
+4or
+6s
+3m
+4ash
+7es
+7im
+4ley
+7s
+4mage
+8s
+5ed
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5y
+4p
+5ed
+5ing
+8s
+5s
+4s
+5hip
+8s
+3nder
+7ed
+7ing
+7ous
+7s
+4k
+5ed
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5s
+5y
+4nel
+7s
+6r
+7ed
+7ing
+7s
+4ter
+7ed
+7ing
+7s
+3pati
+7s
+6ti
+8es
+8s
+7y
+4pa
+6h
+7s
+6s
+5ot
+7h
+4rassies
+8y
+3r
+4ch
+6ed
+7s
+6goer
+9rs
+8ing
+9ngs
+6ianities
+9ity
+7er
+8st
+7ng
+9s
+7sm
+9s
+6less
+7ier
+9st
+8ness
+9esses
+7y
+6man
+9ly
+9ship
+9ships
+7en
+6people
+6ward
+9den
+9dens
+9ds
+8y
+9s
+7oman
+9en
+6y
+7ard
+9ds
+4idar
+8s
+5nga
+8s
+4l
+5ish
+8ly
+8ness
+9esses
+5s
+4n
+5ed
+6r
+7s
+5ing
+8s
+5milk
+9s
+5s
+4r
+5ed
+5igueresco
+9resque
+6ng
+5o
+6s
+5s
+5us
+7es
+3se
+5s
+4ing
+3t
+4e
+5d
+5s
+4ing
+5st
+7s
+4nee
+7s
+6y
+7s
+4zpa
+7h
+8s
+7s
+2yack
+6ed
+6ing
+6s
+3laceous
+4de
+4e
+5s
+4iferous
+6ication
+9tions
+7ed
+8s
+6y
+7ing
+4omicron
+9ons
+5us
+4uria
+8s
+3me
+5s
+4ic
+6s
+5ferous
+6ication
+9tions
+7ed
+8s
+6y
+7ing
+5st
+7ries
+8y
+7s
+4osin
+8s
+5trypsin
+9sins
+9tic
+5us
+3nd
+3pre
+6s
+3trid
+7s
+1iabatta
+8s
+7e
+3o
+2bachrome
+9es
+4tion
+8s
+3ol
+5s
+4ria
+6um
+4ule
+7s
+2cada
+6e
+6s
+5ellid
+9ds
+4la
+6s
+5e
+4trice
+9s
+8hule
+9ules
+8ial
+8le
+9es
+8ose
+8ula
+9las
+7sant
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7x
+8es
+7zant
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+3elies
+5y
+4ro
+6ne
+8d
+8ing
+8s
+7i
+6s
+3hlid
+7ae
+7s
+5oid
+4oraceous
+3innus
+8es
+4sbei
+8sm
+9ms
+7o
+8s
+3laton
+8s
+7un
+9s
+4osporin
+9ins
+3oree
+7s
+3uta
+6s
+5ine
+8s
+2d
+3aris
+7es
+3e
+4d
+4r
+5kin
+8s
+5s
+5y
+4s
+3ing
+3s
+2el
+4ed
+4ing
+7s
+4s
+3rge
+6s
+2g
+3ar
+5et
+7s
+7te
+9s
+5illo
+9s
+5like
+5s
+3gie
+6s
+4y
+3s
+3uatera
+9s
+2lantro
+8s
+3ia
+5ry
+5te
+7d
+7ly
+7s
+6ion
+9s
+4ce
+6s
+5ious
+4olate
+4um
+3l
+4s
+2mar
+5s
+3balom
+8s
+3elia
+4tidine
+9es
+4x
+3ices
+4er
+6s
+4nite
+8s
+3merian
+3olite
+8s
+2nch
+5ed
+6s
+5ing
+8s
+5ona
+8ceous
+8s
+7ic
+8dine
+9ines
+8ne
+9es
+9ic
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+4innate
+7us
+9es
+4t
+5ure
+8d
+8s
+7ing
+3der
+6ed
+6ing
+6ous
+6s
+6y
+3e
+4angiography
+5st
+7e
+8s
+7s
+4ma
+6goer
+9rs
+6s
+6theque
+9ques
+7ic
+9ally
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7ograph
+9raphed
+9rapher
+9raphic
+9raphs
+9raphy
+5icrography
+4ol
+6e
+7s
+6s
+4phile
+9s
+5lex
+8es
+4ramic
+6ria
+9s
+8um
+7y
+6tion
+9ns
+7or
+9s
+5ea
+7l
+7s
+6ous
+5in
+7s
+6tious
+4s
+3gula
+7r
+7te
+9d
+6um
+3nabar
+8ic
+9ne
+8s
+5mic
+6on
+8ic
+8s
+8y
+6yl
+8s
+5rizine
+9nes
+3quain
+8s
+5e
+6centist
+9tisti
+9tists
+9to
+9tos
+6foil
+9ls
+6s
+2on
+4s
+3ppino
+8s
+2pher
+6ed
+7r
+8s
+6ing
+9s
+6s
+6text
+9ts
+4onies
+6y
+3olin
+7s
+5lino
+9s
+3pi
+4us
+3rofloxacin
+9acins
+2rca
+5dian
+5r
+6s
+5ssian
+9ns
+8enne
+9nnes
+4ensial
+9n
+4inate
+9ly
+5ter
+4le
+6d
+6r
+7s
+6s
+6t
+7s
+5ing
+8s
+6p
+7s
+4s
+4uit
+7al
+7ed
+8er
+9rs
+7ies
+8ng
+7ous
+9sly
+9sness
+7ries
+8y
+7s
+7y
+5lable
+7r
+8isation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9ties
+9ty
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8ly
+8ness
+9esses
+8s
+7table
+8e
+9d
+9s
+8ing
+9ngs
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+5mambages
+9agious
+9ience
+9iences
+9iency
+9ient
+9iently
+9ulate
+9ulated
+9ulates
+9ulator
+6bendibus
+6center
+9ters
+9tre
+9tres
+7ircle
+9cles
+8se
+9ed
+9er
+9ers
+9es
+9ing
+9ion
+9ions
+6duce
+9ed
+9es
+9ing
+9t
+9ted
+9ting
+9tion
+9tions
+9tory
+9ts
+6ference
+9ences
+9ential
+9entor
+9entors
+7lect
+9cted
+9cting
+9cts
+9x
+9xes
+9xion
+9xions
+8uence
+9ences
+9ent
+9ous
+7oranean
+9aneous
+7use
+9ed
+9es
+9ile
+9ing
+9ion
+9ions
+6gyrate
+9ated
+9ates
+9ating
+9ation
+9ations
+9atory
+6incession
+8session
+6jacencies
+9ency
+9ent
+6littoral
+7ocute
+9uted
+9utes
+9uting
+9ution
+9utions
+9utory
+7unar
+6mure
+9ed
+9es
+9ing
+6navigable
+9igate
+9igated
+9igates
+9igator
+7utate
+9ated
+9ates
+9ating
+9ation
+9ations
+9atory
+6polar
+8se
+9ed
+9es
+9ing
+9ition
+9itions
+6scissile
+8ribable
+9ibe
+9ibed
+9iber
+9ibers
+9ibes
+9ibing
+9iption
+9iptive
+7olar
+7pect
+9ction
+9ctions
+9ctive
+9ctly
+9ctness
+7tance
+9nced
+9nces
+9ncing
+9ntial
+9ntials
+9ntiate
+8ellar
+6vallate
+9lated
+9lates
+9lating
+9lation
+7ent
+9ted
+9ter
+9ters
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+9ts
+7olution
+9utions
+9utory
+9ve
+9ved
+9ves
+9ving
+5s
+6es
+6sy
+6y
+3e
+4s
+3l
+4s
+3que
+6s
+3rate
+4hipede
+9es
+5osed
+8s
+7is
+6tic
+9s
+4i
+5form
+5grade
+5ped
+8e
+9s
+8s
+4ocumuli
+9lus
+5se
+6trati
+9tive
+9tus
+5us
+4us
+3soid
+2s
+3alpine
+3co
+5es
+5s
+3eleur
+8s
+5ure
+8s
+3lunar
+3montane
+3padane
+4latin
+9s
+4ontine
+3sier
+6s
+7t
+5fied
+5ng
+7s
+4oid
+7s
+4us
+6es
+4y
+3t
+4aceous
+4ed
+5rn
+7a
+8e
+8l
+7s
+4ic
+4ron
+7ic
+7s
+4s
+4us
+6es
+4vaen
+8s
+2t
+3able
+4del
+7s
+4l
+5s
+4tion
+8al
+8s
+5or
+7s
+7y
+3e
+4able
+4d
+4r
+5s
+4s
+5s
+6es
+3hara
+7s
+6ist
+9ic
+9s
+4er
+6n
+7s
+6s
+4ren
+7s
+3ied
+5s
+4fication
+9ions
+6ed
+7s
+5y
+6ing
+4grade
+4ng
+4zen
+7ess
+9ses
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7ly
+7ries
+8y
+7s
+8hip
+9ips
+3o
+4la
+6s
+5e
+6s
+3ral
+6s
+5nge
+8s
+5te
+7d
+7s
+4eous
+4ic
+6ulture
+9ures
+9urist
+9urists
+5n
+6e
+7s
+6in
+8s
+6s
+4on
+6ella
+9al
+9als
+9as
+9ol
+9ols
+6s
+5us
+4ulline
+9es
+5s
+6es
+6sy
+6y
+3s
+3tern
+7s
+3y
+4fication
+9ions
+6ed
+7s
+5y
+6ing
+4scape
+9s
+4ward
+5ide
+2ve
+4s
+4t
+5like
+5s
+3ic
+5ally
+5ism
+8s
+5s
+4e
+5s
+4l
+5ian
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+6sable
+8tion
+9ional
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7t
+8s
+6ties
+7y
+6zable
+8tion
+9ional
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5ly
+5ness
+9es
+5s
+4sm
+6s
+3vies
+4y
+2zers
+1labber
+7ed
+7ing
+7s
+3ch
+5an
+7s
+5s
+4k
+5box
+8es
+5dish
+9es
+5ed
+6r
+7s
+5ing
+5s
+3d
+4dagh
+8s
+5ed
+6r
+7s
+5ie
+7s
+6ng
+8s
+4e
+5s
+4ism
+7s
+6t
+7ic
+9ally
+9s
+7s
+4oceran
+9ns
+5de
+7s
+6ial
+5geneses
+9sis
+9tic
+6ram
+9s
+5phyll
+9la
+9ls
+9lum
+5sporia
+9ium
+9iums
+4s
+3es
+3fouti
+8s
+3g
+4ged
+5ier
+7st
+6ng
+5y
+4s
+3im
+5able
+6nt
+8s
+5ed
+6r
+7s
+5ing
+5s
+4raudience
+9ences
+9ent
+9ently
+9ents
+5colle
+9es
+5schach
+9chs
+5voyance
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9nts
+3m
+4ancies
+7y
+6t
+7ly
+5torial
+4bake
+8s
+5e
+6r
+7ed
+8r
+9s
+7ing
+7s
+4e
+5s
+4jamfries
+9y
+7phrie
+9ries
+4like
+4med
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5y
+4or
+6ed
+7r
+8s
+6ing
+6ous
+9ly
+9ness
+9nesses
+6s
+5ur
+7ed
+8r
+9s
+7ing
+7s
+4p
+5down
+9s
+5ed
+6r
+7ed
+7ing
+7s
+5ing
+5s
+4s
+5hell
+9s
+4worm
+8s
+3n
+4destine
+9nely
+9neness
+9nities
+9nity
+4g
+5box
+8es
+5ed
+6r
+7s
+5ing
+8s
+5or
+7ed
+7ing
+7ous
+9sly
+7s
+6ur
+8ed
+8ing
+8s
+5s
+4jamfray
+9ays
+4k
+5ed
+5ier
+7st
+6ng
+8ly
+8s
+5s
+5y
+4nish
+8ly
+8ness
+9esses
+4s
+5hip
+8s
+5man
+6en
+5woman
+8en
+3p
+4board
+9ed
+9ing
+9s
+5read
+9s
+4dish
+8es
+4net
+7s
+4ometer
+9rs
+4ped
+6r
+7board
+9ards
+9y
+9ys
+7claw
+9awed
+9awer
+9awers
+9awing
+9aws
+7ed
+7ing
+9gs
+7s
+5ing
+8s
+4s
+4t
+5rap
+8peries
+9ery
+8s
+3que
+6r
+7s
+6s
+6ur
+8s
+3rabella
+9as
+5in
+7s
+4ence
+8s
+6don
+9s
+5t
+6ed
+6ing
+6s
+4ibella
+9as
+5chord
+9ds
+5es
+5fication
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5net
+8ist
+9sts
+8s
+8tist
+9ists
+6i
+6o
+7s
+5on
+7ed
+8t
+9s
+7ing
+7s
+5ties
+6y
+4kia
+7s
+4o
+5es
+5s
+4sach
+8s
+4t
+5ed
+5head
+9s
+5ier
+7st
+6ng
+5s
+5y
+4y
+3sh
+5ed
+6r
+7s
+6s
+5ing
+8ly
+8s
+4p
+5ed
+6r
+7s
+5ing
+8s
+5s
+5t
+4s
+5able
+5ed
+6r
+7s
+6s
+5ible
+6c
+7al
+9ism
+9isms
+9ist
+9ists
+9ities
+9ity
+9ly
+9ness
+9nesses
+9s
+7ise
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ze
+9ed
+9es
+9ing
+7o
+7s
+6er
+7st
+6fiable
+8c
+9ation
+9ations
+9atory
+8ed
+9r
+9rs
+9s
+7y
+8ing
+6ly
+6ness
+9ses
+7g
+8s
+6s
+7m
+8s
+7t
+8s
+5less
+9ness
+9nesses
+5man
+7te
+9s
+6en
+5on
+7s
+5room
+9s
+5work
+9s
+5y
+4t
+5ic
+7s
+5s
+3t
+4ch
+6ed
+7s
+6ing
+4hrate
+9s
+4s
+4ted
+6r
+7ed
+8r
+9s
+7ing
+9gly
+7s
+7y
+5ing
+3ucht
+7ed
+7ing
+7s
+4dication
+9ions
+4ght
+7ed
+7ing
+7s
+4sal
+5e
+6s
+5tra
+8l
+8tion
+9ions
+7ophobe
+9hobes
+9hobia
+9hobias
+9hobic
+7um
+5ula
+8e
+8r
+4t
+5ed
+5ing
+5s
+3vate
+7d
+7ly
+6ion
+9s
+4e
+5cin
+8ist
+9sts
+8s
+5r
+6ed
+6ing
+6s
+5s
+4i
+5cembalo
+9alos
+6hord
+9dist
+9dists
+9ds
+6le
+8s
+6orn
+9s
+6ula
+9e
+9r
+9te
+6ytheria
+9erium
+5e
+6r
+7ist
+9tic
+9ts
+7s
+6s
+5form
+5ger
+8ous
+8s
+5s
+4ulate
+5s
+3w
+4back
+8s
+4ed
+5r
+6s
+4hammer
+4ing
+4less
+5ike
+4s
+3xon
+6s
+3y
+4bank
+8s
+4ed
+5y
+4ier
+6st
+5ng
+5sh
+4like
+4mation
+9ns
+5ore
+8s
+4pan
+7s
+4s
+5tone
+9s
+4tonia
+9s
+4ware
+8s
+2ean
+5abilities
+9ity
+7le
+5ed
+6r
+7s
+6st
+5handed
+5ing
+8s
+5lier
+8st
+7ly
+7ness
+9sses
+6y
+5ness
+9es
+5s
+6able
+6e
+7d
+7r
+8s
+7s
+6ing
+9s
+6kin
+9s
+5up
+7s
+4r
+5able
+6ge
+8s
+6nce
+9s
+5cole
+9d
+9s
+8ing
+6ut
+8s
+8ting
+5ed
+6r
+7s
+6st
+6yed
+5headed
+9edly
+9edness
+5ing
+8house
+9ouses
+8s
+5ly
+5ness
+9es
+5s
+6kin
+9s
+6toried
+9ies
+9y
+5way
+8s
+6eed
+9s
+6ing
+9s
+4t
+5ed
+5ing
+5s
+4vabilities
+9ity
+7le
+9ness
+9nesses
+6ge
+8s
+5e
+6d
+6r
+7s
+6s
+5ing
+8s
+3che
+4k
+5ed
+5ier
+7st
+6ng
+8s
+5s
+5y
+3ek
+5ed
+5ing
+6t
+5s
+4p
+5ed
+5ing
+5s
+4ve
+6s
+3f
+4s
+4t
+5ed
+5ing
+5s
+3g
+4s
+3idoic
+4k
+5s
+4stogamic
+9mies
+9mous
+9mously
+9my
+4thral
+3m
+4atis
+8es
+4encies
+7y
+6t
+7ine
+9es
+7ly
+4med
+5ing
+4s
+3nbuterol
+9ols
+4ch
+6ed
+7r
+8s
+7s
+6ing
+3ome
+6s
+4patra
+9s
+3pe
+5d
+5s
+4ing
+4sydra
+9e
+9s
+4t
+5ocracies
+9cy
+6mania
+9iac
+9iacs
+9ias
+3restoried
+9ies
+9y
+4giable
+6es
+5y
+6able
+6man
+7en
+6woman
+9en
+4ic
+6al
+8ism
+9sms
+9st
+9sts
+8ly
+8s
+7te
+9s
+6ities
+8y
+6s
+5d
+6s
+5hew
+8s
+5sies
+6y
+4k
+5dom
+8s
+5ed
+6ss
+8es
+5ing
+6sh
+5lier
+8st
+7ke
+7ness
+9sses
+8g
+9s
+6y
+5s
+6hip
+9s
+4omancies
+9y
+4uch
+7ia
+9l
+9s
+8es
+7s
+7y
+3uch
+6s
+4gh
+6s
+3ve
+5ite
+8s
+5r
+6alities
+9ty
+6er
+7st
+6ish
+6ly
+6ness
+9ses
+5s
+4is
+6es
+3w
+4ed
+4ing
+4s
+2ianthus
+9es
+3che
+6d
+6ed
+6s
+4k
+5able
+5ed
+6r
+7s
+6t
+7ed
+7ing
+7s
+5ing
+8s
+5less
+5s
+6tream
+9ams
+5wrap
+9s
+3ed
+4nt
+6age
+9s
+7l
+6ele
+9s
+6less
+6s
+7hip
+9ps
+4s
+3ff
+5ed
+5hang
+9er
+9ers
+9ing
+9ings
+9s
+6ung
+5ier
+7st
+5like
+5s
+5y
+4t
+5ed
+5ier
+7st
+5s
+5y
+3macteric
+9ical
+9ically
+9ics
+7ic
+9al
+9ally
+5tal
+6e
+7d
+7s
+6ic
+8al
+9lly
+7ng
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6ographies
+9aphy
+7logic
+9gical
+9gies
+9gist
+9gists
+9gy
+6ure
+9s
+5x
+6ed
+7s
+6ing
+6less
+4b
+5able
+5down
+9s
+5ed
+6r
+7s
+5ing
+8s
+5s
+4e
+5s
+3nal
+6ly
+5men
+8s
+5ndria
+9um
+4ch
+6ed
+7r
+8s
+7s
+6ing
+9ly
+4damycin
+9ins
+4e
+5s
+4g
+5ed
+6r
+7s
+5film
+9s
+7sh
+9es
+5ier
+7st
+6ness
+9ses
+7g
+8ly
+8ness
+9esses
+5s
+6tone
+9es
+5y
+4ic
+6al
+8ly
+8ness
+9esses
+6ian
+9s
+6s
+5que
+8s
+4k
+5ed
+6r
+7ed
+7ing
+7s
+5ing
+5s
+6tone
+9es
+4oaxes
+7is
+5chlore
+9res
+5diagonal
+9onals
+5meter
+9rs
+8ric
+9ical
+9ies
+9y
+5pinacoid
+9coids
+9koid
+9koids
+6yroxene
+9xenes
+5stat
+9s
+4quant
+9s
+4t
+5onia
+9s
+5s
+3ometric
+9cal
+9cian
+9cians
+9cs
+3p
+4art
+7s
+4board
+9s
+4e
+5d
+5s
+4ing
+4pable
+5ed
+6r
+7s
+5ie
+7s
+6ng
+8s
+4s
+5hear
+9s
+7et
+9s
+4t
+3que
+6d
+6s
+6y
+5ier
+7st
+6ness
+9ses
+7g
+6sh
+8ly
+8ness
+9esses
+7m
+8s
+5y
+3shmaclaver
+9avers
+4togamies
+9y
+3tella
+8r
+7um
+4hral
+4ic
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6s
+4ter
+7ed
+7ing
+7s
+3vers
+4ia
+6s
+2oaca
+6e
+6l
+7ine
+6s
+5inal
+6tis
+9es
+4k
+5ed
+5ing
+5room
+9s
+5s
+4m
+5s
+3bber
+7ed
+7ing
+7s
+3chard
+8s
+5e
+6s
+4k
+5ed
+6r
+7s
+5ing
+8s
+5like
+5maker
+9rs
+5s
+5wise
+6ork
+9s
+3d
+4ded
+5ier
+7st
+6ng
+6sh
+8ly
+8ness
+9esses
+5y
+4hopper
+9rs
+8ing
+4ly
+4pate
+8d
+8s
+5ole
+8s
+7l
+8s
+4s
+3ff
+5s
+4ibrate
+9es
+3g
+4dance
+9s
+4ged
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5y
+4s
+3ison
+7nage
+9ges
+8e
+9s
+7s
+5ter
+8ed
+9r
+9rs
+8ing
+8s
+6ral
+7ess
+9ses
+3ke
+5d
+5s
+4ing
+3mb
+4iphene
+9es
+4p
+5ed
+5ing
+5s
+3n
+4al
+6ly
+5zepam
+9ms
+4e
+5d
+5r
+6s
+5s
+4ic
+6ities
+8y
+5dine
+9s
+5ng
+7s
+5sm
+7s
+4k
+5ed
+5ing
+5s
+4s
+4us
+6es
+3op
+5s
+4t
+5ie
+5s
+3p
+4ped
+5ing
+4s
+3que
+6s
+3sable
+4e
+5able
+5d
+6own
+9s
+5fisted
+5head
+9s
+5ly
+5mouthed
+5ness
+9es
+5out
+8s
+5r
+6s
+5s
+6t
+7ool
+9ls
+5t
+6ed
+6ful
+9s
+6ing
+6s
+5up
+7s
+4ing
+7s
+4tridia
+9al
+9an
+9um
+9ums
+4ure
+7d
+7s
+6ing
+3t
+4bur
+7s
+4e
+5s
+4h
+5bound
+5e
+6d
+6s
+7horse
+9rses
+7line
+9ned
+9nes
+9ning
+7pin
+9ns
+8ress
+9esses
+5ier
+8s
+6ng
+8s
+5like
+5s
+4poll
+8s
+4s
+4ted
+6r
+7ed
+7ing
+7s
+5ier
+7st
+6ness
+9ses
+7g
+8s
+6sh
+5y
+4ure
+7d
+7s
+6ing
+3u
+4d
+5age
+8s
+5berries
+9y
+6urst
+9ts
+5ed
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5land
+9s
+6ess
+9ly
+9ness
+9nesses
+7t
+8s
+6ike
+5s
+6cape
+9es
+5town
+9s
+5y
+4gh
+6s
+4r
+5ed
+5ing
+5s
+4s
+4t
+5ed
+6r
+7ly
+7s
+5ing
+5s
+3ve
+5n
+5r
+6ed
+6grass
+9sses
+6leaf
+9fs
+9ves
+6s
+6y
+5s
+4is
+3w
+4der
+7s
+4n
+5ed
+6ries
+7y
+5fish
+9es
+5ing
+8s
+6sh
+8ly
+8ness
+9esses
+5s
+4s
+3xacillin
+9ins
+3y
+4e
+5d
+5s
+4ing
+7ly
+4less
+4ment
+8s
+4s
+5ome
+3zapine
+9s
+4e
+5s
+2ub
+4abilities
+9ty
+6le
+4babilities
+9ity
+7le
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+6sh
+7m
+8s
+7t
+8s
+5y
+4face
+8s
+5eet
+5oot
+8ed
+4hand
+8s
+6ul
+8ed
+8ing
+8s
+5ead
+8s
+5ouse
+9s
+4land
+8s
+4man
+7ship
+9ips
+6ster
+9rs
+5en
+4room
+8s
+7t
+8s
+5ush
+8es
+4s
+4woman
+7en
+3ck
+5ed
+5ier
+7st
+6ng
+5s
+5y
+3dgie
+7s
+3e
+4d
+4ing
+4less
+4s
+3ing
+3mber
+7s
+4p
+5ed
+6r
+7s
+5ier
+7st
+6ness
+9ses
+7g
+6sh
+5like
+5s
+5y
+4sier
+7st
+6ly
+6ness
+9ses
+5y
+3nch
+6es
+4g
+4k
+5ed
+6r
+7s
+5ier
+7st
+6ng
+5s
+5y
+3peid
+7s
+5oid
+8s
+3sia
+6s
+4ter
+7ed
+7ing
+9gly
+7s
+7y
+3tch
+6ed
+7s
+6ing
+6y
+4ter
+7ed
+7ing
+7s
+7y
+2y
+3ing
+3pe
+5al
+6te
+5d
+5i
+6form
+5s
+5us
+4ing
+3ster
+7s
+1nemial
+5des
+5s
+2ida
+5e
+5rian
+9s
+4oblast
+9ts
+1oacervate
+9ed
+9es
+9ing
+9ion
+9ions
+4h
+5able
+5builder
+9ders
+9ding
+9dings
+9t
+5dog
+8s
+5ed
+6e
+7s
+6r
+7s
+6s
+5ier
+7s
+8t
+6ng
+8s
+5line
+9s
+6oad
+9s
+5man
+6en
+5whip
+9s
+6ood
+9s
+7rk
+9s
+5y
+4t
+5ed
+5ing
+6on
+8s
+6ve
+8ly
+7ities
+9y
+5or
+7s
+5s
+3daptation
+9ions
+7ed
+4jacencies
+9cy
+9t
+5utant
+9ts
+7or
+9s
+9ship
+9ships
+7ress
+9sses
+8ices
+9x
+9xes
+4mire
+8d
+8s
+7ing
+6t
+7s
+7ted
+8ing
+4unate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+3eval
+7s
+3gencies
+7y
+6t
+7s
+4ula
+7bilities
+9lity
+8le
+7nt
+9s
+7se
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+6um
+8s
+3ita
+6s
+3l
+4a
+5s
+4ball
+8s
+5in
+7s
+5ox
+7es
+4ed
+5r
+6s
+5sce
+8d
+8nce
+9ces
+9t
+8s
+7ing
+4face
+8s
+5ield
+9s
+6sh
+8es
+4hole
+8s
+6use
+9s
+4ier
+6st
+5fication
+9tions
+7ed
+8s
+6y
+7ing
+5ng
+5se
+7d
+7s
+6ing
+5tion
+9al
+9er
+9ers
+9ism
+9isms
+9ist
+9ists
+9s
+5ze
+7d
+7s
+6ing
+4less
+4man
+6ster
+9rs
+5en
+5ine
+8r
+9s
+8s
+4pit
+7s
+4s
+5ack
+8s
+5hed
+8s
+4y
+5ard
+8s
+3ming
+7s
+3nchor
+8ed
+8ing
+8s
+4nex
+7ed
+8s
+7ing
+3ppear
+8ed
+8ing
+8s
+4t
+5ation
+9ns
+5ed
+5ing
+5s
+3rb
+5s
+4ctate
+9d
+9s
+8ing
+9on
+9ons
+4se
+6ly
+6n
+7ed
+8ss
+9ses
+7ing
+7s
+6r
+6st
+5ish
+3ssist
+8ed
+8ing
+8s
+5ume
+8d
+8s
+7ing
+4t
+5al
+7ly
+5ed
+6ering
+9ngs
+6r
+7s
+5guard
+9dman
+9dmen
+9ds
+9dsman
+9dsmen
+5ing
+8s
+5land
+9s
+6ine
+9s
+5s
+5ward
+9s
+6ise
+3t
+4dress
+9es
+4e
+5d
+5e
+6s
+5r
+6s
+5s
+4i
+5mundi
+9is
+5ng
+7s
+5s
+4less
+4rack
+8s
+5oom
+8s
+4s
+5tand
+9s
+4tail
+8s
+5end
+8ed
+8ing
+8s
+6st
+8ed
+8ing
+8s
+3uthor
+8ed
+8ing
+8s
+9hip
+9hips
+3x
+4al
+4ed
+5r
+6s
+5s
+4ial
+7ly
+5ng
+7ly
+2b
+3aea
+6s
+4lamin
+9s
+5t
+6ic
+7ferous
+7ne
+9s
+7te
+9s
+6ous
+6s
+3b
+4ed
+5r
+6s
+4ier
+6st
+5ng
+4le
+6d
+6r
+7ies
+7s
+7y
+6s
+7tone
+9ned
+9nes
+9ning
+5ing
+8s
+4s
+4y
+3elligerent
+9rents
+3ia
+5s
+3le
+5s
+4oaf
+6ves
+3nut
+6s
+3ra
+5s
+4ic
+5form
+3s
+3urg
+6s
+3web
+6bed
+8ries
+9y
+7ier
+9st
+8ng
+7y
+6s
+3za
+5s
+2ca
+4in
+6e
+7s
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+4ptain
+9ed
+9ing
+9s
+4rboxylase
+9lases
+5cinogen
+9genic
+9gens
+4s
+4talyst
+9ts
+3cal
+4i
+5c
+5d
+6ia
+7oses
+9is
+9tat
+9tats
+7um
+6s
+5ferous
+5neous
+4o
+5id
+7al
+7s
+5lite
+9s
+8h
+9s
+5s
+5us
+4us
+4ygeal
+7s
+6ian
+5x
+6es
+3h
+4air
+7ed
+7ing
+7man
+8en
+7person
+9rsons
+7s
+7woman
+9men
+5mpion
+9ns
+4es
+4in
+6eal
+9s
+6s
+4lea
+7e
+7r
+8e
+9s
+8iform
+8s
+7s
+7te
+9d
+3inera
+8s
+3kabullies
+9y
+5de
+7d
+7s
+5leekie
+9ies
+6orum
+9ms
+5mamie
+8y
+5poo
+8s
+5teel
+9s
+6iel
+9s
+6oo
+8s
+6rice
+9es
+4bill
+8ed
+8ing
+8s
+6rd
+8s
+5oat
+8s
+4chafer
+9rs
+5row
+8ing
+9ngs
+8s
+4ed
+5r
+6ed
+7l
+8s
+6ing
+6nonies
+9y
+6s
+5t
+6s
+5ye
+7d
+8ly
+8ness
+9esses
+7s
+4fight
+9ing
+9ings
+9s
+4horse
+9s
+4ieleekie
+9kies
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+5sh
+4le
+6boat
+9ts
+7ur
+9s
+6d
+6ert
+9s
+6man
+7en
+6r
+7s
+6s
+7hell
+9lls
+5ike
+6ng
+8s
+5oft
+8s
+4match
+9es
+4ney
+7dom
+9ms
+7fication
+9ed
+9es
+8y
+9ing
+7ish
+9m
+9ms
+7s
+5ification
+9ations
+8ed
+9s
+7y
+8ing
+4pit
+7s
+4roach
+9es
+4scomb
+9s
+5foot
+9s
+5hies
+6ot
+8s
+6ut
+8s
+6y
+5ier
+7st
+6ness
+9ses
+5pur
+8s
+5ure
+8ly
+8ness
+9esses
+5wain
+9ed
+9ing
+9s
+5y
+4tail
+8ed
+8ing
+8s
+5easer
+9rs
+5hrowing
+9ings
+4up
+6s
+4y
+5leekies
+9y
+3o
+4a
+5nut
+8s
+5s
+4bola
+8s
+7o
+8s
+4mat
+7s
+5poser
+9rs
+4nscious
+9uses
+9usness
+6pirator
+9ators
+5ut
+7s
+4on
+6ed
+7ries
+8y
+6ing
+9s
+6s
+4pan
+7s
+5lum
+8s
+4s
+4tte
+7s
+4unsel
+9ed
+9ing
+9led
+9ling
+9s
+4yam
+7s
+4zelle
+9s
+3reate
+8d
+8s
+7ing
+7or
+9s
+3tile
+5on
+7s
+3ultivate
+9ted
+9tes
+9ting
+9tion
+9tions
+6ure
+9d
+9s
+8ing
+4rator
+9s
+5ricular
+4swood
+9s
+2d
+3a
+4ble
+4s
+3ded
+5r
+6s
+4ing
+4le
+6d
+6r
+7s
+6s
+5ing
+3e
+4book
+8s
+5tor
+8s
+4c
+5lination
+9tions
+5s
+4d
+4fendant
+9nts
+4ia
+6s
+5n
+6a
+7s
+6e
+7s
+6s
+4less
+4n
+5ame
+8s
+5s
+4pendence
+9nces
+9ncies
+9ncy
+9nt
+9nts
+4r
+5ive
+8d
+8s
+7ing
+5s
+4s
+5ign
+8ed
+8ing
+8s
+4termination
+5ta
+7s
+4velop
+9ed
+9er
+9ers
+9ing
+9s
+4word
+8s
+4x
+3fish
+7es
+3ger
+6s
+3ices
+5il
+7lary
+7s
+5ological
+9ies
+9y
+4fiabilities
+9lity
+6cation
+9ions
+6ed
+7r
+8s
+7s
+5y
+6ing
+4lla
+7s
+6e
+7s
+4ng
+6s
+4rect
+8ed
+8ing
+9on
+9ons
+8or
+9rs
+8s
+4scover
+9red
+9rer
+9rers
+9ring
+9rs
+5t
+6s
+3lin
+6g
+7s
+6s
+3ologies
+7y
+4main
+8s
+5inance
+9ces
+9t
+9ts
+4n
+5s
+3piece
+8s
+3rive
+7n
+7r
+8s
+7s
+6ing
+4ove
+3s
+4wallop
+9ps
+2ed
+4it
+6ed
+6ing
+6or
+8s
+6s
+4s
+4ucation
+9onal
+9onally
+9ons
+3ffect
+8s
+5icient
+9nts
+3horn
+7s
+3lacanth
+9hic
+9hs
+5naglyphic
+4entera
+9ate
+9ates
+9ic
+9on
+4iac
+7s
+4om
+6ata
+8e
+9s
+8ic
+6e
+7s
+6ic
+6s
+5stat
+9s
+4urosaur
+9urs
+3mbodied
+9s
+7y
+8ing
+4ploy
+8ed
+8ing
+8s
+5t
+6ed
+6ing
+7on
+9s
+6s
+3nacle
+8s
+6t
+7ed
+7ing
+7s
+5estheses
+9esia
+9esias
+9esis
+5mor
+8ed
+8ing
+8s
+4dure
+8d
+8s
+7ing
+4enchyma
+9mas
+9mata
+5stheses
+9sia
+9sias
+9sis
+9tic
+4obia
+7te
+9s
+8ic
+9cal
+9sm
+9sms
+7um
+5cyte
+9s
+8ic
+5sarc
+9s
+6pecies
+6teum
+9ms
+4ure
+7s
+6i
+6us
+4zymatic
+9ically
+7e
+8s
+3qual
+7ities
+9y
+7ly
+7ness
+9sses
+7s
+6te
+8d
+8s
+7ing
+3rce
+6d
+6r
+7s
+6s
+5ible
+8y
+6meter
+9ers
+6ng
+6on
+8ist
+9sts
+8s
+6ve
+8ly
+8ness
+9esses
+7ities
+9y
+4ect
+7ed
+7ing
+7s
+3site
+7s
+4sential
+9ality
+9ally
+9alness
+3taneous
+9sly
+9sness
+4ernal
+9ly
+7ities
+9y
+3val
+6ities
+8y
+6ly
+6s
+4olution
+9onary
+9ons
+6ve
+8d
+8s
+7ing
+3xecutor
+9rs
+8rices
+9ix
+9ixes
+5rt
+7ed
+7ing
+7s
+4ist
+7ed
+8nce
+9ces
+9t
+7ing
+7s
+4tend
+8ed
+8ing
+8s
+7sion
+9ons
+9ve
+9vely
+2factor
+8s
+4vorite
+9es
+3eature
+9d
+9s
+8ing
+3f
+4ed
+5e
+6cake
+9es
+6house
+9ses
+6maker
+9ers
+6pot
+9s
+6s
+5r
+6dam
+9s
+6ed
+6ing
+6s
+4in
+6ed
+6g
+6ing
+7te
+9s
+6s
+4le
+6d
+6s
+5ing
+4ret
+7s
+4s
+3inance
+9d
+9s
+8ing
+4ring
+8s
+3ound
+7ed
+8r
+9s
+7ing
+7s
+3t
+3unction
+9ns
+2g
+3ence
+7s
+6ies
+6y
+5er
+7ation
+9ions
+9or
+9ors
+7s
+5t
+6ly
+3ged
+5r
+6s
+4ie
+6s
+5ng
+7s
+4le
+6d
+6s
+5ier
+7st
+6ng
+5y
+3ie
+5s
+4table
+6te
+8d
+8s
+7ing
+9gly
+8on
+9ns
+8ve
+9ely
+9eness
+7or
+9s
+5o
+6s
+3nac
+6s
+5te
+7ly
+7ness
+9sses
+7s
+6ion
+9s
+4isable
+9y
+7nce
+9es
+8t
+6e
+7d
+7r
+8s
+7s
+6ing
+5tion
+9al
+9s
+7ve
+9ly
+8ism
+9sms
+9ties
+9ty
+5zable
+9y
+7nce
+9es
+8t
+6e
+7d
+7r
+8s
+7s
+6ing
+4omen
+8s
+6ina
+9l
+9lly
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+5sce
+8d
+8nte
+9ti
+8s
+7ible
+8ng
+5vit
+8s
+3on
+5s
+3s
+3ue
+5s
+3way
+6s
+4heel
+8s
+2hab
+5it
+7ant
+9ts
+8tion
+9ions
+7ed
+8e
+9s
+8r
+9s
+7ing
+7s
+5s
+3ead
+6ed
+6ing
+6s
+4ir
+6ess
+9es
+6s
+4n
+5s
+4re
+6d
+6nce
+9s
+8ies
+8y
+7t
+8ly
+6r
+7s
+6s
+5ing
+6tor
+9s
+4sibilities
+9ity
+7le
+6on
+8less
+8s
+6ve
+8ly
+8ness
+9esses
+3ibit
+7ed
+7ing
+8on
+9ns
+8ve
+7s
+3o
+4bate
+8d
+8s
+7ing
+4e
+5s
+4g
+5s
+4lder
+8s
+4mological
+9ies
+9y
+4rn
+6s
+5t
+6ative
+9ves
+6s
+4s
+5h
+6es
+5t
+6ed
+7ss
+9ed
+9es
+9ing
+6ing
+6s
+4using
+9s
+3une
+6s
+3yponym
+9s
+2if
+4ed
+4fe
+6d
+6s
+6ur
+8s
+7se
+9s
+5ing
+5ure
+8d
+8s
+7ing
+4ing
+4s
+3gn
+5e
+6d
+6s
+5ing
+5s
+3l
+4abilities
+9ty
+4ed
+5r
+6s
+4ing
+4s
+3n
+4able
+5ge
+7s
+4cide
+8d
+8nce
+9ces
+9cies
+9cy
+9t
+9tal
+9tally
+9tly
+8s
+7ing
+4ed
+5r
+6s
+4fect
+8ed
+8ing
+8s
+6r
+7red
+8ing
+7s
+4here
+8d
+8nce
+9ces
+8s
+7ing
+8tance
+9ances
+9or
+9ors
+4ing
+7s
+4mate
+8s
+4op
+4s
+5tantaneity
+9aneous
+5urance
+9ces
+7e
+8d
+8r
+9s
+8s
+7ing
+4ter
+7red
+8ing
+7s
+5reau
+9s
+4vent
+8ed
+8ing
+8or
+9rs
+8s
+6stigator
+9gators
+8or
+9rs
+3r
+4s
+3strel
+8s
+6il
+8s
+3t
+4al
+6ly
+4ion
+7al
+7s
+4s
+4us
+6es
+2join
+6ed
+6ing
+6s
+4nes
+2ke
+4d
+4head
+8s
+4like
+4rnut
+8s
+4s
+5es
+3ier
+5st
+4ng
+3uloris
+9es
+3y
+2l
+3a
+4nder
+8s
+4s
+4titude
+9es
+3bies
+4y
+5s
+3cannon
+9s
+4hica
+7ine
+9es
+7um
+9s
+4othar
+9s
+3d
+4blood
+9s
+4cock
+8ed
+8ing
+8s
+4er
+5st
+4hearted
+9edly
+9edness
+5ouse
+9s
+4ie
+6s
+5sh
+4ly
+4ness
+8es
+4s
+3e
+4ad
+6er
+8s
+6ing
+6s
+4ctomies
+8y
+4d
+4manite
+9es
+4opter
+9a
+9al
+9an
+9ans
+9ist
+9ists
+9on
+9ons
+9ous
+9s
+7ile
+9es
+5rhiza
+9ae
+9as
+6rhiza
+9zae
+9zas
+4s
+5eed
+8s
+5law
+8s
+5see
+8s
+6or
+8s
+5tipol
+9ls
+4tit
+7s
+4us
+6es
+4wort
+8s
+4y
+5s
+3ibri
+7s
+4c
+5in
+7e
+8s
+7s
+5kier
+8st
+6y
+5root
+9s
+5s
+5weed
+9s
+4es
+4form
+8s
+4n
+5ear
+8ities
+9ty
+5s
+4phage
+9s
+4seum
+8s
+5tin
+8s
+4tic
+6s
+7es
+3l
+4aborate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tively
+9tives
+9tor
+9tors
+5ge
+7d
+7n
+8ase
+9ses
+8ic
+8ous
+8s
+7s
+6ing
+7st
+9s
+5psability
+9le
+8r
+9s
+7e
+8d
+8s
+7ibility
+9le
+8ng
+5r
+6bone
+9es
+6d
+7s
+6ed
+7t
+8s
+8te
+9es
+6ing
+6less
+6s
+5table
+6e
+7d
+7ral
+9lise
+9lised
+9lises
+9lising
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9ls
+7s
+6ing
+7on
+9s
+7ve
+6or
+8s
+4eague
+9d
+9s
+9ship
+9ships
+8ing
+5ct
+7able
+9les
+8nea
+7ed
+9ly
+9ness
+9nesses
+7ible
+9les
+8ng
+9gs
+8on
+9ns
+8ve
+9ely
+9eness
+9es
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9istic
+9ists
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+7or
+9ate
+9ates
+9s
+9ship
+9ships
+7s
+5d
+5en
+7s
+5ge
+7r
+8s
+7s
+6ia
+8l
+9ism
+9isms
+9ities
+9ity
+9ly
+8n
+9er
+9ers
+9s
+8te
+9ely
+9es
+7um
+9s
+5mbolan
+9ans
+9ous
+5nchyma
+9mas
+9mata
+9matous
+5t
+6ed
+7rial
+6ing
+6s
+4iculi
+8us
+5de
+7d
+7r
+8s
+7s
+6ing
+5e
+6d
+6r
+7ies
+7s
+7y
+6s
+7hangie
+9ngies
+5gate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+5mate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+5near
+9ities
+9ity
+9ly
+6g
+7s
+6s
+7es
+7ia
+9s
+5quable
+8nt
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+7escence
+9cences
+5sion
+9al
+9ally
+9s
+4ocate
+9d
+9s
+8ing
+9on
+9onal
+9ons
+6utor
+9rs
+9ry
+5dion
+9s
+7um
+9s
+5gue
+8d
+8s
+7ing
+5id
+7al
+9ities
+9ity
+9ly
+7s
+5p
+6s
+5que
+8d
+8s
+7ia
+9l
+9lism
+9lisms
+9list
+9lists
+9lities
+9lity
+9lly
+9lness
+9ls
+8ed
+9s
+8ng
+8se
+9ed
+9es
+9ing
+9t
+9ts
+8um
+9ms
+8ze
+9ed
+9es
+9ing
+7y
+8ing
+5type
+9s
+8ic
+9es
+8y
+4s
+4uctation
+9ions
+5de
+7d
+7r
+8s
+7s
+6ing
+5sion
+9s
+7ve
+9ly
+5via
+8l
+7es
+7um
+9s
+4y
+5ing
+5ria
+7um
+9s
+5wobbles
+3obi
+6d
+5oma
+8s
+8ta
+5us
+7es
+4cate
+8d
+8s
+7ing
+5ynth
+9s
+4g
+5arithm
+9hms
+5ne
+7d
+7s
+5s
+4mbard
+9s
+4n
+5e
+6l
+7cies
+8y
+7ling
+9ngs
+7s
+8hip
+9ips
+6s
+5i
+6al
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9stic
+9sts
+9ze
+9zed
+9zes
+9zing
+8ly
+8ness
+9esses
+8s
+6c
+7s
+6es
+6sable
+8tion
+9ionist
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7t
+8s
+6tis
+9es
+6zable
+8tion
+9ionist
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5nade
+9d
+9s
+5oscope
+9pes
+9pies
+9py
+5s
+5us
+5y
+4phon
+8ies
+8s
+8y
+4quintida
+9idas
+4r
+5able
+8y
+6do
+6nt
+8s
+6tion
+9ns
+7ura
+9as
+9e
+9es
+5blind
+9dness
+6red
+8ed
+9ding
+9ds
+5cast
+9ed
+9ing
+9s
+5ectal
+6d
+7s
+6r
+7s
+5fast
+9ness
+9nesses
+6ul
+8ly
+8ness
+9esses
+5ific
+6meter
+9ers
+9ric
+9rical
+9ries
+9ry
+6ng
+8s
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+9cally
+8s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5less
+9ly
+9ness
+9nesses
+5man
+6en
+5point
+9ts
+5s
+5way
+8s
+5y
+4ssal
+8ly
+6eum
+9s
+6i
+6us
+8es
+5tomies
+8y
+6ral
+7ic
+7ous
+7um
+9s
+4tomies
+7y
+4ur
+6abilities
+9lity
+8le
+9eness
+9y
+7nt
+9s
+7tion
+9ons
+6ed
+8s
+7r
+8s
+6fast
+9tness
+7ul
+9ly
+9ness
+9nesses
+6ing
+9s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8t
+9ic
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6less
+9sly
+9sness
+6man
+7en
+6point
+9nts
+6s
+6wash
+9hed
+9hes
+9hing
+8y
+9s
+6y
+3pitis
+8es
+4ortage
+9es
+7eur
+9rs
+5scope
+9es
+9ical
+9ically
+9ies
+9y
+5tomies
+8y
+3s
+3t
+4an
+6s
+4ed
+5r
+6s
+4ing
+5sh
+7ly
+7ness
+9sses
+4s
+5foot
+9s
+4wood
+8s
+3ubriad
+9s
+7d
+8s
+7form
+7ne
+4go
+6s
+4mbaria
+9es
+9um
+8y
+7te
+9s
+6ic
+7ne
+9s
+7te
+9s
+7um
+9s
+6ous
+5el
+7la
+9e
+9r
+7s
+5n
+6al
+7r
+8ities
+9ty
+7ted
+6ea
+8s
+7d
+6iated
+9ion
+9ions
+7st
+9ic
+9s
+6s
+4re
+6s
+3y
+3za
+5s
+2ma
+4de
+4e
+4ke
+6r
+7s
+6s
+5ing
+4l
+4nage
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+5chero
+9os
+4rb
+6s
+5t
+6s
+4s
+4te
+6s
+5ic
+6k
+7s
+5ose
+8ly
+5ula
+8e
+7id
+9s
+3b
+4at
+6able
+7nt
+9s
+6ed
+7r
+8s
+6ing
+7ve
+9ly
+9ness
+9nesses
+6s
+6ted
+7ing
+4e
+5d
+5r
+6s
+5s
+4i
+5er
+6s
+7t
+5nabilities
+9lity
+8le
+7te
+8ion
+9onal
+9ons
+9ve
+8orial
+9rially
+9rics
+9ry
+6e
+7d
+8s
+7r
+8s
+7s
+6g
+7s
+6ing
+9s
+5s
+4le
+6s
+7s
+5ike
+4o
+5s
+5ver
+8s
+4retum
+9s
+4s
+4urgess
+9ses
+5st
+7ed
+7ibility
+9le
+9leness
+9les
+9ly
+8ng
+8on
+9ns
+9us
+8ve
+9es
+7or
+9s
+7s
+4wise
+4y
+3e
+4back
+8s
+4ddle
+8d
+8s
+7ing
+5ian
+8s
+6c
+7ally
+6enne
+9es
+7s
+7tta
+9as
+5o
+6genic
+6nes
+6s
+6wn
+8s
+5y
+4lier
+7st
+6ly
+6ness
+9ses
+5y
+4mber
+8s
+4over
+8s
+4r
+5s
+4s
+5tible
+9es
+4t
+5ary
+5h
+6er
+8s
+5ic
+5ographies
+9phy
+6logies
+9y
+5s
+4uppance
+9ces
+3fier
+6st
+5ness
+9es
+5t
+6s
+6ure
+9s
+4ort
+7able
+9leness
+9ly
+7ed
+8r
+9s
+7ing
+9gly
+7less
+9ssly
+9ssness
+7s
+4rey
+7s
+4y
+3ic
+5al
+7ities
+9y
+7ly
+7ness
+9sses
+5e
+6s
+5s
+4ng
+6le
+8d
+8s
+7ing
+6s
+4que
+7s
+4tadji
+9s
+6l
+6tive
+9es
+7us
+9es
+5ia
+7l
+7s
+6es
+5y
+4x
+3m
+4a
+5nd
+7able
+8nt
+9ts
+9tship
+9tships
+7ed
+8er
+9red
+9ring
+9rs
+8r
+9ies
+9s
+9ship
+9ships
+9y
+7ing
+9gly
+7ment
+9nts
+7o
+8es
+8s
+7s
+5s
+5ta
+4easurable
+9e
+9ed
+9es
+9ing
+5morable
+9te
+9ted
+9tes
+9ting
+9tion
+9tional
+9tions
+9tive
+9tively
+9tives
+9tor
+9tors
+9tory
+5nce
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+6d
+7able
+9leness
+9ly
+8m
+9s
+8tion
+9ions
+9or
+9ors
+9ory
+7ed
+8r
+9s
+7ing
+7s
+6sal
+9ism
+9isms
+9ities
+9ity
+9ly
+9s
+7urable
+9ably
+9ate
+9ately
+9ation
+9ations
+6t
+7arial
+9iat
+9iats
+9ies
+9y
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9orial
+9ors
+7ed
+8r
+9s
+7ing
+7or
+9s
+7s
+5r
+6ce
+8d
+8s
+7ial
+9lese
+9leses
+9lise
+9lised
+9lises
+9lising
+9lism
+9lisms
+9list
+9listic
+9lists
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9ls
+8ng
+6e
+7s
+6ge
+8d
+8s
+7ing
+6s
+4ie
+6s
+5nate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8ory
+6gle
+9d
+9s
+8ing
+6ute
+9d
+9s
+8ing
+9on
+9ons
+5s
+6erable
+9te
+9ted
+9tes
+9ting
+9tingly
+9tion
+9tions
+9tive
+9tively
+9tor
+9tors
+6saire
+9res
+8r
+9ial
+9iat
+9iats
+9ies
+9s
+9y
+9yship
+9yships
+7ion
+9naire
+9naires
+9nal
+9nary
+9ned
+9ner
+9ners
+9ning
+9ns
+7ural
+9e
+9es
+5t
+6ment
+9ts
+6s
+6table
+8l
+9s
+7ed
+8e
+9man
+9men
+9s
+9ship
+9ships
+9woman
+9women
+8r
+9s
+7ing
+5x
+6ed
+7s
+6ing
+6t
+7ion
+9ns
+7ure
+9es
+4o
+5de
+7s
+6ification
+9ed
+9es
+8y
+9ing
+7ous
+9sly
+9sness
+7ties
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+8y
+6o
+7re
+9s
+5n
+6able
+7ge
+9s
+7lities
+9ty
+8ties
+9y
+6ed
+7r
+8s
+7st
+7y
+8s
+6hold
+9ds
+6ing
+9s
+6ly
+6ness
+9ses
+6place
+9ced
+9ceness
+9ces
+9cing
+6s
+7ense
+9sible
+9sical
+6weal
+9ls
+9lth
+9lths
+5rant
+9s
+6ientes
+5s
+5t
+6e
+7s
+6ion
+9al
+9s
+6s
+5ve
+7d
+7s
+6ing
+4s
+4unal
+8isation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9sm
+9sms
+9st
+9stic
+9sts
+9ties
+9ty
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8ly
+7rd
+9s
+7utaire
+9aires
+6e
+7d
+7r
+8s
+7s
+6icability
+9ble
+9bly
+9nt
+9nts
+9te
+9ted
+9tee
+9tees
+9tes
+9ting
+9tion
+9tional
+9tions
+9tive
+9tively
+9tor
+9tors
+9tory
+7ng
+9s
+7on
+9al
+9ally
+9s
+7que
+9es
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ically
+9s
+7taire
+9ires
+9rian
+9rians
+8ies
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+5tabilities
+9lity
+8le
+9eness
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9vely
+9vities
+9vity
+8or
+9rs
+6e
+7d
+7r
+8s
+7s
+6ing
+6ual
+4y
+3odo
+4nomer
+9s
+4rbid
+4se
+4us
+3p
+4act
+7ed
+9ly
+9ness
+9nesses
+8r
+9s
+8st
+7ible
+8fied
+9ies
+9y
+9ying
+8ng
+8on
+9ns
+7ly
+7ness
+9sses
+7or
+9s
+7s
+7ure
+9es
+5dre
+8s
+5ge
+7s
+6inate
+9ted
+9tes
+9ting
+9tion
+9tions
+5nd
+7ed
+8r
+9s
+7ing
+7or
+9s
+7s
+6iable
+7ed
+8s
+7ng
+7on
+9able
+9ably
+9ate
+9ed
+9hood
+9hoods
+9ing
+9less
+9s
+9ship
+9ships
+9way
+9ways
+6y
+7ing
+5rabilities
+9lity
+8le
+9eness
+9y
+7tist
+9sts
+9ve
+9vely
+9veness
+9ves
+9vist
+9vists
+8or
+9rs
+6e
+7d
+7r
+8s
+7s
+6ing
+7son
+9ns
+6t
+7ed
+7ing
+7ment
+9ntal
+9ntally
+9nted
+9nting
+9nts
+7s
+5s
+6s
+7able
+7ed
+8s
+7ing
+9gs
+8on
+9nable
+9nate
+9nated
+9nately
+9nates
+9nating
+9ned
+9ning
+9nless
+9ns
+6t
+5tibilities
+9lity
+8le
+9eness
+9es
+9y
+6riot
+9tic
+9tism
+9tisms
+9ts
+4ear
+7ance
+9ces
+9t
+9ts
+7ed
+7ing
+7s
+5d
+5er
+7ed
+7ing
+7s
+5l
+6lable
+9ly
+8tion
+9ions
+9ive
+9ives
+7ed
+8r
+9s
+7ing
+9gly
+6s
+5nd
+7ia
+8ous
+9usly
+9usness
+8um
+9ms
+7s
+6sability
+9le
+8te
+9ed
+9es
+9ing
+9ion
+9ional
+9ions
+9ive
+9or
+9ors
+9ory
+5r
+6e
+7d
+7s
+6ing
+6s
+5sce
+8d
+8s
+7ing
+5te
+7d
+7nce
+9es
+9ies
+9y
+8t
+9ly
+9ness
+9nesses
+7s
+6ing
+7tion
+9ons
+9ve
+9vely
+9veness
+8or
+9rs
+4ilation
+9ons
+8or
+9rs
+9ry
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+5ng
+5tal
+4lacence
+9ces
+9cies
+9cy
+9t
+9tly
+6in
+8ant
+9nts
+8ed
+9r
+9rs
+8ing
+9ngly
+9ngs
+8s
+8t
+9s
+7sance
+9nces
+9nt
+9ntly
+6nate
+9ion
+9ions
+5eat
+6ct
+8ed
+8ing
+8s
+6ment
+9tal
+9tally
+9taries
+9tarily
+9tarity
+9tary
+9tation
+9ted
+9ting
+9tiser
+9tisers
+9tizer
+9tizers
+9ts
+6table
+7e
+8d
+8ly
+8ness
+9esses
+8r
+9s
+8s
+9t
+7ing
+8on
+9ns
+8st
+9ts
+8ve
+7ory
+6x
+7ation
+9ions
+7ed
+9ness
+9nesses
+8r
+8s
+9t
+7ified
+9ies
+9y
+9ying
+8ng
+8on
+9nal
+9ned
+9nless
+9ns
+8ties
+9y
+7ly
+7ness
+9sses
+7ometric
+8ne
+9es
+7us
+9es
+5iable
+9eness
+9y
+7nce
+9es
+9ies
+9y
+8t
+9ly
+9ness
+9nesses
+6cacies
+9y
+8nt
+8te
+9ed
+9edly
+9edness
+9es
+9ing
+9ion
+9ions
+9ive
+7e
+8s
+7it
+9ies
+9ous
+9y
+6ed
+7r
+8s
+7s
+6ment
+9tal
+9tarily
+9tary
+9ted
+9ter
+9ters
+9ting
+9ts
+6n
+7e
+8s
+7s
+6sh
+8ed
+9s
+8ing
+5ot
+7s
+7ted
+9r
+9rs
+8ing
+5uvia
+8um
+9ms
+5y
+6ing
+4o
+5ne
+7ncies
+9y
+8t
+9al
+9ial
+9s
+6y
+5rt
+7ance
+9ces
+7ed
+7ing
+7ment
+9nts
+7s
+5s
+6e
+7d
+8ly
+8ness
+9esses
+7r
+8s
+7s
+6ing
+7te
+9d
+9ly
+9ness
+9nesses
+9s
+8ing
+9on
+9onal
+9onally
+9ons
+9ve
+8or
+9rial
+9rs
+9us
+6sibility
+9le
+6t
+7able
+7ed
+8r
+9s
+7ing
+7s
+7ure
+9ed
+9es
+9ing
+6ure
+9s
+5t
+6ation
+9ons
+9onship
+8or
+9rs
+9ry
+6e
+7s
+6ier
+9s
+6s
+5und
+8able
+8ed
+9r
+9rs
+8ing
+8s
+4rador
+9e
+9es
+9s
+5ehend
+9ded
+9dible
+9ding
+9ds
+9sible
+9sibly
+9sion
+9sions
+9sive
+9sively
+9sives
+9sivise
+9sivize
+6ss
+8ed
+9dly
+9s
+8ibility
+9ble
+9bly
+9ng
+9on
+9onal
+9ons
+9ve
+9vely
+8or
+9rs
+8ure
+9res
+5imario
+9ios
+6nt
+8ed
+8ing
+8s
+6sable
+8l
+9s
+7e
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5omise
+9ed
+9er
+9ers
+9es
+9ing
+9ingly
+6vincial
+4s
+4t
+5able
+5ed
+6r
+7s
+5ible
+6ng
+5roll
+9ed
+9er
+9ers
+9ership
+9ing
+9s
+5s
+4ulsative
+9ory
+7e
+8d
+8s
+7ing
+8on
+9nist
+9nists
+9ns
+8tor
+9ors
+8ve
+9ely
+9eness
+9es
+9ities
+9ity
+7ories
+9ily
+9iness
+9y
+5nction
+9ons
+9ous
+9ously
+5rgation
+9ions
+9or
+9orial
+9ors
+9ory
+6sion
+9ns
+5tabilities
+9lity
+8le
+7nt
+9s
+7tion
+9onal
+9onally
+9ons
+9ve
+8or
+9rs
+6e
+7d
+7r
+8ate
+8dom
+9oms
+8ese
+9ses
+8isable
+9sation
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9zable
+9zation
+9ze
+9zed
+9zes
+9zing
+8less
+9ike
+8nik
+9iks
+8phobe
+9hobes
+9hobia
+9hobias
+9hobic
+8s
+7s
+6ing
+9s
+7st
+9s
+3rade
+7liness
+9nesses
+8y
+7ries
+8y
+7s
+8hip
+9ips
+3s
+4tocker
+9ries
+9rs
+9ry
+8ism
+9sms
+4ymp
+7s
+3te
+5s
+3us
+5es
+2n
+3acre
+7d
+7ism
+9ms
+7s
+6ing
+4ria
+7l
+6um
+4tion
+8al
+8s
+6ve
+5us
+3canavalin
+9lins
+5tenate
+9ted
+9tes
+9ting
+9tion
+9tions
+5use
+8s
+5ve
+7d
+7ly
+7ness
+9sses
+7s
+6ing
+7ties
+8y
+4eal
+7able
+7ed
+8r
+9s
+7ing
+9gly
+7ment
+9nts
+7s
+5de
+7d
+8ly
+7r
+8s
+7s
+6ing
+6o
+5it
+7ed
+9ly
+9ness
+9nesses
+7ful
+7ing
+7less
+7s
+7y
+6vability
+9le
+9leness
+9ly
+7e
+8d
+8r
+9s
+8s
+7ing
+5lebrant
+9ants
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+5nt
+7er
+9ed
+9ing
+9s
+7rate
+9ted
+9tedly
+9tes
+9ting
+9tion
+9tions
+9tive
+9tively
+9tor
+9tors
+8e
+9d
+9s
+8ic
+9cal
+9cally
+9cities
+9city
+9ng
+7s
+7us
+5pt
+7acle
+9les
+7i
+8on
+9nal
+9ns
+9us
+8ve
+7s
+7ual
+9lise
+9lised
+9liser
+9lisers
+9lises
+9lising
+9lism
+9lisms
+9list
+9listic
+9lists
+9lities
+9lity
+9lize
+9lized
+9lizer
+9lizers
+9lizes
+9lizing
+9lly
+8s
+9es
+5rn
+7ancies
+9cy
+7ed
+9ly
+9ness
+9nesses
+7ing
+7ment
+9nts
+7s
+6t
+7ante
+9tes
+9ti
+7ed
+9ly
+9ness
+9nesses
+7goer
+9ers
+9ing
+9ings
+7i
+8na
+9aed
+9aing
+9as
+9g
+9i
+9ist
+9ists
+9o
+9os
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7master
+9sters
+8eister
+9isters
+7o
+8s
+7s
+8tuck
+9ucks
+5ssible
+8on
+9naire
+9naires
+9nal
+9naries
+9nary
+9ner
+9ners
+9nist
+9nists
+9nnaire
+9ns
+8ve
+9ely
+5tti
+8sm
+9ms
+9t
+9ts
+7o
+4h
+5a
+6e
+6l
+6s
+6te
+5e
+6d
+6s
+5ie
+7s
+6ferous
+7orm
+6glie
+6ng
+6olin
+9ns
+6tis
+9es
+5o
+6id
+8al
+9lly
+8s
+6logical
+9ies
+9ist
+9ists
+9y
+6s
+5s
+5y
+4ierge
+9s
+5liable
+8r
+9ly
+9y
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9orily
+9ors
+9ory
+5nnities
+9y
+7ous
+5piencies
+9cy
+9t
+5se
+7d
+7ly
+7ness
+9sses
+7r
+7s
+8t
+6ing
+7on
+9s
+4lamation
+9ions
+6ve
+8s
+7ist
+9ts
+5ude
+8d
+8r
+9s
+8s
+7ing
+6sion
+9nary
+9ns
+8ve
+9ely
+9eness
+7ory
+4oct
+7ed
+8r
+9s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+7s
+5lor
+8ate
+8ous
+5mitance
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9nts
+5rd
+7al
+8nce
+9ces
+9t
+9tly
+8t
+9s
+7ed
+7ial
+8ng
+7s
+6porate
+9ated
+9ates
+9ating
+5urs
+8e
+9s
+4reate
+9d
+9s
+8ing
+6mation
+9ions
+6scence
+9nces
+9nt
+6te
+8d
+8ly
+8ness
+9esses
+8s
+7ing
+8on
+9nary
+9ns
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9ts
+8ve
+9ely
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+6w
+7ed
+7ing
+7s
+4ubinage
+9ges
+9ries
+9ry
+8e
+9s
+7tancies
+9ncy
+9nt
+9nts
+5pies
+7scence
+9ences
+9ent
+9ible
+6y
+5r
+6red
+8nce
+9ces
+9cies
+9cy
+9t
+9tly
+9ts
+7ing
+9gly
+6s
+5ss
+7ed
+8s
+7ing
+8on
+9ns
+8ve
+4yclic
+9ally
+3d
+4emn
+7able
+9ly
+8tion
+9ions
+9ory
+7ed
+8r
+9s
+7ing
+9gly
+7or
+9s
+7s
+5nsability
+9le
+8te
+9ed
+9es
+9ing
+9ion
+9ional
+9ions
+7e
+8d
+8r
+9ies
+9s
+9y
+8s
+7ibility
+9le
+8ng
+5r
+6s
+5scend
+9ded
+9dence
+9dences
+9ding
+9dingly
+9ds
+9sion
+9sions
+4iddle
+9d
+9s
+8ing
+5e
+6s
+5gn
+7ly
+7ness
+9sses
+5ment
+9al
+9ed
+9ing
+9s
+5sciple
+9les
+5tion
+9able
+9al
+9ality
+9ally
+9als
+9ate
+9ated
+9ates
+9ating
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+4o
+5es
+5latory
+6e
+7d
+7ment
+9nts
+7nce
+9es
+8t
+7r
+8s
+7s
+6ing
+9ly
+5m
+6inium
+9ums
+6s
+5nable
+7tion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+5r
+6es
+6s
+5s
+5ttiere
+9ri
+4uce
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ible
+7ng
+9ly
+7ve
+9ness
+9nesses
+6t
+7ance
+9ces
+7ed
+7i
+8bility
+9le
+8metric
+8ng
+8ometric
+9n
+9nal
+9ns
+8ve
+9ely
+9ities
+9ity
+7ometric
+8r
+9ial
+9s
+9ship
+9ships
+7ress
+9sses
+7s
+7us
+5it
+7s
+5plicate
+9ation
+9ations
+4ylar
+6e
+7s
+6oid
+7ma
+9s
+9ta
+9tous
+3e
+4d
+4flower
+9rs
+4lrad
+8s
+4nose
+8s
+4pate
+8s
+7l
+8s
+4s
+4y
+5s
+3f
+4ab
+6bed
+7ing
+6s
+6ular
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+9tory
+5rreate
+9tion
+9tions
+4ect
+7ed
+7ing
+8on
+9naries
+9nary
+9ner
+9neries
+9ners
+9nery
+9ns
+7s
+5deracies
+9cy
+9l
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+5r
+6ee
+8s
+7nce
+9es
+9ier
+9iers
+9ing
+9ings
+8tial
+6ment
+9ts
+6rable
+8l
+9s
+7ed
+8e
+9s
+8nce
+9ces
+8r
+9s
+7ing
+6s
+6va
+8e
+8l
+8s
+7oid
+9ds
+5ss
+7able
+8nt
+9ts
+7ed
+9ly
+8s
+7ing
+8on
+9nal
+9nalism
+9nalist
+9nally
+9nals
+9naries
+9nary
+9ns
+7or
+9ess
+9esses
+9s
+9ship
+9ships
+6t
+7ly
+5tti
+7o
+4idant
+9e
+9es
+9s
+6e
+7d
+7nce
+9es
+9ies
+9y
+8t
+9ial
+9iality
+9ially
+9ly
+9s
+7r
+8s
+7s
+6ing
+9ly
+9ness
+9nesses
+5gurate
+9ted
+9tes
+9ting
+9tion
+9tional
+9tions
+9tive
+8e
+9d
+9s
+8ing
+5nable
+6e
+7able
+7d
+8ly
+8ness
+9esses
+7less
+7ment
+9nts
+7r
+8s
+7s
+6ing
+5rm
+7ability
+9le
+8nd
+9ds
+8tion
+9ional
+9ions
+9ive
+9or
+9ors
+9ory
+7ed
+9ly
+9ness
+9nesses
+8e
+9s
+8r
+9s
+7ing
+9gs
+7or
+9s
+7s
+5scable
+8table
+9e
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+9ory
+6erie
+9es
+7ur
+9s
+5t
+6eor
+9s
+6s
+6ure
+9s
+5x
+6ed
+7s
+6ing
+4lagrant
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+6te
+8d
+8s
+7ing
+8on
+9ns
+5ict
+8ed
+8ful
+8ing
+9ngly
+9on
+9ons
+9ve
+8ory
+8s
+8ual
+5uence
+9es
+8t
+9ly
+9s
+6x
+7es
+4ocal
+8ly
+5rm
+7ability
+9le
+9leness
+9ly
+8l
+8nce
+9ces
+8tion
+9ional
+9ions
+7ed
+8r
+9s
+7ing
+9gly
+8sm
+9ms
+9t
+9ts
+8ties
+9y
+7s
+5und
+8able
+8ed
+9dly
+9dness
+9r
+9rs
+8ing
+9ngly
+8s
+4raternal
+9nities
+9nity
+5ere
+8s
+7ie
+9s
+5ont
+8al
+9ls
+9tion
+9tional
+9tions
+8e
+9d
+9r
+9rs
+8ing
+8ment
+9ents
+8s
+4s
+4usabilities
+9lity
+8le
+9es
+6e
+7d
+8ly
+8ness
+9esses
+7s
+6ible
+9es
+7ng
+9ly
+7on
+9al
+9s
+5table
+7tion
+9ons
+9ve
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+3ga
+5ed
+5ing
+5s
+4e
+5al
+7able
+9leness
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+5d
+5e
+6d
+6ing
+6s
+5ing
+5lation
+9ons
+5ner
+8ic
+9cal
+9cs
+8ous
+8s
+7tic
+6ial
+9ities
+9ity
+9ly
+9ness
+9nesses
+7c
+7tal
+9lly
+9lness
+5r
+6ies
+6s
+5s
+6t
+7ed
+7ible
+8ng
+8on
+9ns
+8ve
+7s
+4iaries
+7y
+5i
+5us
+4lobate
+9ed
+9es
+9ing
+9ion
+9ions
+7e
+8d
+8s
+7ing
+7ulate
+9ated
+9ates
+9ating
+9ation
+9ations
+6merate
+9ated
+9ates
+9ateur
+9ateurs
+9atic
+9ating
+9ation
+9ations
+9ative
+9ator
+9ators
+5utinant
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+9ator
+9ators
+4o
+5es
+5s
+5u
+6s
+4rats
+7ters
+7ulable
+9ant
+9ants
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+9ator
+9ators
+9atory
+5ee
+7d
+7ing
+7s
+7t
+8ed
+8ing
+8s
+6gant
+9ts
+8te
+9ed
+9es
+9ing
+9ion
+9ional
+9ions
+9ive
+9or
+9ors
+6ss
+8ed
+9s
+8ing
+9onal
+9onally
+8man
+9en
+8people
+9erson
+9ersons
+8woman
+9omen
+5ue
+7d
+7nce
+9es
+9ies
+9y
+8t
+9ly
+7s
+6ing
+7ties
+8y
+6ous
+9ly
+9ness
+9nesses
+3i
+4a
+5s
+4c
+5al
+7ly
+5ine
+8s
+6ties
+7y
+5s
+4dia
+7l
+7n
+6ophore
+9ores
+9orous
+7spore
+9ores
+6um
+4es
+4fer
+7ous
+7s
+5orm
+4ine
+7s
+4ma
+6s
+4n
+5e
+6s
+5g
+5s
+4ologies
+8y
+5ses
+6is
+4rostral
+4um
+6s
+3ject
+7ed
+7ing
+7s
+7urable
+9ably
+9al
+9ally
+9e
+9ed
+9er
+9ers
+9es
+9ing
+5e
+6d
+6ing
+6s
+4oin
+7ed
+8r
+9s
+7ing
+7s
+7t
+8ly
+4ugable
+7l
+8ities
+9ty
+8ly
+7nt
+9s
+7te
+9d
+9ly
+9ness
+9nesses
+9s
+8ing
+9ngs
+9on
+9onal
+9onally
+9ons
+9ve
+8or
+9rs
+5nct
+8ion
+9onal
+9onally
+9ons
+9va
+9vae
+9val
+9vas
+9ve
+9vely
+9veness
+9ves
+9vites
+9vitis
+8ly
+8s
+8ural
+9re
+9res
+6to
+8s
+5ration
+9ons
+8or
+9rs
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ies
+7ng
+9s
+6or
+8s
+6y
+3k
+4ed
+5r
+6s
+4ier
+6st
+5ng
+4s
+4y
+3n
+4ascence
+9ces
+9cies
+9cy
+9t
+5te
+7ly
+7ness
+9sses
+6ion
+9s
+6ural
+9lise
+9lised
+9lises
+9lising
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9lness
+8e
+9s
+4e
+5ct
+7able
+7ed
+9ly
+9ness
+9nesses
+8r
+9s
+7ible
+8ng
+8on
+9nal
+9nism
+9nisms
+9ns
+8ve
+9ely
+9es
+9ities
+9ity
+7or
+9s
+7s
+5d
+5r
+6s
+5s
+5xion
+9al
+9s
+7ve
+4ie
+6s
+5ng
+7s
+5ption
+9ns
+5vance
+9es
+9ies
+9y
+6e
+7d
+7nce
+9es
+9ies
+9y
+8t
+9ly
+7r
+8ies
+8s
+8y
+7s
+6ing
+9ly
+4oisseur
+9urs
+9urship
+5tate
+9d
+9s
+8ing
+9on
+9onal
+9ons
+9ve
+9vely
+6e
+7d
+7s
+6ing
+7ve
+9ly
+4s
+4ubial
+9ism
+9isms
+9ities
+9ity
+9ly
+5merate
+9ted
+9tes
+9ting
+9tion
+9tions
+3odont
+8s
+4id
+6al
+8ly
+6ic
+8al
+6s
+4minee
+9s
+4scente
+9i
+3quer
+7able
+9leness
+7ed
+8r
+9s
+8ss
+9ses
+7ing
+9gly
+7or
+9s
+7s
+6st
+8s
+5ian
+8s
+6stador
+9dores
+9dors
+3s
+4anguine
+9neous
+9nities
+9nity
+4cience
+9eless
+9es
+8t
+9ious
+9iously
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+6onable
+9bly
+7us
+9es
+9ly
+9ness
+9nesses
+5ribe
+9d
+9s
+8ing
+7pt
+9ed
+9ing
+9ion
+9ional
+9ionist
+9ions
+9s
+4ecrate
+9ed
+9edness
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+6taneous
+8ries
+9y
+6ution
+9ons
+9ve
+9vely
+9veness
+5il
+7s
+5nescence
+9ences
+9encies
+9ency
+6sion
+9ns
+7ual
+9lly
+8s
+9es
+6t
+7aneities
+9eity
+9eous
+9eously
+7ed
+8r
+9s
+7ience
+9nces
+9nt
+8ng
+9gly
+7s
+5quence
+9ced
+9ces
+9cing
+9t
+9tial
+9tially
+9tly
+9ts
+5rvable
+8ncies
+9cy
+9t
+8tion
+9ional
+9ionist
+9ions
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ive
+9ively
+9ives
+9ize
+9ized
+9izes
+9izing
+9oire
+9oires
+9or
+9oria
+9orial
+9ories
+9orium
+9oriums
+9ors
+9orship
+9ory
+9rices
+9rix
+9rixes
+7e
+8d
+8r
+9s
+8s
+7ing
+4ider
+8able
+9bles
+9bly
+9nce
+9nces
+9te
+9tely
+9teness
+9tion
+9tions
+9tive
+9tively
+8ed
+9r
+9rs
+8ing
+9ngly
+8s
+5gliere
+9res
+9ri
+6n
+7able
+8tion
+9ions
+9ories
+9ory
+7ed
+8e
+9s
+8r
+9s
+7ified
+9ies
+9y
+9ying
+8ng
+7ment
+9nts
+7or
+9s
+7s
+5lience
+9ces
+9t
+5milar
+9rities
+9rity
+8ities
+9tude
+9tudes
+9ty
+5st
+7ed
+8nce
+9ces
+9cies
+9cy
+9t
+9tly
+7ing
+7orial
+9ian
+9ies
+9y
+7s
+4ociate
+9ed
+9es
+9ing
+9ion
+9ional
+9ions
+7es
+5l
+6able
+7te
+9d
+9s
+8ing
+9on
+9ons
+8ories
+9ry
+8rices
+9ix
+9ixes
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+6idate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+7ng
+9ly
+6s
+6ute
+5mme
+8s
+5nance
+9es
+9ies
+9y
+8t
+9al
+9ally
+9ly
+9s
+6ous
+5rt
+7able
+7ed
+8r
+9s
+7ia
+9l
+8ng
+8sm
+9ms
+8um
+9ms
+7s
+4pecific
+9ics
+7tuities
+9ity
+9s
+9ses
+5icuities
+9ty
+8ous
+9usly
+9usness
+6racies
+9y
+8nt
+8tion
+9ional
+9ions
+9or
+9orial
+9ors
+9ory
+9ress
+9resses
+7e
+8d
+8r
+9s
+8s
+7ing
+9gly
+5ue
+7d
+7s
+6ing
+6rcation
+9tions
+4table
+9s
+9ship
+9ships
+9wick
+9wicks
+7ularies
+9ary
+6ncies
+8y
+7t
+8an
+9ns
+8ly
+8s
+6tation
+9ions
+7e
+8d
+8s
+7ing
+8ve
+9es
+5ellate
+9ted
+9tes
+9ting
+9tion
+9tional
+9tions
+9tory
+6r
+7ed
+7ing
+7nate
+9ted
+9tes
+9ting
+9tion
+9tions
+7s
+5ipate
+9ed
+9es
+9ing
+9ion
+9ions
+6tuencies
+9ncy
+9nt
+9ntly
+9nts
+8te
+9ed
+9er
+9ers
+9es
+9ing
+9ion
+9ional
+9ionals
+9ionist
+9ions
+9ive
+9ively
+9or
+9ors
+5rain
+9able
+9ed
+9edly
+9er
+9ers
+9ing
+9s
+9t
+9ts
+6ict
+9ed
+9ing
+9ion
+9ions
+9ive
+9ively
+9or
+9ors
+9s
+7nge
+9ed
+9ence
+9ences
+9encies
+9ency
+9ent
+9es
+9ing
+6uability
+9le
+8l
+9s
+7ct
+9able
+9ed
+9er
+9ers
+9ible
+9ing
+9ion
+9ional
+9ionism
+9ionist
+9ions
+9ive
+9ively
+9ivism
+9ivisms
+9ivist
+9ivists
+9or
+9ors
+9s
+9ure
+9ures
+7e
+8d
+8r
+9s
+8s
+7ing
+5uprate
+9ted
+9tes
+9ting
+9tion
+9tions
+4ubsist
+9ted
+9ting
+9ts
+7tantial
+9ntiate
+5etude
+9es
+9inary
+5l
+6age
+9s
+7r
+8s
+7te
+9s
+6s
+7hip
+9ps
+6t
+7a
+8ble
+8ncies
+9cy
+9t
+9ts
+9tship
+9tships
+8s
+8tion
+9ions
+9ive
+9ively
+9ory
+7ed
+8e
+9s
+8r
+9s
+7ing
+8ve
+7or
+9s
+9y
+7s
+5mable
+9es
+6e
+7d
+8ly
+7r
+8ism
+9sms
+9st
+9stic
+9sts
+8s
+9hip
+9hips
+7s
+6ing
+9ly
+9s
+6mate
+9ed
+9ely
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+6pt
+8ion
+9ons
+9ve
+9vely
+9veness
+9ves
+9vities
+9vity
+8s
+3tabescence
+9ences
+9ent
+5ct
+7able
+7ed
+8e
+9s
+7ing
+7less
+7or
+9s
+7s
+7ual
+9lly
+5dina
+9s
+8e
+8i
+8o
+5gia
+7on
+9ist
+9ists
+9s
+8us
+9sly
+9sness
+7um
+5in
+7able
+7ed
+8r
+9board
+9boards
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9less
+9port
+9ports
+9s
+9ship
+9ships
+7ing
+7ment
+9nts
+7s
+5minable
+9nt
+9nts
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+5ngo
+8ed
+9s
+8ing
+8s
+4e
+5ck
+7s
+5mn
+7ed
+8r
+9s
+7ible
+9ly
+8ng
+7or
+9s
+7s
+6per
+9ation
+9ations
+9ature
+9atures
+9ed
+9ing
+9s
+7lable
+9nt
+9nts
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tist
+9tists
+9tive
+9tively
+9tives
+9tor
+9tors
+7o
+8ranean
+9aneans
+9aneity
+9aneous
+9aries
+9arily
+9ary
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+7t
+8ibility
+9ble
+9bly
+8s
+8uous
+9ously
+5nd
+7ed
+8nt
+9ts
+8r
+9s
+7ing
+9gly
+9gs
+7s
+6ement
+9nts
+6t
+7ation
+9ions
+7ed
+9ly
+9ness
+9nesses
+7ing
+8on
+9ns
+9us
+9usly
+9usness
+7less
+8y
+7ment
+9nts
+7s
+5rminal
+9ally
+9ant
+9ate
+9ous
+9ously
+5s
+6sa
+8s
+7eration
+9ations
+6t
+7ability
+9le
+9leness
+9ly
+8nt
+9ts
+8tion
+9ions
+7ed
+8r
+9s
+7ing
+9gly
+7s
+5xt
+7less
+7s
+7ual
+9lise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+9lly
+8ral
+9e
+9es
+4icent
+5gnation
+9ions
+6uities
+9y
+7ous
+9sly
+9sness
+5nence
+9es
+9ies
+9y
+8t
+9al
+9alism
+9alisms
+9alist
+9alists
+9ally
+9als
+9ly
+9s
+6gence
+9ces
+9cies
+9cy
+9t
+9tly
+9ts
+6ua
+8ble
+8l
+9ities
+9ity
+9ly
+9ness
+9nesses
+8nce
+9ces
+9t
+9ts
+8te
+9ion
+9ions
+9ive
+9ively
+9ives
+9or
+9ors
+7e
+8d
+9ly
+9ness
+9nesses
+8r
+9s
+8s
+7ing
+9gly
+8ties
+9y
+7o
+8s
+8us
+9sly
+9sness
+7um
+9s
+4line
+8s
+4o
+5rniate
+9tes
+7o
+8s
+6t
+7ed
+9ly
+9ness
+9nesses
+7ing
+8on
+9nal
+9nate
+9ned
+9nism
+9nisms
+9nist
+9nistic
+9nists
+9ns
+8ve
+7s
+5s
+5ur
+7ed
+7ing
+7s
+4ra
+6band
+9dism
+9disms
+9dist
+9dists
+9ds
+8ss
+9ses
+9si
+9sist
+9sists
+9so
+9soon
+9soons
+9sos
+7bassi
+9sso
+9ssos
+6ception
+9tions
+9tive
+9tives
+7lockwise
+7t
+8ability
+9ble
+8ed
+9dly
+9dness
+8ibility
+9ble
+9bly
+9le
+9lities
+9lity
+9ng
+9on
+9onal
+9onary
+9ons
+9ve
+9vely
+9veness
+8or
+9rs
+8s
+8ual
+9ally
+9ral
+9re
+9res
+7yclical
+6dance
+9ces
+7ict
+9table
+9ted
+9ter
+9ters
+9ting
+9tion
+9tions
+9tious
+9tive
+9tively
+9tor
+9tories
+9torily
+9tors
+9tory
+9ts
+6fagotto
+9ottos
+7low
+9ws
+6gestion
+9tions
+9tive
+9tives
+6hent
+9ts
+6il
+8s
+7ndicant
+9icants
+9icate
+9icated
+9icates
+7r
+6lateral
+7ti
+8o
+9s
+6natant
+6octave
+9aves
+6plex
+7osition
+9itions
+9itive
+9itives
+7posto
+9stos
+7rop
+9peller
+9ps
+7tion
+9ons
+7untal
+9talist
+9tally
+9tist
+9tists
+6rian
+9ns
+8ed
+9s
+9ties
+9ty
+8ly
+8ness
+9esses
+8ous
+9usly
+9usness
+8wise
+7y
+8ing
+6s
+7exual
+9uals
+7t
+8able
+9bly
+8ed
+8ing
+9ve
+9vely
+8s
+8y
+6t
+7e
+8rrene
+7s
+6vallation
+7ene
+9ed
+9er
+9ers
+9es
+9ing
+9tion
+9tions
+6yerva
+9vas
+5ecoup
+9ps
+6dance
+9ces
+9se
+9ses
+6temps
+5ibutable
+9aries
+9ary
+9e
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9ively
+9or
+9ories
+9ors
+9ory
+6st
+8ation
+9tions
+8ed
+8ing
+8s
+6te
+8ly
+8ness
+9esses
+7ion
+9ns
+7urate
+9ated
+9ates
+9ating
+6vable
+8nce
+9ces
+7e
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+5ol
+7e
+7lability
+9ble
+9bly
+8ed
+9r
+9rs
+9rship
+9rships
+8ing
+7ment
+9nts
+7s
+6ul
+8ed
+8ing
+8s
+6verse
+9ses
+9sial
+9sially
+9sies
+9sy
+9t
+9ted
+9ter
+9ters
+9tible
+9tibly
+9ting
+9tist
+9tists
+9ts
+4ubernal
+9yal
+5macies
+9ous
+9ously
+9ties
+9ty
+8y
+6elies
+9ous
+9ously
+8y
+5nd
+7ed
+7ing
+7s
+5se
+7d
+7s
+6ing
+7on
+9ed
+9s
+7ve
+3undrum
+9s
+4rban
+7tion
+9ons
+6ia
+8s
+5e
+6s
+4s
+3valesce
+9ed
+9ence
+9ences
+9encies
+9ency
+9ent
+9ently
+9ents
+9es
+9ing
+4ect
+7ed
+7ing
+8on
+9nal
+9ns
+8ve
+7or
+9s
+7s
+5nable
+7nce
+9es
+6e
+7d
+7r
+8s
+9hip
+9hips
+7s
+6ience
+9ces
+9cies
+9cy
+9t
+9tly
+7ng
+6or
+8s
+9hip
+9hips
+6t
+7ed
+7icle
+9led
+9ler
+9lers
+9les
+9ling
+8ng
+8on
+9nal
+9nalise
+9nalism
+9nalist
+9nality
+9nalize
+9nally
+9nals
+9nary
+9neer
+9neers
+9ner
+9ners
+9nist
+9nists
+9ns
+7s
+7ual
+9lly
+9ls
+5rge
+8d
+8nce
+9ces
+9cies
+9cy
+9t
+8s
+7ing
+6sable
+9leness
+9ly
+8nce
+9ces
+9cies
+9cy
+9t
+9tly
+8tion
+9ional
+9ionism
+9ionist
+9ions
+9ive
+8zione
+9iones
+9ioni
+7e
+8d
+8ly
+8r
+9s
+8s
+7ing
+8on
+9nal
+9nary
+9ns
+7o
+8s
+6t
+7aplane
+9lanes
+7ed
+8nd
+9ds
+8r
+9s
+7ibility
+9le
+9leness
+9les
+9ly
+8ng
+8plane
+9lanes
+8te
+9es
+8ve
+7oplane
+9lanes
+8r
+9s
+7s
+5x
+6ed
+8ly
+7s
+6ing
+7ties
+8y
+6ly
+6ness
+9ses
+5y
+6able
+7l
+8s
+7nce
+9er
+9ers
+9es
+9ing
+9ings
+6ed
+7r
+8s
+6ing
+6or
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+6s
+4icinities
+9ty
+6t
+7able
+7ed
+7ible
+8ng
+8on
+9nal
+9ns
+8sm
+9ms
+8ve
+9ely
+7s
+5nce
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ible
+8ng
+9gly
+9gness
+5ve
+7d
+7s
+6ial
+9ist
+9ists
+9ities
+9ity
+9ly
+7ng
+4o
+5cate
+9d
+9s
+8ing
+9on
+9onal
+9onist
+9onists
+9ons
+9ve
+8or
+9rs
+5ke
+7d
+7r
+8s
+7s
+6ing
+5lute
+9d
+9dly
+9dness
+9ly
+9s
+8ing
+9on
+9onal
+9onary
+9ons
+6ve
+8d
+8s
+7ing
+7ulaceous
+9i
+9us
+9uses
+5s
+5y
+6ed
+6ing
+6s
+4ulsant
+9ts
+7e
+8d
+8s
+7ible
+8ng
+8on
+9nal
+9naries
+9nary
+9nist
+9nists
+9ns
+8ve
+9ely
+9eness
+3y
+2o
+3ch
+5es
+4oo
+3ed
+4e
+5d
+5ing
+5s
+4r
+5s
+4y
+5ed
+5ing
+5s
+3f
+4s
+3ing
+6ly
+6s
+3k
+4able
+4book
+8s
+4ed
+5r
+6ies
+6s
+6y
+5y
+6s
+4house
+9s
+4ie
+6s
+5ng
+7s
+4less
+4maid
+8s
+4off
+7s
+5ut
+7s
+4room
+8s
+4s
+5hack
+9s
+6op
+8s
+5tove
+9s
+4top
+7s
+4ware
+8s
+4y
+3l
+4abah
+8s
+5mon
+8s
+5nt
+7s
+4down
+8s
+4ed
+5r
+6s
+5st
+4headed
+5ouse
+9s
+4ibah
+8s
+7r
+8s
+5e
+6s
+5ng
+7ly
+7ness
+9sses
+7s
+5sh
+4ly
+4ness
+8es
+4s
+4th
+6s
+4y
+3m
+4b
+5e
+6s
+5s
+4ceiled
+4ed
+4ier
+6st
+5ng
+4s
+4y
+3ncan
+7s
+4dog
+7s
+4hound
+9s
+4skin
+8s
+4tie
+7s
+5y
+3p
+4ed
+5r
+6age
+9s
+7te
+9d
+9s
+8ing
+9on
+9onist
+9onists
+9ons
+9ve
+9vely
+9veness
+9ves
+9vities
+9vity
+8or
+9rs
+6ed
+6ies
+7ng
+9s
+6s
+6y
+4ing
+4s
+4t
+5ation
+9ns
+8ve
+5ed
+5ing
+6on
+8s
+5s
+3rdinal
+8nce
+9ces
+8te
+9ed
+9ely
+9eness
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+4ie
+6d
+6ing
+6s
+3s
+4en
+6ed
+6ing
+6s
+5r
+6s
+4in
+6ed
+6ing
+6s
+4t
+3t
+4ch
+6ed
+7s
+6ing
+4er
+6s
+4ie
+6s
+5kin
+8s
+4s
+3ze
+5s
+2p
+3acetic
+4iba
+7s
+5va
+7s
+4l
+5m
+6s
+5s
+4rcenaries
+9ry
+8er
+9ries
+9rs
+9ry
+8ies
+8y
+5ent
+8ed
+8ing
+8s
+5tner
+9ed
+9ies
+9ing
+9s
+9ship
+9ships
+9y
+4setic
+5tor
+8s
+4taine
+5riot
+9s
+6on
+8s
+4y
+5ment
+9s
+5s
+3e
+4ck
+6s
+4d
+4mate
+8s
+4n
+5s
+4pod
+7s
+4r
+5ed
+5ing
+5s
+4s
+5etic
+5tone
+9s
+3ied
+5r
+6s
+5s
+4hue
+7s
+4lot
+7s
+4ng
+6s
+7tone
+9nes
+4ous
+7ly
+7ness
+9sses
+4ta
+6s
+3lanar
+8ities
+9ty
+4ot
+6s
+6ted
+7ing
+3olymer
+9ic
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9s
+4ut
+6s
+3ped
+5r
+6ah
+8s
+7s
+8es
+6ed
+6head
+9ds
+6ing
+9s
+7sh
+6plate
+9tes
+6s
+7kin
+9ns
+7mith
+9ths
+6work
+9ks
+9m
+9ms
+6y
+4ice
+7d
+7s
+6ing
+9s
+5es
+5n
+6g
+6s
+4le
+6s
+4ra
+6s
+4y
+3ra
+5h
+6s
+5s
+4emia
+8s
+7c
+5sence
+9es
+8t
+9ed
+9ing
+9s
+6ident
+9nts
+4ince
+8s
+7ipal
+9als
+5soner
+9rs
+4ocessing
+9ings
+9or
+9ors
+5duce
+9d
+9r
+9rs
+9s
+8ing
+8t
+9ion
+9ions
+9s
+5lalia
+9ac
+9as
+6ite
+9s
+8h
+9s
+8ic
+6ogies
+8y
+5moter
+9rs
+5phagan
+9ans
+9ic
+9ies
+9ist
+9ists
+9ous
+9y
+6rietor
+9tors
+5sma
+8s
+6perities
+9ity
+6terol
+9ols
+5zoic
+3s
+4e
+5d
+5s
+5wood
+9s
+4hop
+7s
+4ier
+6st
+5ng
+4y
+3ter
+6s
+3ublish
+9ed
+9er
+9ers
+9es
+9ing
+4la
+6e
+6r
+6s
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+9es
+7ory
+4rified
+9s
+7y
+8ing
+3y
+4able
+4book
+8s
+6y
+7s
+4cat
+7s
+7ted
+8ing
+4desk
+8s
+4edit
+8ed
+8ing
+8s
+4fight
+9s
+4girl
+8s
+5raph
+9s
+4hold
+8er
+9rs
+8s
+4ing
+5sm
+7s
+6t
+7s
+4left
+8ed
+8ing
+8s
+4read
+8er
+9rs
+8ing
+9ngs
+8s
+5ight
+9able
+9ed
+9er
+9ers
+9ing
+9s
+4taker
+9s
+4writer
+9rs
+8ing
+9ngs
+2quelicot
+9ts
+5t
+6ries
+7y
+6s
+6te
+8d
+8s
+7ing
+8sh
+9hly
+9hness
+4illa
+8s
+7e
+8s
+5mbite
+9es
+5na
+7s
+5to
+7s
+2r
+3aciiform
+5le
+7s
+5oid
+8s
+4dicate
+4ggio
+4l
+5bells
+7rries
+9y
+5la
+7ceous
+6iferous
+8orm
+7genous
+7ne
+9s
+7te
+9s
+6oid
+9al
+6um
+5root
+9s
+5s
+5wort
+9s
+4m
+4nach
+8s
+5to
+7es
+7s
+3ban
+6s
+4e
+5au
+7s
+5il
+7le
+9s
+7s
+5l
+6ed
+6ing
+9s
+6led
+7ing
+9gs
+6s
+5s
+4icula
+9e
+9te
+5e
+6s
+5na
+7s
+4y
+3cass
+7es
+3d
+4age
+7s
+5te
+7ly
+4ectomies
+9y
+5d
+5lle
+8d
+8s
+7ing
+5r
+6s
+4grass
+9es
+4ial
+7ise
+9ed
+9es
+9ing
+8ties
+9y
+8ze
+9ed
+9es
+9ing
+7ly
+7ness
+9sses
+7s
+5erite
+9es
+5form
+5llera
+9an
+9as
+5ner
+8s
+6g
+7s
+5te
+7s
+4less
+8es
+5ike
+4oba
+7s
+5centeses
+9esis
+5n
+6ed
+6ing
+6net
+9s
+6s
+5tomies
+8y
+5van
+8s
+4s
+4uroy
+8ed
+8ing
+8s
+4wain
+8er
+9ries
+9rs
+9ry
+8s
+5ood
+8s
+4yline
+9s
+3e
+4cipient
+9nts
+4d
+5eem
+8ed
+8ing
+8s
+4ferential
+4gent
+8s
+5onine
+4ign
+7s
+4late
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9es
+5ess
+5igionist
+9nists
+5la
+7s
+4mia
+6um
+4opsis
+9es
+4pressor
+9ors
+4quisite
+9tes
+4r
+5s
+4s
+5earcher
+9hers
+5ident
+9tial
+9ts
+5pondent
+9ents
+4y
+5s
+3f
+4house
+9s
+3gi
+5s
+3ia
+5ceous
+5nder
+9s
+4es
+4ng
+5thianise
+9nised
+9nises
+9nising
+9nize
+9nized
+9nizes
+9nizing
+4ous
+4um
+6s
+4val
+7led
+8ing
+7ries
+8y
+7s
+8hip
+9ips
+4xid
+7s
+3k
+4age
+7s
+4board
+9s
+6rer
+9s
+4ed
+5r
+6s
+4ier
+6st
+5ness
+9es
+6g
+5r
+6s
+4like
+4s
+5crew
+9ed
+9ing
+9s
+4tree
+8s
+4wing
+8s
+5ood
+8s
+4y
+3m
+4el
+6s
+4idia
+7um
+4like
+4oid
+5phyte
+9es
+9ic
+5rant
+9s
+5us
+4s
+4us
+6es
+3n
+4aceous
+6re
+8s
+5ge
+7s
+4ball
+8s
+5orer
+9s
+5raid
+9ed
+9ing
+9s
+7ndies
+9y
+7sh
+9es
+6ead
+9s
+4cake
+8s
+5ob
+7s
+6ckle
+9es
+5rake
+9s
+6ib
+8s
+4ea
+6e
+6l
+6s
+5d
+5itis
+9es
+5l
+6ian
+9s
+6s
+5muse
+9s
+5ous
+5r
+6back
+9ks
+6ed
+6ing
+6man
+7en
+6s
+7tone
+9nes
+6ways
+7ise
+5t
+6cies
+7y
+6ist
+9s
+6s
+6t
+7i
+8ni
+9o
+8st
+9ts
+7o
+7s
+4fed
+5ield
+9s
+5lag
+8s
+7ke
+9s
+6ies
+6our
+9s
+7wer
+9rs
+6y
+4husk
+8er
+9rs
+8ing
+9ngs
+8s
+4i
+5ce
+7d
+7s
+6he
+8s
+7on
+9s
+6ing
+6le
+8s
+6ula
+9te
+8um
+9ms
+5er
+6st
+5ferous
+6ic
+8ation
+9tions
+7ed
+8s
+6orm
+6y
+7ing
+5gerous
+5ly
+5ness
+9es
+6g
+5st
+7s
+4land
+8s
+5oft
+8s
+4meal
+8s
+5ill
+8s
+5oth
+8s
+4o
+5pean
+9s
+4pipe
+8s
+5one
+8s
+4row
+7ed
+7ing
+7s
+4s
+5talk
+9s
+7rch
+9hes
+6one
+9s
+4u
+5a
+6l
+5copia
+9an
+9as
+5s
+6es
+5te
+7d
+7s
+6ing
+6o
+7s
+4worm
+8s
+4y
+3ocore
+8s
+7o
+8s
+4dies
+5y
+4lla
+7ceous
+7ries
+8y
+7s
+7te
+6ifloral
+9orous
+8orm
+7ne
+4mandel
+9ls
+4na
+6ch
+8s
+6e
+6graph
+9phs
+6l
+7ly
+7s
+6ries
+7y
+6s
+6te
+8d
+8s
+7ing
+8on
+9ns
+6virus
+9uses
+5el
+7s
+6r
+7s
+8hip
+9ips
+6t
+7ed
+7s
+5is
+7es
+6um
+8s
+5ograph
+9phs
+6id
+4tate
+8d
+8s
+7ing
+8on
+9ns
+4zo
+6s
+3pora
+7l
+8e
+9s
+8ities
+9ty
+8ly
+8s
+9hip
+9hips
+7s
+8es
+7te
+9ly
+9ness
+9nesses
+9s
+8ion
+9ons
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9ve
+9vism
+9visms
+9ze
+9zed
+9zes
+9zing
+8or
+9rs
+6eal
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9ists
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+9ly
+9ness
+9nesses
+7ities
+9y
+6ification
+9ed
+9es
+8y
+9ing
+5sant
+9s
+4s
+5e
+6d
+6s
+5ing
+5man
+6en
+4ulence
+9es
+9ies
+9y
+8t
+9ly
+5s
+6cle
+9s
+7ular
+9arian
+9arians
+9arity
+9e
+9es
+6es
+3rade
+7d
+7s
+6ing
+5l
+6led
+7ing
+6s
+5sion
+9s
+7ve
+4ea
+6s
+5ct
+7able
+7ed
+8r
+8st
+7ible
+8ng
+8on
+9nal
+9ner
+9ners
+9ns
+8tude
+9udes
+8ve
+9ely
+9es
+7ly
+7ness
+9sses
+7or
+9s
+9y
+7s
+5gidor
+9rs
+5latable
+8e
+9d
+9s
+8ing
+9on
+9onal
+9ons
+9ve
+9vely
+9veness
+9ves
+9vities
+9vity
+8or
+9rs
+6igionist
+9onists
+5ption
+9ns
+5spond
+9ded
+9dence
+9dences
+9dency
+9dent
+9dently
+9dents
+9ding
+9dingly
+9ds
+9sive
+4ida
+7s
+6or
+8s
+5e
+6s
+5genda
+9um
+8t
+9s
+6ibilities
+9lity
+8le
+9y
+5val
+8led
+9ing
+8ries
+9y
+8s
+9hip
+9hips
+4oborable
+9nt
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tively
+9tives
+9tor
+9tors
+9tory
+8ee
+9ed
+9eing
+9es
+5dant
+9s
+6e
+7d
+7nt
+9s
+7r
+8s
+7s
+6ibilities
+9lity
+8le
+7es
+7ng
+6y
+5sibilities
+9lity
+8le
+7on
+9s
+7ve
+9ly
+9ness
+9nesses
+9s
+4ugate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+5pt
+7ed
+8r
+9s
+8st
+7ibility
+9le
+9leness
+9ly
+8ng
+8on
+9nist
+9nists
+9ns
+8ve
+9ely
+7ly
+7ness
+9sses
+7or
+9s
+7s
+3s
+4ac
+6s
+5ge
+7s
+5ir
+7s
+4e
+5let
+8s
+8te
+9es
+5s
+5t
+6ed
+6ier
+9e
+9es
+9s
+7ng
+6ries
+7y
+6s
+5y
+6s
+4ive
+7s
+4let
+7ed
+7s
+4ned
+7s
+4o
+5s
+3tege
+7s
+5x
+6es
+4ical
+8ly
+7te
+9d
+8ion
+9ons
+6es
+6oid
+9s
+7lous
+7se
+8teroid
+9eroids
+9erone
+9erones
+7trophic
+9ophin
+9ophins
+9opic
+9opin
+9opins
+5le
+6i
+5n
+6a
+7s
+6s
+5sol
+8s
+7ne
+9s
+3uler
+7s
+4ndum
+8s
+4scant
+7te
+9d
+9s
+8ing
+9on
+9ons
+3vee
+6s
+5s
+5t
+6ed
+6ing
+6s
+6te
+8d
+8s
+7ing
+4id
+6s
+5na
+7s
+6e
+4us
+6es
+3y
+4bant
+8es
+8ic
+9sm
+9sms
+8s
+4daline
+9es
+8s
+9es
+4lopses
+8is
+5us
+7es
+4mb
+6ed
+6ose
+9ly
+7us
+6s
+4nebacteria
+9terial
+9terium
+6form
+4phaei
+8us
+6e
+7e
+8s
+7ne
+9s
+7s
+4za
+6l
+6s
+2s
+3cinomancies
+9ncy
+4ript
+8ed
+8ing
+8s
+3e
+4c
+5ant
+8s
+5h
+6s
+5s
+4d
+4ismal
+9s
+7ic
+9s
+4ntient
+4s
+4t
+5s
+4y
+5s
+3h
+4ed
+5r
+6ed
+7r
+8s
+6ies
+7ng
+9s
+6s
+6y
+5s
+4ing
+3ie
+5d
+5r
+6s
+5s
+6t
+4gn
+6atories
+9ry
+6ed
+7r
+8s
+6ificative
+7ng
+6s
+4ly
+4ne
+6s
+7s
+8es
+5g
+3mea
+6s
+5ceutical
+9icals
+5ses
+6is
+5tic
+8al
+9lly
+8ian
+9ans
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+8ologies
+9logy
+8s
+6ologies
+9gist
+9gists
+9gy
+4ic
+6al
+8ly
+5d
+6s
+5n
+6e
+7s
+6s
+5sm
+7s
+6t
+7s
+4ochemical
+9ist
+9istry
+9ists
+6rat
+9ic
+9s
+5drome
+9es
+5genic
+9es
+8y
+6onal
+8ic
+9cal
+9es
+9st
+9sts
+8y
+6rapher
+9hers
+9hic
+9hical
+9hies
+9hist
+9hists
+9hy
+5id
+5latries
+9y
+6ine
+9d
+9s
+8ing
+6ogic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+5naut
+9ics
+9s
+5plastic
+6olis
+9ses
+9tan
+9tanism
+9tans
+9te
+9tes
+9tic
+9tical
+9tics
+9tism
+9tisms
+5rama
+9s
+8ic
+5s
+6es
+6phere
+9res
+5theism
+9sms
+8tic
+9ical
+6ron
+9s
+3phered
+4onsor
+9ed
+9ing
+9s
+9ship
+9ships
+3s
+4ack
+7s
+4es
+5t
+6ed
+6ing
+6s
+4ie
+6s
+3t
+4a
+5e
+5l
+6gia
+9s
+6ly
+6s
+5r
+6d
+7monger
+9ngers
+7s
+6red
+7ing
+6s
+5te
+7d
+4e
+5an
+7ed
+7ing
+9gs
+7s
+5d
+5r
+6monger
+9gers
+6s
+5s
+4ing
+7s
+5ve
+7ly
+7ness
+9sses
+4less
+8ly
+5ier
+7st
+6ness
+9ses
+5y
+4maries
+7y
+4otomies
+8y
+4rel
+7s
+4s
+4ume
+7d
+7r
+8ies
+8s
+8y
+7s
+7y
+6ier
+9s
+7ng
+5s
+6es
+3urfactant
+9ants
+3y
+4ing
+2t
+3an
+5gent
+9ial
+9s
+5s
+3e
+4au
+6x
+4d
+4lette
+9s
+5ine
+8s
+4mporaneous
+9ry
+4nancies
+8y
+7t
+8s
+4rie
+7s
+5minous
+9usly
+4s
+3h
+4s
+4urn
+7al
+7i
+7s
+7us
+3icular
+4dal
+4llion
+9s
+6on
+8s
+4ng
+6a
+7s
+5ine
+8s
+4se
+6d
+6s
+5ing
+3land
+7s
+3oneaster
+9ers
+3quean
+8s
+3ransduce
+9ced
+9ces
+9cing
+9ction
+9ctions
+7fer
+9rred
+9rring
+9rs
+7port
+9rted
+9rting
+9rts
+4ustee
+9s
+3s
+3t
+4a
+5bus
+8es
+5e
+5ge
+7d
+7r
+8s
+7s
+7y
+6ing
+9s
+5r
+6s
+5s
+4ed
+5r
+6ed
+6ing
+6less
+6s
+4id
+6s
+5er
+7ism
+9ms
+7s
+5ng
+5se
+7d
+7s
+6ing
+4oid
+5n
+6ade
+9s
+6ed
+6ing
+6mouth
+9ths
+6ocracies
+9acy
+6s
+7eed
+9ds
+6tail
+9ls
+6weed
+9ds
+7ood
+9ds
+6y
+5wn
+7s
+4s
+4us
+6es
+3urnix
+8es
+3wal
+6s
+3ylae
+5e
+6don
+9al
+9ary
+9oid
+9ous
+9s
+6s
+5iform
+5oid
+8al
+9ls
+8s
+6saur
+9rs
+4pe
+6s
+2ucal
+6s
+4h
+5ant
+5e
+6d
+6e
+7s
+6r
+7s
+6s
+6tte
+9s
+5ing
+8s
+3de
+3gan
+6s
+5r
+6s
+4h
+5ed
+6r
+7s
+5ing
+8s
+5s
+4uar
+7s
+3ld
+5est
+5st
+4ee
+6s
+4ibiac
+9a
+9as
+9s
+5s
+6es
+6se
+8s
+4oir
+7s
+5mb
+7ic
+7meter
+9ters
+7s
+6eter
+9rs
+8ric
+9ically
+9ies
+9y
+4ter
+7s
+3maric
+7lic
+7n
+8s
+6one
+9s
+7u
+8s
+3ncil
+7lor
+9rs
+9rship
+9rships
+7man
+9nic
+8en
+7or
+9s
+9ship
+9ships
+7s
+7woman
+9men
+4sel
+7able
+7ed
+8e
+9s
+7ing
+9gs
+7lable
+8ed
+8ing
+9ngs
+8or
+9rs
+9rship
+9rships
+7or
+9s
+9ship
+9ships
+7s
+4t
+5abilities
+9ity
+7le
+8y
+5back
+9s
+5down
+9s
+5ed
+6nance
+9ced
+9cer
+9cers
+9ces
+9cing
+6r
+7act
+9ted
+9ting
+9tion
+9tions
+9tive
+9tively
+9ts
+8gent
+9ents
+8rgue
+9gued
+9gues
+9guing
+9gument
+8ssault
+9saults
+8ttack
+9tacked
+9tacker
+9tacks
+7bade
+9lance
+9lanced
+9lances
+9se
+9ses
+8id
+9dden
+9dder
+9dders
+9dding
+9ds
+8last
+9asts
+9ockade
+9ow
+9ows
+9uff
+9uffs
+8ond
+9nds
+9re
+9red
+9res
+9ring
+8race
+9aced
+9aces
+9acing
+8uff
+9ffed
+9ffing
+9ffs
+7campaign
+8hange
+9anged
+9anges
+9anging
+9arge
+9arged
+9arges
+9arging
+9arm
+9armed
+9arming
+9arms
+9eck
+9ecked
+9ecking
+9ecks
+8laim
+9aimant
+9aimed
+9aiming
+9aims
+8oup
+9ups
+8ries
+9y
+8ultural
+9lture
+9ltures
+9rrent
+9rrents
+8yclical
+7demand
+9mands
+8raw
+9awing
+9awn
+9aws
+9ew
+7ed
+8ffort
+9forts
+8vidence
+8xample
+9amples
+7factual
+9ctuals
+8ect
+9isance
+9it
+9ited
+9iter
+9iters
+9iting
+9itly
+9its
+9saunce
+8ire
+9red
+9res
+9ring
+8low
+9ows
+8oil
+9ils
+9rce
+9rces
+9rt
+9rts
+7glow
+9ows
+8uerilla
+7image
+9ages
+8ng
+9stance
+8on
+9ns
+8rritant
+7light
+9ghts
+7man
+9nd
+9ndable
+9nded
+9nding
+9nds
+9rch
+9rched
+9rches
+9rching
+9rk
+9rks
+8easure
+9asures
+9lodies
+9lody
+9mo
+9mos
+9n
+8ine
+9ned
+9nes
+9ning
+8otion
+9tions
+9ve
+9ved
+9vement
+9ves
+9ving
+8ure
+9red
+9res
+9ring
+8yth
+9ths
+7offer
+9fers
+8rder
+9dered
+9dering
+9ders
+7pace
+9ces
+9ne
+9nes
+9rt
+9rties
+9rts
+9rty
+8eise
+9ised
+9ises
+9ising
+9tition
+8icket
+9cketed
+9ckets
+8lan
+9ans
+9ay
+9ayer
+9ayers
+9ays
+9ea
+9ead
+9eaded
+9eading
+9eads
+9eas
+9ed
+9ot
+9ots
+9otted
+9otting
+9oy
+9oys
+8oint
+9inted
+9inting
+9ints
+9ise
+9ised
+9ises
+9ising
+9se
+9sed
+9ses
+9sing
+9wer
+9wers
+8ressure
+9oject
+9ojects
+9oof
+9oofs
+9oposal
+9otest
+9otests
+8unch
+9nched
+9ncher
+9nchers
+9nches
+9nching
+7question
+7raid
+9ided
+9iding
+9ids
+9llied
+9llies
+9lly
+9llying
+8eaction
+9form
+9former
+9forms
+9sponse
+7s
+8ank
+8carp
+9arps
+8eal
+9aled
+9aling
+9als
+8hading
+9adings
+9aft
+9afts
+9ot
+9ots
+8ign
+9gned
+9gning
+9gns
+9nk
+9nking
+9nks
+8niper
+9ipers
+8pell
+9ells
+9ies
+9y
+9ying
+9yings
+8tain
+9ained
+9aining
+9ains
+9ate
+9ated
+9ates
+9ating
+9ep
+9epped
+9epping
+9eps
+9rategy
+9ream
+9reams
+9ricken
+9rike
+9rikes
+9riking
+9roke
+9rokes
+9ruck
+9yle
+9yles
+8ubject
+9bjects
+9e
+9ed
+9es
+9ing
+9it
+9its
+9nk
+7tactic
+9ctics
+8endency
+9nor
+9nors
+9rror
+9rrors
+8hreat
+9reats
+9rust
+9rusts
+8op
+9ps
+8rade
+9aded
+9ades
+9ading
+9end
+9ends
+8ype
+9pes
+7vail
+9ilable
+9iled
+9iling
+9ils
+8iew
+9ews
+9olence
+7weigh
+9ighed
+9ighing
+9ighs
+9ight
+9ighted
+9ights
+8ord
+9rds
+9rk
+9rked
+9rker
+9rkers
+9rking
+9rks
+9rld
+9rlds
+6ss
+8es
+5ian
+8s
+6es
+6ng
+8house
+9ouses
+5less
+9ly
+6ine
+9s
+5ries
+7fied
+6ol
+8led
+9ing
+8s
+6y
+7fied
+7ish
+7man
+8en
+7seat
+9ats
+8ide
+9des
+7wide
+8oman
+9men
+5s
+6hip
+9s
+5y
+3p
+4e
+5d
+5e
+6s
+5r
+6s
+5s
+4ing
+4le
+6d
+7om
+9s
+6ment
+9ts
+6r
+7s
+6s
+6t
+7s
+5ing
+8s
+4on
+6ing
+9s
+6s
+4s
+4ure
+7s
+3r
+4age
+7ful
+7ous
+9sly
+9sness
+7s
+5nt
+7e
+8s
+7o
+8es
+8s
+7s
+4b
+5aril
+9s
+5ed
+6tte
+9s
+5ing
+5s
+4d
+4e
+5d
+5s
+4gette
+9s
+4ie
+6d
+6ing
+6r
+7ed
+7ing
+7s
+6s
+5ng
+4lan
+7s
+4s
+5e
+6book
+9ks
+6d
+6r
+7s
+6s
+6ware
+9es
+7ork
+9ks
+5ing
+8s
+4t
+5craft
+9ts
+5ed
+6ous
+9ly
+9ness
+9nesses
+6r
+7s
+6san
+9s
+7ied
+9s
+7y
+8ing
+6zan
+9s
+5house
+9es
+5ier
+8ism
+9sms
+8like
+9y
+8s
+6ng
+8s
+5let
+8s
+6ier
+8st
+7ke
+7ness
+9sses
+8g
+9s
+6y
+5room
+9s
+5s
+6hip
+9s
+6ide
+9s
+5yard
+9s
+3scous
+8es
+8ou
+9us
+4in
+6age
+9s
+6hood
+9ds
+6ly
+6ries
+7y
+6s
+7hip
+9ps
+3ta
+5s
+4eau
+7x
+5r
+6s
+4h
+5er
+6st
+5ie
+7r
+7st
+5s
+5y
+4il
+6le
+8s
+6s
+4ure
+7s
+6ier
+9e
+9es
+9s
+3vade
+7s
+4ert
+7s
+3zin
+6s
+2valence
+9s
+8ies
+8y
+7t
+8ly
+4riance
+9es
+8t
+9s
+7te
+9s
+8ion
+9ons
+6ed
+7s
+5y
+6ing
+3e
+4d
+4let
+7s
+5line
+9s
+7te
+9s
+4n
+5ant
+8al
+9lly
+8ed
+9e
+9es
+9r
+9rs
+8ing
+8or
+9rs
+8s
+5s
+5t
+6s
+4r
+5able
+6ge
+8s
+6ll
+8ed
+8s
+5ed
+6r
+7s
+5ing
+8s
+5less
+7t
+8s
+6id
+8s
+5mount
+9ted
+9ting
+9ts
+5s
+6ed
+6ine
+9s
+6lip
+9s
+5t
+6ly
+6ness
+9ses
+6s
+6ure
+9s
+5up
+7s
+4s
+4t
+5able
+5ed
+6r
+7s
+5ing
+8ly
+6se
+8s
+6veness
+9esses
+5ous
+8ly
+8ness
+9esses
+5s
+4y
+5s
+3in
+5g
+6s
+5ous
+5s
+3yne
+6s
+2w
+3age
+6s
+4l
+5s
+4n
+5s
+4rd
+6ed
+6ice
+9s
+7ng
+6liness
+9esses
+7y
+6ries
+7y
+6s
+7hip
+9ps
+3bane
+7s
+4ell
+7s
+5rries
+7y
+4ind
+7s
+5rd
+7s
+4oy
+6ed
+6ing
+6s
+3catcher
+9rs
+3ed
+5ly
+4r
+5ed
+5ing
+8ly
+5s
+3feeder
+9s
+5teria
+9as
+4ish
+7es
+4lap
+7s
+5op
+7s
+3girl
+7s
+4rass
+8es
+3hage
+7s
+5nd
+7s
+4eard
+8s
+5el
+7s
+5rb
+7s
+6d
+7s
+4ide
+7d
+7s
+6ing
+4ouse
+8s
+3ier
+5st
+4ng
+5ner
+8s
+4sh
+4tch
+7es
+3k
+4ed
+4ing
+4s
+3l
+4ed
+4ick
+7s
+5ng
+7s
+4s
+5taff
+9s
+7ves
+3man
+4en
+3orker
+8s
+3p
+4at
+6s
+4ea
+6s
+5d
+4ie
+6s
+5ng
+4lop
+7s
+4oke
+7s
+5x
+6es
+4s
+4uncher
+9rs
+3rie
+6s
+5te
+7r
+8s
+7s
+6ing
+6ten
+4ote
+4y
+3s
+4hed
+7s
+4kin
+7s
+4lip
+7s
+3tree
+7s
+3y
+2xa
+4e
+4l
+5gia
+8s
+7c
+7es
+6y
+3comb
+7ic
+9al
+9ality
+9ally
+7ries
+8y
+7s
+6ical
+3ed
+4s
+3ib
+5s
+4er
+5st
+4ness
+8es
+5g
+4tides
+6s
+3less
+3swain
+8ed
+8ing
+8s
+3y
+2y
+3dog
+6s
+3ed
+4r
+4st
+3ing
+4sh
+6ly
+6ness
+9ses
+3ly
+3ness
+7es
+3ote
+6s
+5illo
+9s
+3pou
+6s
+4u
+5s
+3s
+4trel
+8s
+6il
+8s
+2z
+3e
+4d
+4n
+5age
+8s
+5ed
+6r
+7s
+5ing
+5s
+4s
+4y
+5s
+3ie
+5d
+5r
+6s
+5s
+6t
+4ly
+4ness
+8es
+5g
+3y
+4ing
+3zes
+1raal
+5ed
+5ing
+5s
+3b
+4apple
+9s
+4bed
+7ly
+7ness
+9sses
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+6t
+5y
+4eater
+9s
+4grass
+9es
+4like
+4meat
+8s
+4s
+5tick
+9s
+4wise
+5ood
+8s
+3chach
+4k
+5a
+6jack
+9ks
+6s
+5back
+9s
+6erries
+9y
+6rain
+9ned
+9ns
+5down
+9s
+5ed
+6r
+7jack
+9cks
+7s
+6t
+7s
+5head
+9s
+5ing
+8s
+5jaw
+8s
+5le
+7d
+7s
+7ware
+9res
+6ier
+8st
+7ng
+9s
+6y
+5nel
+8s
+5pot
+8s
+5s
+6man
+7en
+5up
+7s
+5y
+4ovienne
+9nes
+5we
+7s
+3dle
+6d
+6r
+7s
+6s
+7ong
+9gs
+6walk
+9ks
+5ing
+8s
+3ft
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5less
+5manship
+9hips
+5s
+6man
+9like
+9ly
+9ship
+9ships
+7en
+6people
+8rson
+9sons
+6woman
+9en
+5work
+9s
+5y
+3g
+4fast
+4ged
+7ness
+9sses
+5ier
+7st
+6ly
+6ness
+9ses
+5y
+4s
+5man
+6en
+3ic
+5s
+4g
+5fluke
+9es
+5s
+3ke
+5berries
+9y
+5d
+5s
+4ing
+3m
+4be
+6s
+5o
+6clink
+9nks
+6es
+6s
+4e
+5s
+6ies
+6y
+4full
+4mable
+5ed
+6r
+7s
+5ing
+4oisie
+9s
+7y
+4p
+5bark
+9s
+5ed
+6r
+7s
+6t
+7s
+5fish
+9es
+5ier
+7st
+6ng
+6t
+7s
+5on
+7ed
+7ing
+7s
+6on
+8s
+5s
+5y
+4s
+3n
+4achan
+9s
+5ge
+7s
+4berries
+8y
+4ch
+6ed
+7s
+6ing
+4e
+5d
+5flies
+7y
+5s
+6bill
+9ls
+4ia
+6l
+7ly
+6te
+8s
+5ectomies
+9my
+5ng
+5ocerebral
+6facial
+6gnomies
+9my
+6logical
+9ically
+9ies
+9ist
+9ists
+9y
+6meter
+9ers
+9ric
+9rical
+9ries
+9rist
+9rists
+9ry
+6pagi
+9us
+6sacral
+7copies
+9pist
+9pists
+9py
+6tomies
+9y
+5um
+7s
+4k
+5case
+9s
+5ed
+6r
+6st
+5handle
+9les
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+6sh
+5le
+7d
+7s
+6ing
+6y
+5ness
+9es
+5ous
+5pin
+8s
+5s
+6haft
+9ts
+5y
+4nied
+7s
+5og
+7e
+8s
+7s
+5y
+6ing
+4reuch
+9s
+4s
+4ts
+6es
+3paud
+7s
+4e
+5d
+5hanger
+9ers
+9ing
+9ings
+5like
+5s
+4ier
+6st
+5ng
+4le
+6s
+4ola
+7s
+4ped
+6r
+7s
+5ie
+7r
+7s
+8t
+6ng
+5y
+4s
+5hoot
+9er
+9ers
+9s
+4ulence
+9es
+8t
+9ly
+6osities
+9ty
+7us
+9ly
+9ness
+9nesses
+4y
+3quelure
+9es
+3re
+5s
+3ses
+4h
+5ed
+6r
+7s
+6s
+5ing
+8ly
+5pad
+8s
+5worthiness
+9hy
+4is
+4s
+5amenta
+9tum
+5er
+6st
+5itude
+9es
+5ly
+5ness
+9es
+5ulacean
+9eous
+3tch
+6es
+4e
+5d
+5ful
+8s
+5r
+6ed
+6iform
+7ng
+9s
+6less
+8t
+9s
+7ike
+6ous
+6s
+5s
+4hur
+7s
+4ing
+4on
+6ic
+6s
+4ur
+6s
+3unch
+7able
+7ed
+8s
+7ier
+9st
+8ness
+9esses
+9g
+7y
+3vat
+6s
+6ted
+7ing
+4e
+5d
+5n
+6ed
+6ing
+6ly
+6ness
+9ses
+6s
+5r
+6s
+5s
+4ing
+7s
+3w
+4dad
+7dies
+8y
+7s
+4fish
+8ed
+9s
+8ing
+4l
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5s
+6pace
+9es
+5way
+8s
+5y
+4s
+3y
+4er
+6s
+4fish
+8es
+4on
+6ed
+7r
+8s
+6ing
+7st
+9s
+6s
+4s
+4thur
+8s
+3ze
+5d
+5s
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+4y
+5weed
+9s
+2each
+6s
+4gh
+6s
+4k
+5ed
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+5s
+5y
+4m
+5cups
+5ed
+6r
+7ies
+7s
+7y
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5laid
+6ike
+5puff
+9s
+5s
+5ware
+9s
+6ove
+5y
+4nce
+7s
+5t
+4se
+6d
+6less
+6r
+7s
+6s
+5ier
+7st
+6ng
+5ote
+8d
+8s
+7ing
+5y
+4table
+5e
+6d
+6s
+5ic
+6n
+7e
+8s
+7g
+7ine
+9es
+7s
+6on
+8al
+8ism
+9sms
+9st
+9stic
+9sts
+8s
+6ve
+8ly
+8ness
+9esses
+8s
+7ities
+9y
+5or
+7s
+8hip
+9ips
+5ress
+9es
+6ix
+8es
+5ural
+7e
+8hood
+9oods
+8liness
+9y
+8s
+9hip
+9hips
+3che
+6s
+3d
+4al
+4ence
+8s
+6da
+7um
+6t
+7ial
+9led
+9ling
+9lism
+9lisms
+9lled
+9lling
+9ls
+6za
+8s
+4ibilities
+9ty
+6le
+8ness
+9esses
+7y
+5t
+6abilities
+9lity
+8le
+9eness
+9y
+6ed
+6ing
+6less
+6or
+8s
+6s
+6worthy
+4o
+5s
+4s
+4ulities
+8y
+6ous
+9ly
+9ness
+9nesses
+3e
+4d
+5al
+5s
+4ing
+4k
+5ier
+7st
+5s
+5y
+4l
+5ed
+5ing
+5s
+4p
+5age
+8s
+5ed
+6r
+7ed
+7s
+5ie
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+8ly
+5mouse
+5s
+5y
+4s
+5e
+6d
+6s
+5h
+6ed
+7s
+6ier
+8st
+7ng
+6y
+5ing
+3m
+4aillere
+9res
+6ns
+5nt
+5ster
+9s
+5te
+7d
+7s
+6ing
+7on
+9ism
+9isms
+9ist
+9ists
+9s
+6or
+8ia
+9al
+9es
+9um
+9ums
+8s
+8y
+4e
+5s
+4ini
+7s
+4ocarp
+9s
+5na
+7s
+5r
+6ne
+8s
+6s
+5sin
+4s
+5in
+3na
+5s
+5te
+7d
+7ly
+6ion
+9s
+6ure
+9s
+4el
+6ate
+9d
+9s
+8ing
+9on
+9ons
+6ed
+6ing
+6late
+9ed
+9es
+9ing
+9ion
+9ions
+7e
+8d
+8s
+7ing
+6s
+4shaw
+8s
+4ulate
+9d
+8ion
+9ons
+3odont
+8s
+4le
+6s
+5ian
+8s
+6sation
+9ions
+7e
+8d
+8s
+7ing
+7t
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+4phagies
+8ous
+8y
+4sol
+7s
+6te
+8d
+8s
+7ic
+8ng
+3pance
+8s
+4e
+5d
+5hanger
+9ers
+9ing
+9ings
+5rie
+8s
+5s
+5y
+4ier
+6st
+5ness
+9es
+6g
+5tant
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+6us
+8es
+4oline
+9s
+5n
+6s
+4s
+4t
+4uscle
+9s
+7ular
+9e
+9es
+9ous
+4y
+3scendi
+8o
+9ed
+9es
+9ing
+9s
+7t
+8ade
+9des
+8ed
+8ic
+8s
+5ive
+8ly
+5ograph
+9phs
+4ol
+6s
+4s
+5es
+6t
+7s
+5ier
+7st
+5y
+4t
+5a
+6l
+5ed
+5fallen
+9enly
+9enness
+5ing
+8s
+5less
+5on
+7s
+5s
+4yl
+6ic
+6s
+3taceous
+9ses
+9sly
+4ic
+6s
+5n
+6ise
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+6oid
+9s
+7us
+6s
+5sm
+7s
+4onne
+8s
+6s
+3utzer
+8s
+3valle
+8s
+5sse
+8d
+8s
+7ing
+4ette
+8s
+4ice
+7d
+7s
+3w
+4cut
+7s
+4e
+5d
+5l
+6ist
+9s
+6led
+8ries
+9y
+7ing
+6s
+6work
+9ks
+5s
+4ing
+4less
+4man
+6te
+8s
+5en
+4neck
+8s
+4s
+2ia
+4nt
+4s
+3b
+4bage
+8s
+5ed
+6r
+7s
+5ing
+8s
+5le
+7d
+7s
+6ing
+4ella
+8r
+7um
+4le
+4rate
+7ion
+9ns
+5iform
+5ose
+6us
+4s
+4work
+8s
+3cetid
+8s
+4k
+5ed
+6t
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6y
+5ing
+5s
+5y
+4oid
+7s
+3ed
+4r
+5s
+4s
+3key
+3m
+4e
+5d
+5ful
+5less
+5n
+5s
+5wave
+9s
+4ina
+7l
+8ese
+9ses
+8isation
+9se
+9sed
+9ses
+9sing
+9st
+9stics
+9sts
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+6e
+6g
+6i
+7s
+6ogenic
+7logic
+9gical
+9gies
+9gist
+9gists
+9gy
+7us
+9ness
+9nesses
+6y
+4mer
+7s
+4p
+5ed
+6r
+7s
+5ier
+7st
+6ng
+5le
+7d
+7s
+6ing
+5s
+5y
+4s
+5on
+7ed
+7ing
+7ness
+9sses
+7s
+3nal
+5te
+7d
+4e
+5d
+5s
+4ge
+6d
+6ling
+9gs
+6r
+7s
+6s
+6worthy
+5ing
+8ly
+8s
+5le
+7s
+4icultural
+5gerous
+5ng
+5te
+7s
+4kle
+7d
+7root
+9ots
+7s
+6ier
+8s
+9t
+7ng
+6y
+4oid
+7al
+7ean
+9ns
+7s
+5lette
+9es
+6ine
+9d
+9s
+5se
+4um
+6s
+3ollo
+7s
+4s
+5es
+3pe
+5s
+4ple
+7d
+8om
+9ms
+7r
+8s
+7s
+7ware
+9res
+6ing
+9ly
+9s
+3s
+4e
+5s
+4ic
+5s
+4p
+5ate
+8d
+7ion
+9ns
+7ure
+9es
+5bread
+9ds
+5ed
+6n
+7ed
+7ing
+7s
+6r
+7s
+6st
+5head
+9s
+5ier
+7s
+8t
+6ly
+6n
+7ess
+9ses
+7g
+7s
+5ly
+5ness
+9es
+5s
+5y
+4sa
+6l
+5cross
+9sed
+9ses
+9sing
+5um
+4ta
+6e
+6te
+8d
+5iform
+5obalite
+9ites
+3t
+4eria
+8l
+7on
+9s
+7um
+9s
+4h
+5idial
+5omancies
+9cy
+5s
+4ic
+6al
+8ities
+9ty
+8ly
+8ness
+9esses
+7ster
+9ers
+6isable
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+8m
+9s
+7zable
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+6s
+5que
+8d
+8s
+7ing
+4s
+4ter
+7s
+5ur
+7s
+3vens
+4vens
+2oak
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5s
+5y
+3c
+4eate
+5in
+7e
+8s
+7s
+5ous
+4he
+6s
+6t
+7ed
+8r
+9s
+7ing
+9gs
+7s
+4i
+5dolite
+9tes
+5ne
+4k
+5ed
+6ries
+7y
+6t
+7ed
+7s
+5ing
+5pot
+8s
+5s
+4odile
+9s
+8ian
+9ans
+5isite
+9es
+6te
+8s
+5smia
+9s
+4s
+4us
+6es
+3ft
+5ed
+6r
+7s
+5ing
+8s
+5s
+3g
+4ged
+5ies
+6ng
+5y
+4s
+3issant
+9s
+3jik
+6s
+3kinole
+9s
+3mack
+7s
+4b
+5ec
+7s
+6d
+5ing
+5s
+4e
+5d
+5s
+4ing
+4lech
+8s
+4orna
+8s
+7e
+8s
+3ne
+5s
+5t
+6s
+4ies
+5sh
+4k
+5er
+6st
+4y
+5ism
+8s
+3odle
+7d
+7s
+6ing
+4k
+5back
+9ed
+9s
+5ed
+7er
+8st
+7ly
+7ness
+9sses
+6r
+7ies
+7y
+6st
+5ing
+5neck
+9s
+5s
+4l
+5ed
+5ing
+5s
+4n
+5ed
+6r
+7s
+5ing
+8s
+5s
+4ve
+6s
+3p
+4bound
+4duster
+9rs
+4ful
+7l
+7s
+4land
+8s
+5ess
+4ped
+6r
+7s
+5ie
+7s
+6ng
+8s
+5y
+4s
+5ick
+3quante
+9s
+5et
+7ed
+7ing
+7s
+7te
+9s
+5ignole
+9les
+6s
+3re
+5pati
+9s
+5s
+3sier
+7ed
+7s
+4s
+5abilities
+9ity
+7le
+6ndra
+9as
+6rm
+8s
+5band
+9ed
+9ing
+9ings
+9s
+7r
+8red
+9ing
+8s
+6eam
+9s
+8rer
+9ers
+7nch
+9her
+9hers
+9hes
+6ill
+9s
+7rth
+9hs
+7t
+8e
+9s
+8ing
+8ten
+6ones
+7w
+8er
+9rs
+8man
+9en
+8s
+6red
+9s
+8ed
+9ding
+9dings
+9ds
+6uck
+9s
+5check
+9ked
+9king
+9ks
+6laim
+9ms
+6ourt
+6urrent
+9ents
+7t
+8s
+8ting
+9ings
+5e
+6d
+6r
+7s
+6s
+7t
+6tte
+9s
+5fall
+9s
+6ield
+7re
+9s
+7sh
+9es
+5hair
+9s
+7tch
+9hed
+9hes
+9hing
+9hings
+6ead
+9s
+5ing
+8s
+6sh
+5jack
+9s
+5let
+8s
+6ight
+9ts
+7nguistic
+6y
+5ness
+9es
+5opterygian
+6ver
+9s
+5patch
+9hes
+6iece
+9es
+5road
+9s
+6uff
+9ed
+9ing
+9s
+5talk
+9s
+6ie
+8d
+8s
+6own
+6ree
+9s
+5walk
+9s
+7y
+8s
+6ind
+9s
+7se
+6ord
+9s
+8t
+9s
+4t
+5ini
+8s
+7o
+3tal
+6a
+7ria
+9as
+6ine
+7sm
+9s
+6s
+6um
+4ch
+6ed
+7s
+7t
+8ed
+9er
+9ers
+8ier
+9est
+9ness
+9nesses
+8s
+8y
+4on
+6bug
+9s
+6ic
+6s
+4tle
+7s
+3uch
+6ed
+7s
+6ing
+4p
+5ade
+8s
+5e
+6d
+6r
+7s
+6s
+5ier
+8s
+7st
+6ly
+6ness
+9ses
+7g
+5on
+7s
+6us
+5s
+5y
+4se
+6ly
+5tade
+9s
+4t
+5e
+6s
+5on
+7s
+5s
+3w
+4bar
+7red
+8ing
+7s
+5erries
+8y
+5oot
+8s
+4d
+5ed
+7ly
+7ness
+9sses
+6r
+7s
+5ie
+7s
+6ng
+5s
+6ource
+9ced
+9ces
+9cing
+9cings
+5y
+4ea
+6s
+5d
+5r
+6s
+4feet
+5oot
+8s
+4ing
+7ly
+4keeper
+9rs
+4n
+5ed
+6r
+7s
+6t
+7s
+5ing
+8s
+5land
+9s
+6ess
+7t
+8s
+5piece
+9es
+5s
+5work
+9s
+4s
+5feet
+6oot
+5tep
+8ped
+8s
+3ze
+5r
+6s
+5s
+4ier
+7s
+4zled
+2u
+3been
+7s
+3ces
+4ial
+7ly
+6n
+7s
+6te
+8ly
+8s
+5ble
+8s
+5fer
+8ous
+8s
+6ied
+8r
+9s
+8s
+7x
+8es
+8ion
+9ons
+6orm
+9ly
+9s
+6y
+7ing
+5verbal
+9alism
+9alisms
+9alist
+9alists
+4k
+5s
+3d
+4ded
+5ier
+7st
+6ng
+5le
+7d
+7s
+6ing
+5y
+4e
+5ly
+5ness
+9es
+5r
+5s
+6t
+4ites
+6ies
+6y
+4s
+4y
+3e
+4l
+5er
+6st
+5ler
+7st
+6s
+6y
+5ness
+9es
+5s
+5ties
+6y
+4s
+4t
+5s
+3ft
+5ier
+7st
+5y
+3ise
+6d
+6r
+7s
+7weight
+9ights
+6s
+6way
+9s
+7ear
+9rs
+5ie
+7s
+6ng
+8s
+4ve
+6s
+4zie
+7s
+3ller
+7s
+3mb
+5cloth
+9hs
+5ed
+6r
+7s
+5ier
+7st
+6ng
+5le
+7d
+7s
+6ier
+8s
+9t
+7ness
+9sses
+8g
+9s
+6y
+5s
+5um
+7s
+5y
+4en
+6al
+8s
+6s
+4horn
+8s
+4mack
+8s
+5ie
+7r
+7s
+8t
+6ness
+9ses
+5ock
+8s
+5y
+4p
+5ed
+6r
+6st
+6t
+7s
+5ier
+7st
+6ng
+5le
+7d
+7s
+6ier
+8st
+7ng
+9s
+6y
+5s
+5y
+3nch
+6able
+6ed
+7r
+8s
+7s
+6ie
+8r
+8s
+9t
+7ly
+7ness
+9sses
+8g
+9s
+6y
+4k
+5ed
+5le
+7d
+7s
+6ing
+5s
+4odal
+6e
+7s
+3or
+5es
+5s
+3pper
+7s
+3ra
+5l
+3s
+4ade
+7d
+7r
+8s
+7s
+6ing
+6o
+7es
+7s
+4e
+5s
+5t
+6s
+4h
+5abilities
+9ity
+7le
+5ed
+6r
+7s
+6s
+5ing
+8ly
+5proof
+4ian
+7s
+5e
+6s
+5ly
+4t
+5a
+6cea
+9n
+9ns
+8ous
+6e
+6l
+6te
+8d
+7ion
+9ns
+5ed
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5less
+5ose
+5s
+5y
+4y
+3tch
+6ed
+7s
+6ing
+9s
+3ve
+5s
+3x
+4es
+3zado
+7es
+7s
+4eiro
+8s
+4ie
+6s
+2wth
+5s
+2y
+3babies
+6y
+3ing
+6ly
+6s
+3motherapies
+9apy
+3obank
+8s
+5iological
+9gies
+9gist
+9gists
+9gy
+4cable
+9s
+5onite
+9es
+4gen
+7ic
+9ally
+9s
+8es
+7s
+7y
+5lobulin
+9lins
+4hydrate
+9tes
+4lite
+8s
+4meter
+9s
+7ric
+9es
+8y
+4nic
+7s
+4philic
+6orus
+9ses
+6ysics
+7te
+9s
+5lankton
+9tons
+5recipitate
+7serve
+9rved
+9rves
+9rving
+6obe
+9s
+7tectant
+9ctants
+9ctive
+4scope
+9s
+8ic
+9es
+8y
+5tat
+8ic
+8s
+5urgeon
+9ons
+9ries
+9ry
+8ical
+4therapies
+9py
+5ron
+8s
+3pt
+5adia
+6esthesia
+9hesias
+9hetic
+6l
+6nalyses
+9ysis
+9yst
+9ysts
+9ytic
+9ytical
+6rithm
+9hms
+5esthesia
+9esias
+5ic
+7al
+9ly
+5o
+6biont
+9nts
+9ses
+9sis
+6clastic
+7occal
+9ci
+9coses
+9cosis
+9cus
+6gam
+9ian
+9ic
+9ies
+9ist
+9ists
+9ous
+9s
+9y
+7enic
+7ram
+9ms
+9ph
+9pher
+9phers
+9phic
+9phical
+9phies
+9phist
+9phists
+9phs
+9phy
+6logic
+9ical
+9ies
+9ist
+9ists
+9y
+6meria
+9ias
+8ter
+9ers
+7nesia
+9sias
+9sic
+6n
+7s
+7ym
+9ous
+9s
+6phyte
+9tes
+9tic
+6rchid
+9idism
+9idisms
+9ids
+9ism
+9isms
+6s
+7poridia
+9ridium
+6zoic
+9te
+9tes
+8ologies
+9logist
+9logy
+5s
+3stal
+7isable
+9ation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8zable
+9ation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7line
+9nes
+9nities
+9nity
+9sable
+9sation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9te
+9tes
+9tic
+9tis
+9tises
+9zable
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8ography
+9id
+9idal
+9ids
+9mancy
+7s
+1sardas
+7es
+1tene
+5s
+4idia
+7um
+5form
+4oid
+5phoran
+9ans
+9e
+9es
+1uadrilla
+9s
+3tro
+6s
+2b
+3age
+6s
+4ne
+6lle
+9s
+6s
+4ture
+8s
+3bed
+4ier
+6s
+7t
+5ng
+7s
+5sh
+7ly
+4y
+5hole
+9s
+3e
+4b
+5s
+4d
+4r
+5s
+4s
+3hood
+7s
+3ic
+5a
+6l
+7ly
+7ness
+9sses
+6s
+5ities
+7y
+5le
+7s
+6y
+5s
+5ula
+7um
+4form
+4ng
+4sm
+6s
+5t
+6ic
+8ally
+6s
+4t
+5al
+5i
+5s
+5us
+7es
+3less
+3oid
+6al
+6s
+3s
+2cking
+4old
+7ed
+7ing
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7ly
+7om
+9s
+7ries
+8y
+7s
+5o
+6ed
+6flower
+9wers
+6ing
+6pint
+9ts
+6s
+3uliform
+5late
+9d
+9ly
+4mber
+8s
+5iform
+4rbit
+8aceous
+9l
+8s
+2d
+3bear
+7s
+3den
+6s
+4ie
+6s
+5n
+6s
+4le
+6d
+6r
+7s
+6s
+7ome
+5ier
+7st
+6ng
+5y
+4y
+3gel
+6ed
+7r
+8s
+6ing
+6led
+8r
+9s
+7ing
+9gs
+6s
+5rie
+8s
+3s
+3weed
+7s
+2e
+3d
+3ing
+6s
+4st
+6s
+3s
+4ta
+6s
+2ff
+4ed
+4in
+6g
+6s
+4le
+6d
+6s
+7s
+5ing
+7k
+8s
+4o
+4s
+4uffle
+9s
+2if
+4s
+3ng
+3rass
+7ed
+8s
+7ier
+9rs
+8ng
+3sh
+5es
+4inart
+9s
+6e
+7s
+6ier
+9s
+4se
+6r
+7s
+6s
+3t
+4er
+6ed
+6ing
+6s
+4ikin
+8s
+4s
+4tle
+7d
+7s
+6ing
+2ke
+4s
+2lch
+5es
+5ie
+7s
+3et
+5s
+4x
+5es
+3ices
+5id
+7s
+6form
+6ne
+8s
+4narian
+9ns
+8ly
+7y
+3l
+4ay
+6s
+4ed
+5nder
+9s
+5r
+6s
+5t
+6s
+4ied
+6s
+5ng
+7s
+5on
+7ly
+7s
+5s
+6es
+4s
+4y
+5ing
+6sm
+8s
+3m
+4ed
+5n
+4iferous
+5na
+7nt
+7te
+9d
+9s
+8ing
+9on
+9ons
+6g
+4s
+3otte
+7s
+3pa
+5bilities
+9ty
+6le
+8ness
+9esses
+7y
+5e
+5tory
+4rit
+7s
+3t
+4ch
+6es
+4er
+6s
+4i
+5c
+5er
+6st
+5gen
+8s
+5sh
+7ly
+7ness
+9sses
+6m
+7s
+6t
+7s
+5vabilities
+9lity
+8le
+7r
+8s
+7table
+8e
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+4like
+4rate
+8d
+5iform
+4s
+4urable
+7l
+8ly
+7ti
+6e
+7d
+7less
+7s
+6ing
+7st
+9s
+5s
+6es
+4y
+3ver
+6in
+8eer
+9ers
+8s
+6s
+6t
+7age
+9es
+8iled
+7s
+2macean
+8s
+4ric
+6n
+7s
+5one
+8s
+3bent
+5r
+6bund
+9ds
+6ed
+7r
+8s
+6ing
+6less
+6ment
+9ts
+6s
+7ome
+9ely
+9eness
+4ia
+6s
+4rance
+9s
+5ous
+8ly
+8ness
+9esses
+4ungi
+8s
+3ec
+5s
+3in
+5s
+3merbund
+9ds
+6s
+4in
+6gtonite
+9nites
+6s
+3quat
+7s
+3shaw
+7s
+3ulate
+8d
+8ly
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+9eness
+5et
+7s
+5i
+6form
+5ocirri
+9rus
+6nimbi
+9bus
+9buses
+6se
+7trati
+9atus
+6us
+5us
+2nabula
+3ctation
+9ns
+9us
+8ve
+7or
+9s
+9y
+3dies
+4um
+6s
+4y
+3eal
+5te
+7d
+7ly
+6ic
+4i
+5form
+9s
+4tte
+7s
+4us
+3iform
+8s
+3jevoi
+8s
+3ner
+6s
+4ilinctus
+9tuses
+5ng
+7er
+8st
+7ly
+7ness
+9sses
+7s
+2p
+3bearer
+9s
+4oard
+8ed
+8ing
+8s
+3cake
+7s
+3el
+5ed
+6r
+7s
+5ing
+5lation
+9ons
+6ed
+7r
+8s
+6ing
+5s
+3ferron
+9s
+4ul
+6s
+3gall
+7s
+3head
+7s
+3id
+5inous
+6ties
+7y
+5s
+3like
+3man
+4en
+3ola
+6ed
+6ing
+6r
+6s
+6ted
+3pa
+5s
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7s
+4y
+3rammonium
+9iums
+4eous
+5ssus
+9es
+4ic
+5ferous
+5te
+7s
+4onickel
+9els
+5us
+4um
+6s
+3s
+4ful
+3ula
+6e
+6r
+6te
+5e
+6s
+5iferous
+2r
+3abilities
+9y
+5le
+7ness
+9sses
+6y
+4cao
+7s
+5ies
+5oa
+7s
+5y
+4gh
+6s
+4ndera
+9s
+8o
+9s
+4ra
+6s
+5e
+6s
+5i
+6ne
+8s
+6s
+7ation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+4ssow
+8s
+4t
+5e
+6d
+6s
+7hip
+9ps
+5ing
+6on
+6ve
+8ly
+8ness
+9esses
+8s
+5or
+7ial
+7s
+8hip
+9ips
+7y
+5rix
+8es
+5s
+3b
+4able
+4ed
+5r
+6s
+4ing
+7s
+4less
+4s
+5ide
+8s
+5tone
+9s
+3ch
+5ef
+7s
+6s
+4ulio
+8s
+5ma
+7s
+6in
+8e
+9s
+8s
+3d
+4ed
+4ier
+6st
+5ness
+9es
+6g
+4le
+6d
+6r
+7s
+6s
+5ing
+4s
+4y
+3e
+4d
+4less
+4r
+5s
+4s
+4t
+5s
+5tage
+9s
+6e
+7d
+7ment
+9nts
+7s
+6ing
+3f
+4ew
+6s
+4s
+4uffle
+9d
+9s
+8ing
+3ia
+5e
+5l
+6ism
+9s
+8t
+9ic
+9s
+5s
+4e
+5s
+5t
+6herapies
+9apy
+6s
+4ng
+4o
+5s
+6a
+6ities
+8y
+5us
+7er
+8st
+7ly
+7ness
+9sses
+4te
+6s
+4um
+6s
+3l
+4ed
+5r
+6s
+5w
+6s
+4i
+5cue
+8d
+8s
+7ing
+5er
+6s
+7t
+6wurlie
+9lies
+5ly
+5ness
+9es
+6g
+7s
+4paper
+9s
+4s
+4y
+5cue
+8s
+3mudgeon
+9nly
+9ns
+5rring
+9gs
+3n
+4aptious
+4ey
+4ier
+6st
+4s
+4y
+3pel
+6s
+3r
+4ach
+7s
+5gh
+7s
+5jong
+9s
+5n
+6s
+6t
+7ier
+9st
+7s
+7y
+5wong
+9s
+4ed
+5jong
+9s
+5ncies
+7y
+6t
+7ly
+7ness
+9sses
+7s
+4icle
+8s
+6ula
+9r
+8um
+9ms
+5e
+6d
+6r
+7ies
+7s
+7y
+6s
+5jong
+9s
+5ng
+5sh
+7ly
+7ness
+9sses
+4s
+4y
+5comb
+9ed
+9ing
+9s
+5ing
+8s
+3s
+4al
+4e
+5d
+6er
+7st
+6ly
+6ness
+9ses
+5larie
+5nary
+5r
+6s
+5s
+4i
+5ng
+7s
+5tor
+8s
+8y
+5ve
+7ly
+7ness
+9sses
+7s
+4or
+6ary
+6es
+6ial
+7ly
+7ness
+9sses
+6s
+6y
+4t
+5ness
+9es
+4us
+3t
+4ail
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+6n
+7ed
+7ing
+7less
+7s
+5l
+6ax
+8e
+9s
+6s
+5na
+7s
+5te
+6ion
+9s
+5xe
+7s
+4er
+5sies
+6t
+6y
+4ilage
+9s
+4ly
+4ness
+8es
+4sey
+7ed
+7ing
+7s
+5ied
+7s
+5y
+6ing
+3ule
+3vaceous
+9sly
+6ious
+5te
+7d
+6ion
+9s
+7ve
+6ure
+9s
+4e
+5ball
+9ed
+9ing
+9s
+5d
+6ly
+6ness
+9ses
+5s
+6ome
+5t
+6ed
+6ing
+6s
+6ted
+7ing
+5y
+4icaudate
+6ostate
+5er
+6st
+5foliate
+7rm
+5lineal
+9ally
+9ar
+9arity
+9arly
+5ness
+9es
+6g
+5rostral
+5tal
+6ies
+6y
+4y
+2scus
+6es
+3ec
+5s
+3h
+4at
+6s
+5w
+6s
+4es
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+5on
+7ed
+8t
+9s
+7ing
+7less
+7s
+7y
+4ty
+4y
+3k
+4s
+3p
+4al
+5te
+7d
+4ed
+4id
+6al
+7te
+9d
+8ion
+9ons
+6es
+6or
+8e
+9s
+8s
+6s
+5er
+6st
+5s
+4s
+4y
+3s
+4ed
+6ly
+6ness
+9ses
+5r
+6s
+5s
+4ing
+4o
+5s
+4word
+8s
+3tard
+7s
+7y
+4ock
+7s
+5de
+7s
+6ial
+8n
+9s
+9ship
+9ships
+7er
+9s
+8s
+6y
+5m
+6able
+7ries
+9ly
+9ness
+9nesses
+8y
+6ed
+7r
+8s
+6house
+9ses
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6s
+7house
+9uses
+5s
+4rel
+7s
+4umal
+8s
+7ries
+8y
+3um
+5s
+2t
+3abilities
+9y
+4neous
+9ly
+4way
+7s
+3back
+7s
+5nk
+7s
+3ch
+5a
+5eries
+7ries
+8y
+7y
+6s
+3down
+7s
+3e
+4ly
+4ness
+8es
+4r
+4s
+5ie
+7r
+7st
+5t
+5y
+4y
+5s
+3glass
+4rass
+8es
+3icle
+7s
+5ula
+8e
+8r
+4e
+5s
+4kin
+7s
+4n
+5isation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5s
+4s
+5es
+3las
+6es
+6s
+7es
+4er
+6ies
+6s
+6y
+5t
+6s
+4ine
+7s
+3off
+6s
+4ut
+6s
+4ver
+7s
+3purse
+8s
+3s
+4cene
+8s
+3table
+5ge
+7s
+4er
+6s
+4hroat
+9s
+4ier
+6s
+7t
+5ng
+7ly
+7s
+4le
+6bone
+9es
+6d
+6fish
+9hes
+6s
+5ing
+4o
+5e
+6s
+4y
+3up
+5s
+3water
+8s
+4ork
+7s
+6m
+7s
+2vee
+5s
+4tte
+7s
+2z
+3zes
+4ie
+6s
+1wm
+3s
+2tch
+5ed
+6s
+5ing
+1yan
+4amid
+8e
+9s
+8s
+5te
+7s
+4ic
+5d
+6ation
+9ons
+6e
+7d
+7s
+6ing
+9s
+6s
+5n
+6e
+7s
+6s
+5se
+7d
+7s
+6ing
+5te
+7s
+6ic
+5ze
+7d
+7s
+6ing
+4o
+5acetylene
+9ylenes
+7rylate
+9lates
+5bacteria
+9erium
+5cobalamin
+9lamine
+9lamins
+5ethylate
+9lated
+9lates
+9lating
+9lation
+5gen
+8amide
+9mides
+8eses
+9sis
+9tic
+8ic
+8s
+5hydrin
+9ins
+5meter
+9rs
+5phyte
+9es
+5sed
+7s
+6is
+5tic
+6ype
+9s
+4s
+4urate
+9s
+6et
+8s
+3thi
+6a
+6form
+6um
+5us
+2ber
+5athlete
+9etes
+9etics
+5cafe
+9s
+7st
+9s
+6hondria
+9driac
+9driacs
+9drias
+6rime
+9es
+9inal
+9inals
+5nate
+9d
+9s
+8ing
+9on
+9ons
+7ut
+9s
+6etic
+9cal
+9cally
+9cian
+9cians
+9cist
+9cists
+9cs
+5pet
+8s
+6hobia
+9ias
+9ic
+6unk
+9s
+5securities
+9rity
+6pace
+9es
+6quatter
+9tters
+9tting
+9ttings
+5terrorism
+9orisms
+9orist
+9orists
+5war
+8s
+3org
+6s
+3rarian
+9s
+4id
+6s
+2cad
+5aceous
+5eoid
+9s
+5ophyte
+9tes
+5s
+4s
+5es
+5in
+7s
+3lamate
+9s
+6en
+8s
+5ndelate
+9ates
+6thaceous
+5se
+7s
+5zocine
+9nes
+4e
+5car
+8s
+5d
+5path
+9s
+5r
+6ies
+6s
+6y
+5s
+5way
+8s
+4ic
+6al
+8ities
+9ty
+8ly
+8s
+6ism
+9s
+7ties
+8y
+6ly
+5n
+6g
+7s
+6s
+5sation
+9ons
+6e
+7d
+7s
+6ing
+6t
+7s
+5tol
+8s
+5zation
+9ons
+6e
+7d
+7s
+6ine
+9s
+8g
+4o
+5addition
+9tions
+6liphatic
+7kane
+9nes
+5barbitone
+9itones
+5dextrin
+9rins
+6ialyses
+9ysis
+7ene
+9es
+5geneses
+9sis
+6iro
+9s
+6raph
+9hic
+9hs
+5hexane
+9nes
+9none
+9nones
+8imide
+9mides
+8ylamine
+5id
+7al
+9ly
+7ian
+9ns
+7s
+5lith
+9s
+5meter
+9rs
+8ries
+9y
+5nal
+6e
+7s
+6ic
+8al
+9lly
+7te
+9s
+5olefin
+9inic
+9ins
+5paedia
+9ias
+9ic
+9ist
+9ists
+7raffin
+9ffins
+6ean
+7dia
+9as
+9c
+9st
+9sts
+7ntadiene
+9ane
+9anes
+9olate
+9olates
+7s
+6ian
+7c
+6legia
+9ias
+9ic
+6ropane
+9anes
+6s
+5rama
+9s
+8ic
+5s
+6erine
+9nes
+7s
+6is
+6permous
+7orin
+9ine
+9ines
+9ins
+6tomate
+9atous
+9e
+9es
+9ous
+7yle
+9ed
+9es
+9ing
+5thyme
+9es
+9ia
+9iac
+9iacs
+9ias
+9ic
+9ics
+6omic
+6ron
+9s
+4us
+6es
+2der
+5s
+2eses
+4is
+2gnet
+6s
+2lices
+4nder
+8ed
+8ing
+8s
+6raceous
+7ic
+9al
+9ality
+9ally
+9alness
+9ities
+9ity
+8form
+8te
+9es
+7oid
+9ds
+4x
+2ma
+4e
+4graph
+9s
+4r
+5s
+4s
+4tia
+6cs
+6um
+3bal
+6eer
+9s
+7r
+8s
+6ist
+9s
+6o
+7es
+7m
+8s
+7s
+6s
+4idia
+7um
+9s
+5form
+4ling
+8s
+3e
+4ne
+6s
+4s
+3iferous
+3lin
+6g
+7s
+6s
+3ogene
+8s
+5raph
+9ic
+9s
+4id
+4l
+5s
+4phane
+9s
+8ous
+4se
+6ly
+4trichies
+9ous
+9y
+4us
+2nanche
+8s
+3egetic
+3ghanedd
+9ds
+3ic
+5al
+7ly
+7ness
+9sses
+5ism
+8s
+5s
+3odont
+8s
+4molgi
+8us
+4philia
+9as
+9st
+9sts
+6obia
+9as
+5odous
+4sural
+7e
+8s
+2peraceous
+3her
+6ed
+6ing
+6s
+3res
+6es
+6s
+7es
+4ian
+7s
+5d
+6es
+6s
+5ne
+6id
+8s
+6odont
+9nts
+7id
+9s
+5pedia
+9um
+9ums
+5s
+4oheptadine
+9adines
+5terone
+9nes
+4us
+6es
+3sela
+7e
+2st
+4eamine
+9es
+5ctomies
+9y
+5in
+7e
+8s
+7ic
+7s
+4ic
+6erci
+9oid
+9oids
+9oses
+9osis
+9us
+5d
+6ean
+9s
+6s
+5form
+5ne
+7s
+6oses
+8is
+6uria
+9as
+5tides
+7s
+8es
+4ocarp
+9ic
+9s
+6ele
+9s
+5genous
+6raphies
+9hy
+5id
+7s
+5lith
+9iases
+9iasis
+9s
+5scope
+9es
+9ic
+9ies
+9y
+6tomies
+9y
+5tomies
+8y
+4s
+2tase
+6s
+5ter
+8s
+3e
+4s
+3idine
+8s
+5ylic
+4si
+6ne
+8s
+5us
+3ochalasin
+9sins
+6emical
+9stries
+9stry
+6rome
+9es
+4de
+6s
+5iagnoses
+9osis
+4geneses
+9is
+8tic
+9ical
+9ically
+9icist
+9icists
+9ics
+7ies
+7y
+4id
+4kine
+8s
+9es
+9is
+8tic
+7in
+9s
+4logic
+9al
+9ally
+8es
+8st
+9ts
+7y
+5yses
+7in
+9s
+8s
+6tic
+4megalic
+9ovirus
+6mbrane
+9anes
+6ter
+9s
+7ric
+9es
+8y
+4n
+5s
+4pathic
+8ogenic
+9logies
+9logy
+5enia
+9s
+5hilic
+6otometric
+9metry
+5lasm
+9ic
+9ically
+9s
+8t
+9ic
+9s
+4sine
+8s
+5keletal
+9ton
+9tons
+5ol
+7ic
+7s
+6me
+8s
+5tatic
+9cally
+9cs
+4taxes
+7is
+7onomic
+9omies
+9omist
+9omists
+9omy
+5echnology
+5oxic
+9ities
+9ity
+8n
+9s
+1zapka
+6s
+3r
+4das
+7es
+5om
+7s
+4evich
+9es
+7tch
+9hes
+6na
+8s
+4ina
+7s
+5sm
+7s
+6t
+7s
+5tsa
+8s
+6za
+8s
+4s
+0da
+2al
+4s
+2b
+3ba
+5s
+4ed
+5r
+6s
+4ing
+5ties
+6y
+4le
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+3chick
+8s
+3s
+4ter
+7s
+2ce
+4s
+3ha
+5s
+4shund
+9s
+3ite
+6s
+3k
+4ed
+5r
+6ed
+6ing
+6s
+4ing
+4s
+3oit
+6age
+9s
+6ies
+6s
+6y
+3quoise
+9s
+3ron
+6s
+3tyl
+6ar
+6i
+7c
+8ally
+8s
+7ography
+8logies
+9ogy
+8mancies
+9ancy
+7st
+9s
+6ogram
+9ams
+9apher
+9aphers
+9aphic
+9aphies
+9aphy
+7logies
+9gy
+7scopies
+9opy
+6s
+6us
+2d
+3a
+4h
+5s
+4ism
+7s
+6t
+7ic
+7s
+4s
+3ded
+4ies
+5ng
+4le
+6d
+6s
+5ing
+4ock
+7s
+4y
+3gum
+3o
+4ed
+5s
+4ing
+4s
+3s
+2e
+3dal
+6ean
+6ian
+7c
+3ing
+3mon
+6es
+6ic
+6s
+3s
+2ff
+4adowndilly
+4ed
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+4odil
+8lies
+9y
+8s
+4s
+4y
+3t
+4ar
+6s
+4er
+5st
+4ie
+6s
+4ly
+4ness
+8es
+2g
+3aba
+6s
+3ga
+5s
+4ed
+5r
+6board
+9rds
+6ed
+6ing
+6like
+6s
+4ier
+6st
+5ng
+7s
+4le
+6d
+6s
+5ing
+4y
+3lock
+7s
+3o
+4ba
+6s
+4es
+4s
+3s
+3uerrean
+8otype
+9typed
+9typer
+9typers
+9types
+9typies
+9typing
+9typist
+9typy
+3wood
+7s
+2h
+3abeah
+8s
+6eah
+9s
+7yah
+9hs
+5iah
+8s
+6eh
+8s
+6ya
+8h
+9s
+8s
+7eh
+9s
+3l
+4ia
+6s
+4s
+3oon
+6s
+3s
+2idle
+6d
+6s
+5ing
+4zein
+8s
+3ker
+6ed
+6ing
+6s
+4o
+5n
+6s
+5s
+3lies
+5ness
+9es
+4y
+5ness
+9es
+3men
+4io
+6s
+4oku
+7s
+5n
+6es
+6ic
+6s
+4yo
+6s
+3ne
+5d
+5s
+4ing
+4t
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+5y
+3quiri
+8s
+3ries
+4y
+5ing
+8s
+5maid
+9s
+7n
+6en
+3s
+4es
+4hiki
+8s
+4ied
+6s
+4y
+5wheel
+9ls
+2k
+3er
+5ed
+5hen
+8s
+5ing
+5s
+3oit
+6i
+7es
+7s
+6s
+6y
+3s
+2l
+3apon
+7s
+4si
+6s
+3e
+4d
+5h
+6s
+5s
+4s
+5man
+6en
+4th
+6s
+3gyte
+7s
+3i
+4s
+3le
+5s
+4iance
+9s
+5ed
+6r
+7s
+6s
+4op
+6s
+4y
+5ing
+3mahoy
+8s
+5tian
+9s
+7c
+8s
+3s
+3t
+4on
+6ian
+7c
+7sm
+9s
+6s
+4s
+2m
+3age
+6abilities
+9lity
+8le
+6d
+6r
+7s
+6s
+5ing
+8ly
+4n
+5s
+4r
+5s
+4sceene
+9ed
+9es
+9ing
+7ne
+9d
+9s
+8ing
+9ngs
+5k
+6ed
+7en
+9ed
+9ing
+9s
+6in
+8ed
+8g
+8ing
+8s
+6s
+5quin
+9ed
+9ing
+9s
+5sin
+8s
+3board
+8s
+4rod
+7s
+3e
+4s
+4wort
+8s
+3fool
+3iana
+7s
+4nozide
+9es
+3mar
+6s
+4e
+5d
+5r
+6s
+4ing
+5t
+3nabilities
+9ty
+6le
+8ness
+9esses
+7y
+5tion
+9s
+6ory
+4dest
+8s
+4ed
+6er
+7st
+9s
+5r
+6s
+4ification
+9tions
+7ed
+8s
+6y
+7ing
+5ng
+7ly
+4s
+3oisel
+8le
+9es
+8s
+4sel
+7s
+4zel
+7s
+3p
+4course
+9es
+4ed
+5n
+6ed
+7r
+8s
+6ing
+6s
+5r
+6s
+5st
+4ier
+6st
+5ng
+7s
+5sh
+7ness
+9sses
+4ly
+4ness
+8es
+4s
+4y
+3s
+4el
+6fish
+9hes
+7lies
+8y
+6s
+4on
+6s
+2n
+3azol
+7s
+3ce
+5able
+5d
+5hall
+9s
+5r
+6s
+5s
+5tte
+8e
+8s
+7y
+5y
+4ical
+8s
+5er
+6st
+5ng
+7s
+4y
+3delion
+9s
+5r
+6ed
+6ing
+6s
+4iacal
+5er
+6s
+7t
+5fication
+9tions
+7ed
+8s
+6y
+7ing
+5ly
+5prat
+9s
+4le
+6d
+6r
+7s
+6s
+5ing
+4riff
+8s
+5uff
+8s
+8y
+4y
+5funk
+9s
+5ish
+8ly
+7m
+8s
+5prat
+9s
+3egeld
+8s
+7t
+8s
+4lagh
+8s
+6w
+7s
+4weed
+8s
+5ort
+8s
+3g
+4ed
+5r
+6ed
+6ing
+6less
+6ous
+9ly
+9ness
+9nesses
+6s
+4ing
+4le
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8ly
+8s
+5y
+4s
+3io
+5s
+4sh
+6es
+3k
+4er
+5st
+4ish
+4ly
+4ness
+8es
+4s
+3nebrog
+9s
+4ies
+4y
+3s
+4eur
+7s
+6se
+8s
+3t
+4ed
+4honia
+9s
+4ing
+4on
+6ed
+6ing
+6s
+4s
+2p
+3hne
+6s
+5ia
+7s
+6d
+7s
+3ped
+5r
+6er
+7st
+6ling
+9gs
+7y
+6ness
+9ses
+6s
+4ing
+4le
+6d
+6s
+5ing
+3s
+4one
+7s
+2quiri
+7s
+2raf
+5s
+3b
+4ar
+6s
+4ies
+4s
+3cies
+4y
+5s
+3e
+4d
+5evil
+9ries
+9ry
+9s
+9tries
+9try
+4ful
+4r
+5s
+4s
+5ay
+3g
+4a
+5h
+6s
+5s
+4le
+6s
+4s
+3i
+4c
+5s
+4ng
+6ly
+6ness
+9ses
+6s
+4ole
+7s
+4s
+3k
+4ed
+5n
+6ed
+7r
+8s
+6ing
+6s
+5r
+5st
+5y
+6s
+4field
+4ies
+5ng
+5sh
+4le
+6d
+6s
+5ier
+7st
+6ng
+8s
+5y
+4mans
+4ness
+8es
+6t
+7s
+4room
+8s
+4s
+5ome
+4y
+3ling
+7ly
+7ness
+9sses
+7s
+3n
+4ation
+9s
+4dest
+8s
+4ed
+6er
+7st
+9s
+5l
+6s
+5r
+6s
+4ing
+7s
+4s
+3ogha
+7s
+3raign
+8e
+9d
+9s
+8ing
+8ment
+9ents
+8s
+6n
+7e
+8d
+8s
+7ing
+7s
+5yn
+7ed
+7ing
+7s
+4e
+5d
+5s
+4ing
+3shan
+7s
+3t
+4board
+9s
+4ed
+5r
+6s
+4ing
+7ly
+5tis
+8es
+4le
+6d
+6s
+5ing
+4re
+6s
+5ous
+4s
+3zi
+5s
+2s
+3h
+4board
+9s
+4ed
+5en
+7s
+5ki
+7s
+5r
+6s
+5s
+4i
+5er
+6st
+5ki
+7s
+5ng
+7ly
+5s
+4pot
+7s
+4y
+3sie
+6s
+3tard
+7ies
+7liness
+9nesses
+8y
+7ness
+9sses
+7s
+7y
+3ymeter
+9s
+4paedal
+5hyllous
+5od
+7s
+4ure
+7s
+2ta
+4bank
+8s
+6se
+8d
+8s
+7ing
+5le
+5us
+7es
+7ses
+4card
+8s
+5omms
+4flow
+4glove
+9s
+5ram
+8s
+4l
+5ler
+8s
+5s
+4mation
+9ns
+4ria
+7s
+6es
+5y
+4veillance
+9ances
+3cha
+6s
+3e
+4able
+4book
+8s
+4d
+5ly
+5ness
+9es
+4less
+5ine
+8d
+8s
+7ing
+4r
+5s
+4s
+3ing
+6s
+4val
+5e
+6ly
+6s
+3o
+4lite
+8s
+4s
+3to
+5s
+3um
+5s
+4ra
+6s
+5ic
+6ne
+8s
+2ub
+4e
+5d
+5r
+6ies
+6s
+6y
+5s
+4ier
+6st
+5ng
+7ly
+7s
+4ries
+5y
+4s
+4y
+3d
+4ed
+4ing
+4s
+3ghter
+8hood
+9oods
+8less
+9iness
+9ing
+9ings
+9y
+8s
+3lt
+5s
+3nder
+7ed
+7ing
+7s
+4er
+6ed
+6ing
+6s
+4omycin
+9ns
+5rubicin
+9cins
+4t
+5ed
+6r
+7s
+5ing
+8ly
+5less
+9ly
+9ness
+9nesses
+5on
+7ed
+7ing
+7s
+5s
+3phin
+7e
+8s
+9s
+9ses
+7s
+3r
+4ed
+4ing
+4s
+3t
+4ed
+4ie
+6s
+5ng
+4s
+2ven
+5ed
+5ing
+5port
+9s
+5s
+3idia
+7s
+4es
+4t
+5s
+3y
+2w
+3ah
+5s
+3bake
+7s
+4ries
+5y
+3cock
+7s
+3d
+4ed
+4ing
+4le
+6d
+6r
+7s
+6s
+5ing
+8ly
+4s
+3ed
+4n
+3ing
+4sh
+3k
+4s
+3n
+4ed
+5r
+6ed
+6ing
+6s
+5y
+4ing
+7s
+4like
+4s
+3s
+4onite
+9s
+3t
+4ed
+4ie
+6s
+5ng
+4s
+2y
+3an
+5im
+5s
+3bed
+6s
+4oat
+7s
+5ok
+7s
+5y
+6s
+4reak
+8s
+3care
+7s
+4entre
+9s
+4h
+5ed
+6s
+5ing
+3dream
+8ed
+9r
+9rs
+8ing
+8like
+8s
+8t
+8y
+3flies
+5ower
+9s
+5y
+3girl
+7s
+4lo
+6w
+7s
+3light
+8ed
+8ing
+9ngs
+8s
+5lies
+6y
+5t
+4ong
+3mare
+7s
+6k
+7s
+3nt
+3pack
+7s
+3room
+7s
+3s
+4ack
+7s
+5iler
+9s
+7or
+9s
+4hell
+8s
+4ide
+7s
+4man
+5en
+4pring
+9s
+4tar
+7s
+3tale
+7r
+8s
+7s
+4ime
+7s
+3wear
+7s
+4ork
+7er
+9s
+7s
+2ze
+4d
+5ly
+5ness
+9es
+4r
+5s
+4s
+3ing
+3zle
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+8s
+1e
+2acidification
+9ed
+9es
+8y
+9ing
+4on
+6ed
+7ss
+9es
+6hood
+9ds
+6ing
+6ries
+7y
+6s
+7hip
+9ps
+4tivate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+3d
+4beat
+8s
+5olt
+8s
+6y
+7s
+4ed
+5n
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+5r
+6s
+5st
+5ye
+7s
+4fall
+8s
+4head
+8ed
+8ing
+8s
+5ouse
+9s
+4ing
+4lier
+7st
+6ft
+8ed
+8ing
+8s
+6ght
+9s
+6ne
+8d
+8s
+9s
+9ses
+7ing
+5ock
+8ed
+8ing
+8s
+5y
+4man
+5en
+4ness
+8es
+4pan
+7ned
+9r
+9rs
+8ing
+7s
+4s
+5tock
+9s
+6roke
+4weight
+9ts
+5ood
+8s
+3erate
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+3f
+4blind
+4en
+6ed
+6ing
+9ly
+9s
+6s
+5r
+5st
+4ish
+4ly
+4ness
+8es
+3ir
+5ed
+5ing
+5s
+3l
+4ate
+7d
+7s
+6ion
+9s
+4bate
+7ion
+9ns
+4er
+6s
+7hip
+9ps
+4fish
+8es
+4ing
+7s
+4s
+4t
+3mbulatories
+9ory
+4inase
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+3n
+4ed
+5r
+6ies
+6s
+6y
+4ing
+4s
+5hip
+8s
+3r
+4bought
+4e
+5d
+5r
+5s
+6t
+7s
+4ie
+6s
+5ng
+4ling
+8s
+5y
+4n
+5ess
+8es
+5ful
+5ly
+5s
+4s
+4th
+6s
+5iculate
+9ated
+9ates
+9ating
+4y
+3sh
+5ed
+6s
+5ing
+4il
+6s
+5ul
+7s
+4oil
+7s
+4pirate
+9ed
+9es
+9ing
+9ion
+9ions
+3th
+5bed
+8s
+6low
+9s
+5cup
+8s
+5ful
+5ier
+7st
+5less
+9ly
+9ness
+9nesses
+6ier
+8st
+7ke
+7ness
+9sses
+6y
+5s
+6man
+7en
+5trap
+9s
+5ward
+9s
+7tch
+9hes
+5y
+4tribute
+9ted
+9tes
+9ting
+3ve
+5d
+5s
+4ing
+3w
+4ie
+4s
+4y
+2b
+3acle
+7s
+4g
+5ged
+6ing
+9s
+5s
+4r
+5cation
+9ons
+5k
+6ation
+9ons
+6ed
+7r
+8s
+6ing
+6s
+5ment
+9s
+5rass
+9ed
+9es
+9ing
+6ed
+6ing
+5s
+4se
+6d
+7ness
+9sses
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+4table
+8y
+5e
+6able
+6d
+6ful
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+4uch
+7ed
+9ly
+9ness
+9nesses
+8e
+9s
+8r
+9ies
+9s
+9y
+8s
+7ing
+7ment
+9nts
+3bier
+6s
+7t
+4y
+3e
+4ak
+6ed
+6ing
+6s
+5rd
+7ed
+7ing
+7s
+4l
+5led
+6ing
+5s
+4nture
+9d
+9s
+4s
+3ile
+5itate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+7ies
+7y
+4t
+5ed
+5ing
+5or
+7s
+5s
+3onair
+8e
+8ly
+8ness
+9esses
+5e
+6d
+6r
+7s
+6s
+5ing
+5naire
+4sh
+6ed
+7s
+6ing
+5s
+6ed
+7s
+6ing
+4uch
+7e
+8d
+8s
+7ing
+7ment
+9nts
+7ure
+9es
+3ride
+7d
+7ment
+9nts
+7s
+6ing
+5ef
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5s
+4uise
+8d
+8s
+7ing
+3s
+3t
+4ed
+5e
+6s
+4less
+4or
+6s
+4s
+3ud
+5ded
+6ing
+5s
+4g
+5ged
+7r
+8s
+6ing
+5s
+4nk
+6ed
+7r
+8s
+6ing
+6s
+4r
+5r
+6ed
+6ing
+6s
+5s
+4s
+5ed
+6s
+5ing
+5sed
+7s
+6ing
+4t
+5ant
+8e
+9s
+8s
+5ed
+5ing
+5s
+3ye
+5s
+2cachord
+9s
+4d
+5al
+5e
+6nce
+9s
+8ies
+8y
+7t
+8ly
+8s
+6s
+5s
+4f
+5f
+6einate
+9ated
+9ates
+9ating
+9ation
+9ations
+6s
+5s
+4gon
+7al
+9ly
+7s
+5ram
+8me
+9es
+8s
+5ynian
+7ous
+4hedra
+9l
+8on
+9ns
+4l
+5cification
+9ed
+9er
+9ers
+9es
+8y
+9ing
+6omania
+9nias
+5ed
+6scence
+9nces
+9nt
+5ing
+6ter
+9s
+7re
+9s
+5led
+6ing
+5og
+7ist
+9ts
+7s
+7ue
+9s
+5s
+4meronic
+8us
+6ter
+9s
+7honium
+9niums
+7re
+9s
+8ic
+5p
+6ed
+6ing
+6ment
+9ts
+6s
+4nal
+7ly
+5drian
+7ous
+5e
+6dioic
+6s
+5i
+6cally
+5oic
+5t
+6ate
+9d
+9s
+8ing
+9on
+9ons
+6ed
+7r
+8s
+6ing
+6s
+4pitalise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+5od
+7al
+8n
+9s
+7ous
+7s
+5sulate
+9ted
+9tes
+9ting
+9tion
+9tions
+4rb
+6ed
+6ing
+6onate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+8isation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+7xylase
+9lases
+9late
+9lated
+9lates
+9lating
+9lation
+6s
+6uration
+9tions
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+5e
+6s
+4stere
+9s
+6ich
+9s
+6yle
+9s
+5ualisation
+9zation
+5yllabic
+9bics
+9ble
+9bles
+4thlete
+9es
+7on
+9s
+4udate
+9d
+9s
+8ing
+4y
+5able
+5ed
+6r
+7s
+5ing
+5less
+5s
+3cie
+6s
+3ease
+7d
+7s
+6ing
+4dent
+8s
+4it
+6ful
+9ly
+9ness
+9nesses
+6s
+5vabilities
+9lity
+8le
+9eness
+9y
+6e
+7d
+7r
+8s
+7s
+6ing
+9ly
+9s
+4lerate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7ometer
+9eters
+8n
+9s
+4mvir
+8al
+9te
+9tes
+8i
+8s
+4naries
+7y
+5cies
+6y
+5naries
+8y
+6ia
+8l
+9ly
+9s
+7um
+9s
+6oval
+5t
+6er
+8ed
+8ing
+8s
+7st
+6ly
+6ness
+9ses
+6ralise
+9ised
+9ises
+9ising
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+7e
+8d
+8s
+7ing
+4ptibilities
+9lity
+8le
+7on
+9al
+9s
+8us
+7ve
+9ly
+9ness
+9nesses
+6ory
+4rebrate
+9ted
+9tes
+9ting
+9tion
+9tions
+8ise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+5n
+6ed
+6ing
+6s
+5tification
+9ed
+9es
+8y
+9ing
+4ssion
+9s
+3heance
+9s
+4lorinate
+9ated
+9ates
+9ating
+9ation
+9ations
+4ristianise
+9anised
+9anises
+9anize
+9anized
+9anizes
+3iare
+7s
+4bel
+7s
+4dabilities
+9ity
+7le
+5e
+6d
+7ly
+7ness
+9sses
+6r
+7s
+6s
+5ing
+5ua
+7e
+7l
+7s
+7te
+6ous
+9ly
+9ness
+9nesses
+4gram
+8me
+9es
+8s
+4le
+6s
+5iter
+9s
+7re
+9s
+5lion
+9s
+9th
+9ths
+4mal
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5e
+6s
+6ter
+9s
+7re
+9s
+8ic
+4normal
+4pher
+8ability
+9ble
+8ed
+9r
+9rs
+8ing
+8ment
+9ents
+8s
+4sion
+8al
+8ed
+8ing
+8s
+6ve
+8ly
+8ness
+9esses
+5ory
+5tere
+9s
+4tizenise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+4vilise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+3k
+4chair
+9s
+4ed
+5l
+6s
+5r
+6s
+4hand
+8s
+5ouse
+9s
+4ing
+7s
+4le
+6d
+6s
+4o
+5ed
+5ing
+5s
+4s
+3laim
+7ant
+9ts
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5mation
+9ons
+8orily
+9ry
+5rable
+7nt
+9s
+7tion
+9ons
+9ve
+9vely
+8or
+9rily
+9rs
+9ry
+6e
+7d
+8ly
+7r
+8s
+7s
+6ing
+5ss
+7e
+8d
+8e
+8s
+7ifiable
+9ied
+9ies
+9y
+9ying
+8ng
+5w
+6ed
+6ing
+6s
+4ension
+9nal
+9nally
+9ns
+4inable
+7l
+7nt
+7te
+8ion
+9onal
+9ons
+8or
+9rs
+9ry
+8ure
+9res
+6e
+7d
+7r
+8s
+7s
+6ing
+7st
+9s
+6ometer
+9ters
+5vities
+8ous
+8y
+6ous
+4utch
+8ed
+9s
+8ing
+6ter
+9ed
+9ing
+9s
+3o
+4ct
+6ed
+6ible
+7ng
+7on
+9s
+7ve
+6s
+6ure
+9s
+4de
+6d
+6r
+7s
+6s
+5ing
+4herence
+9ces
+8r
+9s
+4ke
+6d
+6s
+5ing
+4llate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6etage
+9ges
+8e
+9s
+5onisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+6r
+7ant
+9ts
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+7ed
+7ing
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7s
+6ur
+8ed
+8ing
+9sation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+4mmission
+9ioned
+9ioner
+9ioners
+9ioning
+9ions
+7t
+8s
+8ted
+9ing
+5pensate
+9ated
+9ates
+9ating
+9ation
+9ations
+6lex
+6osability
+9ble
+8e
+9d
+9r
+9rs
+9s
+8ing
+9te
+9tion
+9tions
+7und
+9dable
+9ded
+9ding
+9ds
+6ress
+9sed
+9ses
+9sing
+9sion
+9sions
+9sive
+9sor
+9sors
+4ncentrate
+9rated
+9rates
+9rating
+9ration
+5dition
+9oned
+9oning
+9ons
+5gest
+9ant
+9ants
+9ed
+9ing
+9ion
+9ions
+9ive
+9s
+5secrate
+9ated
+9ates
+9ating
+9ation
+9ations
+6truct
+9cted
+9cting
+9ction
+9ctions
+9ctive
+9ctor
+9ctors
+9cts
+5taminant
+9nants
+9nate
+9nated
+9nates
+9nating
+9nation
+9native
+9nator
+9nators
+6rol
+9led
+9ling
+9s
+4r
+5ate
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+9eness
+7or
+9s
+5ous
+8ly
+8ness
+9esses
+5s
+5ticate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+5um
+7s
+4s
+4upage
+9d
+9s
+8ing
+6le
+8d
+8r
+9s
+8s
+7ing
+9gs
+4y
+5ed
+6r
+7s
+5ing
+5s
+3rassified
+9ies
+9y
+9ying
+4ease
+8d
+8s
+7ing
+9gly
+9gs
+5e
+6able
+6d
+6ing
+6r
+7s
+6s
+6t
+7s
+5ment
+9al
+9ed
+9ing
+9s
+5pit
+8ate
+9ted
+9tes
+9ting
+9tion
+9tions
+8ly
+8ness
+9esses
+8ude
+9des
+5scence
+9ces
+9do
+9dos
+9t
+5tal
+8ist
+9sts
+8s
+6ist
+9s
+7ve
+6ory
+5w
+6ed
+6ing
+6s
+4ial
+7s
+5ed
+6r
+7s
+6s
+5minalise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+4own
+7ed
+7ing
+7s
+4ustation
+9ions
+4y
+5ing
+5pt
+7ed
+7ing
+8on
+9ns
+7s
+3tet
+6s
+3ubital
+7i
+7us
+4man
+7s
+5bence
+9es
+9ies
+9y
+8t
+9ly
+6iture
+9res
+4ple
+7d
+7s
+6ing
+4ria
+7s
+6es
+6on
+8ate
+9tes
+8s
+5rencies
+9y
+8t
+9ly
+5sion
+9s
+7ve
+9ly
+5vation
+9ons
+6e
+7d
+7s
+6ing
+5y
+4ssate
+9d
+9ly
+9s
+8ing
+9on
+9ons
+2dal
+5ian
+4ns
+3icant
+8s
+6te
+8d
+9ly
+8e
+9s
+8s
+7ing
+8on
+9nal
+9ns
+8ve
+7or
+9ial
+9s
+9y
+4fferentiate
+4mus
+7es
+3ramatise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+3uce
+6d
+6ment
+9ts
+6s
+5ibilities
+9ity
+7le
+9ness
+9nesses
+8y
+6ng
+5t
+6ed
+6ibilities
+9lity
+8le
+9es
+7ng
+7on
+9s
+7ve
+9ly
+6s
+4plicate
+9ted
+9tes
+9ting
+9tion
+9tions
+2e
+3d
+4ed
+5r
+5st
+4ful
+4ier
+6st
+5ly
+5ng
+4less
+4s
+4y
+3ing
+3jay
+6ed
+6ing
+6s
+3k
+3ly
+3m
+4ed
+4ing
+4s
+5ter
+8s
+9hip
+9hips
+3n
+4s
+3p
+4en
+6ed
+7r
+8s
+6ing
+6s
+5r
+5st
+4felt
+5reeze
+9es
+9ing
+6oze
+9n
+4ie
+6s
+4ly
+4most
+4ness
+8es
+4s
+4water
+9man
+9men
+3r
+4berries
+8y
+4e
+4flies
+6y
+4grass
+9es
+4hound
+9s
+4let
+7s
+5ike
+4s
+5kin
+8s
+5talker
+9ers
+9ing
+9ings
+4weed
+8s
+4yard
+8s
+3s
+4calate
+9ed
+9es
+9ing
+9ion
+9ions
+3t
+4s
+3v
+4e
+5d
+5s
+4ing
+4s
+3wan
+6s
+2f
+3ace
+6able
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+4ecate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+4lcate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+4mation
+9ns
+7orily
+9y
+5e
+6d
+6r
+7s
+6s
+5ing
+8s
+4ng
+6ed
+6ing
+6s
+4st
+6e
+4t
+5s
+5ted
+6ing
+4ult
+7ed
+8r
+9s
+7ing
+7s
+3easance
+9ed
+9es
+6ibilities
+9lity
+8le
+9eness
+5t
+6ed
+7r
+8s
+6ing
+7sm
+9s
+8t
+9s
+6s
+6ure
+9d
+9s
+8ing
+4cate
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5t
+6ed
+6ibilities
+9lity
+8le
+7ng
+7on
+9ist
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+9s
+6or
+8s
+6s
+4minisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+4nce
+7d
+7less
+9ssly
+9ssness
+7man
+8en
+7s
+6ing
+5d
+6able
+7nt
+9s
+6ed
+7r
+8s
+6ing
+6s
+5estrate
+9ated
+9ates
+9ating
+9ation
+9ations
+5sative
+9ves
+6e
+7d
+7less
+9ssly
+9ssness
+7man
+8en
+7s
+6ibilities
+9lity
+8le
+9eness
+9y
+7ng
+7ve
+9ly
+9ness
+9nesses
+9s
+4r
+5able
+5ence
+9s
+7t
+8ial
+9ally
+8s
+5ment
+9s
+5rable
+9es
+7l
+8s
+6ed
+7r
+8s
+6ing
+5s
+5vescence
+9ences
+9encies
+9ency
+4udalise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+3fer
+5st
+4ly
+4o
+3i
+4ance
+8s
+6t
+7ly
+7ness
+9sses
+4brillate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ator
+9ators
+7nate
+9ted
+9tes
+9ting
+9tion
+9tions
+8ise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+4cience
+9es
+9ies
+9y
+8t
+9ly
+9ness
+9nesses
+9s
+6t
+7s
+4ed
+5r
+6s
+5s
+4lade
+8d
+8s
+7ing
+5e
+6d
+6ment
+9ts
+6r
+7s
+6s
+5iation
+9ons
+6ng
+4nabilities
+9ity
+7le
+8y
+5e
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ienda
+9um
+8s
+8tia
+6ng
+6te
+8ly
+8ness
+9esses
+7ion
+9nal
+9ns
+8se
+9ed
+9es
+9ing
+8ve
+9ely
+9eness
+9es
+8ze
+9ed
+9es
+9ing
+7ude
+9es
+4s
+3lagrability
+9le
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+5te
+7d
+7r
+8s
+7s
+6ing
+7on
+9ary
+9ist
+9ists
+9s
+6or
+8s
+4ea
+6ed
+6ing
+6s
+5ct
+7able
+7ed
+7ing
+8on
+9nal
+9ns
+8ve
+7or
+9s
+7s
+5x
+6ed
+7s
+6ing
+7on
+9al
+9s
+6ure
+9s
+4occulant
+9ants
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+5rate
+9d
+9s
+8ing
+9on
+9ons
+5wer
+8ed
+9r
+9rs
+8ing
+8s
+4uent
+5xion
+9s
+3o
+4am
+6ed
+7r
+8s
+6ing
+6s
+4cus
+7ed
+8s
+7ing
+7sed
+9s
+8ing
+4g
+5ged
+7r
+8s
+6ing
+5s
+4liant
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+4rce
+7d
+7ment
+9nts
+7r
+8s
+7s
+6iant
+9ts
+8tion
+9ions
+7ng
+5est
+8ation
+9tions
+8ed
+9r
+9rs
+8ing
+8s
+5m
+6abilities
+9lity
+8le
+7lise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+7tion
+9onal
+9ons
+9ve
+6ed
+8ly
+8ness
+9esses
+7r
+8s
+6ing
+7ties
+8y
+6s
+4ul
+6ed
+6ing
+6s
+3rag
+6ged
+8r
+9s
+7ing
+9gs
+6ment
+9ted
+9ting
+9ts
+6s
+5ud
+7ation
+9ions
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+5y
+6able
+7l
+8s
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4eeze
+8s
+7ing
+4ock
+7ed
+7ing
+7s
+5st
+7ed
+8r
+9s
+7ing
+7s
+5ze
+7n
+3t
+4er
+5st
+4ly
+4ness
+8es
+3uel
+6ed
+6ing
+6led
+7ing
+6s
+4nct
+7ion
+9ns
+8ve
+7ness
+9sses
+7s
+5d
+6ed
+6ing
+6s
+4se
+6d
+6r
+7s
+6s
+5ing
+4ze
+6d
+6s
+5ing
+3y
+4ing
+2g
+3age
+4me
+6s
+5i
+6s
+4rnish
+9ed
+9es
+9ing
+4s
+5es
+5sed
+7r
+8s
+7s
+6ing
+4uss
+7ed
+8r
+9s
+8s
+7ing
+3earing
+9s
+4nder
+8ed
+8ing
+8s
+5eracies
+9y
+8te
+9ed
+9ely
+9eness
+9es
+9ing
+9ion
+9ionist
+9ions
+9ive
+7ous
+4rm
+6ed
+6ing
+6s
+3ged
+4ing
+3laciated
+9ion
+9ions
+5morisation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+5ze
+7d
+7s
+6ing
+4utinate
+9ted
+9tes
+9ting
+9tion
+9tions
+7tion
+9ons
+9ve
+8ory
+3out
+6s
+3radabilities
+9lity
+8le
+7tion
+9ons
+9ve
+6e
+7d
+8ly
+7r
+8s
+7s
+6ing
+9ly
+9ness
+9nesses
+5nulation
+9tions
+5s
+4easant
+9ts
+7e
+8d
+8r
+9s
+8s
+7ing
+5e
+6d
+6less
+6s
+5ssion
+9ns
+8ve
+9ely
+4ingolade
+9aded
+9ades
+9ading
+9er
+9ered
+9ering
+9ers
+3s
+3u
+4m
+5med
+6ing
+5s
+4s
+5t
+6ate
+9d
+9s
+8ing
+9on
+9ons
+8ory
+6ed
+6ing
+6s
+2hisce
+7d
+7nce
+9es
+8t
+7s
+6ing
+3orn
+6ed
+7r
+8s
+6ing
+6s
+5t
+6ation
+9ons
+9ve
+8ory
+6ed
+7r
+8s
+6ing
+6s
+3umanisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5idified
+9ier
+9iers
+9ies
+9y
+9ying
+3ydrate
+9d
+9r
+9rs
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6ogenase
+9nases
+9nate
+9nated
+9nates
+9nating
+9nation
+9nise
+9nised
+9nises
+9nising
+9nize
+9nized
+9nizes
+9nizing
+7retinol
+9tinols
+4pnotisation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+2i
+3ce
+5d
+5r
+6s
+5s
+4idal
+6e
+7s
+5ng
+4tic
+7ally
+7s
+3d
+4er
+5st
+4s
+3f
+4er
+5st
+4ic
+6al
+7tion
+9ons
+5ed
+6r
+7s
+6s
+4orm
+4y
+5ing
+3gn
+5ed
+5ing
+5s
+3l
+4s
+3ndex
+7ed
+8s
+7ing
+5ividuation
+5ustrialise
+9ialize
+4onychus
+9uses
+5saur
+9s
+5there
+9es
+9ium
+9iums
+3onisation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+3parous
+4nosophist
+9hists
+3seal
+7s
+4heal
+8s
+4m
+5s
+4t
+5ic
+7al
+9ly
+5s
+3ties
+4y
+3xes
+4is
+6es
+2ject
+6a
+6ed
+8ly
+8ness
+9esses
+6ing
+7on
+9s
+6ory
+6s
+4une
+7r
+8s
+7s
+2kagram
+8s
+4liter
+9s
+7re
+9s
+5ogies
+7y
+4meter
+9s
+7re
+9s
+8ic
+4re
+6s
+3e
+4d
+4ing
+4s
+3ing
+3ko
+5ed
+5ing
+5s
+2l
+3aine
+7s
+4minate
+9ed
+9es
+9ing
+9ion
+9ions
+4pse
+7d
+7s
+6ing
+7on
+9s
+4ssement
+9nts
+4te
+6d
+6s
+5ing
+6on
+8s
+5or
+7s
+4y
+5able
+5ed
+6r
+7ing
+9gs
+7s
+5ing
+8ly
+5s
+3e
+4ad
+6ed
+6ing
+6s
+5ve
+7d
+7s
+6ing
+4ble
+4ctabilities
+9lity
+8le
+9eness
+9es
+9y
+7te
+9d
+9s
+8ing
+9on
+9ons
+4d
+4gable
+6cies
+7y
+6te
+8d
+8e
+9s
+8s
+7ing
+8on
+9ns
+7or
+9s
+5itimation
+9ations
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+4ing
+4nda
+4s
+4table
+5e
+6d
+6rious
+9usly
+9usness
+6s
+5ing
+6on
+8s
+6ve
+5ory
+4verage
+9ed
+9es
+9ing
+3f
+4s
+4t
+5s
+5ware
+9s
+3i
+4bate
+8d
+8s
+7ing
+8on
+9ns
+5erate
+9ed
+9ely
+9eness
+9es
+9ing
+9ion
+9ions
+9ive
+9ively
+9or
+9ors
+5le
+4cacies
+7y
+6te
+8ly
+8ness
+9esses
+8s
+9sen
+9sens
+5e
+6s
+5ious
+9ly
+9ness
+9nesses
+5t
+6s
+4gation
+9ns
+5ht
+7ed
+9ly
+9ness
+9nesses
+8r
+9s
+7ful
+9lly
+9lness
+7ing
+7less
+7s
+8ome
+4me
+6d
+6s
+5ing
+6t
+7ate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+7ed
+8r
+9s
+7ing
+7s
+4neable
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+7vit
+5quencies
+9cy
+9t
+9tly
+9ts
+4quesce
+9ed
+9ence
+9ences
+9ent
+9es
+9ing
+6ium
+9s
+4ration
+9ns
+5ia
+7nt
+6facient
+9ients
+6ous
+9ly
+9ness
+9nesses
+6um
+8s
+4s
+5h
+5t
+6ed
+6ing
+6s
+4tescence
+9nces
+9nt
+4ver
+7ability
+9le
+8nce
+9ces
+7ed
+8r
+9s
+7ies
+8ng
+7ly
+7s
+7y
+8man
+9en
+3l
+4ies
+4s
+4y
+3o
+4calisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+4pe
+6d
+6s
+5ing
+4s
+4use
+7d
+7r
+8s
+7s
+6ing
+3ph
+5ic
+7ally
+6n
+7ia
+8um
+9ms
+7oid
+5s
+3s
+3t
+4a
+5ic
+5s
+4ic
+5ologies
+9ist
+9ists
+9y
+4oid
+7ei
+8us
+7s
+4s
+3ubrum
+8s
+4dable
+5e
+6d
+6r
+7s
+6s
+5ing
+8ly
+4ge
+6d
+6s
+5ing
+4ndung
+9s
+4sion
+8al
+9ry
+8ist
+9sts
+8s
+6ve
+8ly
+8ness
+9esses
+5ory
+5ter
+8ed
+8ing
+8s
+6rant
+9ts
+4xe
+3ve
+5d
+5r
+6s
+5s
+4ing
+2magnetisation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+5og
+7ed
+7ic
+9al
+9ally
+8es
+8ng
+8sm
+9ms
+7s
+7ue
+9d
+9ries
+9ry
+9s
+8ing
+9sm
+9sms
+7y
+4in
+6e
+7s
+6s
+4n
+5d
+6able
+7nt
+9s
+6ed
+7r
+8s
+6ing
+9ly
+9ness
+9nesses
+6s
+5ned
+6ing
+9s
+5s
+5toid
+9s
+4rcate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6he
+8s
+5k
+6ation
+9ons
+6ed
+7t
+8ed
+8ing
+8s
+6ing
+6s
+4st
+6ed
+6ing
+6s
+4terialise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+4yne
+7s
+3e
+4an
+6e
+7d
+7s
+6ing
+6or
+8s
+7ur
+9s
+6s
+5snure
+9es
+4nt
+6ate
+9d
+9s
+8ing
+6ed
+8ly
+8ness
+9esses
+6i
+7a
+8l
+8s
+7ng
+7s
+6s
+4rara
+8n
+8s
+5ge
+7d
+7r
+8ed
+8ing
+8s
+7s
+6ing
+5it
+7ed
+7ing
+7orious
+9iously
+7s
+5sal
+6e
+7d
+7s
+6ing
+7on
+9s
+4s
+5ne
+7s
+4ton
+7s
+3ibastion
+9ons
+4c
+5anton
+9ns
+4es
+4god
+7dess
+9sses
+7s
+5ration
+9ons
+4john
+8s
+4litarise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+5une
+8s
+4mondaine
+9ines
+8e
+9s
+4neralise
+9ised
+9iser
+9isers
+9ises
+9ising
+9ize
+9ized
+9izer
+9izers
+9izes
+9izing
+4pique
+9s
+4relief
+9fs
+6p
+7dom
+9ms
+7s
+4sable
+5e
+6d
+6miquaver
+9uavers
+6s
+5ing
+5s
+6ion
+9s
+7ve
+6ly
+5t
+6ed
+7r
+8s
+6ing
+6s
+4t
+5asse
+9s
+5s
+5ted
+6ing
+4urge
+8ous
+8s
+7ic
+9al
+9ally
+7us
+9es
+4veg
+7es
+7ges
+5ierge
+9es
+5olt
+8e
+9s
+8s
+4world
+9s
+3o
+4b
+5bed
+6ing
+5ilisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5s
+4cracies
+8y
+7t
+8ic
+9cal
+9cally
+9es
+9fiable
+9sation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9st
+9sts
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8s
+8y
+4de
+6d
+5ulate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+4ed
+4grapher
+9ers
+9ic
+9ical
+9ically
+9ics
+9ies
+9ist
+9ists
+9y
+4ing
+5selle
+9es
+4lish
+8ed
+9r
+9rs
+9s
+8ing
+8ment
+9ents
+6tion
+9nist
+9nists
+9ns
+5ogies
+7y
+4n
+5ess
+8es
+6tarise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5iac
+8al
+9lly
+8ism
+9sms
+8s
+7n
+8ism
+9sms
+6c
+7al
+9ly
+6sation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8s
+7t
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ocracies
+9cy
+6later
+9ers
+9ries
+9ry
+7ogic
+9ical
+9ies
+9ist
+9ists
+9y
+6mania
+9ias
+5ries
+6y
+5s
+6trability
+9ble
+9bly
+9te
+9ted
+9tes
+9ting
+9tion
+9tional
+9tions
+9tive
+9tively
+9tives
+9tor
+9tors
+9tory
+5ym
+7s
+4ralisation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9ingly
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9ingly
+4s
+5cene
+9s
+5es
+4te
+6d
+6s
+5ic
+7ist
+9ts
+7s
+6ng
+6on
+8s
+6st
+8s
+6vate
+9ed
+9es
+9ing
+4unt
+7able
+7ed
+7ing
+7s
+3pster
+8s
+4t
+3ulcent
+9s
+5sification
+9ed
+9er
+9ers
+9es
+8y
+9ing
+5tiplexer
+9exers
+4r
+5e
+6d
+6ly
+6ness
+9ses
+6r
+6s
+7t
+5ing
+5rable
+7ge
+9s
+7l
+8s
+6ed
+7r
+8s
+6ing
+5s
+4tualisation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+3y
+4elinate
+9ted
+9tes
+9ting
+9tion
+9tions
+4ship
+8s
+5tification
+9ed
+9es
+8y
+9ing
+4thologise
+9gised
+9giser
+9gisers
+9gises
+9gising
+9gize
+9gized
+9gizer
+9gizers
+9gizes
+9gizing
+2n
+3ar
+5i
+6es
+6i
+6us
+5s
+5y
+4tionalise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+5uralise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+8nt
+9ts
+8tion
+9ions
+7e
+8d
+8s
+7ing
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+4y
+5ed
+5ing
+5s
+4zification
+9ations
+8ed
+9s
+7y
+8ing
+3drachate
+9tes
+5iform
+6mer
+9s
+6te
+8s
+7ic
+9al
+9ally
+5obium
+9ms
+6glyph
+9phs
+7ram
+9ms
+6id
+8al
+6latries
+9ry
+7ogic
+9ical
+9ies
+9ist
+9ists
+9ous
+9y
+6meter
+9ers
+6n
+7s
+6phis
+9ses
+3e
+4gation
+9ns
+4rvate
+9d
+9s
+8ing
+9on
+9ons
+4s
+4t
+5s
+5ted
+6ing
+3gue
+6s
+3i
+4abilities
+9ty
+6le
+7y
+5l
+6s
+4ed
+5r
+6s
+5s
+4grate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+4m
+5ed
+5s
+4s
+5ation
+9ns
+4trate
+9d
+9s
+8ing
+9on
+9ons
+6ification
+9cator
+9cators
+9ed
+9er
+9ers
+9es
+8y
+9ing
+4zation
+9ns
+5en
+7ed
+7ing
+7s
+8hip
+9ips
+3ned
+5t
+6s
+4ing
+3ominable
+8l
+8te
+9ed
+9es
+9ing
+9ion
+9ional
+9ions
+9ive
+9ively
+9ives
+9or
+9ors
+4table
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+5e
+6d
+6ment
+9ts
+6s
+5ing
+6ve
+4uement
+9ts
+5nce
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+3s
+4e
+5ly
+5ness
+9es
+5r
+5st
+4ification
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5meter
+9rs
+8ric
+9ies
+9y
+5ties
+6ometer
+9ters
+9tric
+9tries
+9try
+6y
+3t
+4al
+6ia
+7ties
+8y
+7um
+9s
+6ly
+6s
+5ria
+8s
+7es
+6y
+5te
+7d
+7ly
+6ion
+9s
+4ed
+5l
+6le
+8s
+6s
+5x
+6es
+4icle
+8s
+6ulate
+9ted
+9tely
+9tion
+9tions
+5form
+6rice
+9es
+5gerous
+5l
+6abial
+6ed
+6ingual
+9uals
+6s
+5n
+6al
+6e
+7s
+6g
+6s
+5rostral
+5st
+7ries
+8y
+7s
+5tion
+9s
+4oid
+4s
+4ulous
+5ral
+6e
+7s
+6ist
+9s
+3uclearise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+4date
+8d
+8s
+7ing
+8on
+9ns
+5e
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+4merability
+9le
+9ly
+4nciate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+3y
+4ing
+7ly
+2obstruent
+9nts
+3dand
+7s
+5r
+6a
+7s
+6s
+5te
+7s
+4orant
+9s
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+3ntic
+7s
+5ological
+9ies
+9ist
+9ists
+9y
+3ppilate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+3rbit
+7ed
+7ing
+7s
+3xidate
+9d
+9s
+8ing
+9on
+9ons
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+4y
+5cortone
+9ones
+5genate
+9ted
+9tes
+9ting
+9tion
+9tions
+8ise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+5ribose
+9ses
+2paint
+7ed
+7ing
+7s
+4nneur
+9s
+4rt
+6ed
+7e
+8s
+7ment
+9nts
+7r
+8s
+6ing
+9s
+6ment
+9tal
+9talise
+9talism
+9talize
+9tally
+9ts
+6s
+6ure
+9s
+4sture
+9d
+9s
+8ing
+4uperate
+9ted
+9tes
+9ting
+8ise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+3eche
+7s
+4inct
+8ed
+8ing
+8s
+4nd
+6abilities
+9lity
+8le
+9eness
+9y
+7nce
+9es
+9ies
+9y
+8t
+9s
+6ed
+7nce
+9es
+9ies
+9y
+8t
+9ly
+9s
+6ing
+9ly
+6s
+4ople
+8d
+8s
+7ing
+4rm
+6ed
+6ing
+6s
+5sonalise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+3hlegmate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+5ogisticate
+4osphorylate
+3ict
+6ed
+7r
+8s
+6ing
+7on
+9s
+7ve
+6or
+8s
+6s
+6ure
+9d
+9s
+8ing
+4gment
+9ation
+9ations
+9ed
+9ing
+9s
+4late
+8d
+8s
+7ing
+8on
+9ns
+7or
+9ies
+9s
+9y
+3lane
+7d
+7s
+6ing
+4etable
+6e
+7d
+7r
+8s
+7s
+6ing
+7on
+9s
+7ve
+6ory
+4orabilities
+9lity
+8le
+9eness
+9y
+7tion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+9ly
+5y
+6able
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4umation
+9ons
+6e
+7d
+7s
+6ing
+3olarisation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+5ish
+8ed
+9s
+8ing
+6ticise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+5ymerise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+4ne
+6d
+6nt
+8s
+6s
+5ing
+4pulate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+4rt
+6able
+7tion
+9ons
+6ed
+7e
+8s
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4sable
+6l
+7s
+5e
+6d
+6r
+7s
+6s
+5ing
+6t
+7aries
+9y
+8tion
+9ions
+7ed
+7ing
+8on
+9nal
+9ns
+8ve
+7or
+9ies
+9s
+9y
+7s
+4t
+5s
+3ravation
+9ons
+6e
+7d
+8ly
+8ness
+9esses
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9ly
+7ties
+8y
+4ecable
+7te
+9d
+9s
+8ing
+9ngly
+9on
+9ons
+9ve
+9vely
+8or
+9rily
+9rs
+9ry
+6iable
+8te
+9ed
+9es
+9ing
+9ingly
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+5date
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+9ry
+5hend
+9ed
+9ing
+9s
+5nyl
+8s
+5ss
+7ant
+9ts
+7ed
+8s
+7ible
+8ng
+9gly
+8on
+9ns
+8ve
+9ely
+9eness
+9es
+7omotor
+9otors
+8r
+9s
+7urise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+4ivable
+7l
+8s
+7tion
+9ons
+9ve
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+4ogram
+9ed
+9ing
+9me
+9med
+9mer
+9mers
+9mes
+9ming
+9s
+3side
+7s
+3th
+5less
+5s
+3urant
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9es
+7or
+9s
+9y
+4table
+6tion
+9ns
+5e
+6d
+6s
+5ies
+6ng
+6sation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5y
+2queue
+7d
+7ing
+7s
+6ing
+2racialise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+6nate
+9ed
+9es
+9ing
+9ion
+9ions
+7e
+4ign
+7ed
+7ing
+7ment
+9nts
+7s
+5l
+6ed
+7r
+8s
+6ing
+6leur
+9rs
+6ment
+9ts
+6s
+4nge
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+4t
+5e
+6d
+6s
+5ing
+8s
+6on
+8ed
+8ing
+8s
+5s
+5ted
+6ing
+4y
+5ed
+5ing
+5s
+3bies
+4y
+3e
+4alisation
+9tions
+7zation
+9tions
+4cognise
+9sed
+9ses
+9sing
+9tion
+9tions
+9ze
+9zed
+9zes
+9zing
+4d
+4gister
+9red
+9ring
+9rs
+8ration
+9ations
+5ulate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+9ory
+4lict
+8ion
+9ons
+8s
+6gionise
+9nised
+9nises
+9nising
+9nize
+9nized
+9nizes
+9nizing
+4press
+9ed
+9es
+9ing
+9ion
+9ions
+4quisition
+9tioned
+9tions
+4s
+5trict
+9ted
+9ting
+9tion
+9tions
+9ts
+3ham
+6s
+3ide
+6d
+6r
+7s
+6s
+5ing
+8ly
+4g
+5ged
+6ing
+5s
+4ng
+6er
+8s
+4sible
+6on
+8s
+6ve
+8ly
+8ness
+9esses
+5ory
+4vable
+8y
+6te
+8s
+7ion
+9nal
+9nist
+9nists
+9ns
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8ve
+9ely
+9eness
+9es
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5e
+6d
+6r
+7s
+6s
+5ing
+3m
+4a
+5brasion
+9ions
+5l
+5pteran
+9ans
+5s
+5tic
+7tes
+8ides
+9s
+9ses
+6ogen
+9ns
+8lyphic
+9yphics
+8raphia
+9aphias
+9aphic
+9aphies
+9aphy
+7id
+7logic
+9gical
+9gies
+9gist
+9gists
+9gy
+7mal
+8e
+9s
+8ic
+8yositis
+7phyte
+9ytes
+9ytic
+9ytoses
+9ytosis
+8lastic
+9asties
+9asty
+7ses
+8is
+4estid
+9s
+4ic
+5s
+6es
+4ographies
+9hy
+5id
+7s
+4s
+3n
+4ful
+4ier
+4ly
+4s
+3o
+4gate
+8d
+8ly
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+7orily
+9iness
+9y
+4s
+3rick
+7ed
+7ing
+7s
+5ere
+8s
+6s
+5nger
+9s
+5s
+6es
+4o
+5s
+4y
+3th
+5s
+3v
+4ish
+7es
+4s
+2sacralisation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+4grement
+9nts
+4linate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5t
+6ed
+7r
+8s
+6ing
+9s
+6s
+4nd
+6ed
+6ing
+6s
+4turation
+9ions
+3cale
+7d
+7s
+6ing
+5nt
+7ed
+8r
+9s
+7ing
+7s
+4end
+7able
+8nt
+9ts
+7ed
+8nt
+9ts
+8r
+9s
+8ur
+9rs
+7ible
+8ng
+9gs
+7s
+6sion
+9nal
+9ns
+6t
+7s
+4hool
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+4ramble
+9ed
+9er
+9ers
+9es
+9ing
+5ibable
+7e
+8d
+8r
+9s
+8s
+7ing
+6ed
+7r
+8s
+7s
+6ption
+9ons
+9ve
+9vely
+9veness
+9vism
+9visms
+9vist
+8or
+9rs
+6ve
+8d
+8s
+7ing
+5y
+6ing
+3ecrate
+9d
+9r
+9rs
+9s
+8ing
+9on
+9ons
+8or
+9rs
+4ed
+6ed
+6ing
+6s
+4gregate
+9ted
+9tes
+9ting
+9tion
+9tions
+4lect
+8ed
+8ing
+9on
+9ons
+8s
+4nsitisation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+4rpidine
+9nes
+5t
+6ed
+7r
+8s
+6ic
+7fication
+9ed
+9es
+8y
+9ing
+7ng
+7on
+9s
+7sation
+9tions
+7zation
+9tions
+6less
+6s
+5ve
+7d
+8ly
+8ness
+9esses
+7r
+8s
+7s
+6ing
+9ly
+9ness
+9nesses
+9s
+4x
+5ed
+6s
+5ing
+5ualisation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+3habille
+9es
+4i
+3i
+4ccant
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9ves
+8or
+9rs
+4derata
+9e
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9ives
+9um
+7ium
+9ms
+4gn
+6able
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+6ed
+8ly
+7e
+8s
+7r
+8s
+6ful
+6ing
+9ly
+9s
+6less
+6ment
+9ts
+6s
+4lver
+8ed
+8ing
+9sation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+4ne
+6d
+6nce
+9s
+7t
+8ial
+6s
+5ing
+4pience
+9es
+8t
+5ramine
+9nes
+4rabilities
+9ity
+7le
+9ness
+9nesses
+9s
+8y
+5e
+6d
+6less
+6r
+7s
+6s
+5ing
+5ous
+8ly
+8ness
+9esses
+4st
+6ance
+9es
+6ed
+7nce
+9es
+6ing
+6s
+3k
+4bound
+4fast
+8s
+4ill
+7ed
+7ing
+9gs
+7s
+5ng
+7s
+4man
+5en
+4note
+8s
+4s
+4top
+7s
+3man
+6s
+4id
+6ian
+6s
+5ne
+7s
+4odium
+9s
+6romic
+5id
+7s
+5somal
+8e
+9s
+3nood
+7ed
+7ing
+7s
+3obligeante
+9antes
+4euvre
+4late
+8d
+8ly
+8ness
+9esses
+8r
+9s
+8s
+7ing
+9gly
+8on
+9ns
+7or
+9s
+9y
+4rb
+6ed
+6ing
+6s
+5iente
+5ption
+9ns
+4xy
+6ribose
+9oses
+3pair
+7ed
+8r
+9s
+7ful
+7ing
+9gly
+7s
+5tch
+8ed
+9r
+9rs
+9s
+8ing
+4erado
+9es
+9s
+7te
+9ly
+9ness
+9nesses
+8ion
+9ons
+4icabilities
+9lity
+8le
+9eness
+9y
+5ght
+8s
+5ritualise
+9alised
+9alises
+9alize
+9alized
+9alizes
+5sable
+7l
+8s
+6e
+7d
+8ness
+9esses
+7ment
+9nts
+7r
+8s
+7s
+6ing
+5te
+7d
+7ful
+9lly
+9lness
+7ous
+9sly
+7s
+6ing
+4oil
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+5liation
+9ions
+5nd
+7ed
+8nce
+9ces
+9cies
+9cy
+9t
+9tly
+7ing
+9gly
+9gs
+7s
+5t
+6at
+8e
+9s
+8s
+6ic
+8al
+9lly
+9lness
+7sm
+9s
+6ocracies
+9acy
+6s
+4umate
+9d
+9s
+8ing
+9on
+9ons
+3quamate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9ory
+3se
+5rt
+7s
+8poon
+9oonful
+9oons
+5s
+4iatine
+9es
+5gnment
+9nts
+4yatine
+9es
+3tabilisation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+5in
+7ed
+7ing
+7s
+4emper
+9ed
+9ing
+9s
+4inate
+9d
+9s
+8ing
+9on
+9ons
+6e
+7d
+7s
+6ies
+7ng
+6y
+5tute
+9d
+9ness
+9nesses
+9s
+8ing
+9on
+9ons
+4ock
+7ed
+7ing
+7s
+4rier
+8s
+5oy
+7able
+7ed
+8r
+9s
+7ing
+7s
+5uct
+8ed
+8ibility
+9ble
+9ng
+9on
+9onal
+9onist
+9onists
+9ons
+9ve
+9vely
+9veness
+9ves
+9vist
+9vists
+9vities
+9vity
+8o
+9r
+9rs
+9s
+8s
+3uetude
+9s
+4gar
+7ed
+7ing
+7s
+4lfur
+8ed
+8ing
+9sation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+5phur
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ed
+9ing
+9ise
+9ised
+9iser
+9isers
+9ises
+9ising
+9ize
+9ized
+9izer
+9izers
+9izes
+9izing
+9s
+5torily
+9ness
+9nesses
+8y
+3yatin
+8s
+4ne
+6d
+6s
+5ing
+2tach
+6abilities
+9lity
+8le
+9y
+6ed
+8ly
+8ness
+9esses
+7r
+8s
+7s
+6ing
+6ment
+9ts
+4il
+6ed
+8ly
+8ness
+9esses
+7r
+8s
+6ing
+9s
+6s
+5n
+6able
+6ed
+7e
+8s
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4ngle
+8d
+8r
+9s
+8s
+7ing
+4ssel
+8ed
+8ing
+8led
+9ing
+8s
+3ect
+6abilities
+9lity
+8le
+6ed
+7r
+8s
+6ible
+7ng
+7on
+9s
+7ve
+9like
+9s
+8ist
+9sts
+6ophone
+9ones
+7r
+8ist
+9sts
+8s
+6s
+4nt
+6e
+7s
+6ion
+9s
+7st
+9s
+6s
+5u
+6e
+7s
+6s
+4r
+5ge
+7d
+7nce
+9es
+9ies
+9y
+8t
+9s
+7r
+8s
+7s
+6ing
+5iorate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+8ism
+9sms
+9ties
+9ty
+5ment
+9s
+6inability
+9ble
+9bly
+9cies
+9cy
+9nt
+9ntal
+9nts
+9te
+9ted
+9tely
+9teness
+9tes
+9ting
+9tion
+9tions
+9tive
+9tively
+9tives
+9tor
+9tors
+8e
+9d
+9dly
+9dness
+9r
+9rs
+9s
+8ing
+9sm
+9sms
+9st
+9stic
+9sts
+5rabilities
+9lity
+8le
+6ed
+7nce
+9es
+8t
+9ly
+9s
+7r
+8s
+6ing
+5s
+6ion
+9s
+7ve
+9s
+4st
+6abilities
+9lity
+8le
+9eness
+9y
+7tion
+9ons
+6ed
+7r
+8s
+6ing
+6s
+3hatch
+8ed
+9s
+8ing
+4rone
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+9gs
+3ick
+6ed
+7r
+8s
+6ing
+6s
+4nue
+7s
+3onabilities
+9ity
+7le
+6table
+7e
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+4rsion
+9s
+5t
+6ed
+6ing
+7on
+9s
+6s
+4ur
+6ed
+6ing
+6s
+4x
+5ed
+6s
+5icant
+9ts
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+6fication
+9ations
+8ed
+9s
+7y
+8ing
+6ng
+3ract
+7ed
+7ing
+9gly
+9gs
+8on
+9ns
+8ve
+9ely
+7or
+9s
+9y
+7ress
+9sses
+7s
+5in
+7ed
+7ing
+7ment
+9nts
+7s
+5que
+8e
+9s
+8s
+4ibalisation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+5ment
+9al
+9ally
+9als
+9s
+5tal
+6ion
+9s
+6ovore
+9res
+6us
+4ude
+7d
+7s
+6ing
+5ncate
+9ed
+9es
+9ing
+9ion
+9ions
+5sion
+9s
+6or
+8s
+3umescence
+9nces
+9nt
+4ne
+6d
+6s
+5ing
+2uce
+5d
+6ly
+5s
+4ing
+3ddarn
+8s
+3s
+3teragonist
+9nists
+7nomalies
+9malous
+9maly
+9pe
+9pes
+9pia
+9pias
+9pic
+7te
+9d
+9s
+8ing
+9on
+9ons
+6ic
+7de
+9s
+7um
+9s
+6ogamies
+9mist
+9mists
+9my
+7n
+8s
+7plasm
+9asms
+7scopic
+9opies
+9opy
+8tome
+9omes
+7tokies
+9ky
+4on
+6s
+5plasm
+9mic
+9ms
+9tic
+4zia
+7s
+2v
+3a
+4ll
+6ed
+6ing
+6s
+5orisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5uate
+9d
+9s
+8ing
+9on
+9ons
+6e
+7d
+7s
+6ing
+4nagari
+9is
+4s
+5tate
+9d
+9s
+8ing
+9ngly
+9on
+9ons
+9ve
+8or
+9rs
+7vit
+9ts
+3ein
+6ed
+6ing
+6s
+4l
+5ed
+5ing
+5led
+6ing
+5op
+7able
+7e
+8d
+8r
+9s
+8s
+7ing
+7ment
+9ntal
+9ntally
+9nts
+7pe
+9s
+7s
+5s
+4rbal
+8s
+7tive
+9ves
+4st
+6ed
+6ing
+6s
+3iance
+8s
+7ies
+7y
+6t
+7s
+5te
+7d
+7s
+6ing
+7on
+9ism
+9isms
+9ist
+9ists
+9s
+7ve
+6or
+8s
+8y
+4ce
+6ful
+6s
+4l
+5dom
+8s
+5ed
+6ss
+8es
+6t
+7s
+5fish
+9es
+5ing
+8s
+6sh
+8ly
+8ness
+9esses
+7m
+8s
+5kin
+8s
+5led
+6ing
+5ment
+9s
+5ries
+6y
+5s
+6hip
+9s
+5tries
+7y
+5wood
+9s
+4ous
+7ly
+7ness
+9sses
+4sable
+6l
+7s
+5e
+6d
+6e
+7s
+6r
+7s
+6s
+5ing
+5or
+7s
+4talisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5rification
+9ed
+9es
+8y
+9ing
+3ling
+7s
+3ocalise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+4ice
+7d
+7s
+6ing
+5d
+5r
+6s
+4lution
+9nary
+9nist
+9nists
+9ns
+5ve
+7d
+7ment
+9nts
+7s
+6ing
+4n
+5ian
+5port
+9s
+5s
+4re
+6s
+4t
+5e
+6d
+7ly
+7ness
+9sses
+6e
+7s
+6ment
+9ts
+6s
+5ing
+6on
+8al
+9list
+9lists
+9lities
+9lity
+9lly
+9lness
+9ls
+8ist
+9sts
+8s
+5s
+4ur
+6ed
+7r
+8s
+6ing
+9ly
+6ment
+9ts
+6s
+5t
+6er
+7st
+6ly
+6ness
+9ses
+3s
+3vel
+6led
+7ing
+6s
+2w
+3an
+5i
+6s
+5nies
+6y
+5s
+4r
+5s
+4ter
+7ed
+8r
+9s
+7ing
+9gs
+7s
+4x
+5ed
+6s
+5ing
+3berries
+7y
+3claw
+7ed
+7s
+3drop
+7s
+3ed
+3fall
+7s
+4ull
+3ier
+5st
+4ly
+4ness
+8es
+5g
+4tt
+6ed
+6ing
+6s
+3lap
+6ped
+6s
+6t
+4ess
+3ool
+6ed
+6ing
+6s
+4rm
+6ed
+7r
+8s
+6ing
+6s
+3point
+8s
+3s
+3y
+2x
+3amethasone
+9sones
+5phetamine
+9amines
+3es
+3ie
+5s
+4otropic
+3ter
+6ities
+8y
+6ous
+9ly
+9ness
+9nesses
+6s
+6wise
+4ral
+7ities
+9y
+7ly
+6n
+7ase
+9es
+7s
+5in
+7e
+8s
+7s
+5o
+6cardia
+9diac
+9diacs
+9dias
+6glucose
+9coses
+7yrate
+9e
+6rotary
+9ation
+9ations
+9atory
+7sal
+8e
+9ly
+6se
+8s
+6us
+8ly
+8ness
+9esses
+3y
+2y
+3s
+2zinc
+6ed
+6ing
+6ked
+7ing
+6s
+1hak
+4s
+3l
+4s
+3mma
+6s
+3nsak
+7s
+3rma
+6s
+5ic
+5sala
+9s
+6hala
+9as
+4na
+6s
+2immi
+6s
+2obi
+5s
+3l
+4e
+5s
+4l
+5s
+4s
+3olies
+5y
+4ra
+6s
+4ti
+6e
+7s
+6s
+3ti
+5s
+3urra
+7s
+3w
+4s
+2urna
+6s
+4ra
+6s
+5ie
+7s
+3ti
+5s
+1i
+2abase
+7s
+6ic
+4etes
+6ic
+8al
+8s
+6ogenic
+7logist
+9gists
+4le
+6rie
+9s
+7y
+6s
+4olic
+8al
+9lly
+9lness
+7se
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7ze
+9d
+9s
+8ing
+6o
+7gies
+8y
+7logies
+9gy
+7s
+3catholicon
+9icons
+5ustic
+9cs
+4etyl
+8s
+4hronic
+9cally
+9es
+9sm
+9sms
+9stic
+8ous
+8y
+5ylon
+9s
+7um
+9s
+4id
+6ic
+6s
+4odion
+9s
+7um
+9s
+5nal
+7te
+9s
+6icon
+9ns
+5ustic
+9cs
+4ritic
+9al
+9ally
+9s
+4t
+5inal
+7e
+7ic
+8sm
+9ms
+3delphous
+5m
+6ed
+6ing
+6s
+4ochi
+8es
+7y
+4rom
+7ous
+7s
+3ereses
+7is
+6tic
+3geneses
+8is
+7tic
+9cally
+5otropic
+9pism
+9pisms
+4lyph
+8s
+4nosability
+9le
+7e
+8able
+8d
+8s
+7ing
+8s
+7tic
+9cal
+9cally
+9cian
+9cians
+9cs
+4ometer
+9rs
+5nal
+8isable
+9sation
+9se
+9sed
+9ses
+9sing
+9zable
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+4ram
+7ed
+7ing
+7mable
+9tic
+9tical
+8ed
+8ing
+7s
+6ph
+8ic
+8s
+5id
+7s
+3heliotropic
+9ropism
+3kineses
+8is
+3l
+4ect
+7al
+9ly
+7ic
+9al
+9ally
+9ian
+9ians
+9ism
+9isms
+9s
+7ological
+9ogies
+9ogist
+9ogists
+9ogy
+7s
+5d
+5r
+6s
+4ing
+7s
+5st
+7s
+4lage
+8s
+7ic
+7oid
+5ed
+6l
+6r
+7s
+5ing
+8s
+6st
+8s
+4og
+6ed
+7r
+8s
+6ic
+8al
+9lly
+7ng
+7se
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ical
+9s
+7te
+9s
+7ze
+9d
+9s
+8ing
+6s
+6ue
+8d
+8r
+9s
+8s
+7ing
+4s
+4ypetalous
+5sabilities
+9lity
+8le
+7te
+9s
+8ion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+7s
+5tic
+8ally
+5zabilities
+9lity
+8le
+7te
+9s
+8ion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+3magnet
+9ic
+9ically
+9ism
+9isms
+9s
+5nte
+8s
+7iferous
+8ne
+4eter
+8s
+6ral
+9ly
+7ic
+9al
+9ally
+4ide
+7s
+5n
+6e
+7s
+6s
+4ond
+7back
+9cks
+7ed
+7iferous
+8ng
+7s
+5rphine
+9nes
+4yl
+3ndries
+6ous
+6y
+4e
+4odal
+5etic
+5ia
+7s
+4thus
+8es
+3pase
+7s
+6on
+8al
+8ic
+8s
+5use
+8d
+8s
+7ing
+4edeses
+8is
+7tic
+5nte
+8s
+5r
+6ed
+6ing
+9s
+6s
+4haneities
+9ty
+7ometer
+9eters
+8us
+9sly
+9sness
+5one
+8s
+7ic
+8es
+7y
+6rase
+9es
+7eses
+9is
+8tic
+9ics
+6totropic
+9ropies
+9ropism
+9ropy
+5ragm
+9al
+9atic
+9atitis
+9ed
+9ing
+9s
+5yseal
+8s
+7ial
+8s
+4ir
+6ic
+7sm
+9s
+6s
+4ophyses
+9ial
+9is
+5sitive
+9ves
+4sid
+7s
+4yeses
+7is
+6tic
+9s
+3rch
+6al
+6ic
+8al
+7es
+6y
+4ial
+6n
+5es
+5se
+7d
+7s
+6ing
+6t
+7ic
+7s
+5ze
+7d
+7s
+6ing
+4rhea
+8l
+8s
+7ic
+7tic
+6oea
+9l
+9s
+8ic
+4throdial
+8ses
+9is
+4y
+3scia
+7s
+5ope
+8s
+6rdium
+9ums
+4keuast
+9ts
+4pora
+8s
+7e
+8s
+7ic
+4talses
+8is
+7tic
+6se
+8s
+7ic
+8s
+6tic
+5em
+7a
+8s
+8ta
+9ic
+7s
+6r
+7eoisomer
+9mer
+9meric
+9mers
+7s
+5ole
+8s
+7ic
+5ral
+6ophic
+9ically
+9ism
+9isms
+5yle
+8s
+3tessaron
+9ons
+4hermacies
+9cy
+9l
+9ncies
+9ncy
+9neity
+9nous
+8ia
+9as
+9c
+9es
+8ous
+8y
+6ses
+7is
+6tic
+4om
+6aceous
+6ic
+8ities
+9ty
+7st
+9s
+7te
+9s
+6s
+5nic
+8ally
+8ism
+9sms
+4reta
+7um
+9s
+5ibe
+8s
+7ist
+9ts
+5on
+7s
+6pic
+8sm
+9ms
+3xon
+6s
+3zepam
+8s
+5uctic
+6xes
+7is
+4in
+6e
+7s
+6on
+8s
+6s
+4o
+5es
+5le
+7s
+5methane
+9anes
+5nium
+9s
+5s
+5tisation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+2b
+3asic
+7ities
+9y
+3bed
+5r
+6s
+4ing
+4le
+6d
+6r
+7s
+6s
+5ing
+4s
+4uk
+6im
+6kim
+6s
+3enzofuran
+9rans
+3ranchiate
+9ates
+4omide
+9s
+3s
+3utyl
+2cacious
+6ties
+7y
+5odyl
+9s
+4mba
+7s
+4rboxylic
+5pellary
+4st
+6eries
+8y
+6ic
+6s
+3e
+4d
+4ntra
+8s
+7ic
+9s
+4phalism
+9sms
+8ous
+4r
+5s
+4s
+4y
+3h
+4asia
+8l
+9ly
+7um
+4lamydeous
+5oracetic
+7ide
+9es
+7obenzene
+8ethane
+9thanes
+8methane
+7vos
+9ses
+4ogamic
+9es
+8ous
+8y
+5ndra
+9s
+5ptic
+5rd
+7s
+5tic
+8ally
+6omic
+9es
+9sation
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9zation
+9ze
+9zed
+9zes
+9zing
+8ous
+9usly
+9usness
+8y
+4roic
+7scope
+9opes
+9opic
+8m
+9s
+7te
+9s
+8ic
+6mat
+9e
+9es
+9ic
+9icism
+9icisms
+9ics
+9ism
+9isms
+9s
+7ic
+8sm
+9ms
+6oscope
+9opes
+9opic
+6scope
+9pes
+9pic
+4t
+5ed
+5ing
+5s
+3ier
+5st
+4ng
+6s
+3kcissel
+9ls
+4ens
+7es
+5r
+6ed
+6ing
+6s
+5y
+6bird
+9ds
+6s
+4ie
+6r
+6s
+7t
+5ngs
+4tier
+7st
+4y
+5bird
+9s
+3linies
+7sm
+9s
+6ous
+6y
+3ot
+5s
+5yl
+7edon
+9onous
+9ons
+7s
+4umarin
+9ns
+8ol
+9ls
+3rotal
+6ic
+7sm
+9s
+6ous
+3t
+4a
+5te
+7d
+7s
+6ing
+7on
+9al
+9s
+6or
+8ial
+9ally
+9alness
+8s
+9hip
+9hips
+8y
+6ress
+9ses
+7ices
+8x
+9es
+6ure
+9s
+4ed
+4ier
+6st
+5ng
+5on
+7al
+9ly
+8ries
+9y
+7s
+4s
+4um
+6s
+4y
+5ogen
+9s
+6pteran
+9rans
+6some
+9es
+7tele
+9les
+3umarol
+9s
+3yclic
+7es
+6y
+4nodont
+9ts
+2d
+3act
+6ic
+8al
+9lly
+8ism
+9sms
+8s
+6s
+6yl
+8ism
+9sms
+8ous
+8s
+4kai
+7s
+5ei
+7s
+4pper
+8s
+4scalic
+3der
+6ed
+6ing
+6s
+4icoy
+8s
+5er
+6s
+7t
+4le
+6d
+6r
+7s
+6s
+6y
+7s
+5ies
+6ng
+5y
+6squat
+4y
+3elphian
+8c
+8d
+9s
+8ne
+7ous
+3geridoo
+9os
+3icoi
+7s
+6y
+7s
+4e
+5s
+3jeridoo
+9os
+8u
+9s
+3o
+4es
+4s
+3rachm
+8a
+9s
+8s
+3st
+3y
+4mium
+8s
+5ous
+4namian
+8es
+7ous
+7y
+2e
+3b
+4ack
+7s
+4s
+3cious
+8ly
+8ness
+9esses
+3d
+4ral
+7s
+5e
+6s
+3ffenbachia
+9chias
+3geses
+6is
+5tic
+3hard
+7s
+3ing
+3l
+4drin
+8s
+4ectric
+9cally
+9cs
+4ytra
+8s
+3maker
+8s
+3ncephala
+9lic
+9lon
+9lons
+4e
+5s
+3off
+6s
+3reses
+6is
+5tic
+3s
+4el
+6ed
+6ing
+9s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+5s
+4inker
+9s
+5s
+4ter
+7s
+5ock
+8s
+5rous
+6um
+8s
+7s
+8es
+3t
+4arian
+9s
+7es
+7ly
+6y
+4ed
+5r
+6s
+5tic
+8al
+9lly
+8s
+4her
+7s
+5yl
+7amide
+9ides
+9ine
+9ines
+7ene
+9es
+7s
+4ician
+9s
+5ne
+7s
+6g
+7s
+5st
+7s
+5tian
+9s
+4s
+2f
+3f
+4arreation
+9tions
+4er
+6ed
+7nce
+9ed
+9es
+9ied
+9ies
+9ing
+9y
+9ying
+8t
+9ia
+9iable
+9iae
+9ial
+9ially
+9ials
+9iate
+9iated
+9iates
+9iating
+9iation
+9iator
+9iators
+9ly
+9ness
+9nesses
+6ing
+6s
+4icile
+6ult
+9ies
+9ly
+9y
+5dence
+9es
+8t
+9ly
+4luent
+4orm
+7ities
+9y
+4ract
+8ed
+8ing
+9on
+9ons
+9ve
+9vely
+9veness
+8ometer
+9meters
+9metric
+9metry
+8s
+6ngibility
+9ble
+4s
+4use
+7d
+8ly
+8ness
+9esses
+7ly
+7ness
+9sses
+7r
+8s
+7s
+6ibilities
+9lity
+8le
+9eness
+7ng
+7on
+9al
+9ism
+9isms
+9ist
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+8ities
+9ty
+6or
+8s
+3s
+3unctional
+9nals
+2g
+3amies
+6st
+8s
+5ma
+7s
+5ous
+5y
+4stric
+9s
+3eneses
+7is
+6tic
+4rati
+4st
+6ant
+9s
+6ed
+8ly
+7r
+8s
+6ibilities
+9lity
+8le
+9eness
+9y
+7f
+8s
+7ng
+7on
+9al
+9s
+7ve
+9ly
+9s
+6or
+8s
+6s
+3gable
+4ed
+5r
+6s
+4ing
+7s
+3ht
+5ed
+5ing
+5s
+3icam
+7s
+4pack
+8s
+4t
+5al
+7in
+9s
+8s
+9ation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7s
+6te
+8d
+8ly
+7ion
+9ns
+5iform
+6grade
+9des
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5onin
+9s
+6rium
+9ms
+6xigenin
+9enins
+8n
+9s
+5ron
+8s
+5s
+5ule
+8s
+3ladiate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+4ossia
+9s
+8c
+5t
+6s
+6tic
+4yceride
+9des
+5ph
+7s
+3nification
+9tions
+7ed
+9ly
+9ness
+9nesses
+8s
+6y
+7ing
+5taries
+8y
+6ies
+6y
+3onal
+5eutic
+9sm
+9sms
+4xin
+7s
+3raph
+7ic
+9ally
+7s
+4ess
+7ed
+8r
+9s
+8s
+7ing
+8on
+9nal
+9nary
+9ns
+8ve
+9ely
+9eness
+3s
+3ynian
+5ous
+2hedra
+7l
+8s
+6on
+8s
+3ybrid
+8ism
+9sms
+8s
+4dric
+6ocodeine
+9deines
+7gen
+2judicate
+9ed
+9es
+9ing
+9ion
+9ions
+2ka
+4s
+5t
+6s
+3dik
+6s
+3e
+4d
+4r
+5s
+4s
+4tone
+4y
+3ier
+5st
+4ng
+3kop
+6s
+3tat
+6s
+2lacerate
+9ed
+9es
+9ing
+9ion
+9ions
+4pidate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+4tabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6ncies
+8y
+7t
+8s
+6te
+7ion
+9nal
+9ns
+7or
+9s
+5e
+6d
+6r
+7s
+6s
+5ing
+6on
+8s
+6ve
+5ometer
+9ers
+9ric
+9ries
+9ry
+6r
+7ily
+8ness
+9esses
+7s
+7y
+3emma
+7s
+7tic
+6ic
+4ttante
+9eish
+9eism
+9eisms
+9es
+9i
+9ish
+9ism
+9isms
+3igence
+9s
+7t
+8ly
+3l
+4ed
+4i
+5er
+6s
+7t
+5ng
+7s
+5s
+4s
+4y
+5dallied
+9ies
+9y
+9ying
+3tiazem
+9s
+3ucidate
+9ed
+9es
+9ing
+9ion
+9ions
+4ent
+7s
+4table
+9s
+5e
+6d
+6e
+7s
+6ness
+9ses
+6r
+7s
+6s
+5ing
+6on
+8ary
+8s
+6ve
+5or
+7s
+4via
+7l
+8ism
+9sms
+9st
+9sts
+7n
+6on
+8s
+6um
+8s
+2m
+3ble
+6s
+3e
+4nhydrinate
+9inates
+5sion
+9al
+9ality
+9ally
+9ed
+9ing
+9less
+9s
+4r
+5caprol
+9ols
+5ic
+6sation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ous
+5s
+4s
+4ter
+7s
+5hoate
+9es
+6yl
+8amine
+9mines
+9niline
+8s
+5ric
+3idiate
+9d
+9s
+8ing
+9on
+9ons
+4nish
+8able
+8ed
+9s
+8ing
+9ngly
+9ngs
+8ment
+9ents
+5uendo
+9oes
+9os
+6tion
+9ns
+8val
+9e
+9ely
+9eness
+9es
+4ssory
+4ties
+5y
+3ly
+3mable
+4ed
+5r
+6s
+5st
+4ing
+7s
+5sh
+3ness
+7es
+3orph
+7ic
+8sm
+9ms
+7ous
+7s
+4ut
+6s
+3p
+4le
+6d
+6ment
+9ts
+6s
+5ier
+7st
+6ng
+5y
+4s
+5ies
+5y
+3s
+3wit
+6s
+6ted
+3yarian
+2n
+3anderie
+9es
+4r
+5chies
+7y
+5s
+3dle
+6d
+6s
+5ing
+3e
+4d
+4r
+5ic
+5o
+6s
+5s
+4s
+4tte
+7s
+3ful
+3g
+4bat
+7s
+4dong
+8ed
+8ing
+8s
+4e
+5d
+5r
+6s
+5s
+6es
+5y
+6s
+4hies
+5y
+4ied
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+4le
+6s
+4o
+5ed
+6s
+5ing
+4s
+4us
+6es
+4y
+5ing
+3ic
+5s
+4ng
+4tro
+7benzene
+9nzenes
+7gen
+7phenol
+9enols
+3ked
+5r
+5st
+5y
+6s
+4ie
+6r
+6s
+7t
+5ng
+4ly
+4um
+6s
+4y
+3mont
+7s
+3na
+5e
+4ed
+5r
+6ed
+6ing
+6less
+6s
+6time
+9es
+6ware
+9es
+4ing
+4le
+6d
+6s
+5ing
+3o
+4ceras
+9es
+4flagellate
+9llates
+4mania
+9s
+4s
+5aur
+8ian
+9c
+8s
+4there
+9s
+8ium
+9ums
+5urbation
+9tions
+3s
+3t
+4ed
+4ing
+4less
+4s
+3ucleotide
+9ides
+2obol
+6on
+8s
+6s
+3cesan
+8s
+6e
+7s
+3de
+5s
+3ecies
+6ous
+9ly
+9ness
+9nesses
+6sm
+8s
+5y
+4strus
+9es
+3icous
+8ly
+8ness
+9esses
+3l
+4efin
+8s
+4s
+3nysiac
+8n
+3physite
+9es
+4side
+8s
+7ic
+4tase
+8s
+5er
+7s
+5ometer
+9ers
+9ries
+9ry
+5ral
+7te
+6e
+7s
+6ic
+8al
+9lly
+8s
+3rama
+7s
+6ic
+4ism
+7s
+6tic
+9al
+9ally
+5te
+7s
+6ic
+4thoses
+8is
+7tic
+3scoreaceous
+4genin
+9s
+3ta
+5s
+4helete
+9es
+9ic
+9ical
+7ism
+9ms
+8te
+9es
+3xan
+6e
+7s
+6s
+4id
+6e
+7s
+6s
+5n
+6s
+4onitric
+2p
+3chick
+8s
+3eptidase
+9ses
+8e
+9s
+4talous
+3hase
+6ic
+4enhydramine
+6yl
+8amine
+9mines
+8enimine
+8ketone
+9etones
+8s
+4one
+7s
+5sgene
+9es
+6phate
+9tes
+4theria
+9al
+9as
+9c
+9tic
+9tis
+9tises
+8oid
+9ids
+6ong
+9al
+9ally
+9ed
+9ic
+9ing
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9s
+4ycercal
+5letic
+6lous
+5odont
+9ts
+5site
+9s
+8ism
+9sms
+3legia
+8s
+7c
+5idoscope
+9copes
+5x
+6er
+8s
+4obiont
+9tic
+9ts
+6lastic
+5cardiac
+6occal
+9i
+9ic
+9us
+5docus
+9ses
+5e
+6s
+5gen
+8eses
+9sis
+8s
+5ic
+6d
+7ic
+8es
+7s
+7y
+5ma
+7cies
+8y
+7ed
+7ing
+7s
+7t
+8a
+8e
+9d
+9s
+9se
+9ses
+8ic
+9cal
+9cally
+9cs
+9ng
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+8ologies
+9logy
+8s
+5n
+6ema
+9s
+6s
+6t
+7ic
+7s
+5phase
+9es
+6ia
+8s
+7c
+6od
+8s
+5ses
+6is
+6temonous
+5tene
+9s
+5zoa
+7ic
+7on
+3net
+6s
+6ted
+7ing
+4oan
+7s
+5ous
+3odic
+6es
+5y
+4lar
+5e
+6s
+3pable
+4ed
+5r
+6ful
+9s
+6s
+4ier
+6st
+5ness
+9es
+6g
+7s
+4y
+3rionidian
+4opellant
+9ants
+5tic
+6odon
+9ns
+9nt
+9ntid
+9ntids
+9nts
+3s
+4ades
+5s
+4o
+5mania
+9ac
+9acal
+9acs
+9as
+5s
+4tick
+8s
+4witch
+9es
+3t
+4era
+7l
+7n
+8s
+7s
+6ist
+9s
+6ocarp
+9rpous
+9rps
+7i
+7n
+8s
+7s
+8es
+7us
+4yca
+7s
+6h
+7s
+2quark
+7s
+5t
+6s
+2ram
+5s
+3dam
+6s
+4um
+6s
+3e
+4ct
+6ed
+8ness
+9esses
+7r
+7st
+6ing
+7on
+9al
+9ality
+9less
+9s
+7ve
+9s
+8ities
+9ty
+6ly
+6ness
+9ses
+6or
+8ate
+9tes
+8ial
+9ally
+9es
+8s
+9hip
+9hips
+8y
+6ress
+9ses
+7ice
+9es
+8x
+9es
+6s
+4ful
+7ly
+7ness
+9sses
+4ly
+4mpt
+7ed
+7ing
+8on
+9ns
+7s
+4ness
+8es
+4r
+4st
+3ge
+5ful
+5like
+5s
+3ham
+6s
+4em
+6s
+3ige
+6nt
+6s
+5ibilities
+9ity
+7le
+9s
+6sm
+8e
+9s
+8s
+7te
+4ment
+3k
+4e
+5d
+5s
+4ing
+4s
+3l
+4ed
+4ing
+4s
+3ndl
+6s
+3t
+4bag
+7s
+4ed
+4ied
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+4s
+4y
+5ing
+2s
+3a
+4bilities
+9y
+5le
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+7sm
+9s
+8t
+9s
+5usal
+9s
+7e
+8d
+8s
+7ing
+4ccharid
+9idase
+9idases
+9ide
+9ides
+9ids
+6ommodate
+9odated
+9odates
+7rd
+9ant
+9ed
+9ing
+9s
+6redit
+9ited
+9iting
+9its
+6ustom
+9omed
+9oming
+9oms
+5knowledge
+9ledged
+9ledges
+4dorn
+8ed
+8ing
+8s
+5vance
+9ed
+9es
+9ing
+8tage
+9aged
+9ageous
+9ages
+9aging
+6enture
+9ures
+9urous
+4ffect
+9ed
+9edly
+9edness
+9ing
+9ion
+9ionate
+9ions
+9s
+6iliate
+9ated
+9ates
+9ating
+9ation
+9ations
+7rm
+9ance
+9ances
+9ation
+9ations
+9ed
+9ing
+9s
+6orest
+9sted
+9sting
+9stment
+9sts
+4ggregate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+5ree
+8ability
+9ble
+9bles
+9bly
+8d
+8ing
+8ment
+9ents
+8s
+4llied
+8s
+6ow
+8able
+9nce
+9nces
+8ed
+8ing
+8s
+6y
+7ing
+4mbiguate
+9ated
+9ates
+9ating
+9ation
+9ations
+5enities
+9y
+4nalogies
+9ous
+9y
+5chor
+9ed
+9ing
+9s
+5imate
+9ed
+9es
+9ing
+5nex
+8ed
+9s
+8ing
+6ul
+8led
+9er
+9ers
+9ing
+9ings
+8ment
+9ents
+8s
+5oint
+9ed
+9ing
+9s
+4pparel
+9lled
+9lling
+9ls
+6ear
+9ance
+9ances
+9ed
+9ing
+9s
+6lication
+9ations
+8ed
+9s
+7y
+8ing
+6oint
+9ted
+9tedly
+9ting
+9tingly
+9tment
+9tments
+9ts
+6robation
+9ations
+9ative
+9atory
+8priate
+9riated
+9riates
+8val
+9als
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9ingly
+4rm
+6ament
+9nts
+6ed
+7r
+8s
+6ing
+9ly
+6s
+5range
+9ed
+9ement
+9ements
+9es
+9ing
+7y
+8ed
+8ing
+8s
+5ticulate
+9lated
+9lates
+9lating
+9lation
+9lator
+9lators
+4s
+5semble
+9led
+9ler
+9lers
+9les
+9lies
+9ling
+9ly
+6imilate
+9lated
+9lates
+9lating
+9lation
+9lative
+6ociate
+9ated
+9ates
+9ating
+9ation
+9ations
+5ter
+8s
+6rous
+9sly
+4ttire
+9d
+9s
+8ing
+6ribution
+9utions
+6une
+9d
+9s
+8ing
+4uthorise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+4vaunce
+9ed
+9es
+9ing
+5entrous
+8ure
+9res
+5ouch
+9ed
+9es
+9ing
+6w
+7able
+8l
+9s
+7ed
+9ly
+8r
+9s
+7ing
+7s
+3band
+7ed
+7ing
+7ment
+9nts
+7s
+5r
+6k
+7ed
+7ing
+7s
+6ment
+9ts
+6red
+7ing
+6s
+4elief
+9s
+8ve
+9ed
+9er
+9ers
+9es
+9ing
+9ingly
+5nch
+8ed
+9s
+8ing
+6efit
+9ts
+4odied
+5som
+8ed
+8ing
+8s
+5und
+5wel
+8ed
+8ing
+8led
+9ing
+8s
+4ranch
+9ed
+9es
+9ing
+4ud
+6ded
+7ing
+6s
+5rden
+9ed
+9ing
+9ment
+9ments
+9s
+6sable
+8l
+9s
+7e
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+6then
+9ned
+9ning
+9ns
+3c
+4age
+7d
+7s
+6ing
+5l
+6ceate
+9tes
+8d
+5ndering
+9ings
+7ie
+9d
+9s
+7y
+8ing
+9ngs
+6t
+7ed
+8r
+9s
+7ing
+7s
+5pacitate
+9tated
+9tates
+9tating
+5rd
+7able
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+6nate
+5se
+7d
+7s
+6ing
+4ed
+5pt
+7ation
+9ions
+9ious
+9or
+9orial
+9ors
+7ed
+7ing
+7s
+5rn
+7able
+9ly
+7ed
+8r
+9s
+7ible
+9ly
+8ng
+9gly
+7ment
+9nts
+7s
+6p
+7ed
+7ibility
+9le
+8ng
+7s
+7tible
+9on
+9ons
+9ve
+4harge
+9able
+9d
+9e
+9es
+9r
+9rs
+9s
+8ing
+5uffed
+6rch
+9ed
+9es
+9ing
+4i
+5de
+7d
+7s
+6ing
+5form
+5nct
+6g
+5ple
+8d
+8s
+9hip
+9hips
+7inable
+9al
+9ant
+9ants
+9arian
+9arians
+9arily
+9arity
+9arium
+9ariums
+9ary
+9e
+9ed
+9er
+9ers
+9es
+9g
+9ing
+6ular
+5ssion
+9ns
+4laim
+8ed
+9r
+9rs
+8ing
+8s
+6mation
+9ions
+5ike
+6max
+9es
+5ose
+8d
+8r
+9s
+8s
+7ing
+7t
+7ure
+9es
+4o
+5boli
+8os
+8us
+9ses
+5ed
+6r
+7s
+5grapher
+9hers
+9hic
+9hical
+9hies
+9hy
+5id
+7al
+7s
+6ng
+5logies
+9st
+9sts
+8y
+7r
+8ation
+9tions
+8ed
+8ing
+8ment
+9ents
+8s
+7ur
+9ation
+9ations
+9ed
+9ing
+9ment
+9ments
+9s
+5mboberate
+9erated
+9erates
+9ulate
+9ulated
+9ulates
+6edusan
+9sans
+6fit
+9ed
+9er
+9ers
+9ing
+9s
+9ure
+9ures
+7ort
+9table
+9ted
+9ting
+9ts
+6mend
+9dable
+9dation
+9ded
+9ding
+9ds
+7ission
+9sioned
+9sions
+7ode
+9ed
+9es
+9ing
+9ious
+9iously
+9ities
+9ity
+8n
+9ed
+9ing
+9s
+7unities
+9ity
+6pose
+9ed
+9edly
+9es
+9ing
+9ingly
+9ure
+9ures
+6ycete
+9tes
+9tous
+5ncert
+9ted
+9tedly
+9ting
+9tingly
+9tion
+9tions
+9tment
+9tments
+9ts
+6firm
+9mation
+9med
+9ming
+9ms
+7ormable
+9mities
+9mity
+6nect
+9ted
+9tedly
+9ter
+9ters
+9ting
+9tion
+9tions
+9tive
+9ts
+8xion
+9ions
+6sent
+9ted
+9ting
+9ts
+7olate
+9ately
+9ation
+9ations
+6tent
+9ted
+9tedly
+9tful
+9ting
+9tment
+9tments
+9ts
+7iguities
+9uity
+9uous
+8nuance
+9uances
+9uation
+9ue
+9ued
+9uer
+9uers
+9ues
+9uing
+9uities
+9uity
+9uous
+9uously
+5phile
+9es
+7oran
+9ans
+9ous
+5rd
+7ance
+9ces
+9cies
+9cy
+9t
+9tly
+7ed
+7ful
+7ing
+7s
+6porate
+5s
+5theque
+9ues
+5unsel
+9lled
+9lling
+9ls
+7t
+8able
+8ed
+9nance
+9nanced
+9nances
+9r
+9rs
+8ing
+8s
+6rage
+9eable
+9ed
+9ement
+9ements
+9er
+9ers
+9es
+9ing
+9ingly
+7e
+8d
+8s
+7ing
+7sal
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ve
+7teise
+9ous
+9ously
+9sies
+9sy
+5ver
+8able
+8ed
+9r
+9rs
+8ies
+9ng
+8s
+8t
+9ure
+9ures
+8y
+4redit
+9able
+9ably
+9ed
+9ing
+9s
+6et
+8er
+9st
+8ly
+8ness
+9esses
+6pance
+9ces
+9cies
+9cy
+9t
+9tly
+6te
+8ly
+8ness
+9esses
+8r
+8st
+7ion
+9nal
+9nally
+9narily
+9nary
+9ns
+8ve
+9ely
+5iminable
+9ably
+9ant
+9ants
+9ate
+9ated
+9ately
+9ates
+9ating
+9ation
+9ations
+9ative
+9ator
+9ators
+9atory
+5own
+8ed
+8ing
+8s
+4s
+4ulpate
+9ed
+9es
+9ing
+5mber
+9ed
+9ing
+9s
+5re
+7d
+7s
+6ing
+6sion
+9ns
+8st
+9ts
+8ve
+9ely
+9eness
+7ory
+7us
+9es
+5s
+6es
+6s
+7able
+8nt
+9ts
+7ed
+8r
+9s
+8s
+7ible
+8ng
+8on
+9nal
+9ns
+8ve
+5tient
+9ts
+3dain
+7ed
+7ful
+9lly
+9lness
+7ing
+7s
+3ease
+7d
+8ness
+9esses
+7ful
+7s
+6ing
+4conomies
+9y
+4dge
+7d
+7s
+6ing
+4mbark
+9ation
+9ations
+9ed
+9ing
+9ment
+9ments
+9s
+8rass
+9assed
+9asses
+9assing
+6ellish
+9ished
+9ishes
+9ishing
+6itter
+9ered
+9ering
+9ers
+6odied
+9es
+9ment
+9ments
+8y
+9ing
+7gue
+9ed
+9ement
+9ements
+9es
+9ing
+7som
+9med
+9ming
+9ms
+7wel
+9led
+9ling
+9lled
+9lling
+9lment
+9lments
+9ls
+6rangle
+9gled
+9gles
+9gling
+7oil
+9led
+9ling
+9ls
+6urden
+9ened
+9ening
+9ens
+5ploy
+9ed
+9ing
+9ment
+9ments
+9s
+6ower
+9red
+9ring
+9rment
+9rments
+9rs
+5vowel
+9lled
+9lling
+9ls
+4nable
+9d
+9ment
+9ments
+9s
+8ing
+5chain
+9ned
+9ning
+9ns
+8nt
+9ted
+9ter
+9ters
+9ting
+9tingly
+9tment
+9tments
+9tress
+9ts
+6lose
+9ed
+9es
+9ing
+6umber
+9ered
+9ering
+9erment
+9ers
+9rance
+9rances
+5dow
+8ed
+9r
+9rs
+8ing
+8ment
+9ents
+8s
+5franchise
+9chised
+9chises
+5gage
+9d
+9dness
+9ment
+9ments
+9s
+8ing
+5noble
+9ed
+9es
+9ing
+5rol
+8led
+9ing
+8s
+5shroud
+9uded
+9uding
+9uds
+6lave
+9ed
+9es
+9ing
+5tail
+9ed
+9ing
+9ment
+9ments
+9s
+7ngle
+9led
+9lement
+9les
+9ling
+6hral
+9ll
+9lled
+9lling
+9llment
+9lls
+9lment
+9lments
+9ls
+8one
+9ned
+9nes
+9ning
+6itle
+9ed
+9es
+9ing
+6omb
+9ed
+9ing
+9s
+6rail
+9led
+9ling
+9ls
+9n
+9ned
+9ning
+9nment
+9nments
+9ns
+8nce
+9ced
+9cement
+9ces
+9cing
+8yle
+9led
+9les
+9ling
+6wine
+9ed
+9es
+9ing
+5velop
+9ped
+9ping
+9ps
+6iron
+9ned
+9ning
+9ns
+4palous
+4quilibrate
+9brated
+9brates
+9bria
+9brium
+9briums
+4spouse
+9ed
+9es
+9ing
+5tablish
+9ished
+9ishes
+9ishing
+6eem
+9ed
+9ing
+9s
+6imation
+9tions
+4ur
+6s
+5se
+7s
+3fame
+7s
+5vor
+8ed
+8ing
+8s
+7ur
+9ed
+9er
+9ers
+9ing
+9s
+4eature
+9ed
+9ement
+9ements
+9es
+9ing
+5llowship
+9shiped
+9ships
+4iguration
+9tions
+8e
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+4lesh
+8ed
+9s
+8ing
+5uencies
+9y
+8t
+4orest
+9ation
+9ations
+9ed
+9ing
+9s
+6m
+7ed
+7ing
+7s
+4ranchise
+9ised
+9ises
+9ising
+5ock
+8ed
+8ing
+8s
+4unction
+9onal
+9ons
+5rnish
+9hed
+9hes
+9hing
+9hment
+9hments
+3garnish
+9hed
+9hes
+9hing
+6rison
+9oned
+9oning
+9ons
+5vel
+8led
+9ing
+8s
+4est
+7ed
+7ing
+8on
+9ns
+7s
+4lorified
+9ies
+9y
+9ying
+4odded
+5rge
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+5spelling
+5wn
+7ed
+7ing
+7s
+4race
+8d
+8ful
+9ully
+9ulness
+8r
+9s
+8s
+7ing
+8ous
+6dation
+9ions
+7e
+8d
+8s
+7ing
+5egation
+9ions
+5untle
+9ed
+9ement
+9ements
+9es
+9ing
+4uisable
+7e
+8d
+9ly
+9ness
+9nesses
+8less
+8ment
+9ents
+8r
+9s
+8s
+7ing
+9gs
+5st
+7ed
+9ly
+9ness
+9nesses
+7ful
+9lly
+9lness
+7ing
+9gly
+9gness
+7s
+3h
+4abilitate
+9tated
+9tates
+9tating
+9tation
+8le
+9es
+7t
+8ed
+8ing
+8s
+6le
+8d
+8s
+7ing
+5llow
+9ed
+9ing
+9s
+5rmonic
+9ies
+9ious
+9iously
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9y
+4cloth
+9s
+7ut
+9s
+4dash
+8a
+9s
+8es
+4earten
+9ned
+9ning
+9ningly
+9nment
+9nments
+9ns
+5d
+5lm
+7ed
+7ing
+7s
+5rison
+9ns
+7t
+8ed
+8ing
+8or
+9rs
+8s
+5s
+5vel
+8ed
+8ing
+8led
+9ing
+8ment
+9ents
+8s
+4ful
+7s
+4ier
+6st
+5ng
+7s
+4like
+4ome
+7d
+7s
+6ing
+5nest
+9ies
+9ly
+9y
+6or
+8able
+9bly
+9ry
+8ed
+9r
+9rs
+8ing
+8s
+7ur
+9able
+9ably
+9ed
+9er
+9ers
+9ing
+9s
+5rn
+7ed
+7ing
+7s
+6se
+8d
+8s
+7ing
+5use
+8d
+8s
+7ing
+4pan
+7s
+4rag
+7s
+4towel
+9s
+4umour
+9ed
+9ing
+9s
+4ware
+8s
+6sher
+9rs
+6ter
+9s
+4y
+3illude
+9d
+9s
+8ing
+7minate
+9nated
+9nates
+9nating
+7sion
+9onary
+9oned
+9oning
+9onise
+9onised
+9onises
+9onize
+9onized
+9onizes
+9onment
+9ons
+9ve
+4magine
+9ed
+9es
+9ing
+5mure
+9d
+9s
+8ing
+5passioned
+6rison
+9oned
+9oning
+9onment
+9ons
+7ove
+9ed
+9es
+9ing
+4ncarcerate
+9erated
+9erates
+6entive
+9ives
+6lination
+9ations
+9e
+9ed
+9es
+9ing
+7ose
+9ed
+9es
+9ing
+6orporate
+9orated
+9orates
+5fect
+9ant
+9ants
+9ed
+9ing
+9ion
+9ions
+9or
+9ors
+9s
+7st
+9ant
+9ants
+9ation
+9ations
+9ed
+9ing
+9s
+6lation
+9ionary
+9ions
+6orm
+9ation
+9ations
+9ed
+9ing
+9s
+5genuities
+9ity
+9ous
+9ously
+5herison
+9sons
+9t
+9tance
+9tances
+9ted
+9ting
+9ts
+6ibit
+9ted
+9ting
+9tion
+9tions
+9tory
+9ts
+6ume
+9d
+9s
+8ing
+5tegrable
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+9ator
+9ators
+7r
+8est
+9sted
+9stedly
+9sting
+9sts
+8ment
+9ents
+8red
+9ing
+8s
+6hral
+9lled
+9lling
+9ls
+6oxicate
+9cated
+9cates
+9cating
+9cation
+6ricate
+9ated
+9ates
+9ating
+5ure
+8d
+8s
+7ing
+5vent
+9ed
+9ing
+9s
+7st
+9ed
+9ing
+9iture
+9itures
+9ment
+9ments
+9s
+6igorate
+9rated
+9rates
+9rating
+7te
+9d
+9s
+8ing
+6olve
+9ed
+9es
+9ing
+3jaskit
+4ect
+7ed
+7ing
+8on
+9ns
+7s
+4oin
+7able
+7ed
+7ing
+7s
+7t
+8ed
+9dly
+9dness
+8ing
+8s
+4unct
+8ion
+9ons
+9ve
+9vely
+9ves
+8or
+9rs
+8s
+8ure
+9res
+6e
+7s
+3k
+4ed
+5tte
+8s
+4ing
+4less
+5ike
+4s
+3leaf
+7ed
+7ing
+7s
+6l
+6ve
+8d
+8s
+7ing
+4ikable
+6e
+7able
+7d
+7ful
+7n
+8ed
+9ss
+9sses
+8ing
+8s
+7r
+8s
+7s
+6ing
+5mb
+7ed
+7ing
+7s
+6n
+7ed
+7ing
+7s
+5nk
+7ed
+7ing
+7s
+4oad
+7ed
+7ing
+7s
+5cate
+9d
+9dly
+9s
+8ing
+9on
+9ons
+5dge
+8d
+8ment
+9ents
+8s
+7ing
+7ment
+9nts
+5ign
+8ed
+8ing
+8s
+5yal
+8ly
+8ties
+9y
+4ustre
+9d
+9s
+8ing
+3mal
+6er
+7st
+6ities
+8y
+6ler
+8st
+7y
+6ness
+9ses
+6s
+5n
+6ned
+7ing
+6s
+6tle
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+5sk
+7ed
+7ing
+7s
+6t
+7ed
+7ing
+7ment
+9nts
+7s
+5y
+6d
+6ed
+8ness
+9esses
+6ful
+9ly
+6ing
+9ly
+6l
+7ed
+7ing
+7s
+6s
+4e
+5mber
+9ed
+9er
+9ers
+9ing
+9ment
+9ments
+9s
+5s
+4iss
+7al
+9s
+7ed
+8s
+7ible
+8ng
+8on
+9ns
+8ve
+9ely
+7ory
+4oded
+5unt
+8able
+8ed
+8ing
+8s
+4utation
+9ons
+3naturalise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+8ed
+4est
+7ed
+7ing
+7s
+3obedience
+9nces
+9nt
+9ntly
+6y
+7ed
+8r
+9s
+7ing
+7s
+5ligation
+9tions
+9tory
+8e
+9d
+9ment
+9ments
+9s
+8ing
+9ngly
+9ngness
+4dium
+4mic
+6es
+5y
+4peration
+9ions
+4rbed
+5der
+8ed
+9dly
+9dness
+8ing
+8lies
+9iness
+9y
+8s
+6inate
+9tely
+5ganic
+9sation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+5ient
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ed
+9ing
+9s
+4wn
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+3pace
+7d
+7s
+6ing
+5rage
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+9ngly
+7te
+9ly
+9ness
+9nesses
+9s
+6ities
+8y
+6k
+7ed
+7ing
+7s
+6t
+7ed
+7ing
+7s
+5ssion
+9nate
+9nately
+9ns
+5tch
+8ed
+9r
+9rs
+9s
+8ful
+8ing
+6hies
+7y
+5uper
+9ed
+9ing
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9s
+4eace
+8s
+5l
+6led
+8r
+9s
+7ing
+6s
+5nce
+8d
+8s
+7ing
+6d
+7ed
+7ing
+7s
+6sability
+9le
+9leness
+9ly
+8ries
+9y
+8tion
+9ional
+9ions
+9ive
+9ively
+9or
+9ories
+9orily
+9ors
+9ory
+7e
+8d
+8r
+9s
+8s
+7ing
+5ople
+9d
+9s
+8ing
+5rmous
+6sal
+9s
+8nt
+9ts
+7e
+8d
+9ly
+9ness
+9nesses
+8r
+9s
+8s
+7ible
+8ng
+8on
+9ns
+8ve
+9ely
+9eness
+7oid
+9ds
+4irit
+8ed
+9dly
+9dness
+8ing
+9ngly
+8ment
+9ents
+8s
+5teous
+9sly
+9sness
+4lace
+8able
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+6nt
+8ation
+9tions
+8ed
+8ing
+8s
+6y
+7able
+7ed
+8r
+9s
+7ing
+7s
+5e
+6asance
+9nces
+9nt
+8e
+9d
+9dly
+9dness
+9s
+8ing
+9ngly
+9ngness
+8ure
+9red
+9res
+9ring
+6d
+6nish
+9hed
+9hes
+9hing
+9hment
+9hments
+6s
+5ing
+5ode
+8d
+8s
+7ing
+6sion
+9ns
+5ume
+8d
+8s
+7ing
+4ondaic
+7ee
+9s
+6e
+7d
+7e
+8s
+7r
+8s
+7s
+6ge
+8d
+8s
+7ing
+6ing
+5rt
+7ed
+7ing
+7ment
+9nts
+7s
+5sabilities
+9lity
+8le
+9eness
+9es
+7l
+8s
+6e
+7d
+8ly
+7r
+8s
+7s
+6ing
+9ly
+9s
+7tion
+9onal
+9oned
+9ons
+9ve
+9vely
+8or
+9rs
+6sess
+9sed
+9ses
+9sing
+9sion
+9sions
+9sor
+9sors
+9sory
+6t
+7ed
+7ing
+7s
+6ure
+9s
+4rad
+6ise
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+5ead
+8ing
+8s
+6d
+7den
+8ing
+7s
+5inced
+6son
+9ed
+9ing
+9s
+6vacied
+7ilege
+9eged
+9eges
+9eging
+6ze
+8d
+8s
+7ing
+5ofess
+9sed
+9ses
+9sing
+7it
+9s
+6of
+8s
+7ve
+9d
+9s
+8ing
+6pertied
+9ties
+9ty
+9tying
+7ortion
+9tional
+9tioned
+9tions
+7riate
+9ated
+9ates
+9ating
+6vable
+8l
+9s
+7e
+8d
+8n
+8r
+9s
+8s
+7ide
+9ed
+9es
+9ing
+8ng
+4unge
+8d
+8s
+7ing
+5rse
+8d
+8s
+7ing
+6vey
+9ance
+9ances
+9ed
+9ing
+9s
+5tabilities
+9lity
+8le
+9eness
+9y
+7nt
+9s
+7tion
+9ons
+9ous
+9ously
+9ve
+9vely
+9veness
+6e
+7d
+7r
+8s
+7s
+6ing
+3qualifiable
+9ied
+9ier
+9iers
+9ies
+9y
+9ying
+6ntitied
+9ties
+9ty
+9tying
+5iet
+8ed
+9dly
+9dness
+9n
+9ned
+9ning
+9ns
+8ful
+8ing
+9ngly
+9ve
+8ly
+8ness
+9esses
+8ous
+8s
+8ude
+9des
+6sition
+9ional
+9ionary
+9ions
+9ive
+9ory
+3rank
+7ed
+7ing
+7s
+5te
+7d
+7s
+6ing
+4egard
+9ed
+9er
+9ers
+9ful
+9fully
+9ing
+9s
+5lated
+8ion
+9ons
+6ish
+9ed
+9es
+9ing
+5member
+9ered
+9ering
+9ers
+5pair
+9s
+6utability
+9ble
+9bly
+9tion
+9tions
+8e
+9s
+5spect
+9table
+9ted
+9tful
+9tfully
+9ting
+9ts
+4obe
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+5ot
+7ed
+7ing
+7s
+4upt
+7ed
+8r
+9s
+7ing
+8on
+9ns
+8ve
+9ely
+9eness
+7or
+9s
+7s
+3s
+4atisfaction
+9actory
+9ied
+9iedly
+9ies
+9y
+9ying
+5ve
+7d
+7s
+6ing
+9s
+4eat
+7ed
+7ing
+7s
+5ct
+7ed
+7ible
+8ng
+9gs
+8on
+9ns
+8ve
+7or
+9s
+7s
+5d
+5ise
+8d
+8e
+9s
+8s
+7in
+9g
+9s
+7or
+9s
+6ze
+8d
+8e
+9s
+8s
+7in
+9g
+9s
+7or
+9s
+5lboom
+9ms
+5mblance
+9nces
+8e
+9d
+9r
+9rs
+9s
+8ies
+9ng
+9ngly
+9ngs
+8y
+6inate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+8ule
+9les
+5nsion
+9ns
+7us
+9es
+6t
+7ed
+8r
+9ish
+9ism
+9isms
+9s
+7ience
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9nts
+8ng
+9gly
+8on
+9ns
+9us
+7s
+5piment
+9ntal
+9nts
+5rt
+7ate
+9ed
+9es
+9ing
+9ion
+9ional
+9ionist
+9ions
+9ive
+9or
+9ors
+7ed
+7ing
+7s
+6ve
+8d
+8s
+7ice
+9eable
+9es
+8ng
+5s
+5ver
+8ance
+9nces
+9tion
+9tions
+8ed
+8ing
+8ment
+9ents
+8s
+4heathe
+9ed
+9es
+9ing
+5iver
+9ed
+9ing
+9s
+4idence
+9es
+8t
+9ly
+9s
+5ght
+8s
+5lience
+9ces
+9t
+5milar
+9rities
+9rity
+9rly
+9rs
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tory
+8e
+9s
+8itude
+9tudes
+6ulate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+5ng
+5pable
+7te
+9d
+9dly
+9dness
+9r
+9rs
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+4ociability
+9le
+9leness
+9ly
+8l
+9ise
+9ised
+9ises
+9ising
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+5lubilities
+9lity
+8le
+9eness
+7te
+9ly
+9ness
+9nesses
+9s
+8ion
+9onism
+9onisms
+9onist
+9onists
+9ons
+9ve
+6vability
+9le
+9leness
+7e
+8d
+8nt
+9ts
+8r
+9s
+8s
+7ing
+9gs
+5nance
+9es
+9ies
+9y
+8t
+9ly
+4uadable
+7e
+8d
+8r
+9s
+8s
+7ing
+6sion
+9ns
+8ve
+9ely
+9eness
+9es
+7ories
+9y
+5nder
+9ed
+9ing
+9s
+4yllabic
+9le
+9les
+5mmetric
+9rical
+9ries
+9ry
+3taff
+7s
+5in
+7ed
+7ing
+7s
+5l
+6ly
+5nce
+8d
+8less
+8s
+7ing
+6t
+7ly
+7ness
+9sses
+5ste
+8d
+8ful
+9ully
+9ulness
+8s
+7ing
+5ves
+4elfink
+9ks
+5mper
+9ate
+9ature
+9atures
+9ed
+9ing
+9s
+5nd
+7ed
+8r
+9s
+7ing
+7s
+6sibility
+9le
+8le
+8on
+9ns
+8ve
+6t
+7ion
+9ns
+4hene
+8s
+5rone
+9d
+9s
+8ing
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+4ich
+7al
+7ous
+9sly
+7s
+5l
+6l
+7able
+8nd
+9ds
+8te
+9es
+9ion
+9ions
+9ory
+7ed
+8r
+9ies
+9s
+9y
+7ing
+9gs
+7s
+6ment
+9ts
+6s
+5nct
+8er
+9st
+8ion
+9ons
+9ve
+9vely
+9veness
+9ves
+8ly
+8ness
+9esses
+8ure
+9res
+6gue
+9e
+8ish
+9shable
+9shably
+9shed
+9sher
+9shers
+9shes
+9shing
+9shment
+4ome
+7s
+5rt
+7ed
+9ly
+9ness
+9nesses
+8r
+9s
+7ing
+8on
+9nal
+9ns
+8ve
+7s
+4ract
+8able
+8ed
+9dly
+9dness
+9r
+9rs
+8ibility
+9ble
+9ng
+9ngly
+9on
+9ons
+9ve
+9vely
+8s
+6il
+8s
+7n
+8able
+8ed
+9e
+9es
+9r
+9rs
+8ing
+8ment
+9ents
+8or
+9rs
+8s
+8t
+9s
+7t
+8e
+6ught
+9tly
+5ess
+8ed
+9r
+9rs
+9s
+8ful
+9ully
+9ulness
+8ing
+9ngly
+9ngs
+5ibuend
+9nds
+8table
+9aries
+9ary
+9e
+9ed
+9ee
+9ees
+9er
+9ers
+9es
+9ing
+9ion
+9ional
+9ions
+9ive
+9ively
+9ives
+9ivity
+9or
+9ors
+9orship
+6ct
+8ed
+8ing
+8s
+6ngas
+9ses
+6x
+7es
+5ouble
+9ed
+9es
+9ing
+5ust
+8ed
+9r
+9rs
+8ful
+9ully
+9ulness
+8ing
+8less
+8s
+4une
+7d
+7s
+6ing
+5rb
+7ance
+9ces
+9t
+9ts
+8tive
+7ed
+8r
+9s
+7ing
+9gly
+7s
+4yle
+7s
+3ubstituted
+4lfate
+9s
+6id
+8e
+9s
+8s
+7ram
+9ms
+6oton
+9ns
+5phate
+9es
+7ide
+9es
+7uret
+9ets
+9ic
+4nion
+8ist
+9sts
+8s
+6te
+8d
+8r
+9s
+8s
+7ies
+8ng
+7y
+4sage
+8s
+5e
+6d
+6s
+5ing
+4tilities
+9y
+3value
+8d
+8s
+7ing
+4ouch
+8ed
+9s
+8ing
+3worship
+9ps
+3yllabic
+9fied
+9fies
+9fy
+9fying
+9sm
+9sms
+8le
+9es
+4oke
+7d
+7s
+6ing
+2t
+3a
+4l
+5s
+4s
+3ch
+5digger
+9ers
+5ed
+6r
+7s
+6s
+5ing
+5less
+5water
+9rs
+3e
+4d
+4s
+3hecal
+6ous
+5ism
+8s
+7t
+8ic
+9cal
+8s
+5lete
+9s
+8ic
+9cal
+9sm
+9sms
+6ism
+9s
+7tism
+9sms
+5r
+6ed
+7r
+8s
+6ier
+8st
+7ng
+6s
+6y
+4iocarbamate
+6l
+6nate
+9es
+7ic
+8te
+9es
+7ous
+4yramb
+9ic
+9ically
+9ist
+9ists
+9s
+3ing
+3okous
+4ne
+6s
+3ransitive
+9ives
+4iglyph
+9hic
+9hs
+4ochean
+8e
+9s
+3s
+4ier
+6st
+5ness
+9es
+4y
+3t
+4ander
+9s
+6ies
+6y
+5y
+6s
+4ed
+4ied
+6s
+5ng
+5t
+4o
+5ed
+5graphic
+9hies
+9hy
+5ing
+5logies
+8y
+5s
+4s
+4y
+5ing
+3z
+4es
+4ier
+6st
+5ness
+9es
+4y
+2ureses
+6is
+5tic
+8ally
+9lness
+8s
+4nal
+7ist
+9ts
+7ly
+7s
+4on
+6s
+3turnal
+7ities
+9y
+2v
+3a
+4gate
+8d
+8s
+7ing
+8on
+9ns
+4lence
+9s
+8ies
+8y
+7t
+8s
+4n
+5s
+4ricate
+9ed
+9ely
+9es
+9ing
+9ingly
+9ion
+9ions
+9or
+9ors
+4s
+3e
+4bomb
+8ed
+8ing
+8s
+4d
+4llent
+6icate
+9ted
+9tes
+9ting
+4r
+5ge
+7d
+7ment
+9nts
+7nce
+9es
+9ies
+9y
+8t
+9ly
+7s
+6ing
+9ly
+5s
+6e
+7d
+7ly
+7ness
+9sses
+7s
+6ifiable
+9cation
+9ed
+9er
+9ers
+9es
+8orm
+8y
+9ing
+7ng
+7on
+9al
+9ary
+9ist
+9ists
+9s
+7ties
+8y
+6ly
+5t
+6ed
+7r
+8s
+6ibilities
+9lity
+8le
+7cula
+9lar
+9late
+9lated
+9lites
+9litis
+9loses
+9losis
+9lum
+7menti
+9nto
+9ntos
+7ng
+9ly
+7sement
+9ments
+8sement
+9ements
+7ve
+6s
+4s
+5t
+6ed
+6ible
+7ng
+7ture
+9res
+6ment
+9ts
+6s
+6ure
+9s
+3i
+4dable
+6nt
+5e
+6d
+7ly
+7ness
+9sses
+6nd
+8less
+8s
+6r
+7s
+6s
+5ing
+8s
+6vi
+8s
+5ual
+6ous
+4ed
+4nable
+6tion
+9ns
+7or
+9ial
+9s
+9y
+5e
+6d
+6ly
+6ness
+9ses
+6r
+7ess
+9ses
+7s
+6s
+7t
+5g
+6s
+5ified
+9s
+7y
+8ing
+6ng
+6sation
+9ions
+7e
+8d
+8s
+7ing
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8s
+7ing
+4s
+5ibilities
+9ity
+7le
+9ness
+9nesses
+8y
+6m
+6on
+8al
+9lly
+9ry
+8ism
+9sms
+9st
+9sts
+8s
+6ve
+8ly
+8ness
+9esses
+5or
+7s
+3na
+3o
+4rce
+7able
+7d
+7e
+8s
+7ment
+9nts
+7r
+8s
+7s
+6ing
+7ve
+4s
+4t
+5s
+3s
+3ulgate
+9d
+9r
+9rs
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6e
+7d
+7ment
+9nts
+7nce
+9es
+7r
+8s
+7s
+6ing
+5se
+7d
+7s
+6ing
+7on
+9s
+7ve
+3vied
+6r
+6s
+7t
+4y
+5ing
+3ying
+2wan
+5s
+2xi
+4e
+5s
+4t
+5s
+3y
+2ya
+4s
+2zain
+6s
+3en
+5ed
+5ing
+5ment
+9s
+5s
+3ygotic
+6us
+3zard
+7s
+4ied
+6r
+6s
+7t
+5ly
+5ness
+9es
+4y
+5ing
+8ly
+1jebel
+6s
+3llaba
+8h
+9s
+8s
+3mbe
+6s
+2ibbah
+7s
+3n
+4n
+5i
+5s
+5y
+4s
+1o
+2ab
+4le
+4s
+3t
+4ed
+5r
+6s
+4ing
+7s
+4s
+2b
+3bed
+5r
+6s
+4ie
+6s
+5n
+6g
+6s
+4y
+3chick
+8s
+3hash
+7es
+3ie
+5s
+3la
+5s
+4on
+6es
+6s
+3ra
+5s
+4o
+5s
+3s
+4on
+6flies
+8y
+6s
+3y
+2c
+3ent
+6s
+7hip
+9ps
+4tic
+3hmiac
+8al
+6i
+6us
+8es
+4t
+3ibilities
+9y
+5le
+7ness
+9sses
+4le
+6ly
+6r
+6st
+5ities
+7y
+4masies
+7tic
+7y
+5ologies
+9y
+3k
+4age
+7s
+4ed
+5n
+6s
+5r
+6s
+5t
+6ed
+6ing
+6s
+4hand
+8s
+4ing
+7s
+5sation
+9ons
+6e
+7d
+7s
+6ing
+5zation
+9ons
+6e
+7d
+7s
+6ing
+4land
+8s
+4master
+9rs
+4s
+5ide
+8s
+4worker
+9rs
+4yard
+8s
+3o
+4s
+3quet
+7ed
+7ing
+7s
+3s
+3tor
+6al
+7nd
+9s
+7te
+9d
+9s
+8ing
+6ed
+7ss
+9es
+6ial
+7ng
+6less
+7y
+6s
+7hip
+9ps
+4ress
+8es
+5inaire
+9res
+9rism
+9risms
+8l
+9ities
+9ity
+9ly
+8rian
+9ianism
+9ians
+9ism
+9isms
+7e
+8s
+7ism
+9ms
+9t
+9ts
+3udrama
+9s
+4ment
+8able
+9l
+9list
+9lists
+9rian
+9rians
+9ries
+9rily
+9rise
+9rised
+9rises
+9rising
+9rist
+9rists
+9rize
+9rized
+9rizes
+9rizing
+9ry
+9tion
+9tional
+9tions
+8ed
+9r
+9rs
+8ing
+8s
+4soap
+8s
+2d
+3dard
+4ed
+5r
+6ed
+7r
+8s
+6ier
+8st
+7ng
+6s
+6y
+4ier
+6s
+7t
+5ng
+5poll
+9s
+4le
+6s
+4y
+5poll
+9s
+3ecagon
+9al
+9s
+7ynian
+9ous
+6hedra
+9ral
+9ron
+9rons
+6ndrous
+7oic
+6phonic
+9nies
+9nism
+9nisms
+9nist
+9nists
+9ny
+6style
+9les
+7yllabic
+9lable
+9lables
+3ge
+5ball
+9s
+5d
+5m
+6s
+5r
+6ies
+6s
+6y
+5s
+4ier
+6st
+5ness
+9es
+6g
+7s
+4y
+3kin
+6s
+3man
+6s
+3o
+4es
+4ism
+7s
+4s
+3s
+2e
+3k
+4s
+3n
+3r
+4s
+3s
+4kin
+7s
+4t
+3th
+2f
+3f
+4ed
+5r
+6s
+4ing
+4s
+2g
+3aressa
+9s
+4te
+6s
+3bane
+7s
+4erries
+7y
+8ism
+9sms
+4olt
+7s
+3cart
+7s
+5tcher
+9rs
+3dom
+6s
+3e
+4ar
+6ed
+6ing
+6s
+5te
+7s
+4dom
+7s
+4s
+5hip
+8s
+4y
+5s
+3face
+7s
+4ight
+8ing
+9ngs
+8s
+5sh
+7es
+4ought
+5x
+6es
+3ged
+6er
+7st
+6ly
+6ness
+9ses
+5r
+6el
+8s
+6ies
+6man
+7en
+6s
+6y
+5ss
+7es
+4ie
+6r
+6s
+7t
+5ness
+9es
+6gs
+5sh
+7ly
+7ness
+9sses
+4o
+5ne
+7d
+8er
+9st
+7r
+7s
+8t
+6ing
+4rel
+7s
+4y
+3hanged
+4ole
+7s
+5use
+8s
+3ie
+5s
+3leg
+6ged
+7ing
+6s
+4ike
+3ma
+5n
+5s
+5ta
+6ic
+8al
+9lly
+9lness
+8s
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ologies
+9gy
+7ry
+4en
+3nap
+6ed
+7r
+8s
+6ing
+9s
+6ped
+8r
+9s
+7ing
+9gs
+6s
+3robber
+9s
+3s
+4bodied
+9s
+7y
+8ing
+4hip
+7s
+5ores
+4kin
+7s
+4led
+7ded
+9r
+9rs
+8ing
+7s
+6ep
+8s
+3teeth
+4ooth
+5wn
+7s
+4rot
+7s
+7ted
+8ing
+3vane
+7s
+3watch
+8es
+4ood
+7s
+3y
+2h
+3s
+3yo
+5s
+2iled
+4ies
+4t
+5er
+6st
+4y
+3ng
+5s
+3t
+4ed
+4it
+4kin
+7s
+4s
+2jo
+4s
+2l
+3abrate
+6iform
+3ce
+5latte
+9es
+5mente
+5s
+5tto
+8s
+4i
+3drums
+3e
+4d
+4ful
+7ler
+9st
+8y
+7ness
+9sses
+4nt
+6e
+4rite
+8s
+7ic
+4s
+5ome
+8ly
+3ia
+4chocephal
+9phalic
+9phals
+9phaly
+7s
+8aurus
+9uruses
+8es
+6uri
+8us
+9ses
+4na
+6s
+5e
+6s
+5g
+4um
+3l
+4ar
+6bird
+9ds
+6ed
+6fish
+9hes
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6less
+6ocracies
+9acy
+6s
+7hip
+9ps
+4dom
+7s
+4ed
+4hood
+8s
+6use
+9s
+4ied
+6r
+7s
+6s
+5ness
+9es
+6g
+5sh
+7ly
+7ness
+9sses
+4op
+6ed
+6ing
+6s
+4s
+4y
+5bird
+9s
+5ing
+3ma
+5des
+5n
+6s
+5s
+4en
+6ic
+6s
+3omite
+8s
+7ic
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+4r
+5iferous
+7ic
+6metries
+9ry
+5oso
+6us
+8ly
+8ness
+9esses
+5s
+4s
+5se
+5tone
+9s
+4ur
+6s
+3phin
+7aria
+9ium
+9iums
+7et
+9s
+7fish
+9shes
+7s
+3s
+3t
+4ish
+7ly
+7ness
+9sses
+4s
+2m
+3ain
+6al
+6e
+7s
+6s
+4l
+4nial
+4tia
+6um
+3e
+4d
+4like
+4s
+5day
+8s
+5tic
+8able
+9l
+9lly
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+8ise
+9sed
+9ses
+9sing
+9ties
+9ty
+9ze
+9zed
+9zes
+9zing
+8s
+4tt
+6s
+3ic
+5al
+7ly
+5il
+7e
+8d
+8s
+7iary
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+8ng
+7s
+4er
+5st
+4nance
+9s
+8ies
+8y
+7t
+8ly
+8s
+6te
+8d
+8s
+7ing
+9gly
+8ons
+8ve
+7or
+9s
+7rices
+5e
+6e
+7r
+8ed
+8ing
+9ngly
+9ngness
+8s
+7s
+6s
+5g
+5ical
+7k
+8er
+9rs
+8s
+6e
+7s
+6on
+8s
+6que
+9s
+6um
+8s
+5o
+6es
+6s
+3oic
+3s
+3y
+2n
+3a
+4h
+5s
+4ries
+5y
+4s
+4taries
+7y
+5e
+6d
+6s
+5ing
+6on
+8s
+6sm
+8s
+7tic
+9cal
+6ve
+8s
+5or
+7ies
+7s
+7y
+3der
+6ed
+6ing
+6s
+3e
+4e
+5s
+4ness
+8es
+4pezil
+9s
+4r
+3g
+4a
+5s
+4ed
+4ing
+4le
+6s
+4ola
+7s
+4s
+3ing
+6s
+3jon
+6s
+3key
+6s
+6work
+9ks
+4o
+5s
+3na
+5rd
+6t
+5s
+5t
+6s
+4e
+5d
+5e
+6s
+5rd
+6ed
+6t
+5s
+4icker
+9s
+5es
+5ker
+8s
+5ng
+5sh
+7ly
+7ness
+9sses
+6m
+7s
+4ot
+6s
+4y
+5brook
+9ks
+3or
+5s
+6hip
+9s
+3s
+4hip
+7s
+4ie
+6r
+6st
+4y
+3ut
+5s
+5ted
+6ing
+3zel
+6s
+2o
+3b
+4ie
+6s
+4rey
+7s
+5ie
+7s
+4s
+3ce
+5d
+5s
+4ing
+4ot
+6s
+3dad
+6s
+5h
+6s
+4ies
+4le
+6bug
+9s
+6d
+6r
+7s
+6s
+5ing
+4oo
+6s
+4y
+3fer
+6s
+4us
+6es
+3hickey
+9s
+7ies
+3k
+4ed
+5t
+6s
+4ing
+4s
+3l
+4ally
+5n
+6s
+4e
+5e
+6s
+5s
+4ie
+6s
+4s
+4y
+3m
+4ed
+4ful
+7ly
+4ier
+6st
+5ly
+5ng
+4s
+5ayer
+9s
+7ing
+9gs
+5day
+8er
+9rs
+8s
+5man
+6en
+5ter
+8s
+4watch
+9ed
+9er
+9ers
+9es
+9ing
+9ings
+4y
+3n
+4a
+5s
+3r
+4bell
+8s
+4case
+8s
+4frame
+9s
+4jamb
+8s
+4keeper
+9rs
+5nob
+8s
+7ck
+9ed
+9er
+9ers
+9ing
+9s
+4less
+4man
+6t
+7s
+5en
+4n
+5ail
+8s
+5boom
+9s
+5s
+4plate
+9s
+5ost
+8s
+4s
+5ill
+8s
+5man
+6en
+5tep
+8ped
+9er
+9ers
+9ing
+9ings
+8s
+6one
+9s
+7p
+8s
+4way
+7s
+5oman
+7en
+4yard
+8s
+3s
+4ra
+6s
+3wop
+6s
+3zer
+6s
+4ie
+6s
+4y
+2p
+3a
+4mine
+8rgic
+8s
+4nt
+6s
+4s
+4tta
+7s
+3e
+4d
+4head
+8s
+4r
+5s
+4s
+5heet
+9s
+5ter
+8s
+4y
+5ness
+9es
+3iaza
+7s
+4er
+5st
+4ly
+4ness
+8es
+5g
+6s
+3ped
+5lganger
+9gers
+5r
+6s
+4ie
+6s
+5ng
+7s
+5o
+6s
+4lerite
+9es
+3s
+3y
+2r
+3ad
+5o
+6s
+5s
+3b
+4a
+5s
+4eetle
+9s
+4s
+4ug
+6s
+3e
+4e
+5s
+4s
+3hawk
+7s
+3ic
+4doid
+8s
+4es
+4s
+5e
+6d
+6s
+5ing
+4ze
+6d
+6s
+5ing
+3k
+4ier
+6st
+5ness
+9es
+5sh
+4s
+4y
+3lach
+7s
+3m
+4ancies
+7y
+6t
+7s
+4er
+6ed
+6s
+4ice
+5e
+6nt
+5n
+6s
+5tion
+9s
+7ve
+9s
+6ories
+8y
+4ouse
+4s
+4y
+3neck
+7s
+4ick
+7s
+4ock
+7s
+3onicum
+9s
+3p
+4er
+6s
+4s
+3r
+4ed
+4ing
+4s
+3s
+4a
+5d
+5l
+6ly
+6s
+4e
+5l
+6s
+5r
+6s
+5s
+4ibranchiate
+5ferous
+6ixed
+6lex
+9ion
+9ions
+5grade
+5ventral
+9rality
+9rally
+4olateral
+6umbar
+5ventral
+9rality
+9rally
+4um
+3t
+4ed
+5r
+6s
+4ier
+6st
+5ness
+9es
+6g
+4our
+7s
+4s
+4y
+3y
+2s
+3age
+6s
+3e
+4d
+4h
+5s
+4meter
+9s
+4r
+5s
+4s
+3h
+4es
+3imeter
+9s
+7ric
+9cian
+9cians
+9es
+9st
+9sts
+8y
+4ng
+4ologies
+8y
+3ologies
+7y
+3s
+4al
+6s
+4ed
+5l
+6s
+5r
+6et
+8s
+6s
+5s
+4house
+9s
+4ier
+7s
+5l
+6s
+5ng
+3t
+2t
+3age
+6s
+4l
+4nt
+6s
+4rd
+6ly
+6s
+4tion
+8s
+3com
+6mer
+9s
+6s
+3e
+4d
+4r
+5s
+4s
+3h
+3ier
+5st
+4ng
+6ly
+6s
+4sh
+3s
+3ted
+5l
+6s
+5r
+6el
+8s
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4le
+6d
+6r
+6s
+7t
+4rel
+7s
+4y
+3y
+2uane
+6s
+5ier
+8s
+4r
+5s
+3ble
+6d
+6header
+9ders
+6ness
+9ses
+6r
+7s
+6s
+7peak
+9aker
+9akers
+9aks
+6t
+7hink
+9nks
+7on
+9s
+7ree
+9es
+7s
+5ing
+8s
+5oon
+8s
+5ure
+8s
+5y
+4t
+5able
+8y
+5ed
+6r
+7s
+5ful
+8ly
+8ness
+9esses
+8s
+5ing
+8ly
+8s
+5less
+9ly
+9ness
+9nesses
+5s
+3c
+4e
+5ly
+5ness
+9es
+5pere
+9s
+5r
+5st
+5t
+6s
+5ur
+7s
+4he
+6bag
+9s
+6d
+6s
+5ing
+4ine
+7s
+4s
+3gh
+5ball
+9s
+6oy
+8s
+5face
+9d
+9s
+5ier
+7st
+6ness
+9ses
+5like
+5nut
+8like
+8s
+8ted
+9ing
+9ings
+5s
+5t
+6ier
+8st
+7ly
+7ness
+9sses
+6y
+5y
+3k
+4ed
+4ing
+4s
+3la
+5s
+4eia
+7s
+4ocracies
+9y
+3m
+4a
+5s
+4s
+3n
+3p
+4ioni
+8s
+4pioni
+9s
+4s
+3r
+4a
+5h
+6s
+5s
+4er
+5st
+4ine
+7s
+4ly
+4ness
+8es
+4oucouli
+9lis
+3se
+5d
+5r
+6s
+5s
+4ing
+3t
+4ed
+5r
+6s
+4ing
+4s
+3x
+3zeper
+8s
+2ve
+4cot
+7e
+8s
+7s
+4d
+4ish
+7ness
+9sses
+4key
+7s
+5ie
+7s
+4let
+7s
+5ike
+4n
+5ed
+5ing
+5s
+4r
+5ed
+5ing
+5s
+4s
+4tail
+8ed
+8ing
+9ngs
+8s
+3ie
+5r
+5st
+4ng
+4sh
+6ness
+9ses
+2w
+3able
+4ger
+7s
+4r
+5s
+3d
+4ier
+6s
+7t
+5ly
+5ness
+9es
+4s
+4y
+5ish
+7m
+8s
+3ed
+4l
+5ed
+5ing
+8s
+5led
+6ing
+9s
+5s
+4r
+5ed
+5ies
+6ng
+5less
+5s
+5y
+3f
+4ness
+8es
+3ie
+5r
+5st
+4ng
+4tcher
+9s
+3l
+4as
+6es
+4e
+5s
+4ier
+6st
+4ne
+6s
+6y
+4s
+4y
+3n
+4a
+4beat
+8s
+5ow
+7s
+5urst
+9s
+4cast
+8s
+5ome
+8r
+9s
+8s
+6urt
+4draft
+9s
+7ught
+9hts
+4ed
+5r
+6s
+4fall
+8en
+8s
+5ield
+5low
+8s
+5orce
+9s
+4grade
+9d
+9s
+8ing
+4haul
+8s
+5earted
+9edly
+9edness
+5ill
+8er
+9rs
+8s
+5ole
+4ier
+6st
+5ness
+9es
+6g
+4land
+8s
+5ess
+5ight
+9er
+9ers
+9s
+6ke
+6nk
+8ed
+8ing
+8s
+5oad
+8able
+8ed
+8ing
+8s
+6oked
+4most
+4pipe
+8s
+5lay
+8ed
+8ing
+8s
+5our
+8s
+4range
+5egulation
+9ations
+5ight
+9ly
+9ness
+9nesses
+6ver
+5ush
+8es
+4s
+5cale
+9d
+9s
+8ing
+5hift
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+5ide
+8s
+6ze
+8d
+8r
+9s
+8s
+7ing
+9gs
+5lide
+9s
+6ope
+5pin
+8s
+6out
+9s
+5tage
+9s
+7ir
+9s
+9ses
+7te
+9r
+9rs
+9s
+6ream
+7oke
+9es
+5wing
+9s
+4throw
+9s
+5ick
+8s
+6me
+8s
+5own
+8er
+9rs
+8s
+5rend
+9ed
+9ing
+9s
+6od
+8den
+5urn
+8ed
+8s
+4ward
+8ly
+8ness
+9esses
+8s
+6sh
+8es
+5ind
+4y
+4zone
+8d
+8s
+7ing
+3p
+4s
+3ries
+4y
+3s
+4abel
+8s
+4e
+5d
+5r
+6s
+5s
+5t
+6s
+4ing
+3t
+4s
+2xapram
+8s
+4stic
+8s
+3ie
+5s
+3ographer
+9ers
+9ic
+9ies
+9y
+4logical
+9ally
+8es
+7y
+4rubicin
+9ins
+3y
+4cycline
+9nes
+2y
+3en
+5ne
+7s
+5s
+3ley
+6s
+4ies
+4y
+3s
+2ze
+4d
+4n
+5ed
+5ing
+5s
+5th
+7s
+4r
+5s
+4s
+3ier
+5st
+4ly
+4ness
+8es
+5g
+6s
+3y
+1rab
+4bed
+6r
+7s
+6st
+6t
+7s
+5ier
+7st
+6ness
+9ses
+7g
+6sh
+5le
+7d
+7r
+8s
+7s
+6ing
+9s
+5y
+4ette
+8s
+4ler
+7s
+5y
+4ness
+8es
+4s
+3c
+4aena
+8s
+4ena
+7s
+4hm
+6a
+7e
+7i
+7s
+6s
+4k
+4o
+5ne
+7s
+6ian
+9ism
+9isms
+7c
+8ally
+7sm
+9s
+7tes
+6tiases
+9sis
+8c
+4unculus
+9uses
+3d
+3ff
+5ier
+7st
+6sh
+5s
+5y
+4t
+5able
+5ed
+6e
+7s
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5s
+6man
+9ship
+9ships
+7en
+6person
+9sons
+5y
+3g
+4ee
+6s
+4ged
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5le
+7d
+7s
+7tailed
+6ing
+5y
+4hound
+9s
+4line
+8s
+4net
+7s
+4oman
+8s
+6en
+5n
+6ess
+9es
+7t
+8s
+6flies
+8y
+6head
+9ds
+6ise
+9d
+9s
+8h
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+6like
+6nade
+9ed
+9es
+9ing
+7e
+6root
+9ts
+6s
+5on
+7age
+9es
+7ed
+7ing
+7s
+4rope
+8s
+4s
+5man
+6en
+5ter
+8s
+6rip
+9s
+3il
+5ed
+5ing
+5s
+4n
+5able
+6ge
+8s
+5ed
+6r
+7s
+5ing
+5layer
+9rs
+5pipe
+9s
+5s
+4sene
+8s
+5ine
+8s
+3ke
+5s
+6tone
+9es
+3m
+4a
+5dies
+6y
+5s
+5tic
+8al
+9lly
+8ism
+9sms
+8s
+7sable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8t
+9s
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6urg
+9e
+9es
+9ic
+9ical
+9ically
+9ies
+9ist
+9ists
+9s
+9y
+4edies
+6y
+4mach
+8s
+5ed
+5ing
+5ock
+8s
+4s
+5hop
+8s
+3ngway
+8s
+4k
+4t
+5ed
+5ing
+5s
+3p
+4abilities
+9ty
+6le
+4e
+5abilities
+9ity
+7le
+5d
+5r
+6ied
+8s
+6s
+6y
+7ing
+5s
+5t
+6s
+5y
+4ier
+7s
+6st
+5ng
+4ped
+5ie
+7s
+6ng
+5y
+4s
+3stic
+7ally
+7s
+3t
+4chell
+9s
+4s
+4ted
+5ing
+3ught
+7board
+9ards
+7ed
+8r
+9s
+7ier
+9st
+8ly
+8ness
+9esses
+9g
+7man
+8en
+7s
+8man
+9anship
+9en
+8woman
+9omen
+7y
+4nt
+6ed
+6ing
+6s
+3ve
+3w
+4able
+4back
+8s
+6r
+7s
+5ore
+8s
+5ridge
+9es
+4down
+8s
+4ee
+6s
+5r
+6ful
+9s
+6s
+4ing
+7s
+4knife
+7ves
+4l
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8ness
+9esses
+5s
+5y
+4n
+5work
+9s
+4plate
+9s
+4s
+5have
+9s
+5tring
+9gs
+4tube
+8s
+3y
+4age
+7s
+4ed
+4horse
+9s
+4ing
+4man
+5en
+4s
+3zel
+6s
+2ead
+5ed
+6r
+7s
+5ful
+8ly
+8ness
+9esses
+8s
+5ing
+5less
+9ly
+9ness
+9nesses
+6ock
+9ed
+9s
+6y
+5naught
+9hts
+6ought
+9hts
+5s
+4m
+5boat
+9s
+5ed
+6r
+7ies
+7s
+7y
+5ful
+8ly
+8ness
+9esses
+5hole
+9s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+8s
+5land
+9s
+6ess
+9ly
+9ness
+9nesses
+6ike
+5s
+6cape
+9es
+5t
+6ime
+9s
+5while
+9es
+6orld
+9ds
+5y
+4r
+5e
+6r
+6s
+7t
+5ier
+7s
+8t
+6head
+9ds
+7ood
+9ds
+6ly
+6ment
+9ts
+6ness
+9ses
+7g
+8s
+6some
+5s
+5y
+3ck
+5ier
+7st
+5s
+6ill
+9s
+5y
+3dge
+6d
+6r
+7s
+6s
+5ing
+8s
+3e
+4d
+4ing
+4s
+3g
+4gier
+7st
+6ness
+9ses
+6sh
+5y
+4s
+3ich
+6er
+7st
+4del
+7s
+5l
+6s
+4gh
+6er
+7st
+4kanter
+9rs
+3k
+4s
+3nch
+6ed
+7r
+8s
+7s
+6ing
+9s
+4t
+3panid
+8s
+7um
+9s
+3re
+5s
+4ihead
+9s
+3ss
+5age
+8s
+5ed
+6r
+7s
+6s
+5guard
+9ds
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5made
+7ke
+9r
+9rs
+9s
+8ing
+9ngs
+5y
+4t
+3vill
+7s
+3w
+3y
+4s
+2ib
+4bed
+6r
+7s
+5ing
+5le
+7d
+7r
+8s
+7s
+7t
+8s
+6ier
+8st
+7ng
+6y
+4let
+7s
+4s
+3ce
+5s
+4ksie
+8r
+8st
+3ed
+4gh
+4r
+5s
+4s
+5t
+3ft
+5age
+8s
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8ly
+5less
+5pin
+8s
+5s
+5wood
+9s
+5y
+3ll
+5abilities
+9ity
+7le
+5ed
+6r
+7s
+5hole
+9s
+5ing
+8s
+5master
+9ers
+5s
+6hip
+9s
+6tock
+9ks
+4y
+3nk
+5abilities
+9ity
+7le
+9ness
+9nesses
+9s
+8y
+5er
+7s
+5ing
+8s
+5s
+3p
+4less
+4ped
+6r
+7s
+5ier
+7st
+6ly
+6ng
+8s
+5y
+4s
+5tone
+9s
+4t
+3sheen
+8s
+3vabilities
+9ty
+6le
+4e
+5abilities
+9ity
+7le
+5l
+6ed
+7r
+8s
+6ine
+9s
+8g
+6led
+8r
+9s
+7ing
+6s
+5n
+6ness
+9ses
+5r
+6less
+6s
+5s
+6haft
+9ts
+5through
+9ughs
+6rain
+9ns
+5way
+8s
+4ing
+7ly
+7s
+3zzle
+7d
+7s
+6ier
+8st
+7ng
+9ly
+6y
+2oger
+6s
+4her
+7s
+4ue
+6s
+6t
+7s
+3ich
+6ier
+8st
+6s
+6y
+4d
+5s
+4l
+5ed
+5ing
+5s
+4t
+5s
+3le
+5r
+5s
+6t
+4l
+5ed
+6r
+7ies
+7y
+6st
+5ing
+8s
+6sh
+5ness
+9es
+5s
+5y
+3me
+5dare
+9s
+8ies
+8y
+5s
+4ic
+6al
+4oi
+5n
+6d
+7s
+6s
+5phobia
+9ias
+5s
+3ne
+5d
+5r
+6s
+5s
+4go
+6es
+6s
+4ier
+6st
+5ng
+7ly
+5sh
+7ly
+7ness
+9sses
+4klap
+8s
+5verdriet
+4y
+3ob
+5s
+4g
+5ish
+5s
+4k
+5ed
+5ing
+8s
+6t
+5s
+4l
+5ed
+5ier
+7st
+6ng
+5s
+5y
+4me
+6s
+4p
+5ed
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+5s
+5y
+3p
+4cloth
+9s
+4flies
+6y
+5orge
+9d
+9s
+8ing
+4head
+8s
+4kick
+8er
+9rs
+8s
+4let
+7s
+5ight
+9s
+5ock
+4out
+7s
+4pable
+5ed
+6r
+7ful
+9ls
+7s
+8ful
+5ing
+8s
+5le
+7s
+4s
+5hot
+8s
+5ical
+9ly
+6ed
+7s
+5onde
+9s
+5tone
+9s
+5y
+4t
+4wise
+5ort
+8s
+3sera
+7ceous
+7s
+4hkies
+6y
+4kies
+5y
+4ometer
+9rs
+5phila
+9ae
+9as
+4s
+5es
+5ier
+7st
+6ness
+9ses
+5y
+4tdies
+6y
+7s
+3ught
+7ier
+9st
+8ness
+9esses
+7s
+7y
+4k
+5ed
+5ing
+8s
+6t
+5s
+4th
+6ier
+8st
+7ness
+9sses
+6s
+6y
+3ve
+5d
+5r
+6s
+5s
+4ing
+7s
+3w
+4n
+5d
+6ed
+6ing
+6s
+5ed
+6r
+7s
+5ing
+8s
+5s
+4s
+5e
+6d
+6s
+5ier
+7st
+6head
+9ds
+8d
+9s
+6ly
+6ness
+9ses
+7g
+5y
+2ub
+4bed
+6r
+7s
+5ing
+8s
+4s
+3cken
+7ness
+9sses
+3dge
+6d
+6r
+7ies
+7s
+7y
+6s
+5ing
+8ly
+6sm
+8s
+3g
+4ged
+6r
+7s
+6t
+7s
+5ie
+7r
+7s
+8t
+6ng
+6st
+8s
+5y
+4lord
+8s
+4maker
+9s
+4s
+5tore
+9s
+3id
+5ess
+8es
+5ic
+7al
+6sm
+8s
+5ries
+6y
+5s
+3m
+4beat
+8er
+9rs
+8ing
+9ngs
+8s
+5le
+7d
+8or
+9rs
+8rane
+9anes
+7s
+6ing
+4fire
+8s
+6sh
+8es
+4head
+8s
+4lier
+7st
+6ke
+6n
+7s
+5y
+4med
+6r
+7s
+5ies
+6ng
+5ock
+8s
+5y
+4roll
+8s
+4s
+5tick
+9s
+3nk
+5ard
+8s
+6thon
+9ns
+5en
+7ly
+7ness
+9sses
+6r
+6st
+5s
+3paceous
+4e
+5l
+6et
+8s
+6s
+5s
+3se
+5n
+5s
+4ier
+6st
+4y
+3thers
+3xier
+6st
+4y
+2y
+3able
+4d
+5es
+5ic
+5s
+4sdust
+9s
+3beat
+7en
+7ing
+7s
+3er
+5s
+4st
+3ing
+6s
+4sh
+3land
+4ot
+6s
+4y
+3mouth
+8s
+3ness
+7es
+3opithecine
+9cines
+3point
+8s
+3s
+4alter
+9ies
+9s
+9y
+4tone
+4uit
+7s
+3wall
+7ed
+7ing
+7s
+4ell
+7s
+1so
+3bo
+5s
+3mo
+5s
+3s
+1uad
+4s
+3l
+4in
+6s
+5se
+7d
+7s
+6ing
+6m
+7s
+6t
+7ic
+9ally
+7s
+5ties
+6y
+5ze
+7d
+7s
+6ing
+4led
+5ing
+5y
+4s
+3n
+4s
+3r
+4chies
+6y
+4s
+3thlon
+8s
+2b
+3bed
+5r
+6s
+4in
+6g
+7s
+6s
+4o
+5s
+3ieties
+6y
+4osities
+8y
+5us
+7ly
+7ness
+9sses
+4table
+8y
+6ncies
+8y
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+3nium
+7s
+3onnet
+8s
+3s
+4tep
+7s
+2cal
+5ly
+4t
+5oon
+8s
+5s
+3dame
+3e
+4s
+3hess
+7e
+8d
+8s
+7ing
+4ies
+4y
+3i
+3k
+4bill
+8s
+5oard
+9s
+4ed
+5r
+6s
+4foot
+4ie
+6r
+6s
+7t
+5ng
+7s
+4ling
+8s
+4mole
+8s
+4pin
+7s
+4s
+5hove
+9d
+9r
+9rs
+9s
+8ing
+4tail
+8s
+4walk
+8ed
+8ing
+8s
+5eed
+8s
+4y
+3t
+4al
+4ed
+4ile
+7ly
+7ness
+9sses
+6ities
+8y
+5ng
+7s
+4less
+4s
+4ule
+7s
+4work
+8s
+2d
+3der
+6ies
+6s
+6y
+4ie
+6r
+6st
+4y
+3e
+4d
+4en
+6s
+4s
+3geon
+7s
+3heen
+7s
+3ing
+4sh
+6ly
+5m
+6s
+3s
+2e
+3cento
+8s
+3d
+3ful
+3l
+4ed
+5r
+6s
+4ing
+5st
+7s
+4led
+6r
+7s
+5i
+6ng
+8s
+6st
+8s
+5o
+6s
+4s
+5ome
+3nde
+6s
+4ess
+7es
+4na
+6s
+7hip
+9ps
+3s
+3t
+4ed
+4ing
+4s
+4t
+5ed
+5i
+6ng
+7o
+8s
+6st
+8s
+5o
+6s
+5s
+2ff
+4ed
+5l
+6s
+5r
+6dom
+9s
+6ism
+9s
+6s
+5st
+4ing
+7s
+4le
+6s
+4s
+3us
+5es
+2g
+3ite
+6s
+3ong
+6s
+4ut
+6s
+3s
+2h
+3kha
+6s
+2i
+3ker
+6bok
+9s
+6s
+3ng
+3t
+4s
+2ka
+4s
+3e
+4d
+5om
+7s
+4ling
+8s
+4ries
+5y
+4s
+5hip
+8s
+3ing
+3ka
+5h
+6s
+5s
+4eripen
+9ns
+4ha
+6s
+2lcamara
+9s
+4et
+6ly
+6ness
+9ses
+6s
+4ian
+7a
+8s
+7s
+5fication
+9tions
+7ed
+8s
+6luous
+6y
+7ing
+5loquies
+9y
+5mer
+8s
+6ore
+9s
+5nea
+8s
+5te
+7s
+6ol
+8s
+6ude
+9s
+4ose
+7s
+3e
+4s
+3ia
+5s
+3l
+4ard
+7s
+4ed
+5r
+5st
+4ier
+6st
+5ng
+5sh
+7ly
+4ness
+8es
+4s
+5ville
+9es
+4y
+3ness
+7es
+3ocracies
+8y
+4ses
+5is
+4tic
+3se
+5s
+3y
+2ma
+4ist
+7s
+4s
+3b
+4bell
+8s
+4cane
+8s
+4ed
+5r
+5st
+4found
+9ed
+9er
+9ered
+9ering
+9ers
+9ing
+9s
+4head
+8s
+4ing
+4ledore
+9es
+5y
+4ness
+8es
+4o
+5s
+4s
+5how
+8s
+5tricken
+7uck
+4waiter
+9rs
+3dum
+6s
+3ela
+3found
+8ed
+9r
+9red
+9ring
+9rs
+8ing
+8s
+3ka
+4y
+3melhead
+9ds
+5rer
+8s
+4ied
+6r
+6s
+7t
+5ness
+9es
+4kopf
+8s
+4y
+5ing
+3ortierite
+9ites
+4se
+5ities
+7y
+4us
+3p
+4bin
+7s
+4cart
+8s
+4ed
+5e
+6s
+5r
+6s
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+5sh
+7ly
+7ness
+9sses
+4le
+6d
+6s
+5ing
+8s
+4s
+5ite
+8s
+5ter
+8s
+4truck
+9s
+4y
+2n
+3am
+5s
+3ce
+5dom
+8s
+5like
+5ries
+6y
+5s
+4h
+5ed
+6s
+5ing
+4ical
+5sh
+7ly
+3der
+6funk
+9ks
+6head
+9ded
+9dism
+9disms
+9ds
+6pate
+9es
+6s
+4rearies
+3e
+4land
+8s
+5ike
+4s
+3g
+4aree
+8d
+8s
+4ed
+5on
+7ed
+8r
+9s
+7ing
+7s
+5r
+6s
+4heap
+8s
+5ill
+8s
+4ier
+6st
+5ng
+4mere
+8s
+4s
+4y
+3iewassal
+9als
+4te
+6s
+5ic
+4wassal
+9ls
+3k
+4ed
+5r
+6s
+4ing
+4s
+3lin
+6s
+3nage
+7s
+5kin
+8s
+5rt
+7s
+4ed
+5r
+5ss
+7es
+6t
+4ier
+6s
+7t
+6wassal
+9sals
+5ng
+7s
+5sh
+5te
+7s
+4o
+5ck
+7s
+4y
+3s
+4h
+5ed
+6s
+5ing
+3t
+4ed
+4ing
+4s
+2o
+3binary
+3decennial
+6illion
+9ions
+7mal
+9lly
+9ls
+8o
+9s
+5na
+7l
+7ry
+6ectomies
+9omy
+6itis
+9ses
+6um
+8s
+3log
+6s
+6ue
+8s
+3mi
+4o
+5s
+3polies
+7stic
+6y
+4sonies
+7y
+3s
+3tone
+7s
+2p
+3abilities
+9y
+5le
+4tta
+7s
+3e
+4d
+4r
+5ies
+5s
+5y
+4s
+3ing
+4on
+6s
+3le
+5t
+6s
+5x
+6ed
+7r
+8s
+7s
+6ing
+7ties
+8y
+4icabilities
+9lity
+8le
+7nd
+9s
+7te
+9d
+9ly
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+8ure
+9res
+6ident
+7ties
+8ous
+9usly
+8y
+5ed
+6s
+4y
+5ing
+3ondii
+7us
+3ped
+4ies
+5ng
+4y
+3s
+2ra
+4bilities
+9y
+5le
+7ness
+9sses
+7s
+6y
+4l
+5s
+5umin
+9ium
+9iums
+9s
+4men
+7s
+4nce
+7s
+5t
+6s
+4s
+4tion
+8al
+8s
+6ve
+8s
+3bar
+6s
+3chkomponiert
+9onirt
+3dum
+6s
+3e
+4d
+4ful
+4s
+5s
+6e
+7s
+3gah
+6s
+5n
+6s
+4ier
+6st
+4y
+3ian
+6s
+4crust
+9s
+4ng
+4on
+6s
+3mast
+7s
+3n
+4dest
+4ed
+6er
+7st
+4ing
+4s
+3o
+4c
+5s
+4meter
+9s
+4s
+4y
+5s
+3r
+4a
+5s
+4ie
+6s
+4s
+4y
+3st
+3ukuli
+8s
+4m
+5s
+3zi
+5s
+2sh
+4ed
+5s
+4ing
+3k
+4ed
+5n
+6ed
+6ing
+6s
+5r
+5st
+4ier
+6st
+5ly
+5ness
+9es
+6g
+5sh
+7ly
+7ness
+9sses
+4ly
+4ness
+8es
+4s
+4y
+3t
+4bin
+7s
+4cart
+8s
+5oat
+8s
+6ver
+9s
+4ed
+5r
+6s
+4heap
+8s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4less
+5ike
+4man
+5en
+4off
+7s
+4pan
+7s
+5roof
+4rag
+7s
+4s
+5heet
+9s
+5torm
+9s
+4up
+6s
+4y
+2tch
+5es
+5man
+6en
+3eous
+7ly
+7ness
+9sses
+3iabilities
+9ty
+6le
+4ed
+5s
+4ful
+7ly
+7ness
+9sses
+3y
+2umvir
+7al
+8te
+9es
+7i
+7s
+2vet
+5ine
+8s
+5s
+5yn
+7e
+8s
+7s
+2x
+3elles
+4s
+2yker
+6s
+1vandva
+7s
+2ornik
+7s
+1waal
+5s
+3le
+5s
+4m
+5ed
+5ing
+5s
+3m
+4med
+5ing
+4s
+3ng
+5s
+3rf
+5ed
+6r
+6st
+5ing
+6sh
+8ly
+8ness
+9esses
+7m
+8s
+5like
+5ness
+9es
+5s
+4ves
+3um
+5ed
+5ing
+5s
+2eeb
+5ier
+7st
+6sh
+5s
+5y
+3ll
+5ed
+6r
+7s
+5ing
+8s
+5s
+4t
+2ile
+5s
+3ndle
+7d
+7ment
+9nts
+7s
+6ing
+4e
+5d
+5s
+4ing
+1yable
+3d
+4ic
+6ally
+6s
+4s
+3rchal
+6ic
+8al
+7es
+6y
+2bbuk
+6im
+6kim
+6s
+2e
+3abilities
+9y
+5le
+3d
+3ing
+6s
+3line
+7s
+3r
+4s
+3s
+4ter
+7s
+5uff
+8s
+3weed
+7s
+4ood
+7s
+2ing
+5ly
+5ness
+9es
+5s
+2kier
+5st
+4ng
+3on
+5s
+2nameter
+9s
+5ic
+7al
+9ly
+7ist
+9ts
+7s
+6se
+8d
+8s
+7ing
+7m
+8s
+7t
+8ic
+8s
+6tard
+9ds
+7e
+8d
+8r
+9s
+8s
+7ic
+8ng
+6ze
+8d
+8s
+7ing
+5o
+6electric
+6geneses
+9esis
+9ies
+9y
+7raph
+9phs
+6meter
+9ers
+9ric
+9rical
+9ries
+9ry
+6s
+6tor
+9s
+4st
+6ic
+8al
+9lly
+7es
+6s
+6y
+4tron
+8s
+3e
+4in
+6s
+4l
+5s
+4s
+3ode
+6s
+4rphin
+9s
+2ophysite
+9es
+3thelete
+9es
+9ic
+9ical
+9ism
+9isms
+7ism
+9ms
+8te
+9es
+9ic
+9ical
+2saesthesia
+9sias
+9tic
+4rthria
+9as
+3bindin
+9s
+3calculia
+9ias
+4hroa
+8s
+7ia
+9s
+4rasia
+9s
+8c
+8te
+9es
+6tic
+3enteric
+9es
+8y
+3function
+9onal
+9ons
+3geneses
+8is
+6ic
+8s
+4raphia
+9as
+9c
+3harmonic
+3kinesia
+9as
+7tic
+3lalia
+8s
+4ectic
+9s
+5xia
+8s
+7c
+8s
+4ogies
+7stic
+9ically
+6y
+3melia
+8s
+7c
+5norrhea
+9heal
+9heas
+9heic
+9hoea
+9hoeal
+9hoeas
+9hoeic
+4orphic
+8ophobia
+3odil
+7e
+8s
+7s
+5yle
+8s
+3pareunia
+9ias
+5thetic
+7ies
+7y
+4epsia
+9s
+8es
+7y
+6tic
+9al
+9ally
+9s
+4hagia
+9s
+8c
+8es
+7y
+6sia
+9s
+8c
+9s
+5emism
+9ms
+9tic
+5onia
+9s
+8c
+6ria
+9s
+8c
+4lasia
+9s
+7tic
+4nea
+7l
+7s
+6ic
+5oea
+8l
+8s
+7ic
+6ic
+4raxia
+9s
+8c
+5osium
+9ms
+3rhythmia
+9ias
+9ic
+3synergia
+9ias
+3taxia
+8s
+4ectic
+5leological
+9ogies
+9ogist
+9ogists
+9ogy
+4hesia
+9s
+6tic
+5ymia
+9c
+9cs
+9s
+8c
+9s
+4ocia
+8l
+8s
+5nia
+8s
+7c
+5pia
+8n
+9s
+8s
+4rophia
+9as
+9c
+9es
+9n
+9ns
+8y
+3uria
+7s
+6c
+6es
+5y
+2tiscid
+8s
+2vour
+6ies
+6s
+6y
+1zeren
+6s
+2ho
+4s
+2iggetai
+9s
+2o
+3s
+0ea
+2ch
+4where
+2dish
+6es
+2ger
+5er
+6st
+5ly
+5ness
+9es
+5s
+3le
+5d
+5hawk
+9s
+5s
+6tone
+9es
+5t
+6s
+5wood
+9s
+4ing
+3re
+5s
+2ldorman
+7en
+3e
+4s
+2n
+3ed
+3ing
+3ling
+7s
+3s
+2r
+3ache
+7s
+3ball
+7s
+5sh
+7ed
+8r
+9s
+8s
+7ing
+9gs
+4ob
+6s
+4ud
+6s
+3con
+6s
+3d
+4ed
+4ing
+4rop
+7s
+5um
+7s
+4s
+3ed
+3flap
+7s
+4ul
+6s
+3ing
+6s
+3l
+4ap
+6s
+4dom
+7s
+4ess
+4ier
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+6s
+7t
+5ke
+5ness
+9es
+4obe
+7s
+5ck
+7s
+4s
+5hip
+8s
+4y
+5wood
+9s
+3mark
+7ed
+7ing
+7s
+4uff
+7s
+3n
+4ed
+5r
+6s
+5st
+7ly
+7ness
+9sses
+7s
+4ing
+7s
+4s
+3phone
+8s
+4ick
+7s
+5ece
+8s
+4lug
+7s
+3ring
+7ed
+7s
+3s
+4hot
+7s
+4plitting
+4t
+5one
+8s
+3th
+5born
+7und
+5ed
+6n
+7ware
+9res
+5fall
+9s
+7st
+6lax
+9es
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5lier
+8s
+9t
+7ght
+9ts
+7ke
+7ness
+9sses
+8g
+9s
+6y
+5man
+6en
+6over
+9rs
+8ing
+9ngs
+5nut
+8s
+5pea
+8s
+5quake
+9ed
+9es
+9ing
+5rise
+9s
+5s
+6et
+8s
+6haker
+9ers
+9ing
+9ingly
+8ttering
+7ine
+9es
+6tar
+9s
+5ward
+9s
+7x
+8es
+6olf
+8ves
+7man
+8en
+7rk
+9s
+8m
+9s
+5y
+3wax
+6es
+4ig
+6ged
+7ing
+9gs
+7y
+6s
+5tness
+9ses
+4orm
+7s
+2s
+3e
+4d
+4ful
+7ly
+7ness
+9sses
+4l
+5ed
+6ss
+5s
+4ment
+8s
+4r
+5s
+4s
+3ied
+5r
+5s
+6t
+4ly
+4ness
+8es
+5g
+6s
+3le
+5s
+3sel
+6gate
+6ward
+4il
+3t
+4about
+4bound
+4ed
+5r
+6lies
+8ng
+9gs
+7y
+6most
+6n
+7er
+9s
+7most
+6s
+4ing
+7s
+4land
+8s
+5in
+7g
+8s
+7s
+4most
+4s
+4ward
+8ly
+8s
+3y
+4going
+9ness
+9nesses
+4ing
+2t
+3able
+7s
+4ge
+6s
+3che
+6s
+3en
+4r
+5ie
+7s
+5s
+5y
+3h
+4e
+4ly
+3ing
+6s
+3s
+2u
+3s
+3x
+2ve
+4d
+4s
+5drip
+9s
+7op
+9ped
+9per
+9pers
+9ping
+9pings
+9s
+5trough
+9ghs
+1bauche
+7s
+3yer
+6s
+4ing
+7s
+2b
+3ed
+4t
+5s
+3ing
+3less
+3s
+2enezer
+8s
+4iste
+8s
+2ionise
+8d
+8s
+7ing
+7m
+8s
+6tic
+8sm
+9ms
+6ze
+8d
+8s
+7ing
+2on
+4ics
+5es
+5se
+7d
+7s
+6ing
+6t
+7s
+5te
+7s
+5ze
+7d
+7s
+6ing
+4s
+4y
+3ok
+5s
+3ulement
+9ts
+2racteate
+7olate
+3iate
+7d
+4eties
+6y
+4llade
+9s
+4ose
+6ities
+8y
+2ullience
+9es
+9ies
+9y
+8t
+9ly
+6ometer
+9ters
+9tries
+9try
+7scope
+9opes
+9opic
+9opical
+9opies
+9opy
+6tion
+9ns
+3rnation
+9ns
+5ean
+6ous
+5ification
+9ations
+1cad
+4s
+3rdinate
+4inate
+4te
+6s
+3udate
+2blasteses
+9is
+3ole
+6s
+5ic
+7s
+2caleobion
+9ons
+3e
+4ntric
+9al
+9ally
+9ities
+9ity
+9s
+3hymosed
+9s
+8is
+7tic
+3lesia
+8e
+8l
+8rch
+9chs
+8st
+9tic
+9tical
+9ticism
+9tics
+9ts
+7olater
+9aters
+9atries
+9atry
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+3o
+4protic
+9cs
+3remocarpus
+9rpuses
+4ine
+6ologies
+9gy
+5ses
+6is
+5tic
+8s
+2demic
+3yses
+5ial
+7st
+9s
+6s
+5on
+7e
+8s
+7s
+2esic
+5s
+6es
+2h
+3appe
+7s
+4rd
+6s
+3e
+4d
+4lle
+7s
+5on
+7ed
+7ing
+7s
+4s
+4veria
+9s
+3idna
+7e
+7s
+6ine
+9s
+4nacea
+9s
+6te
+8d
+5g
+5i
+5ococci
+9coses
+9cosis
+9cus
+6derm
+9mal
+9matous
+9ms
+6id
+8s
+5us
+7es
+4um
+6s
+5ran
+8s
+6oid
+9s
+3o
+4cardiogram
+9ograms
+4ed
+5r
+6s
+5s
+5y
+4gram
+8s
+7ph
+9ies
+9s
+9y
+4ic
+6ally
+5er
+6st
+5ng
+5se
+7d
+7s
+6ing
+6m
+7s
+6t
+7s
+5ze
+7d
+7s
+6ing
+4lalia
+9s
+8c
+5ess
+5ocation
+9ions
+4praxes
+8ia
+9as
+9s
+4s
+4virus
+9es
+3t
+2lair
+6cissement
+6s
+4mpsia
+9s
+8es
+7y
+6tic
+4t
+5s
+3ectic
+8ally
+8ism
+9sms
+8s
+3ipse
+7d
+7r
+8s
+7s
+6ing
+7s
+8es
+5tic
+8ally
+8s
+3ogite
+8s
+5ue
+7s
+4se
+6d
+6s
+5ing
+6on
+8s
+2o
+3catastrophe
+9rophes
+4entric
+4idal
+6e
+7s
+4limate
+9es
+3d
+3feminism
+9sms
+9st
+9sts
+4reak
+8s
+5iendly
+3lodge
+8s
+5gic
+8al
+9lly
+7es
+7st
+9s
+6y
+3map
+6s
+4merce
+9s
+3nobox
+8es
+5metric
+9ical
+9ically
+9ician
+9icians
+9ics
+9ist
+9ists
+6ic
+8al
+9lly
+8s
+7es
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6y
+4ut
+6s
+3phobia
+9s
+5ysiologies
+9logy
+3rche
+7s
+4egion
+9s
+3s
+4pecies
+8fic
+5here
+9s
+4saise
+9s
+4tate
+4ystem
+9s
+3tage
+7s
+5rian
+9s
+4ecture
+9es
+5rrorism
+9isms
+9ist
+9ists
+4onal
+6e
+7s
+5ur
+7ism
+9ms
+9t
+9ts
+7s
+5xic
+8ologies
+9logist
+9logy
+4ype
+7s
+6ic
+8ally
+2phoneses
+8is
+4ractic
+9cs
+6ses
+7is
+2raseur
+8s
+3itoire
+9s
+3u
+4s
+2stases
+6ied
+8s
+7s
+8e
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6y
+7ing
+5tic
+8ally
+8s
+2tases
+5ia
+7s
+6s
+4tic
+3hlipses
+8is
+4yma
+7s
+7ta
+3oblast
+9ic
+9s
+4crine
+9s
+4derm
+8al
+8ic
+8s
+4enzyme
+9es
+4geneses
+9is
+8tic
+7ic
+9ally
+8es
+7ous
+7y
+4mere
+8s
+7ic
+5orph
+9ic
+9ies
+9s
+9y
+5ycorrhiza
+9rhizae
+9rhizas
+4parasite
+9ites
+9itic
+5hyte
+9s
+8ic
+5ia
+7s
+6c
+7ally
+6es
+5lasm
+9ic
+9s
+8tic
+5roct
+9s
+5y
+4sarc
+8ous
+8s
+4therm
+9ic
+9s
+5rophic
+4zoa
+7n
+8s
+6ic
+6on
+3ropic
+7on
+9s
+7um
+9s
+3ypal
+5e
+6s
+5ographies
+9phy
+2u
+3elle
+7s
+3menic
+8al
+9lism
+9lisms
+9lly
+8ism
+9sms
+9st
+9sts
+9ties
+9ty
+8s
+7sm
+9s
+8t
+9s
+3rie
+6s
+3s
+2zema
+6s
+6tous
+1d
+2acious
+8ly
+8ness
+9esses
+5ties
+6y
+3mame
+7s
+3phic
+7ally
+5ologies
+9y
+2died
+5s
+4sh
+6es
+3o
+4es
+3y
+4ing
+2elweiss
+9es
+3ma
+5s
+5ta
+6ose
+7us
+3nic
+4tal
+6te
+8s
+5ulate
+7ous
+2ge
+4bone
+8s
+4d
+4less
+4r
+5s
+4s
+4ways
+5ise
+3ier
+5st
+4ly
+4ness
+8es
+5g
+6s
+3y
+2h
+3s
+2ibilities
+8y
+4le
+6ness
+9ses
+6s
+3ct
+5al
+7ly
+5s
+3fication
+9ons
+8ory
+6e
+7s
+6ial
+5ed
+6r
+7s
+6s
+4y
+5ing
+8ly
+3le
+5s
+3t
+4able
+4ed
+4ing
+7s
+5on
+7ed
+7ing
+7s
+4or
+6ial
+9ise
+9ised
+9iser
+9isers
+9ises
+9ising
+9ist
+9ists
+9ize
+9ized
+9izer
+9izers
+9izes
+9izing
+9ly
+9s
+6s
+7hip
+9ps
+4ress
+8es
+5ices
+6x
+7es
+4s
+2riophthalmian
+9almic
+9almous
+2s
+2ucabilities
+9ty
+6le
+8s
+5tabilities
+9lity
+8le
+6e
+7d
+8ness
+9esses
+7s
+6ing
+7on
+9al
+9alist
+9alists
+9ally
+9ese
+9eses
+9ist
+9ists
+9s
+7ve
+6or
+8s
+8y
+4e
+5d
+5ment
+9s
+5s
+4ible
+5ng
+4t
+5ion
+8s
+6ve
+5or
+7s
+5s
+3lcorant
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+3tainment
+9nts
+1e
+2ch
+4ed
+5s
+4ing
+2jit
+5s
+2k
+2l
+3fare
+7s
+3grass
+8es
+3ier
+5st
+3like
+3pout
+7s
+3s
+3worm
+7s
+4rack
+8s
+3y
+2n
+2rie
+5r
+5st
+4ly
+4ness
+8es
+3y
+2ven
+5s
+3n
+4ing
+7s
+4s
+1f
+2f
+3able
+4ce
+6able
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+3ect
+6ed
+7r
+8s
+6ible
+7ng
+7ve
+9ly
+9ness
+9nesses
+9s
+8ities
+9ty
+6less
+6or
+8s
+6s
+6ual
+9ities
+9ity
+9ly
+9ness
+9nesses
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+4d
+4ir
+6ed
+6ing
+6s
+4minacies
+9y
+8te
+9ed
+9ely
+9eness
+9es
+9ing
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+4ndi
+7s
+4re
+6d
+6nce
+9s
+7t
+8ly
+8s
+6s
+5ing
+5vesce
+9ed
+9ence
+9ences
+9encies
+9ency
+9ent
+9ently
+9es
+9ible
+9ing
+9ingly
+4te
+6ly
+6ness
+9ses
+3icacies
+8ous
+9usly
+9usness
+8ties
+9y
+7y
+5ience
+9es
+9ies
+9y
+8t
+9ly
+9s
+4erce
+8d
+8s
+7ing
+4gial
+6es
+5urate
+9ion
+9ions
+5y
+4ng
+6s
+3leurage
+9ed
+9es
+9ing
+4oresce
+9ed
+9ence
+9ences
+9ent
+9es
+9ing
+4uence
+9s
+7t
+8s
+5via
+8l
+7um
+9s
+5x
+6es
+6ion
+9s
+3orce
+7d
+7s
+6ing
+5t
+6ful
+9ly
+9ness
+9nesses
+6less
+9sly
+9sness
+6s
+3raide
+5y
+6s
+4onteries
+9y
+3s
+3ulge
+7d
+7nce
+9es
+8t
+9ly
+7s
+6ing
+4se
+6d
+6s
+5ing
+6ometer
+9ters
+7n
+8s
+6ve
+8ly
+8ness
+9esses
+2s
+2t
+3est
+3s
+4oon
+7s
+1gad
+4s
+3l
+4itarian
+9anism
+9anisms
+9ans
+6e
+7s
+6ies
+6y
+4ly
+3rement
+9s
+2ence
+6s
+5ies
+5y
+3r
+4s
+3st
+5a
+5ed
+5ing
+6on
+8s
+6ve
+5s
+2g
+3ar
+5s
+3beater
+9s
+3cup
+6s
+3ed
+4r
+5ies
+5s
+5y
+3fruit
+8s
+3head
+7ed
+9ness
+9nesses
+7s
+3ier
+5st
+4ng
+3ler
+6s
+5ss
+3mass
+7es
+3nog
+6s
+3plant
+8s
+3s
+4hell
+8s
+3wash
+7es
+4hisk
+8s
+3y
+2is
+4es
+2landular
+8ose
+5tine
+9s
+4tere
+8s
+3omise
+2ma
+4s
+2o
+3centric
+9cally
+9cities
+9city
+9cs
+9sm
+9sms
+3ism
+6s
+5t
+6ic
+8al
+9lly
+6s
+4ties
+5y
+3less
+3mania
+8c
+9al
+9ally
+9s
+8s
+3s
+3theism
+9s
+4ise
+7d
+7s
+6ing
+6m
+7s
+6t
+7ic
+9al
+9ally
+7s
+5ze
+7d
+7s
+6ing
+2regious
+9ly
+9ness
+9nesses
+4ss
+6ed
+7s
+6ing
+7on
+9s
+7ve
+9s
+4t
+5s
+2urgitate
+9ed
+9es
+9ing
+2yptian
+8s
+1h
+2ed
+2ing
+2s
+1icosanoid
+9ds
+2de
+4nt
+4r
+5down
+9s
+5s
+4tic
+7ally
+7s
+3ograph
+9s
+4la
+5ic
+5on
+7s
+4s
+2genfrequency
+6unction
+9tions
+5mode
+9s
+5tone
+9s
+5value
+9es
+6ector
+9ors
+3ht
+5ball
+9s
+5een
+8mo
+9os
+8s
+8th
+9hly
+9hs
+5foil
+9s
+7ld
+5h
+6ly
+6s
+5ies
+7th
+9s
+5pence
+9es
+8ny
+5s
+6core
+9es
+6man
+7en
+6ome
+9s
+5vo
+7s
+5y
+3ne
+2k
+3ed
+3ing
+3on
+5es
+5s
+3s
+2ld
+4ing
+7s
+4s
+2na
+3e
+3korn
+7s
+3stein
+8ium
+9ums
+8s
+2rack
+6s
+3enic
+7al
+9ly
+7on
+9s
+2segeses
+7is
+4l
+5l
+6s
+5s
+3h
+3teddfod
+9dau
+9dic
+9ds
+3wein
+7s
+2ther
+1jaculators
+9ry
+2ect
+5a
+6ble
+6menta
+5ed
+5ing
+6on
+8s
+6ve
+8ly
+8s
+5ment
+9s
+5or
+7s
+5s
+1ke
+3d
+3s
+2ing
+3stic
+7al
+7ian
+9ns
+7s
+2ka
+4s
+2logite
+8s
+2phrases
+7is
+3wele
+7s
+2texine
+8s
+2uele
+1l
+2aborate
+9d
+9ly
+9ness
+9nesses
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9ries
+9rs
+9ry
+3eolite
+9s
+5ptene
+9es
+3in
+5s
+4osome
+9s
+3n
+4ce
+6d
+6s
+5ing
+4d
+5s
+4et
+6s
+4s
+3phine
+4id
+6s
+5ne
+4se
+6d
+6s
+5ing
+3smobranch
+9nchs
+6saur
+9rs
+4tance
+9s
+7e
+8s
+6se
+8s
+5ic
+7ally
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+7ise
+9ed
+9es
+9ing
+8ties
+9y
+8ze
+9ed
+9es
+9ing
+7ness
+9sses
+7s
+6n
+7s
+5omer
+9ic
+9s
+3te
+5d
+6ly
+6ness
+9ses
+5r
+6id
+8s
+7n
+8s
+7te
+9s
+7um
+9s
+6s
+5s
+4ing
+5on
+7s
+5ve
+7s
+2bow
+5ed
+5ing
+5room
+9s
+5s
+2chee
+6s
+4i
+5s
+2d
+3er
+5berries
+9y
+5care
+9s
+5lies
+7ness
+9sses
+6y
+5s
+6hip
+9s
+4st
+3in
+5g
+6s
+5s
+3orado
+8s
+3ress
+7es
+4ich
+5tch
+3s
+2ecampane
+9es
+4t
+5abilities
+9ity
+7le
+5ed
+6e
+7s
+5ing
+6on
+8eer
+9ered
+9erer
+9erers
+9ering
+9erings
+9ers
+8s
+6ve
+8ly
+8ness
+9esses
+8s
+7ities
+9y
+5or
+7al
+9ly
+8te
+9es
+7ess
+9ses
+7ial
+9lly
+7s
+8hip
+9ips
+5ress
+9es
+7t
+8s
+6ic
+8al
+9lly
+9ls
+8ian
+9ans
+9ties
+9ty
+8s
+7fiable
+9cation
+9ed
+9er
+9ers
+9es
+8y
+9ing
+9ingly
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6o
+7acoustic
+9tive
+9tivity
+8nalyses
+9alysis
+9alytic
+7biology
+7cautery
+8ement
+9ments
+8hemic
+9emical
+9emist
+9emists
+8lash
+9ashes
+8ulture
+9ltures
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+8yte
+9tes
+7de
+9posit
+9posits
+9rmal
+9s
+8ialyses
+9alysis
+9alytic
+8ynamic
+9namics
+7ed
+7fishing
+9shings
+8luor
+9uors
+8orm
+9rmed
+9rming
+9rmings
+9rms
+7gen
+9neses
+9nesis
+9nic
+9ns
+8ilding
+9ldings
+8ram
+9ams
+9aph
+9aphic
+9aphies
+9aphs
+9aphy
+7ing
+7jet
+9ts
+7kinetic
+9netics
+7less
+8ier
+9ers
+8ogies
+9gist
+9gists
+9gy
+8ysation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9sis
+9te
+9tes
+9tic
+9tics
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+7magnet
+9gnetic
+9gnets
+8er
+9ric
+9rism
+9risms
+9rs
+9ter
+9ters
+9tric
+9trical
+9tries
+9try
+8otance
+9tances
+9tive
+9tor
+9tors
+8yogram
+9ograms
+9ograph
+7n
+8egative
+8ic
+9ca
+9cally
+9cas
+9cs
+8s
+8volt
+9olts
+7osmoses
+9mosis
+9motic
+7phile
+9iles
+9ilic
+9one
+9ones
+9onic
+9orese
+9oresed
+9oreses
+9oresis
+9oretic
+9ori
+9orus
+9oruses
+8late
+9ated
+9ater
+9aters
+9ates
+9ating
+9atings
+8olar
+9sitive
+7receptor
+8heology
+7s
+8cope
+9opes
+9opic
+8hock
+9ocks
+8onde
+9ndes
+8tatic
+9atics
+8urgery
+9rgical
+7technics
+8herapy
+9ermal
+9ermic
+9ermics
+9ermies
+9ermy
+8int
+9nts
+8onic
+9nus
+9nuses
+8ype
+9ped
+9per
+9pers
+9pes
+9pic
+9pies
+9ping
+9pist
+9pists
+9py
+7valence
+9lences
+9lency
+9lent
+9lently
+7weak
+8inning
+9nnings
+6um
+8s
+5s
+5uaries
+8y
+3doisin
+9s
+3emosynary
+3gance
+8s
+7ies
+7y
+6t
+7ly
+4iac
+7al
+9ly
+7s
+6st
+8s
+5es
+5se
+7d
+7s
+6ing
+6t
+7s
+5t
+6s
+5ze
+7d
+7s
+6ing
+4y
+3ment
+7al
+9ism
+9isms
+9ly
+9s
+8rily
+9iness
+9y
+7s
+4i
+5s
+3nch
+6i
+7c
+6s
+6tic
+6us
+5tic
+3optene
+9s
+3phant
+8iases
+9asic
+9asis
+9ne
+8oid
+8s
+3utherarch
+9rchs
+8i
+9an
+8ococci
+9coccus
+9dactyl
+9mania
+9manias
+9phobia
+9phobic
+3vate
+7d
+8s
+7s
+6ing
+7on
+9al
+9s
+6or
+8s
+8y
+4en
+6s
+7es
+6th
+8ly
+8s
+4on
+6s
+2f
+3ed
+3hood
+7s
+3in
+5g
+5s
+4sh
+6ly
+6ness
+9ses
+3land
+7s
+4ike
+4ock
+7s
+3s
+2hi
+2iad
+5s
+3che
+6s
+4it
+6able
+7tion
+9ons
+6ed
+6ing
+6or
+8s
+6s
+3de
+5d
+5s
+4ible
+5ng
+3gibilities
+9ty
+6le
+8s
+7y
+3minabilities
+9lity
+8le
+7nt
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+3nt
+5s
+3sion
+7s
+3te
+5s
+4ism
+7s
+6t
+7s
+3xir
+6s
+2k
+3horn
+5und
+8s
+3s
+2l
+3agic
+3ipse
+7s
+6is
+6ograph
+9aphs
+7id
+9al
+9s
+5tic
+8al
+9lly
+9lness
+9ls
+8ities
+9ty
+3ops
+6es
+3s
+3wand
+7s
+2m
+3en
+3ier
+5st
+3s
+3wood
+7s
+3y
+2ocute
+7d
+7s
+6ing
+7on
+9ary
+9ist
+9ists
+9s
+6ory
+3dea
+6s
+3ge
+5s
+4ies
+5st
+7s
+5um
+7s
+4y
+3ign
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4n
+5ed
+6r
+7s
+5ing
+5ment
+9s
+5s
+3ngate
+8d
+8s
+7ing
+8on
+9ns
+3pe
+5d
+5ment
+9s
+5r
+6s
+5s
+4ing
+4s
+5es
+3quence
+9s
+7t
+8ly
+2pee
+5s
+2s
+3e
+4where
+6ither
+5ise
+3hin
+6s
+3in
+5s
+2t
+3chi
+6s
+3s
+2uant
+6s
+4te
+6s
+3cidate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+4ubrate
+9ed
+9es
+9ing
+9ion
+9ions
+3de
+5d
+5r
+6s
+5s
+4ible
+5ng
+3ent
+6s
+3sion
+7s
+5ve
+7ly
+7ness
+9sses
+4oriness
+9sses
+6y
+3te
+5d
+5s
+4ing
+5on
+7s
+4or
+6s
+4riate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+3via
+6l
+6te
+8d
+8s
+7ing
+8on
+9ns
+5um
+7s
+2van
+5ite
+8s
+5s
+3er
+5s
+4s
+3ish
+6ly
+6ness
+9ses
+2ysian
+3tra
+6l
+5iform
+6gerous
+5oid
+6n
+6us
+5um
+1m
+2aciate
+8d
+8s
+7ing
+8on
+9ns
+4s
+5en
+3il
+5ed
+6r
+7s
+5ing
+8s
+5s
+3langeni
+3nant
+5te
+7d
+7s
+6ing
+7on
+9al
+9s
+7st
+9s
+7ve
+6or
+8s
+8y
+4cipate
+9ed
+9es
+9ing
+9ion
+9ionist
+9ions
+9ive
+9or
+9ors
+9ory
+7ist
+9ts
+3rginate
+9ed
+9ely
+9es
+9ing
+9ion
+9ions
+3sculate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+2bace
+6s
+5ing
+4il
+6ed
+6ing
+6s
+4le
+6d
+6s
+5ing
+5l
+6ed
+6ing
+9s
+6s
+5m
+6ed
+7r
+8s
+6ing
+9s
+6ment
+9ts
+6s
+4nk
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4r
+5cadero
+9ros
+7tion
+9ons
+5go
+7ed
+8s
+7ing
+5k
+6ation
+9ons
+6ed
+6ing
+6ment
+9ts
+6s
+5quement
+9ents
+5rass
+9able
+9ed
+9edly
+9es
+9ing
+9ingly
+9ment
+9ments
+6ed
+6ing
+9s
+5s
+4se
+6d
+6ment
+9ts
+6s
+5ing
+5sade
+9s
+8or
+9rs
+7ge
+9s
+6ies
+6y
+5te
+4the
+7d
+7s
+6ing
+5tle
+8d
+8ment
+9ents
+8s
+7ing
+4y
+5ed
+5ing
+5ld
+5ment
+9s
+5s
+3ed
+5ded
+6ing
+9s
+5ment
+9s
+5s
+4llish
+9ed
+9er
+9ers
+9es
+9ing
+9ingly
+9ment
+9ments
+4r
+5s
+4zzle
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+3itter
+8ed
+9r
+9rs
+8ing
+9ngs
+8ment
+9ents
+8s
+3laze
+7d
+7r
+8s
+7s
+6ing
+6on
+8ed
+9r
+9rs
+8ing
+8ment
+9ents
+8ries
+9y
+8s
+4em
+6a
+7ta
+8ic
+9cal
+9cally
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+6ed
+7nts
+6ing
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6s
+4ic
+6s
+4oom
+7ed
+7ing
+7s
+5ssom
+9ed
+9ing
+9s
+3odied
+7r
+8s
+7s
+6ment
+9ts
+5y
+6ing
+4g
+5ged
+6ing
+5s
+5ue
+7d
+7s
+6ing
+4il
+6ed
+6ing
+6s
+5tement
+9nts
+4lden
+8ed
+9r
+9rs
+8ing
+8s
+5ectomies
+9my
+5i
+6c
+6es
+6sation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8al
+8ic
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5us
+7es
+5y
+4npoint
+9ts
+4rder
+8ed
+8ing
+8s
+4scata
+9s
+5k
+6ed
+6ing
+6s
+5om
+7ed
+7ing
+7s
+5s
+6able
+6ed
+7r
+8s
+7s
+6ing
+6ment
+9ts
+5t
+4thrium
+9ms
+4uchure
+9es
+5nd
+7ed
+7ing
+7s
+5rgeoise
+9ised
+9ises
+9ising
+4w
+5ed
+6l
+7ed
+7ing
+7led
+8ing
+7ment
+9nts
+7s
+6r
+7ed
+7ing
+7ment
+9nts
+7s
+5ing
+5ment
+9s
+5s
+4x
+5ed
+6s
+5ing
+3race
+7able
+7d
+7ment
+9nts
+7or
+9s
+7r
+8ies
+8s
+8y
+7s
+6ing
+9ly
+9ness
+9nesses
+7ve
+5id
+7ed
+7ing
+7s
+5nchment
+9ents
+6gle
+9d
+9ment
+9ments
+9s
+8ing
+5sor
+8s
+6ure
+9d
+9s
+5ve
+7d
+7s
+6ing
+5zure
+9s
+4ead
+7ed
+7ing
+7s
+6the
+9d
+9s
+8ing
+4ittle
+9d
+9ment
+9ments
+9s
+8ing
+4ocate
+9d
+9s
+8ing
+9on
+9ons
+5glio
+9s
+5ider
+9ed
+9er
+9ers
+9ies
+9ing
+9s
+9y
+6l
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+5wn
+7ed
+7ing
+7s
+4ue
+6d
+6ment
+9ts
+6s
+5ing
+5te
+7d
+7s
+6ing
+4yectomies
+9my
+5o
+6geneses
+9esis
+9etic
+9ic
+9ies
+9y
+6id
+8s
+6logic
+9ical
+9ically
+9ies
+9ist
+9ists
+9y
+6n
+7al
+8te
+9ed
+7ic
+9ally
+7s
+6phyte
+9tes
+6s
+6tic
+9ally
+7omies
+9y
+5ulcia
+9as
+3us
+5ed
+6s
+5ied
+7s
+6ng
+5que
+8s
+5sed
+7s
+6ing
+5y
+6ing
+2cee
+5d
+5ing
+5s
+2dash
+6es
+2e
+3er
+5ate
+8s
+5s
+3nd
+5able
+6ls
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+9y
+5ed
+6r
+7s
+5ing
+5s
+3rald
+7s
+5ude
+8s
+4ge
+6d
+6nce
+9s
+8ies
+8y
+7t
+8ly
+8s
+6s
+5ing
+4ied
+6s
+5ta
+7e
+7s
+6i
+6us
+4od
+6s
+5id
+7s
+4se
+6d
+5ion
+8s
+4y
+5ing
+3s
+4es
+4is
+3tic
+6al
+8ly
+6s
+5n
+6e
+7s
+6s
+4ophobia
+9ias
+3u
+4s
+4te
+6s
+2f
+3s
+2ic
+4ant
+5te
+7d
+7s
+6ing
+7on
+9s
+4tion
+8s
+5ory
+3grant
+8s
+6te
+8d
+8s
+7ing
+8on
+9nal
+9nist
+9nists
+9ns
+7ory
+5e
+6s
+3nence
+8s
+7ies
+7y
+6t
+7ial
+7ly
+3r
+4ate
+7s
+4s
+3ssaries
+7y
+5ile
+6on
+8s
+6ve
+7ities
+9y
+3t
+4s
+4tance
+9s
+5ed
+6r
+7s
+5ing
+2lets
+2ma
+4rble
+8d
+8s
+7ing
+4s
+3enagogic
+9ue
+9ues
+5ologies
+9y
+4r
+5s
+4sh
+6ed
+7s
+6ing
+4t
+5rope
+9s
+8ia
+9as
+9c
+5s
+4w
+5ed
+5ing
+5s
+3ove
+6d
+6s
+5ing
+3y
+4s
+2o
+3din
+6s
+3llescence
+9nces
+5iate
+9d
+9s
+8ing
+6ence
+9es
+8t
+9s
+6tion
+9ns
+4ument
+9al
+9ary
+9s
+3ng
+5es
+7t
+5st
+3s
+3te
+5d
+5r
+6s
+5s
+4icon
+8s
+5ng
+5on
+7able
+8l
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9istic
+9ists
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+9ly
+7less
+9ssly
+9ssness
+7s
+5ve
+7ly
+7ness
+9sses
+6ism
+9s
+7ties
+8y
+3ve
+5d
+5s
+4ing
+2packet
+8ed
+8ing
+8s
+4estic
+4ire
+7d
+7s
+6ing
+4le
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+4nada
+8s
+5el
+7ed
+7ing
+7led
+8ing
+7ment
+9nts
+7s
+5oplied
+9es
+8y
+9ing
+4radise
+9ed
+9es
+9ing
+5e
+6d
+6s
+5ing
+5l
+6aunce
+9ces
+6ed
+6ing
+6s
+5t
+6ed
+6ing
+6s
+4ssionate
+9ed
+4thetic
+9cally
+6ic
+8ally
+7es
+7se
+9d
+9s
+8ing
+8t
+9s
+7ze
+9d
+9s
+8ing
+6y
+5ron
+8ed
+8ing
+8s
+4yre
+7d
+7s
+6ing
+3each
+7ed
+8s
+7ing
+4nnage
+9s
+4ople
+8d
+8s
+7ing
+4rce
+7d
+7s
+6ing
+5ies
+6se
+8d
+8s
+7h
+8ed
+9s
+8ing
+7ing
+6ze
+8d
+8s
+7ing
+5or
+7s
+8hip
+9ips
+5y
+3hases
+6is
+8e
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+5tic
+8al
+9lly
+9lness
+8s
+4lyses
+7is
+4ractic
+9cs
+4ysema
+9s
+9tous
+8ic
+9cs
+5teuses
+9is
+8tic
+3iecement
+9nts
+5rce
+8d
+8s
+7ing
+4ght
+4re
+6s
+5ic
+7al
+9ly
+9ness
+9nesses
+9s
+7ism
+9ms
+9t
+9ts
+7s
+7utic
+3lace
+7d
+7ment
+9nts
+7s
+6ing
+5ne
+7d
+7s
+6ing
+5ster
+9ed
+9ing
+9s
+7ic
+9s
+7ron
+9ns
+8um
+9ms
+4each
+8ed
+9s
+8ing
+5cton
+9s
+7um
+9s
+4onge
+8d
+8s
+7ing
+5y
+6abilities
+9lity
+8le
+9es
+6e
+7d
+7e
+8s
+7r
+8s
+7s
+6ing
+6ment
+9ts
+6s
+4ume
+7d
+7s
+6ing
+3oison
+8ed
+8ing
+8ment
+9ents
+8s
+4lder
+8ed
+8ing
+8s
+4ria
+6um
+8s
+4verish
+9hed
+9her
+9hers
+9hes
+9hing
+9hment
+9hments
+4wer
+7ed
+7ing
+7ment
+9nts
+7s
+3ress
+7e
+8ment
+9ents
+8s
+4ise
+7s
+5ze
+7s
+3t
+4ed
+4iable
+5ed
+6r
+7s
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+6s
+5on
+7al
+7s
+4s
+4y
+5ing
+8s
+5ses
+6is
+3urple
+8d
+8s
+7ing
+4sa
+6s
+5e
+6s
+3yema
+7s
+7ta
+6ic
+5ses
+6is
+4real
+7n
+8s
+6uma
+9ta
+9tic
+9tical
+9tise
+9tised
+9tises
+9tising
+9tize
+9tized
+9tizes
+9tizing
+2s
+2u
+3late
+7d
+7s
+6ing
+7on
+9s
+7ve
+9ly
+6or
+8s
+6ress
+9ses
+4e
+5d
+5s
+4ge
+6d
+6nce
+9s
+7t
+6s
+5ing
+4ing
+4ous
+7ly
+7ness
+9sses
+4sible
+6fiable
+8cation
+9ations
+8ed
+9r
+9rs
+9s
+7y
+8ing
+6n
+7s
+6on
+8ise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+8s
+6ve
+5oid
+8al
+8s
+6r
+7s
+3nction
+9s
+6ories
+8y
+4ge
+6d
+6s
+5ing
+3re
+5d
+5s
+4ing
+3s
+2yd
+4e
+5s
+4s
+3s
+1n
+2able
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+3ct
+5able
+5ed
+5ing
+6on
+8s
+6ve
+5ment
+9s
+5or
+7s
+7y
+5s
+5ure
+8s
+3lapril
+9s
+4lage
+8s
+3mel
+6ed
+7r
+8s
+6ing
+7st
+9s
+6led
+8r
+9s
+7ing
+9gs
+8st
+9ts
+6s
+6ware
+9es
+7ork
+9ks
+4ine
+7s
+4or
+6ado
+9s
+7tion
+9ons
+6ed
+6ing
+6s
+5ur
+7ed
+7ing
+7s
+3nthema
+9s
+5iodromia
+9omias
+9omic
+7mer
+9ric
+9rs
+8orph
+9rphic
+9rphies
+9rphism
+9rphous
+9rphs
+9rphy
+7pathies
+9thy
+7ses
+8is
+8tylies
+9ylous
+9yly
+7tropic
+9opies
+9opy
+3rch
+6ed
+7s
+6ing
+4gite
+8s
+4m
+5ed
+5ing
+5s
+4ration
+9ns
+4throdial
+8ses
+9is
+3te
+5s
+4ic
+5on
+7s
+3unter
+2caenia
+8s
+4ge
+6d
+6s
+5ing
+4lm
+6ed
+6ing
+6s
+4mp
+6ed
+6ing
+6ment
+9ts
+6s
+4nthis
+9es
+4psulate
+9ted
+9tes
+9ting
+9tion
+9tions
+8e
+9d
+9s
+8ing
+4rnalise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+5pus
+8es
+4se
+6d
+6ment
+9ts
+6s
+5h
+6able
+6ed
+7s
+6ing
+6ment
+9ts
+5ing
+5tre
+4ustic
+9ally
+9s
+4ve
+6d
+6s
+5ing
+3einte
+8s
+4phala
+9lgia
+9lgias
+8ic
+9n
+9ne
+9nes
+9ns
+9tic
+9tides
+9tis
+9tises
+9togen
+9togens
+8ocele
+9celes
+9gram
+9grams
+9graph
+9graphs
+9graphy
+9id
+9ma
+9mas
+9mata
+9n
+9ns
+9pathic
+9pathy
+9tomies
+9tomy
+9us
+3hafe
+7d
+7s
+6ing
+5in
+7ed
+7ing
+7ment
+9nts
+7s
+5nt
+7ed
+8r
+9s
+7ing
+9gly
+7ment
+9nts
+7ress
+9sses
+7s
+5rge
+8d
+8s
+7ing
+6m
+7ed
+7ing
+7s
+5se
+7d
+7r
+8s
+7s
+6ing
+4eason
+9s
+5er
+7ed
+7ing
+7s
+5iridion
+9ions
+4ilada
+9s
+5ridia
+9on
+9ons
+4ondroma
+9mas
+9mata
+9matous
+5rial
+7c
+3ierro
+8s
+4na
+6l
+6s
+5cture
+9ed
+9es
+9ing
+4pher
+8ed
+9r
+9rs
+8ing
+8ment
+9ents
+8s
+4rcle
+8d
+8ment
+9ents
+8s
+7ing
+3lasp
+7ed
+7ing
+7s
+5ve
+7d
+7s
+6ing
+4ises
+6is
+5tic
+8ally
+8s
+4oister
+9red
+9ring
+9rs
+5sable
+6e
+7d
+7r
+8s
+7s
+6ing
+6ure
+9s
+5the
+8d
+8s
+7ing
+5ud
+7ed
+7ing
+7s
+3odable
+5e
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+4ignure
+9es
+4lour
+8ed
+8ing
+8s
+5pion
+9s
+7um
+9s
+5ure
+8s
+4mendero
+9ros
+5ia
+7st
+9ic
+9ical
+9ically
+9s
+6enda
+9as
+6on
+6um
+8s
+5pass
+9ed
+9es
+9ing
+9ment
+9ments
+4preses
+8is
+7tic
+4re
+6d
+6s
+5ing
+4unter
+9ed
+9er
+9ers
+9ing
+9s
+5rage
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+9ngly
+9ngs
+3radle
+8d
+8s
+7ing
+5ties
+6y
+4ease
+8d
+8s
+7ing
+4imson
+9ed
+9ing
+9s
+5nal
+6ic
+7tal
+8e
+9s
+8ic
+4oach
+8ed
+9r
+9rs
+9s
+8ing
+9ngly
+8ment
+9ents
+4ust
+7ation
+9ions
+7ed
+7ing
+7ment
+9nts
+7s
+4ypt
+7ed
+7ing
+8on
+9ns
+7s
+3ulturate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+4mber
+8ed
+8ing
+9ngly
+8ment
+9ents
+8s
+6rance
+9cer
+9cers
+9ces
+4rtain
+9ed
+9ing
+9s
+3yclic
+8al
+9ls
+8s
+6opaedia
+9edias
+9edic
+9edism
+9edisms
+9edist
+9edists
+8edia
+9dian
+9dias
+9dic
+9dical
+9dism
+9disms
+9dist
+9dists
+4st
+6ation
+9ons
+6ed
+6ing
+6ment
+9ts
+6s
+2d
+3amage
+8d
+8ment
+9ents
+8s
+7ing
+5eba
+8e
+8s
+7ic
+5oeba
+9e
+9s
+4nger
+8ed
+9r
+9rs
+8ing
+8ment
+9ents
+8s
+4rch
+7ies
+7y
+5t
+6ed
+7rectomy
+6ing
+6s
+4sh
+6es
+3brain
+8s
+3ear
+6ed
+6ing
+9ly
+9ness
+9nesses
+6ment
+9ts
+6s
+5vor
+8ed
+9r
+9rs
+8ing
+8s
+7ur
+9ed
+9er
+9ers
+9ing
+9ment
+9ments
+9s
+4cagon
+9s
+4d
+4ictic
+5xes
+6is
+8es
+4mial
+6c
+7al
+9ly
+7ities
+9y
+7s
+6ologies
+9gy
+6sm
+8s
+4nizen
+9ed
+9ing
+9s
+4r
+5gonic
+5matic
+6ic
+8al
+5on
+7s
+5s
+4w
+5ed
+5ing
+5s
+4xine
+8s
+3game
+7s
+5te
+7s
+3ing
+6s
+4ron
+7s
+4te
+6d
+6s
+5ing
+4ve
+6s
+3lang
+4eaf
+7s
+6ves
+5ss
+7ly
+7ness
+9sses
+4ong
+3most
+3note
+7s
+3obiotic
+5last
+9ic
+9s
+4cardia
+9ac
+9al
+9tic
+9tis
+9tises
+9um
+7p
+8al
+8ic
+8s
+6st
+8s
+5entric
+5hondral
+6ylous
+5rania
+9al
+9um
+6inal
+8e
+9s
+8ic
+8ologic
+9logies
+9logist
+9logy
+9pathic
+9pathy
+9us
+7tic
+5uticle
+9les
+5ytic
+7oses
+9is
+9ises
+8tic
+4derm
+8al
+8ic
+9s
+9ses
+8s
+5ontal
+8ic
+9cally
+9cs
+9st
+9sts
+5yne
+4enzyme
+9es
+5rgic
+4gamic
+8es
+7ous
+7y
+5en
+7ic
+8es
+7ous
+9sly
+7s
+7y
+4lithic
+5ymph
+9atic
+9s
+4metria
+9al
+9oses
+9osis
+9osises
+9tes
+9tides
+9tis
+9tises
+9um
+5itoses
+9is
+8tic
+6xes
+7is
+9es
+5orph
+9ic
+9ies
+9ism
+9isms
+9s
+9y
+5ycorrhiza
+4neuria
+9um
+5uclease
+9ases
+9olytic
+4parasite
+9ites
+9itic
+9itism
+9itisms
+5eptidase
+9dases
+6roxide
+9ides
+5hagies
+8ous
+8y
+6yllous
+7te
+9s
+8ic
+9cally
+5lasm
+9ic
+9s
+8tic
+6eura
+9as
+5od
+7ite
+9es
+7s
+6lyploid
+9loidy
+5roct
+9s
+4radiosonde
+9sondes
+5hizal
+5phin
+9s
+5sable
+7tion
+9ons
+6e
+7d
+7e
+8s
+7ment
+9nts
+7r
+8s
+7s
+6ing
+7ve
+6or
+8s
+4sarc
+8s
+5cope
+9s
+8ic
+9cally
+9es
+9st
+9sts
+8y
+5keletal
+9ton
+9tons
+5mometer
+9ters
+9tric
+7s
+8e
+9s
+8is
+7tic
+9cally
+5ome
+8s
+5perm
+9ic
+9s
+6ore
+9s
+8ous
+5s
+6ed
+7s
+6ing
+5tea
+8l
+9ly
+7um
+6oses
+8is
+6yle
+9s
+5ulfan
+9ns
+5ymbiont
+9onts
+9oses
+9osis
+9otic
+4thecia
+9al
+9um
+7lia
+9al
+9oid
+9oma
+9omas
+9omata
+9um
+7rm
+9al
+9ic
+9ically
+9ies
+9ism
+9isms
+9s
+9y
+5oxic
+8n
+9s
+5racheal
+6ophic
+4w
+5ed
+6r
+7s
+5ing
+5ment
+9s
+5s
+4zoa
+6ic
+6on
+3paper
+8s
+4late
+8s
+6y
+7ed
+7ing
+7s
+4oint
+8s
+3rin
+6s
+3s
+4hip
+7s
+3ue
+5d
+5s
+4ing
+4ngeon
+9ed
+9ing
+9s
+4rabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6nce
+9s
+5e
+6d
+6r
+7s
+6s
+5ing
+8ly
+8ness
+9esses
+5o
+6s
+3ways
+4ise
+3yses
+5is
+3zone
+7s
+2e
+3ma
+5s
+5ta
+4ies
+4y
+3rgetic
+9al
+9ally
+9s
+5ic
+6d
+7s
+6es
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5umen
+9s
+5y
+4vate
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+5e
+6d
+6s
+5ing
+3s
+3w
+4ed
+4ing
+4s
+2face
+6d
+6ment
+9ts
+6s
+5ing
+4nt
+6s
+3eeble
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+4lon
+7ed
+7ing
+7s
+4off
+7ed
+7ing
+7ment
+9nts
+7s
+4sted
+7red
+4tter
+8ed
+8ing
+8s
+4ver
+7ed
+7ing
+7s
+3ierce
+8d
+8s
+7ing
+4lade
+8d
+8s
+7ing
+5ed
+4re
+6d
+6s
+5ing
+4x
+5ed
+6s
+5ing
+3lame
+7d
+7s
+6ing
+4esh
+7ed
+8s
+7ing
+5urage
+9es
+4ower
+8ed
+8ing
+8s
+3old
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4rce
+7ability
+9le
+7d
+8ly
+7ment
+9nts
+7r
+8s
+7s
+6ing
+5est
+8ed
+8ing
+8s
+5m
+6ed
+6ing
+6s
+4uldered
+3rame
+7d
+7ment
+9nts
+7s
+6ing
+5nchise
+9sed
+9sement
+9ser
+9sers
+9ses
+9sing
+4ee
+6d
+7om
+9ed
+9ing
+9s
+6ing
+6s
+6ze
+8s
+7ing
+4osen
+5ze
+7n
+2g
+3age
+6d
+7ly
+6e
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+8ness
+9esses
+4ol
+6ed
+6ing
+6s
+4rland
+9ed
+9ing
+9s
+5rison
+9ned
+9ning
+9ns
+3ender
+8ed
+9r
+9rs
+8ing
+8ment
+9ents
+8s
+6rure
+9es
+6ure
+9s
+3ild
+6ed
+6ing
+6s
+5t
+4ne
+6d
+6er
+8ed
+8ing
+9ngs
+8s
+6r
+7ies
+7s
+7y
+6s
+5ing
+5ous
+4rd
+6ed
+6ing
+6le
+8d
+8s
+7ing
+6s
+5t
+3lacial
+9ly
+4ish
+7ed
+8s
+7ing
+4obe
+7d
+7s
+6ing
+5om
+7ed
+7ing
+7s
+4ut
+6s
+6ted
+7ing
+3obe
+6s
+4re
+6d
+6s
+5ge
+7d
+7ment
+9nts
+7s
+6ing
+5ing
+4uement
+9ts
+5led
+5ment
+9s
+3race
+7d
+7s
+6ing
+5ff
+7ed
+7ing
+7s
+6t
+7ation
+9ions
+7ed
+7ing
+7ment
+9nts
+7s
+5il
+7ed
+7ing
+7ment
+9nts
+7s
+6n
+7ed
+9ly
+9ness
+9nesses
+8r
+9s
+7ing
+7s
+5m
+6ma
+8s
+8tic
+7e
+8s
+7ic
+6s
+5sp
+7ed
+7ing
+7s
+5ve
+7d
+7n
+7r
+8ies
+8s
+8y
+7s
+6ing
+9s
+4enage
+9s
+4ieve
+8d
+8s
+7ing
+4oove
+8d
+8s
+7ing
+5ss
+7ed
+9ly
+8r
+9s
+8s
+7ing
+9gly
+7ment
+9nts
+3s
+3uard
+7ed
+7ing
+7s
+4lf
+6ed
+6ing
+6ment
+9ts
+6s
+5ph
+7ed
+7ing
+7s
+3yscope
+9s
+2halo
+6ed
+7s
+6ing
+6s
+4nce
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+7ve
+4rmonic
+9cal
+9cally
+3earse
+8d
+8s
+7ing
+6ten
+9ed
+9ing
+9s
+3unger
+8ed
+8ing
+8s
+3ydrite
+9s
+8ic
+6os
+8es
+7us
+4postasia
+9sias
+9tic
+9tise
+9tised
+9tises
+9tising
+9tize
+9tized
+9tizes
+9tizing
+2iac
+5s
+3gma
+6s
+6ta
+7ic
+9al
+9ally
+8se
+9ed
+9es
+9ing
+9t
+9ts
+8ze
+9ed
+9es
+9ing
+7ography
+3sle
+6d
+6s
+5ing
+2jamb
+6ed
+7ment
+9nts
+6ing
+6ment
+9ts
+6s
+3oin
+6der
+9s
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4y
+5able
+9ness
+9nesses
+8y
+5ed
+6r
+7s
+5ing
+5ment
+9s
+5s
+2kephalin
+9ne
+9nes
+9ns
+4rnel
+8led
+9ing
+8s
+3indle
+8d
+8r
+9s
+8s
+7ing
+2lace
+6d
+6ment
+9ts
+6s
+5ing
+4rd
+6ed
+6ing
+6s
+5ge
+7able
+7d
+8ly
+8ness
+9esses
+7ment
+9nts
+7n
+8ed
+8ing
+8s
+7r
+8s
+7s
+6ing
+3eve
+6ment
+9ts
+3ight
+7ed
+8n
+9ed
+9er
+9ers
+9ing
+9ment
+9ments
+9s
+7ing
+7s
+4nk
+6ed
+6ing
+6s
+4st
+6ed
+7e
+8s
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4t
+4ven
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+3ock
+6ed
+6ing
+6s
+3umine
+8d
+8s
+7ing
+2mesh
+6ed
+7s
+6ing
+6ment
+9ts
+4w
+5ed
+5ing
+5s
+3ities
+5y
+3ossed
+4ve
+6d
+6s
+5ing
+2nage
+6s
+3ead
+6ic
+6s
+5gon
+8al
+8s
+6ram
+9s
+5hedra
+9al
+9on
+9ons
+5ndrian
+8ous
+5style
+3oble
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+4g
+5s
+3ui
+5ed
+5s
+4ye
+6d
+6e
+5ing
+2odal
+3ki
+5dake
+9s
+5s
+5take
+9s
+3l
+4ase
+7s
+4ic
+4ogical
+7es
+7st
+9s
+6y
+4s
+3moties
+6y
+3phile
+8s
+3rm
+5ities
+7y
+5ous
+8ly
+8ness
+9esses
+3ses
+4is
+6es
+3ugh
+6s
+4nce
+7d
+7ment
+9nts
+7s
+6ing
+3w
+4s
+2phytotic
+3lane
+7d
+7s
+6ing
+3rint
+7s
+2queue
+7d
+7ing
+7s
+6ing
+4iration
+9ons
+6e
+7d
+7r
+8s
+7s
+6ies
+7ng
+6y
+2race
+6d
+6s
+5ing
+4ge
+6d
+7ly
+6ment
+9ts
+6s
+5ing
+4nckle
+9d
+9s
+8ing
+5ge
+7d
+7s
+6ing
+5k
+6ed
+6ing
+6s
+4pt
+6ure
+9d
+9s
+8ing
+4unge
+8d
+8s
+7ing
+4vish
+8ed
+9s
+8ing
+3egiment
+9ted
+9ting
+9ts
+6ster
+9red
+9ring
+9rs
+3heum
+7ed
+7ing
+7s
+3ich
+6ed
+7r
+8s
+7s
+6ing
+6ment
+9ts
+4dged
+4ng
+6ed
+6ing
+6s
+4ven
+3obe
+6d
+6r
+7s
+6s
+5ing
+4l
+5l
+6ed
+7e
+8s
+7r
+8s
+6ing
+6ment
+9ts
+6s
+5ment
+9s
+5s
+4ot
+6ed
+6ing
+6s
+4ugh
+7ed
+7ing
+7s
+5nd
+7ed
+7ing
+7s
+2s
+3ample
+8d
+8s
+7ing
+4nguinated
+9e
+9ed
+9es
+9ing
+4te
+3chedule
+9ed
+9es
+9ing
+4once
+8d
+8s
+7ing
+4roll
+8ed
+8ing
+8s
+3eal
+6ed
+6ing
+6s
+5m
+6ed
+6ing
+6s
+5r
+6ed
+6ing
+6s
+4mble
+8s
+4pulchre
+9red
+9res
+9ring
+4rf
+6ed
+6ing
+6ment
+9ts
+6s
+4w
+5ed
+5ing
+5s
+3heath
+8e
+9d
+9s
+8ing
+8s
+5ll
+7ed
+7ing
+7s
+6ter
+9ed
+9ing
+9s
+4ield
+8ed
+8ing
+8s
+4rine
+8d
+8e
+9s
+8ment
+9ents
+8s
+7ing
+5oud
+8ed
+8ing
+8s
+3iform
+4gn
+6cies
+7y
+6ed
+6ing
+6s
+7hip
+9ps
+4labilities
+9ity
+6ge
+8d
+8ing
+8s
+7ing
+5e
+6d
+6s
+5ing
+3kied
+6s
+4y
+5ed
+5ing
+3lave
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+3nare
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+6l
+7ed
+7ing
+7s
+3orcel
+8ed
+8ing
+8l
+9ed
+9ing
+9ment
+9ments
+9s
+8s
+4ul
+6ed
+6ing
+6ment
+9ts
+6s
+3phere
+8d
+8s
+7ing
+3tamp
+7ed
+7ing
+7s
+5tite
+9s
+4eep
+7ed
+7ing
+7s
+4ructured
+4yle
+7d
+7s
+6ing
+3ue
+5d
+5s
+4ing
+4re
+6d
+6r
+7s
+6s
+5ing
+3wathe
+8d
+8ment
+9ents
+8s
+7ing
+4eep
+7ing
+7s
+5pt
+2tablature
+9res
+6ement
+9nts
+4il
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4me
+6ba
+8e
+8s
+6d
+6s
+5ing
+5oeba
+9e
+9s
+4ngle
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+4ses
+5ia
+7s
+6s
+5tic
+4yle
+7d
+7s
+6ing
+3elechies
+8y
+5lus
+8es
+4nder
+8ed
+8ing
+8s
+5te
+7s
+4r
+5a
+6ble
+6l
+7ly
+6te
+5chaunge
+9nged
+9nges
+9nging
+5deale
+9ed
+9es
+9ing
+5ectomies
+9my
+6d
+6r
+7s
+5ic
+7s
+6ng
+8s
+6tides
+8s
+9es
+5obacteria
+9terial
+9terium
+7iases
+9sis
+6cele
+9es
+8nteses
+9tesis
+7occal
+9ci
+9cus
+8el
+9le
+9les
+9lic
+9lous
+9ls
+8litis
+9itises
+6gastrone
+9trones
+6hepatitis
+6kinase
+9ases
+6lith
+9hs
+6n
+7s
+6pathies
+9hy
+7neust
+9ustal
+9usts
+7toses
+9sis
+6stomal
+9mies
+9my
+6tomies
+9y
+8xin
+9ins
+6viral
+9us
+9uses
+5prise
+9ed
+9er
+9ers
+9es
+9ing
+9ingly
+5s
+5tain
+9ed
+9er
+9ers
+9ing
+9ingly
+9ings
+9ment
+9ments
+9s
+7ke
+9n
+9s
+8ing
+6issued
+6ook
+4te
+6e
+3halpies
+7y
+4etic
+4ral
+7dom
+9ms
+7l
+8ed
+9r
+9rs
+8ing
+8ment
+9ents
+8s
+7ment
+9nts
+7s
+5one
+8d
+8ment
+9ents
+8s
+7ing
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+4use
+7d
+7s
+6iasm
+9ms
+9t
+9tic
+9tical
+9ts
+7ng
+4ymematic
+9tical
+8e
+9s
+3ia
+4ce
+6able
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+8ness
+9esses
+8s
+4re
+6ly
+6ness
+9ses
+6s
+6ties
+7y
+4tative
+5ies
+5le
+7d
+7ment
+9nts
+7s
+6ing
+5y
+3oblast
+9ic
+9s
+4derm
+8al
+8ic
+8s
+4il
+6ed
+6ing
+6ment
+9ts
+6s
+4mb
+6ed
+6ing
+6ment
+9ts
+6s
+5ic
+5ofauna
+9nae
+9nas
+6logic
+9ical
+9ically
+9ies
+9ise
+9ised
+9ises
+9ising
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+9y
+6phagies
+9gous
+9gy
+8ilies
+9lous
+9ly
+6stracan
+9acans
+9acous
+4phytal
+8e
+9s
+8ic
+8ous
+5ic
+5lastra
+9ral
+9ron
+5roct
+9s
+5tic
+8s
+4tic
+4urage
+9s
+4zoa
+7l
+7n
+8s
+6ic
+6on
+3rail
+7ed
+7ing
+7s
+6n
+7ed
+8ment
+9ents
+8r
+9s
+7ing
+7ment
+9nts
+7s
+5ll
+7es
+5mmel
+9led
+9ling
+9s
+5nce
+8d
+8ment
+9ents
+8s
+8way
+9ays
+7ing
+9gly
+6t
+7s
+5p
+6ment
+9ts
+6ped
+8r
+9s
+7ing
+6s
+4easure
+9ed
+9es
+9ing
+6t
+7able
+7ed
+7ies
+8ng
+9gly
+8ve
+7ment
+9nts
+7s
+7y
+5chat
+9s
+6ote
+9s
+5e
+6s
+5mes
+8se
+9es
+7ts
+5nch
+8ed
+9r
+9rs
+9s
+8ing
+8ment
+9ents
+5pot
+8s
+6reneur
+9eurial
+9eurs
+9euse
+9euses
+5sol
+8s
+5z
+4ies
+5sm
+7s
+6t
+7s
+4old
+5pic
+8ally
+7es
+7on
+9s
+7um
+9s
+6y
+4ust
+7ed
+7ing
+7ment
+9nts
+7s
+4y
+5ism
+8s
+7t
+8s
+5way
+8s
+3wine
+7d
+7ment
+9nts
+7s
+6ing
+5st
+7ed
+7ing
+7s
+2ucleate
+9d
+9s
+8ing
+9on
+9ons
+3f
+3merabilities
+9lity
+8le
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+3nciable
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9vely
+8or
+9rs
+9ry
+3re
+5d
+6ness
+9ses
+5ment
+9s
+5s
+6es
+6is
+8es
+5tic
+8s
+4ing
+4n
+5ed
+5ing
+5s
+2vassal
+8led
+9ing
+8s
+4ult
+7ed
+7ing
+7s
+3eigle
+8d
+8s
+7ing
+4lop
+7e
+8d
+8r
+9s
+8s
+7ing
+7ment
+9nts
+7s
+4nom
+7ed
+7ing
+8sation
+9ations
+8zation
+9ations
+7s
+4rmeil
+9ed
+9ing
+9s
+3iable
+8ness
+9esses
+7y
+4ed
+5r
+6s
+5s
+4ous
+7ly
+7ness
+9sses
+4ro
+6n
+7ed
+7ics
+8ng
+7ment
+9ntal
+9ntally
+9nts
+7s
+6s
+4sage
+8d
+8ment
+9ents
+8s
+7ing
+5ion
+8ed
+8ing
+8s
+3oi
+5s
+4y
+5s
+6hip
+9s
+3y
+4ing
+7ly
+7s
+2wall
+6ed
+6ing
+6ow
+8ed
+8ing
+8s
+6s
+3heel
+7ed
+7ing
+7s
+3ind
+6ing
+6s
+3omb
+6ed
+6ing
+6s
+4und
+3rap
+6ment
+9ts
+6ped
+7ing
+9gs
+6s
+4eath
+8e
+9d
+9s
+8ing
+8s
+2zian
+6s
+3one
+6d
+6s
+5ing
+4otic
+8ally
+8s
+3ym
+5atic
+9ally
+5e
+6s
+5ic
+7ally
+5ological
+9ies
+9ist
+9ists
+9y
+7yses
+9is
+8tic
+5s
+1oan
+2biont
+7s
+2cene
+2hippus
+8es
+2lian
+4enne
+8s
+4pile
+8s
+4th
+6ic
+6s
+3opile
+8s
+2n
+3ian
+4sm
+6s
+3s
+2rl
+4s
+2sin
+5e
+6s
+5ic
+5ophil
+9le
+9les
+9lia
+9lias
+9lic
+9lous
+9ls
+5s
+2then
+1pacrid
+7s
+6s
+7es
+4t
+5s
+3enetic
+3goge
+7s
+6ic
+5menal
+3nadiploses
+9osis
+5lepses
+9is
+8tic
+5phora
+9al
+9as
+4odos
+8es
+5rthoses
+9sis
+9tic
+3rch
+6ate
+9s
+6ial
+7es
+6s
+6y
+3tant
+3ule
+6ment
+9ts
+6s
+6t
+7s
+7te
+9d
+9s
+3xial
+3zote
+7s
+2edaphic
+3e
+4ist
+7s
+4s
+3ira
+6s
+5ic
+6d
+7s
+5ogeneses
+9esis
+9etic
+9ic
+9ically
+9ies
+9y
+3ncephala
+9lic
+9lon
+9lons
+4dyma
+8l
+8s
+4theses
+8is
+7tic
+3olatries
+8y
+3rdu
+6e
+4gne
+7s
+3xegeses
+8is
+7tic
+9cal
+9cally
+2ha
+4h
+5s
+4s
+3ebe
+6s
+5i
+6c
+5oi
+6philia
+9lias
+6s
+5us
+4dra
+7s
+6in
+8e
+9s
+8s
+4lides
+6s
+4mera
+8e
+8l
+9ities
+9ity
+9ly
+9ness
+9nesses
+9s
+8s
+7id
+9es
+9ian
+9s
+8s
+9t
+9ts
+7on
+9s
+8pteran
+9terans
+8us
+3ialtes
+3od
+5s
+4r
+5al
+7ties
+8y
+6te
+8s
+5i
+5s
+2ibioses
+7is
+6tic
+4last
+8ic
+8s
+5em
+7s
+4olic
+7es
+6y
+3c
+4al
+6ly
+6yces
+7x
+8es
+5nthi
+9c
+8us
+5rdia
+9c
+9l
+8um
+6p
+7s
+4ede
+7s
+6ia
+8l
+8n
+7um
+5ne
+7s
+6ism
+9s
+6ter
+9s
+7ra
+9l
+8e
+9s
+8um
+4heirema
+9mas
+5lorohydrin
+4ier
+7s
+5sm
+7s
+6t
+7s
+4leses
+7is
+5ike
+4ondyle
+9es
+9itis
+9itises
+6tinental
+5rmic
+5tyl
+8s
+4rania
+8um
+5ises
+7is
+6tic
+4s
+4ure
+7an
+9ism
+9isms
+9s
+7s
+6ise
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+5ticle
+9es
+8ular
+4ycle
+8s
+7ic
+9al
+7oid
+9dal
+9ds
+3deictic
+9cal
+5mic
+8al
+9lly
+8ities
+9ty
+8s
+7ologic
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+5ndrone
+9nes
+8um
+9ms
+5rm
+7al
+7ic
+8s
+9es
+7oid
+8lyses
+9ysis
+7s
+4iascope
+9pes
+5ctic
+5dymal
+8ides
+9s
+9tes
+9tides
+9tis
+9tises
+5orite
+9es
+4osite
+9s
+5te
+7s
+6ic
+7sation
+9tions
+8ed
+7zation
+9tions
+8ed
+4ural
+8s
+3fauna
+8e
+8l
+8s
+4ocal
+3gaeal
+7n
+6ous
+5mic
+5stria
+9al
+9c
+9um
+4eal
+6n
+5ic
+5ne
+7ses
+8is
+9st
+9sts
+7tic
+9cally
+9cist
+9cists
+9cs
+6ic
+7st
+9s
+6ous
+5ous
+4lottal
+8ic
+9des
+9s
+9ses
+4nathous
+4on
+6e
+7s
+6i
+7c
+7sm
+9s
+6ous
+6s
+6us
+4ram
+7matic
+9tical
+9tise
+9tised
+9tiser
+9tisers
+9tises
+9tising
+9tism
+9tisms
+9tist
+9tists
+9tize
+9tized
+9tizer
+9tizers
+9tizes
+9tizing
+7s
+6ph
+8ed
+9r
+9rs
+8ic
+9cal
+9cally
+9es
+9ng
+9st
+9sts
+8s
+8y
+4ynies
+6ous
+6y
+3late
+7d
+7s
+6ing
+7on
+9s
+6or
+8s
+4epsies
+7y
+6tic
+9al
+9ally
+9s
+8form
+7ogenic
+8id
+4imnia
+8on
+9ns
+5thic
+4obium
+9s
+5g
+6ic
+7se
+9d
+9s
+8ing
+8t
+9ic
+9s
+7ze
+9d
+9s
+8ing
+6s
+6ue
+8d
+8s
+7ing
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+3meletic
+5r
+6ase
+9s
+6e
+7s
+6ic
+7se
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+6s
+4orphic
+8oses
+9sis
+4ysia
+7um
+3naoi
+6s
+5stic
+9ally
+8es
+7y
+4ephrin
+9ne
+9nes
+9ns
+5ural
+7ia
+9l
+8um
+9ms
+4ician
+7on
+9s
+5kian
+7on
+9s
+4osic
+3pelagic
+5talous
+4hanic
+8es
+7ous
+7y
+5enomena
+9enal
+9enally
+9enon
+5onema
+9as
+5ragm
+9s
+5yllous
+6seal
+8s
+7ial
+8s
+6tal
+7e
+8s
+7ic
+9al
+9ally
+8sm
+9ms
+7ologies
+9ogy
+8tic
+9ics
+4lastra
+9al
+9on
+5oic
+6on
+8s
+4olic
+7sm
+9s
+3rogenetic
+8ic
+9es
+8y
+4rhema
+9s
+9tic
+3scia
+7s
+5opacies
+9y
+8l
+9ian
+9ianism
+9ians
+9ism
+9isms
+9ly
+8nt
+9ts
+8te
+9ed
+9es
+9ing
+7e
+8s
+7ies
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7y
+4ematic
+6on
+8s
+5palous
+4iotomies
+9y
+4odal
+6e
+7s
+6ial
+7c
+8al
+9lly
+5mal
+8ly
+6e
+7s
+4pastic
+9cs
+5erm
+8s
+5ore
+8s
+4tases
+7ies
+8s
+7y
+6tic
+6xes
+7is
+9es
+5emic
+9ally
+9s
+7ological
+9ogies
+9ogist
+9ogists
+9ogy
+6rna
+9l
+8um
+9ms
+5ilbite
+9tes
+5le
+7d
+7r
+8s
+7s
+6ing
+5olarian
+9ians
+9ies
+9y
+8tory
+7er
+9s
+8t
+9s
+7ic
+9al
+8se
+9ed
+9es
+9ing
+9t
+9ts
+8ze
+9ed
+9es
+9ing
+7ography
+6me
+8s
+5rophe
+9es
+5yle
+8s
+3taph
+7ed
+8r
+9s
+7ial
+9n
+8c
+8ng
+8st
+9ts
+7s
+5ses
+6is
+5xes
+6ial
+9ly
+7c
+7es
+7s
+6y
+4halamia
+9ic
+9ion
+9ium
+9iums
+5eca
+8e
+6lia
+9l
+9lise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+8oid
+9ma
+9mas
+9mata
+9matous
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8um
+9ms
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+6m
+7a
+8ta
+7s
+6rmal
+6ses
+7is
+6t
+7ed
+7ic
+9al
+9ally
+8ng
+7on
+9s
+7s
+5ymetic
+4ome
+7s
+6ic
+8al
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8t
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+5nic
+5pe
+7s
+4rachelion
+9lions
+5ite
+8s
+5ochoid
+9ids
+3zeuxes
+7is
+9es
+4oa
+6n
+7s
+5ic
+6sm
+8s
+6te
+8s
+5on
+6tic
+9ally
+9s
+8es
+8ologic
+9logies
+9logy
+7y
+2och
+5a
+6l
+7ly
+6s
+5s
+3de
+5s
+4ic
+3nychium
+9ms
+5m
+6ic
+7es
+6ous
+9ly
+6s
+6y
+3pee
+6s
+4oeia
+8s
+4t
+5s
+3s
+4es
+3xidation
+9ons
+6e
+7s
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+5ed
+6s
+4y
+5ed
+5ing
+2ris
+5e
+3ouvette
+9es
+2silon
+7ic
+7s
+3omite
+8s
+2uise
+6e
+3lary
+5tion
+9s
+4ides
+5s
+6es
+4otic
+8s
+3rate
+7d
+7s
+6ing
+7on
+9s
+2yllia
+6on
+8s
+1quabilities
+9y
+5le
+7ness
+9sses
+6y
+4l
+5ed
+5i
+6ng
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+6tarian
+9ianism
+9ians
+7ies
+7y
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5led
+6ing
+6y
+5ness
+9es
+5s
+4nimities
+9y
+7ous
+9sly
+5t
+6s
+4tabilities
+9ity
+7le
+5e
+6d
+6s
+5ing
+6on
+8al
+9lly
+8s
+6ve
+5or
+7ial
+9lly
+9ls
+7s
+7ward
+3erries
+6y
+4strian
+9nism
+9nisms
+9ns
+8enne
+9nnes
+3iangular
+9arity
+4balance
+9ced
+9ces
+9cing
+4caloric
+4d
+5ifferent
+6stance
+9nces
+9nt
+9ntly
+5s
+4final
+9ly
+4lateral
+9ally
+9als
+5ibrant
+9nts
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+9tory
+8ia
+9st
+9stic
+9sts
+9ties
+9ty
+9um
+9ums
+4molal
+8r
+7ecular
+5ultiple
+9ples
+4nal
+5e
+6ly
+6s
+5ia
+7s
+6ties
+7y
+5octial
+9ally
+9als
+6x
+7es
+5umerous
+4p
+5age
+8d
+8s
+7ing
+6rate
+9ed
+9es
+9ing
+9ion
+9ions
+7tition
+9tions
+5e
+6s
+5ment
+9s
+5oise
+9d
+9s
+8ing
+6llence
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9nts
+6nderance
+9rances
+9rancy
+9rant
+9rate
+9rated
+9rates
+9rating
+6tent
+9tial
+9tials
+5ped
+7r
+8s
+6ing
+5robability
+9ble
+5s
+4seta
+8ceous
+7ic
+8form
+7um
+9s
+4tabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6nt
+6tion
+9ns
+5es
+5ies
+5y
+4valence
+9ces
+9cies
+9cy
+9t
+9tly
+9ts
+7ve
+5ocal
+9ities
+9ity
+9ly
+9ness
+9nesses
+8te
+9ed
+9es
+9ing
+9ingly
+9ion
+9ions
+9or
+9ors
+9ory
+6ke
+8s
+6que
+9s
+1r
+2a
+3diate
+8d
+8s
+7ing
+8on
+9ns
+5cable
+9y
+7nt
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+3s
+4abilities
+9ty
+6le
+4e
+5d
+5ment
+9s
+5r
+6s
+5s
+4ing
+5on
+7s
+4ure
+7s
+3them
+7s
+2bia
+5s
+4um
+6s
+2e
+3ct
+5able
+5ed
+6r
+7s
+5ile
+7ities
+9y
+6ng
+6on
+8s
+6ve
+5ly
+5ness
+9es
+5or
+7s
+5s
+3d
+3long
+3macauses
+9is
+4ic
+5tal
+6e
+7s
+6ic
+8al
+7sh
+8m
+9s
+4uri
+6us
+8es
+3now
+3psin
+7s
+3s
+3thic
+6sm
+8ic
+8s
+7tic
+6tic
+3v
+4s
+3while
+8s
+2f
+2g
+3astic
+6oplasm
+9asmic
+9asms
+4tandromorph
+7er
+9s
+5e
+6s
+5ive
+8s
+7ities
+9y
+5ocracies
+9cy
+6gyne
+9es
+6id
+6morph
+9phic
+9phs
+3o
+4dic
+7ities
+9y
+4genic
+5ram
+8s
+7ph
+9s
+4mania
+9c
+9cs
+9s
+5eter
+9s
+7ric
+9es
+8y
+4n
+5omic
+9ally
+9s
+8st
+9ts
+6vine
+9es
+5s
+4phobia
+9as
+4s
+5terol
+9ls
+4t
+5amine
+9es
+5ic
+6se
+8d
+8s
+7ing
+7m
+8s
+6ze
+8d
+8s
+7ing
+5s
+3s
+2hu
+4s
+2iach
+6s
+3c
+4a
+5ceous
+5s
+4k
+5s
+4oid
+4s
+3geron
+8s
+3naceous
+4g
+5o
+6es
+6s
+4ite
+7s
+4us
+6es
+3ometer
+9s
+4nite
+8s
+4phorous
+8um
+9ms
+6yid
+9s
+4stemon
+9ns
+3stic
+7al
+9ly
+7s
+2k
+3s
+2lang
+6s
+3king
+7s
+2m
+3elin
+7s
+3ine
+6d
+6s
+2n
+3e
+4d
+4s
+3ing
+3s
+2odable
+4e
+5d
+5nt
+7s
+5s
+4ibilities
+9ty
+6le
+5ng
+5um
+7s
+3geneities
+9y
+6ic
+6ous
+3s
+4e
+5ly
+5s
+4ible
+5on
+7al
+9ly
+7s
+5ve
+7ness
+9sses
+6ities
+8y
+4trate
+3tema
+7s
+6e
+7s
+5ses
+6is
+5tic
+4isation
+9ons
+6e
+5ze
+7d
+7s
+6ing
+4ogenic
+8ous
+5logical
+9es
+9st
+9sts
+8y
+5mania
+9ac
+9acs
+9as
+5phobia
+9ias
+2r
+3able
+4ncies
+6y
+5d
+6s
+5t
+6ly
+6ries
+7y
+6s
+4ta
+6s
+5ic
+7al
+9ly
+7ism
+9ms
+7s
+5um
+3ed
+3hine
+7s
+3ing
+6ly
+6s
+3oneous
+9ly
+9ness
+9nesses
+4r
+5ist
+8s
+5less
+5s
+3s
+2s
+3atz
+6es
+3es
+3t
+4while
+2ubescence
+9ces
+9cies
+9cy
+9t
+7ite
+9es
+3cic
+5form
+4t
+5ate
+8d
+8s
+7ing
+8on
+9ns
+8ve
+5ed
+5ing
+5s
+3dite
+7ly
+7ness
+9sses
+7s
+6ion
+9s
+3go
+5s
+3mpent
+3pt
+5ed
+5ible
+6ng
+6on
+8al
+8s
+6ve
+8ly
+8ness
+9esses
+8s
+7ities
+9y
+5s
+3v
+4im
+5n
+4s
+2valenta
+9s
+3en
+3il
+5s
+2yngium
+8s
+5o
+6es
+6s
+3sipelas
+9ses
+9tous
+8oid
+9ids
+3thema
+8l
+8s
+8tic
+9ous
+7ic
+5orbate
+9tes
+5raemia
+9ias
+6emia
+9as
+6ina
+9s
+7sm
+9al
+9s
+8tic
+7te
+9s
+8ic
+8ol
+9ls
+6oblast
+9astic
+9asts
+7cyte
+9tes
+9tic
+7id
+7melalgia
+8ycin
+9cins
+7n
+8ium
+9ums
+8s
+7penia
+9nias
+8hobia
+9obias
+8oieses
+9iesis
+9ietic
+9ietin
+9ietins
+8sia
+9ias
+7sin
+9ne
+9nes
+9ns
+1s
+2cabeche
+9s
+4drille
+9es
+4lade
+8d
+8r
+9s
+8s
+7ing
+7o
+8es
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+9y
+5ier
+8s
+5lonia
+9as
+7p
+8ed
+8ing
+8s
+5op
+7e
+8d
+8s
+7ing
+7s
+4motage
+9es
+4pable
+6de
+8s
+7o
+8es
+5e
+6d
+6e
+7s
+6less
+6ment
+9ts
+6r
+7s
+6s
+5ing
+6sm
+8s
+7t
+8s
+5ologies
+9ist
+9ists
+9y
+4r
+5got
+8s
+5mouche
+9hes
+5ole
+8s
+5p
+6ed
+6ing
+6ment
+9ts
+6s
+5s
+3halot
+8s
+5r
+6otic
+9cs
+6s
+5tologic
+9gical
+9gies
+9gist
+9gists
+9gy
+7n
+4eat
+7able
+8ge
+9es
+7ed
+7ing
+7ment
+9nts
+7or
+9s
+7s
+5w
+6al
+8s
+6ed
+7r
+8s
+6ing
+6s
+4scholtzia
+9tzias
+9zia
+9zias
+3landre
+9s
+3olar
+7s
+4pette
+9s
+4rtage
+9s
+6ed
+6ing
+6s
+4t
+5ed
+5ing
+5s
+5ted
+6ing
+3ribano
+9s
+6e
+7d
+7s
+6ing
+5toire
+9es
+7rial
+4oc
+6s
+5l
+6l
+7s
+6s
+5w
+6ed
+6ing
+6s
+3uage
+7s
+4do
+6s
+4lent
+8s
+4tcheon
+9ned
+9ns
+2emplasies
+8tic
+9ically
+8y
+3rine
+7s
+3s
+2ile
+5s
+2kar
+5s
+3er
+5s
+3ies
+3y
+2loin
+6ed
+6ing
+6s
+4yne
+7d
+7s
+6ing
+2ne
+4cies
+5y
+4s
+2ophageal
+7i
+7oscope
+9copes
+7us
+9es
+3teric
+8a
+9lly
+8ism
+9sms
+9st
+9sts
+7es
+7sm
+9s
+6y
+4ropia
+9s
+8c
+2pada
+6s
+5rille
+9es
+4gnole
+9s
+9tte
+9ttes
+4lier
+8ed
+8ing
+8s
+4nol
+7es
+4rto
+7s
+3ecial
+8ly
+4rance
+9s
+3ial
+6s
+4ed
+5gle
+8rie
+9ies
+5r
+6s
+5s
+4onage
+9s
+3lanade
+9s
+3ousal
+8s
+6e
+7d
+7r
+8s
+7s
+6ing
+3ressivo
+7o
+8s
+4it
+6s
+3umoso
+8s
+3y
+4ing
+2quire
+7d
+7s
+8s
+9es
+6ing
+5sse
+8s
+2s
+3ay
+5ed
+6r
+7s
+6tte
+9s
+5ing
+6sh
+7t
+8ic
+8s
+5s
+3e
+4nce
+7s
+5tial
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9ists
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+9ly
+9ness
+9nesses
+9s
+4s
+3ive
+6s
+3oin
+6er
+8s
+6s
+4nite
+8s
+4yne
+7s
+2t
+3ablish
+9able
+9ed
+9er
+9ers
+9es
+9ing
+9ment
+9ments
+4cade
+8s
+4fette
+9s
+4minet
+9s
+4ncia
+8s
+7ero
+9os
+4te
+6d
+6s
+7man
+8en
+5ing
+3eem
+6ed
+6ing
+6s
+4r
+5ase
+8s
+5ification
+9ations
+8ed
+9s
+7y
+8ing
+5s
+3heses
+6ia
+8s
+7ogen
+9ens
+7s
+8es
+5te
+7s
+6ic
+8al
+9lly
+8ian
+9ans
+9sm
+9sms
+8s
+3imable
+9ness
+9nesses
+8y
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+4pulate
+4val
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+3oc
+5s
+4ile
+7s
+4p
+5page
+9s
+6ed
+7l
+8s
+6ing
+5s
+4ver
+7s
+3rade
+7s
+6iol
+9s
+5gon
+8s
+5l
+5mazone
+9nes
+5nge
+8d
+9ness
+9nesses
+8lo
+9os
+8ment
+9ents
+8r
+9s
+8s
+7helo
+9los
+7ing
+5pade
+9s
+5y
+6ed
+6ing
+6s
+4eat
+7ed
+7ing
+7s
+5pe
+7d
+7ment
+9nts
+7s
+6ing
+4ich
+7es
+5dge
+8s
+5ldid
+9s
+5n
+6s
+5ol
+7s
+4o
+5gen
+8ic
+9cally
+8s
+5ne
+7s
+5s
+5us
+4ual
+5m
+6s
+5s
+6es
+3s
+3uarial
+8n
+7es
+7ne
+6y
+2urience
+9s
+8ies
+8y
+7t
+8ly
+1t
+2a
+3cism
+7s
+3erio
+7s
+3ge
+5re
+7s
+5s
+3lage
+7s
+4on
+6s
+3min
+6e
+7s
+6s
+3pe
+5s
+3s
+3t
+4ism
+7e
+8s
+7s
+6t
+7e
+8s
+4s
+2cetera
+8s
+3h
+4ant
+7s
+4ed
+5r
+6s
+5s
+4ing
+7s
+2en
+4s
+3pimeletic
+3rnal
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9t
+9ts
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7ness
+9sses
+7s
+5e
+5isation
+9ions
+7e
+8d
+8s
+7ing
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8s
+7ing
+3sian
+7s
+2h
+3al
+5s
+4mbutol
+9ls
+4nal
+7s
+5e
+6dioic
+9l
+9ls
+6s
+5oate
+9s
+6ic
+6l
+7amine
+9ines
+7s
+6yl
+8s
+3e
+4ne
+6s
+4ostomine
+4phon
+8s
+4r
+5cap
+8s
+5eal
+8isation
+9se
+9sed
+9ses
+9sing
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8ness
+9esses
+6ous
+5ial
+6c
+7al
+6fication
+9ations
+8ed
+9s
+7y
+8ing
+6on
+8s
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7h
+7ing
+7m
+8s
+7t
+8s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5omania
+9iac
+9iacs
+9ias
+5s
+3ic
+5al
+7ities
+9y
+7ly
+7ness
+9sses
+7s
+5ian
+8s
+6se
+8d
+8s
+7ing
+7m
+8s
+7t
+8s
+6ze
+8d
+8s
+7ing
+5s
+4nyl
+7s
+4on
+6amide
+9des
+6ine
+9s
+6s
+5ps
+7es
+3moid
+7al
+7s
+3narch
+8ies
+8s
+8y
+4ic
+6al
+8ly
+6ism
+9s
+7ties
+8y
+6s
+4obiologies
+9ogy
+6otanical
+9nies
+9nist
+9nists
+9ny
+5centric
+9ricity
+9rism
+9risms
+6ide
+9s
+5genic
+9es
+9st
+9sts
+8y
+6rapher
+9hers
+9hic
+9hica
+9hical
+9hies
+9hy
+5historian
+9orians
+9oric
+9orical
+9ories
+9ory
+5linguist
+9uistic
+9uists
+6ogic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+5medicine
+9cines
+6usicology
+5nym
+8s
+5s
+6cience
+9nces
+6es
+3ogram
+8s
+4logic
+9al
+9ally
+8es
+8st
+9ts
+7y
+4none
+8s
+4s
+5es
+4xide
+8s
+6es
+5y
+6ethane
+9anes
+6l
+7s
+3s
+3yl
+5amine
+9es
+6te
+8d
+8s
+7ing
+8on
+9ns
+5benzene
+9enes
+5ene
+8s
+7ic
+5ic
+5s
+4ne
+6s
+5yl
+7s
+2ic
+3olate
+8d
+8s
+7ing
+8on
+9ns
+5in
+7s
+5ogic
+9al
+9ally
+8es
+8st
+9ts
+7y
+3quette
+9s
+2na
+4s
+2oile
+6s
+3nogestrel
+9rels
+3uffee
+8s
+4rderie
+9es
+6i
+7e
+2ranger
+8e
+9s
+8s
+3enne
+7s
+3ier
+6s
+2tercap
+8s
+3in
+5s
+3le
+5d
+5s
+4ing
+2ude
+5s
+3i
+4s
+2wee
+5s
+2yma
+4ic
+4ologica
+9cal
+9cally
+9con
+9cum
+9es
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+8y
+5n
+6s
+3pic
+6al
+1ubacteria
+9um
+2cain
+6e
+7s
+6s
+4lypt
+8i
+8ol
+9le
+9les
+9ls
+8s
+8us
+9ses
+4ryon
+8s
+7t
+8e
+9s
+8ic
+8s
+3haris
+8es
+8tic
+4loric
+8n
+9e
+9es
+9s
+4ologia
+9es
+9on
+8y
+4re
+6d
+6s
+5ing
+5omatic
+9in
+9ins
+3lase
+7s
+4idean
+6ian
+3rite
+7s
+6ic
+4yphia
+9s
+3yclic
+2daemon
+8ia
+9as
+9c
+9cs
+9es
+9sm
+9sms
+9st
+9stic
+9stical
+9sts
+8s
+8y
+4imon
+8ism
+9sms
+8s
+3emon
+7ia
+9s
+8c
+9s
+8sm
+9ms
+9t
+9tic
+9tical
+9ts
+7s
+3ialyte
+9s
+4cotyledon
+9edons
+4ometer
+9rs
+8ric
+9ical
+9ically
+9ies
+9y
+2garie
+7s
+3e
+4necist
+9ts
+5ia
+7s
+6c
+7al
+9ly
+7ist
+9ts
+7s
+6sm
+8s
+7t
+8s
+5ol
+7s
+4osynclinal
+9line
+9lines
+3h
+4en
+4s
+3lena
+7s
+6id
+8s
+6oid
+9s
+4obulin
+9ns
+2harmonic
+3emerise
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ze
+9ed
+9es
+9ing
+2k
+3aryon
+8s
+7t
+8e
+9s
+8ic
+8s
+3ed
+3ing
+3s
+2lachan
+8s
+6on
+8s
+3ogia
+7e
+7s
+6es
+6se
+8d
+8r
+9s
+8s
+7ing
+7t
+8ic
+9cal
+9cally
+8s
+6um
+8s
+6ze
+8d
+8r
+9s
+8s
+7ing
+5y
+2melanin
+9s
+4rism
+8s
+3ong
+6s
+3ung
+6s
+2nuchise
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+6oid
+9ism
+9isms
+9s
+6s
+2oi
+3nymin
+8s
+6us
+8es
+3uae
+6s
+2pad
+5s
+4torium
+9ms
+5rid
+8ae
+8s
+3epsia
+8s
+7es
+6y
+5tic
+8ities
+9ty
+3hausiacean
+9ceans
+8d
+9s
+8id
+9ds
+4emise
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ically
+9s
+7ze
+9d
+9r
+9rs
+9s
+8ing
+5nic
+8s
+4obia
+8s
+5n
+6ia
+8s
+7c
+8al
+9lly
+7es
+7ous
+9sly
+9sness
+7se
+9d
+9s
+8ing
+8m
+9s
+7um
+9s
+7ze
+9d
+9s
+8ing
+6s
+6y
+5rbia
+9ceous
+9s
+8um
+9ms
+6ia
+8nt
+9ts
+8s
+7c
+8ally
+7es
+6y
+5tic
+4rasia
+9s
+8es
+7y
+5oe
+7s
+4uise
+8d
+8s
+7ing
+7m
+8s
+7t
+8ic
+9cal
+9cally
+8s
+6ze
+8d
+8s
+7ing
+3lastic
+9s
+4oid
+7ies
+7s
+7y
+3nea
+6s
+5ic
+4oea
+7s
+6ic
+2reka
+6s
+3hythmic
+9cal
+9cs
+9es
+9st
+9sts
+8y
+3ipi
+5us
+7es
+3o
+4bond
+8s
+4cheque
+9es
+5rat
+8s
+6eep
+9s
+5urrencies
+9ncy
+4deposit
+9its
+5ollar
+9rs
+4kies
+5ous
+5y
+4market
+9ts
+4note
+8s
+4phile
+9s
+8ia
+9as
+6obia
+9as
+9c
+5ium
+8s
+5op
+7s
+4s
+4terminal
+9nals
+3ybath
+8ic
+8s
+4haline
+4okies
+6ous
+6y
+4pterid
+9ds
+8oid
+9ids
+4therm
+9al
+9ic
+9ous
+9s
+6mic
+9al
+9s
+8es
+7y
+5opic
+2social
+4l
+5s
+3porangiate
+3tacies
+6y
+5sies
+6y
+5tic
+8ally
+4ele
+7s
+4yle
+7s
+2taxia
+7s
+6es
+6te
+8s
+7ic
+5y
+3ectic
+8s
+6oid
+9s
+4xia
+7s
+3hanase
+9d
+9s
+8ia
+9as
+9ast
+9asts
+9c
+9es
+9ng
+8y
+7tise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+7ze
+9d
+9s
+8ing
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+4enics
+7st
+9s
+5rian
+9s
+4ymia
+8s
+5roid
+9s
+3rapelia
+9as
+9es
+8y
+4ophic
+9ation
+9ations
+8es
+7y
+6ic
+7es
+6ous
+6y
+2xenite
+8s
+1vacuant
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9es
+7or
+9s
+5ee
+7s
+3dable
+4e
+5d
+5r
+6s
+5s
+4ible
+5ng
+7ly
+3gation
+9s
+4inate
+9d
+9s
+8ing
+9on
+9ons
+3luable
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+3nesce
+8d
+8nce
+9ces
+9t
+9tly
+8s
+7ing
+4gel
+7iar
+9ries
+9rion
+9rions
+9rium
+9riums
+9rs
+9ry
+8c
+9al
+9alism
+9alisms
+9ally
+9alness
+9als
+9ism
+9isms
+8es
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9taries
+9tarion
+9tary
+9tic
+9ts
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7s
+7y
+4ish
+7ed
+8s
+7ing
+7ment
+9nts
+5tion
+9s
+3porabilities
+9lity
+8le
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+6imeter
+9ters
+7te
+9s
+8ic
+6ograph
+9aphs
+7meter
+9ters
+3sible
+5on
+7al
+7s
+5ve
+7ly
+7ness
+9sses
+2e
+3ction
+8al
+8s
+3jar
+6s
+3n
+4ed
+5ment
+9s
+5r
+6s
+5st
+4fall
+8s
+4handed
+9dly
+9dness
+4ing
+7s
+4ly
+4ness
+8es
+4s
+5ong
+8s
+4t
+5ed
+6r
+7s
+5ful
+8ly
+8ness
+9esses
+5ide
+8s
+6ng
+8s
+5less
+5rate
+9d
+9s
+8ing
+9on
+9ons
+5s
+5ual
+8ise
+9sed
+9ses
+9sing
+9ties
+9ty
+9ze
+9zed
+9zes
+9zing
+8ly
+7te
+9d
+9s
+8ing
+9on
+9ons
+3r
+4blooming
+4during
+4glade
+9s
+5reen
+9s
+4lasting
+9ngly
+9ngness
+9ngs
+4more
+4net
+7s
+4sible
+6on
+8s
+4t
+5ed
+5ing
+5or
+7s
+5s
+4where
+6ich
+4y
+5body
+5day
+8ness
+9esses
+8s
+5man
+6en
+5one
+5place
+5thing
+5way
+6hen
+9ce
+8re
+7ither
+6oman
+8en
+3s
+3t
+4s
+2hoe
+2ict
+5ed
+6e
+7s
+5ing
+6on
+8s
+5or
+7s
+5s
+3dence
+8d
+8s
+7ing
+6t
+7ial
+9lly
+9ry
+7ly
+7s
+3l
+4doer
+8s
+6ing
+9s
+4er
+5st
+4ler
+6st
+5y
+4ness
+8es
+4s
+3nce
+6d
+6ment
+9ts
+6s
+5ible
+8y
+6ng
+6ve
+3rate
+7d
+7s
+6ing
+3scerate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+3table
+5te
+7d
+7s
+6ing
+7on
+9s
+4e
+5d
+5rnal
+9ly
+7ities
+9y
+5s
+4ing
+2o
+3cable
+5te
+7d
+7s
+6ing
+7on
+9s
+7ve
+9ly
+9ness
+9nesses
+6or
+8s
+8y
+3e
+3he
+3ke
+5d
+5r
+6s
+5s
+4ing
+3lue
+6s
+5te
+7d
+7s
+6ing
+7on
+9al
+9arily
+9ary
+9ism
+9isms
+9ist
+9istic
+9ists
+9s
+7ve
+4vable
+5e
+6d
+6ment
+9ts
+6nt
+6r
+7s
+6s
+5ing
+3nymus
+8es
+3s
+3vae
+6s
+2ulgate
+8d
+8s
+7ing
+4se
+6d
+6s
+5ing
+6on
+8s
+2zone
+6s
+1we
+3r
+4s
+3s
+4t
+2ftes
+2ghen
+2how
+2k
+3ed
+3ing
+3s
+2t
+3s
+1x
+2abyte
+7s
+3cerbate
+9ed
+9es
+9ing
+9ion
+9ions
+7escence
+9cences
+4t
+5a
+6ble
+6s
+5ed
+6r
+7s
+6st
+5ing
+8ly
+8ness
+9esses
+6on
+8s
+6tude
+9es
+5ly
+5ment
+9s
+5ness
+9es
+5or
+7s
+5ress
+9es
+5s
+4um
+6s
+3ggerate
+9ed
+9edly
+9edness
+9es
+9ing
+9ingly
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+3hertz
+8es
+3lbuminous
+4t
+5ation
+9ns
+5ed
+7ly
+7ness
+9sses
+6r
+7s
+5ing
+5s
+3m
+4en
+6s
+4inabilities
+9lity
+8le
+7nt
+9s
+7te
+9s
+8ion
+9onal
+9ons
+8or
+9rs
+6e
+7d
+7e
+8s
+7r
+8s
+9hip
+9hips
+7s
+6ing
+4plar
+8s
+6e
+7d
+7s
+6ing
+4s
+3nimate
+8ion
+9ons
+4them
+8a
+9s
+9ta
+9tic
+9tous
+8s
+3pted
+5ive
+3rate
+6ion
+9s
+4ch
+6al
+7te
+9s
+6ies
+7st
+9s
+6s
+6y
+3sperate
+9ed
+9edly
+9er
+9ers
+9es
+9ing
+9ingly
+9ion
+9ions
+9ive
+9or
+9ors
+2camb
+6ed
+6ing
+7on
+9s
+7um
+9s
+6s
+4rnate
+9d
+9s
+8ing
+9on
+9ons
+4udate
+4vate
+8d
+8s
+7ing
+8on
+9nal
+9ns
+7or
+9s
+3eed
+6able
+6ed
+7r
+8s
+6ing
+9ly
+6s
+4l
+5led
+7nce
+9es
+9ies
+9y
+8t
+9ly
+6ing
+5s
+6ior
+9s
+4ntric
+9s
+4pt
+6ant
+9s
+6ed
+6ing
+7on
+9able
+9ably
+9al
+9alism
+9alisms
+9ality
+9ally
+9alness
+9als
+9s
+8us
+7ve
+6less
+6or
+8s
+6s
+4rpt
+7a
+7ed
+8r
+9s
+7ible
+8ng
+9gs
+8on
+9ns
+7or
+9s
+7s
+7um
+4ss
+6ed
+7s
+6ing
+7ve
+9ly
+9ness
+9nesses
+3hange
+8ability
+9ble
+9bly
+8d
+8r
+9s
+8s
+7ing
+4eat
+7s
+5quer
+9ed
+9ing
+9s
+3ide
+6d
+6s
+5ing
+4mer
+7s
+4pient
+9s
+5le
+7s
+4sable
+5e
+6d
+6man
+7en
+6s
+5ing
+6on
+8al
+8s
+4tabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6ncies
+8y
+7t
+8s
+6tion
+9ns
+8ve
+7ory
+5e
+6d
+7ly
+7ness
+9sses
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+5on
+7ic
+7s
+6r
+7s
+3laim
+7ed
+8r
+9s
+7ing
+7s
+5mation
+9onal
+9ons
+9ve
+8orily
+9ry
+5ustration
+9ations
+5ve
+7s
+4osure
+9s
+4udabilities
+9lity
+8le
+6e
+7d
+7e
+8s
+7r
+8s
+7s
+6ible
+7ng
+5sion
+9ary
+9ism
+9isms
+9ist
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+9s
+8ism
+9sms
+9st
+9sts
+9ties
+9ty
+6ory
+3ogitable
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+4mmunicable
+9cate
+9cated
+9cates
+9cating
+9cation
+9cative
+9cator
+9cators
+9catory
+9on
+9ons
+4riate
+9d
+9s
+8ing
+9on
+9ons
+5ticate
+9ted
+9tes
+9ting
+9tion
+9tions
+3rement
+9a
+9al
+9itial
+9itious
+9s
+9um
+5scence
+9ces
+9cies
+9cy
+9t
+9tial
+9tly
+5ta
+7l
+6e
+7d
+7r
+8s
+7s
+6ing
+7on
+9s
+7ve
+6ories
+8y
+4uciate
+9ed
+9es
+9ing
+9ingly
+9ion
+9ions
+3ubant
+4dit
+4lpable
+7te
+9d
+9s
+8ing
+9on
+9ons
+8ory
+4rrent
+5se
+7d
+7s
+6ing
+7on
+9ed
+9ing
+9ise
+9ised
+9ises
+9ising
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+9s
+7ve
+9ly
+9ness
+9nesses
+6us
+8es
+4sable
+9ness
+9nesses
+8y
+6l
+7s
+6tory
+5e
+6d
+6r
+7s
+6s
+5ing
+8ly
+6ve
+2eat
+5s
+3c
+4rable
+9ness
+9nesses
+8y
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+7or
+9s
+9y
+4s
+4utable
+9es
+7ncies
+9y
+8t
+9s
+7ries
+8y
+6e
+7d
+7r
+8s
+7s
+6ing
+7on
+9er
+9ers
+9s
+7ve
+9ly
+9s
+6or
+8ial
+8s
+9hip
+9hips
+8y
+6ress
+9ses
+7ices
+8es
+8x
+9es
+7y
+3d
+4ra
+6e
+3em
+5ed
+5ing
+5s
+3geses
+6is
+5te
+7s
+6ic
+8al
+9lly
+8s
+7st
+9s
+3me
+5d
+5s
+4ing
+4pla
+7r
+8ily
+9ness
+9nesses
+9ties
+9ty
+8s
+8y
+6e
+7s
+6ifiable
+9cation
+9cative
+9ed
+9er
+9ers
+9es
+8y
+9ing
+6um
+5t
+6ed
+6ing
+7on
+9s
+7ve
+6s
+3nterate
+9ed
+9es
+9ing
+9ion
+9ions
+3quatur
+9s
+5ial
+6es
+5y
+3rcisable
+7e
+8d
+8r
+9s
+8s
+7ing
+6tation
+9ions
+5ycle
+9s
+4gaming
+9gs
+5ies
+5onic
+5ual
+6e
+7s
+5y
+4t
+5ainment
+9ents
+5ed
+5ing
+6on
+8s
+6ve
+5s
+3s
+3unt
+2filtrate
+9ed
+9ing
+9ion
+3oliant
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+2halable
+6nt
+8s
+6tion
+9ns
+5e
+6d
+6nt
+8s
+6s
+5ing
+4ust
+7ed
+9ly
+8r
+9s
+7ibility
+9le
+8ng
+9gly
+8on
+9ns
+8ve
+9ely
+9eness
+9ities
+9ity
+7less
+9ssly
+9ssness
+7s
+3edra
+7e
+4redate
+9ed
+9es
+9ing
+9ion
+9ions
+3ibit
+7ed
+8r
+9s
+7ing
+8on
+9ner
+9ners
+9nism
+9nisms
+9nist
+9nistic
+9nists
+9ns
+8ve
+9ely
+7or
+9s
+9y
+7s
+4larant
+9ts
+8te
+9ed
+9es
+9ing
+9ingly
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+3ort
+6ation
+9ons
+9ve
+8ory
+6ed
+7r
+8s
+6ing
+6s
+3umate
+8d
+8s
+7ing
+8on
+9ns
+5e
+6d
+6r
+7s
+6s
+5ing
+2ies
+3geant
+8e
+5nce
+8s
+7ies
+7y
+6t
+7ly
+7s
+4ible
+4uities
+7y
+5ous
+8ly
+8ness
+9esses
+3lable
+4e
+5d
+5ment
+9s
+5r
+6s
+5s
+4ian
+5c
+5ng
+5ties
+6y
+3mious
+8ly
+3ne
+5s
+4g
+3st
+5ed
+6nce
+9s
+7t
+8ial
+9alism
+9alisms
+9alist
+9alists
+9ally
+9als
+8s
+5ing
+5s
+3t
+4ance
+8s
+4ed
+4ing
+4less
+4s
+2o
+3biological
+9ies
+9ist
+9ists
+9y
+3carp
+7s
+4entric
+4rine
+8s
+4uticle
+9es
+4yclic
+5tic
+6ose
+9d
+9s
+8ing
+9s
+7tic
+3de
+5rm
+7al
+7is
+9es
+7s
+5s
+4ic
+5st
+7s
+4oi
+5ntia
+9s
+8cs
+8st
+9ts
+5s
+4us
+6es
+3enzyme
+9s
+4rgic
+5ythrocytic
+3gamic
+7es
+6ous
+6y
+4en
+6etic
+6ism
+9s
+6ous
+9ly
+6s
+3mion
+7s
+5s
+6es
+3n
+4erate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+4ic
+4s
+4uclease
+9ses
+5mia
+7st
+9s
+4ym
+6s
+3parasite
+9tes
+9tic
+4eptidase
+9ases
+4hagies
+7ous
+7y
+5oric
+5thalmia
+9mias
+9mic
+9mos
+9moses
+9mus
+9muses
+4lanet
+9s
+6sm
+8s
+4od
+6ite
+9s
+8ic
+6s
+3rabilities
+9ty
+6le
+5tion
+9s
+4bitance
+9ces
+9cies
+9cy
+9t
+9tly
+8te
+9ed
+9es
+9ing
+4cise
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+9cal
+8s
+6ze
+8d
+8r
+9s
+8s
+7ing
+4dia
+7l
+6um
+8s
+3skeletal
+9on
+9ons
+4mic
+5ose
+8s
+7is
+6tic
+4phere
+9s
+8ic
+9cal
+5oral
+7e
+8s
+7ia
+8um
+7ous
+4toses
+7is
+3teric
+8al
+9lly
+8ism
+9sms
+4hermal
+9lly
+8ic
+9cally
+9cities
+9city
+4ic
+6a
+7lly
+6ism
+9s
+8t
+9s
+6ness
+9ses
+6s
+5sm
+7s
+4oxic
+7n
+8s
+4ropia
+9s
+8c
+2pand
+6abilities
+9lity
+8le
+6ed
+7r
+8s
+6ing
+6or
+8s
+6s
+5se
+7s
+6ibilities
+9lity
+8le
+9y
+7le
+7on
+9al
+9ary
+9ism
+9isms
+9ist
+9istic
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+8ities
+9ty
+4t
+5iate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+5riate
+9ed
+9es
+9ing
+9ion
+9ions
+9ism
+9isms
+5s
+3ect
+6able
+9y
+7nce
+9es
+9ies
+9y
+8t
+9ly
+9s
+7tion
+9onal
+9ons
+9ve
+9ves
+6ed
+8ly
+8ness
+9esses
+7r
+8s
+6ing
+9ly
+9s
+6orant
+9nts
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+6s
+4dience
+9es
+9ies
+9y
+8t
+9ial
+9ially
+9ly
+9s
+6tate
+9ed
+9es
+9ing
+9ion
+9ions
+7e
+8d
+8ly
+8r
+9s
+8s
+7ing
+8on
+9nary
+9ns
+9us
+9usly
+9usness
+8ve
+7or
+9s
+4l
+5lable
+7nt
+9s
+6ed
+7e
+8s
+7nt
+9s
+7r
+8s
+6ing
+5s
+4nd
+6abilities
+9lity
+8le
+9es
+9y
+6ed
+7r
+8s
+6ing
+7ture
+9res
+6s
+5se
+7d
+7s
+6ing
+7ve
+9ly
+9ness
+9nesses
+4rience
+9eable
+9ed
+9eless
+9er
+9ers
+9es
+9ing
+8tial
+9ialism
+9ialist
+9ially
+6ment
+9tal
+9talise
+9talism
+9talist
+9talize
+9tally
+9tation
+9tative
+9ted
+9ter
+9ters
+9ting
+9tist
+9tists
+9ts
+5t
+6ed
+6ing
+7se
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+6ly
+6ness
+9ses
+6s
+3iable
+5te
+7d
+7s
+6ing
+7on
+9s
+6or
+8s
+8y
+4rable
+6nt
+8s
+6tion
+9ns
+7ory
+5e
+6d
+6r
+7s
+6s
+5ies
+6ng
+5y
+4scate
+9d
+9s
+8ing
+9on
+9ons
+8ory
+3lain
+7able
+7ed
+8r
+9s
+7ing
+7s
+5nation
+9ons
+9ve
+9vely
+8orily
+9ry
+6t
+7ation
+9ions
+7ed
+7ing
+7s
+4etive
+9ly
+9s
+6ory
+4icable
+9y
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9vely
+8or
+9rs
+9ry
+6it
+8ly
+8ness
+9esses
+8s
+4ode
+7d
+7r
+8s
+7s
+6ing
+5it
+7able
+8ge
+9es
+8tion
+9ions
+9ive
+9ively
+7ed
+8r
+9s
+7ing
+8ve
+7s
+5ration
+9onal
+9onist
+9onists
+9ons
+9ve
+9vely
+8ory
+6e
+7d
+7r
+8s
+7s
+6ing
+5sible
+7on
+9s
+7ve
+9ly
+9ness
+9nesses
+9s
+3o
+4nent
+8ial
+9ally
+9als
+9ation
+9ations
+8s
+5ible
+4rt
+6abilities
+9lity
+8le
+7tion
+9ons
+6ed
+7r
+8s
+6ing
+6s
+4s
+5able
+6l
+7s
+5e
+6d
+7ness
+9sses
+6r
+7s
+6s
+5ing
+6t
+7ed
+7ing
+8on
+9nal
+9ns
+8ve
+9ely
+7or
+9ily
+9s
+9y
+7ress
+9sses
+7s
+5tulate
+9ted
+9tes
+9ting
+9tingly
+9tion
+9tions
+9tive
+9tor
+9tors
+9tory
+7re
+9s
+5ure
+8s
+4und
+7ed
+8r
+9s
+7ing
+7s
+3ress
+7age
+9es
+7ed
+8r
+9s
+8s
+7ible
+8ng
+8on
+9nal
+9nism
+9nisms
+9nist
+9nistic
+9nists
+9nless
+9ns
+8ve
+9ely
+9eness
+9ities
+9ity
+7ly
+7man
+8en
+7ness
+9sses
+7o
+8s
+7ure
+9es
+7way
+9ys
+4obrate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9ory
+5mission
+9ions
+9or
+9ors
+5priable
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+3ugn
+6able
+7tion
+9ons
+6ed
+6ing
+6s
+4lse
+7d
+7s
+6ing
+7on
+9s
+7ve
+4nct
+7ed
+7ing
+8on
+9ns
+7s
+5ge
+7d
+7r
+8s
+7s
+6ing
+4rgate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rial
+9rs
+9ry
+6e
+7d
+7s
+6ing
+2quisite
+9ly
+9ness
+9nesses
+9s
+2sanguinate
+9ated
+9ates
+9ating
+9ation
+9ations
+9e
+9ed
+9eous
+9ities
+9ity
+9ous
+3cind
+7ed
+7ing
+7s
+3ecant
+8s
+5t
+6ed
+6ing
+7on
+9s
+6s
+4rt
+6ed
+6ile
+7ng
+7on
+9s
+6s
+3iccant
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+3olution
+9ns
+3tipulate
+4rophies
+8y
+3uccous
+4fflate
+9ed
+9es
+9ing
+9ion
+9ions
+7icate
+2tant
+4sies
+5y
+4tic
+3emporal
+9lly
+9neity
+9neous
+9rily
+9riness
+9ry
+8e
+9s
+8isation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+4nd
+6abilities
+9lity
+8le
+7nt
+6ed
+8ly
+8ness
+9esses
+7r
+8s
+6ibilities
+9lity
+8le
+7ng
+6s
+5se
+6ibilities
+9lity
+8le
+9eness
+7fication
+7le
+7meter
+9ters
+7on
+9al
+9alism
+9alisms
+9ality
+9ally
+9ist
+9ists
+9s
+7ties
+8y
+7ve
+9ly
+9ness
+9nesses
+8isation
+9zation
+6ometer
+9ters
+7r
+8s
+5t
+6s
+5uate
+9d
+9s
+8ing
+9ngly
+9ngs
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+4rior
+8isation
+9se
+9sed
+9ses
+9sing
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+5minable
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+9tory
+8e
+9d
+9s
+8ing
+5n
+6al
+8isation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+7t
+8s
+6e
+7s
+6s
+7hip
+9ps
+5oceptive
+9tor
+9tors
+5ritorial
+9rially
+3inct
+7ed
+7ing
+8on
+9ns
+8ve
+7s
+7ure
+9es
+5e
+6s
+5guish
+9hable
+9hant
+9hants
+9hed
+9her
+9hers
+9hes
+9hing
+9hment
+9hments
+4rp
+6able
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+6ed
+6ing
+6s
+3ol
+5d
+5l
+6ed
+7r
+8s
+6ing
+9ly
+6s
+5ment
+9s
+5s
+4rsive
+9ly
+5t
+6ed
+7r
+8s
+6ing
+7on
+9ary
+9ate
+9ately
+9er
+9ers
+9ist
+9ists
+9s
+7ve
+6s
+3ra
+5bold
+9s
+5canonical
+6ellular
+9ularly
+6orporeal
+6ranial
+6t
+7ability
+9le
+8nt
+9ts
+7ed
+7ible
+8ng
+8on
+9ns
+8ve
+9ely
+9es
+7or
+9s
+7s
+6urricular
+5ditable
+8e
+9d
+9s
+8ing
+9on
+9ons
+6os
+8es
+7tal
+6ural
+9ls
+5embryonic
+5floral
+6oraneous
+5galactic
+5hepatic
+5it
+7s
+5judicial
+9cially
+5legal
+9lly
+6imital
+9tary
+7nguistic
+7terary
+8ies
+8y
+6ogical
+5marital
+9tally
+6etrical
+6undane
+7ral
+9lly
+7sical
+5neities
+9y
+7ous
+9sly
+9sness
+7t
+8s
+6uclear
+5ordinaire
+9naries
+9narily
+9nary
+5polate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+9tory
+7se
+9d
+9s
+8ing
+9tion
+9tions
+6yramidal
+5s
+6ensory
+6olar
+6ystole
+9oles
+5textual
+6ropical
+5ught
+6terine
+5vagance
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9nza
+9nzas
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+7sate
+9ted
+9tes
+9ting
+9tion
+9tions
+8cular
+6ehicular
+7rsion
+9ions
+9ive
+9ively
+8t
+9ed
+9ing
+9s
+4eat
+7s
+5ma
+7l
+8s
+6e
+7ly
+7ness
+9sses
+7r
+7s
+8t
+6ism
+9s
+8t
+9s
+7ties
+8y
+6ophile
+9iles
+6um
+4icable
+7te
+9d
+9s
+8ing
+9on
+9ons
+5nsic
+9al
+9ality
+9ally
+4orsal
+7e
+5version
+9ions
+9ive
+9ively
+8t
+9ed
+9ing
+9s
+4udabilities
+9lity
+8le
+6e
+7d
+7r
+8s
+7s
+6ing
+5sible
+7le
+7on
+9s
+7ve
+6ory
+3ubate
+8d
+8s
+7ing
+2uberance
+9es
+9ies
+9y
+8t
+9ly
+7te
+9d
+9s
+8ing
+3date
+7s
+6ion
+9s
+7ve
+4e
+5d
+5s
+4ing
+3l
+4cerate
+9ed
+9es
+9ing
+9ion
+9ions
+4s
+4t
+5ance
+9s
+8ies
+8y
+7t
+8ly
+6tion
+9ns
+5ed
+5ing
+8ly
+5s
+3rb
+5an
+7ite
+9es
+5ia
+7s
+5s
+3via
+6e
+6l
+6te
+8d
+8s
+7ing
+8on
+9ns
+5um
+1yalet
+6s
+3s
+4es
+4s
+5es
+2e
+3able
+3ball
+7ed
+7ing
+7s
+5nk
+7s
+5r
+6s
+5th
+7s
+4eam
+7s
+4lack
+8s
+5ink
+8s
+4olt
+7s
+4right
+9s
+5ow
+7ed
+7ing
+7less
+7s
+3cup
+6s
+3d
+4ness
+8es
+4ropper
+9rs
+7s
+3fold
+7s
+4ul
+6s
+3glass
+8es
+3hole
+7s
+5ok
+7s
+3ing
+3lash
+7es
+4ess
+5t
+6ed
+7er
+9s
+6ing
+6s
+6ted
+7ing
+5vel
+4iad
+7s
+5d
+6s
+5ft
+7s
+5ke
+5ner
+8s
+3n
+3opener
+9s
+3piece
+8s
+4oint
+8s
+5pper
+9s
+3r
+4s
+3s
+4hade
+8s
+7ow
+9s
+5ine
+8s
+5ot
+7s
+4ight
+8s
+4ome
+5re
+7s
+4pot
+7s
+4talk
+8s
+5one
+8s
+5rain
+9s
+6ings
+3teeth
+4ooth
+3wash
+7es
+5ter
+8s
+4ear
+7s
+4ink
+7s
+5tness
+9ses
+2ing
+2liad
+6s
+2ne
+2ot
+4s
+2ra
+4s
+3e
+4s
+3ie
+5s
+4r
+3y
+0fa
+2a
+3ing
+3n
+3s
+2b
+3aceous
+3ber
+5st
+4ier
+6st
+4y
+3le
+5d
+5r
+6s
+5s
+4iau
+7x
+5ng
+7s
+3ric
+6ant
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+6ked
+7ing
+6s
+3s
+3ular
+6te
+8d
+8s
+7ing
+7or
+9s
+5ise
+8d
+8s
+7ing
+7t
+8ic
+8s
+6ze
+8d
+8s
+7ing
+5osities
+9y
+6us
+8ly
+8ness
+9esses
+4rden
+8s
+2cade
+6s
+3e
+4able
+4bar
+7s
+5ook
+8ed
+8ing
+8s
+4cloth
+9s
+4d
+5own
+8s
+4less
+8ness
+9esses
+5ift
+8ed
+8ing
+8s
+4mail
+8s
+6n
+6sk
+8s
+5en
+4plate
+9s
+5rint
+9s
+4r
+5s
+4s
+4t
+5e
+6d
+6ly
+5iae
+6ng
+6ous
+9ly
+9ness
+9nesses
+5s
+5ted
+6ing
+4up
+4worker
+9rs
+3ia
+5e
+5l
+6ist
+9s
+6ly
+6s
+5s
+4end
+7s
+5s
+4le
+6ly
+6ness
+9ses
+5itate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+7ies
+7y
+4nerious
+5g
+6s
+5orous
+9sness
+3onne
+7s
+3simile
+9d
+9ing
+9s
+8ist
+9sts
+3t
+4ful
+4ice
+7s
+6ities
+8y
+5on
+7al
+9ism
+9isms
+9ist
+9ists
+9ly
+8ries
+9y
+7ist
+9ts
+7s
+6us
+8ly
+8ness
+9esses
+5s
+6es
+5tious
+9sly
+9sness
+7ve
+9ly
+5ve
+4oid
+7al
+7s
+5r
+6abilities
+9lity
+8le
+7ge
+9s
+6ed
+6ial
+9ly
+9s
+7es
+7ng
+9s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+7hip
+9ps
+6y
+7like
+5tum
+8s
+4s
+5heet
+9s
+4ual
+7ism
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+7ly
+7ness
+9sses
+5m
+6s
+5re
+7s
+3ula
+6e
+6r
+5tative
+9vely
+6ies
+6y
+4ndities
+8y
+2d
+3able
+4ise
+7s
+3dier
+6st
+5ness
+9es
+5sh
+7ly
+7ness
+9sses
+6m
+7s
+6t
+7s
+4le
+6d
+6s
+5ing
+4y
+3e
+4away
+8s
+4d
+5ly
+5ness
+9es
+4in
+6s
+4less
+8ly
+4out
+7s
+4r
+5s
+4s
+4ur
+6s
+3ge
+5d
+5s
+4ing
+3ier
+5st
+4ng
+6s
+3like
+3o
+4meter
+9s
+4s
+3s
+3y
+2e
+3cal
+4es
+3na
+5s
+3rie
+6s
+4y
+2ff
+4ed
+4ing
+4s
+2gaceous
+3ged
+5ries
+6y
+4ier
+6st
+5ngs
+4y
+3in
+5s
+3oted
+6r
+7s
+5ing
+8s
+5ti
+7st
+9s
+6o
+2h
+3lband
+8s
+4erz
+7es
+4ore
+7s
+3s
+2ible
+6s
+3ence
+7s
+3k
+4ed
+5s
+4ing
+4s
+3l
+4ed
+4ing
+7ly
+7s
+4le
+6s
+4s
+4ure
+7s
+3n
+4e
+5ance
+9s
+8ies
+8y
+7t
+8ise
+9ses
+8s
+5d
+5r
+5s
+6t
+4ing
+5tes
+4ly
+4ne
+6s
+7s
+8es
+4s
+4t
+5ed
+6r
+7s
+6st
+5hearted
+9tedly
+5ier
+7st
+6ng
+8ly
+8s
+6sh
+8ness
+9esses
+5ly
+5ness
+9es
+5s
+5y
+3r
+4ed
+5r
+5st
+4faced
+4goer
+8s
+5round
+9ds
+4ies
+5ly
+5ng
+7s
+5sh
+7ly
+4lead
+8er
+9rs
+8s
+5y
+4ness
+8es
+5itickle
+9kles
+9le
+9les
+5ytickle
+9kles
+9le
+9les
+4s
+4way
+7s
+4y
+5dom
+8s
+5floss
+9ses
+5hood
+9s
+5ism
+8s
+5land
+9s
+6ike
+5tale
+9s
+3th
+5ed
+6r
+7s
+5ful
+8ly
+8ness
+9esses
+8s
+5ing
+5less
+9ly
+9ness
+9nesses
+5s
+5worthiness
+9hy
+4or
+6s
+5ur
+7s
+3x
+2jita
+6s
+2ke
+4d
+4er
+6s
+4ment
+8s
+4r
+5ies
+5s
+5y
+4s
+4y
+3ie
+5r
+5s
+6t
+4ng
+4r
+5ism
+8s
+5s
+2lafel
+7s
+4j
+4ngism
+9s
+8t
+9s
+3bala
+7s
+3cade
+7s
+5te
+7d
+6ion
+9s
+4es
+4hion
+8s
+4iform
+4on
+6er
+8s
+7t
+8s
+6iform
+7ne
+6oid
+6ries
+7y
+6s
+4ula
+7e
+7s
+7te
+3dage
+7s
+4eral
+8ed
+8ing
+8s
+6ol
+8s
+5tta
+8s
+4istories
+9y
+4stool
+9s
+3l
+4acies
+7ous
+9sly
+9sness
+6y
+5l
+6eries
+8y
+6ish
+9ly
+6s
+5way
+8s
+4back
+8s
+5oard
+9s
+4en
+5r
+6s
+4fish
+8es
+4ibilism
+9sms
+9st
+9sts
+9ties
+9ty
+6le
+8ness
+9esses
+7y
+5ng
+7s
+4off
+7s
+5ut
+7s
+5w
+6ed
+7r
+7st
+6ing
+6ness
+9ses
+6s
+4s
+3se
+5d
+5face
+9s
+5hood
+9s
+5ly
+5ness
+9es
+5r
+6s
+5s
+6t
+5tto
+8s
+5work
+9s
+4idical
+5e
+6s
+5fiability
+9le
+7cation
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5ng
+5sh
+6m
+7s
+5ties
+6y
+3tboat
+8s
+4er
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+3x
+2me
+4d
+4less
+4s
+3ilial
+7r
+8isation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9ties
+9ty
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8ly
+8ness
+9esses
+8s
+6es
+6sm
+8s
+7tic
+5le
+7s
+5y
+4ne
+6s
+5g
+4sh
+6ed
+7s
+6ing
+6ment
+9ts
+3ous
+6ed
+7s
+6ing
+6ly
+6ness
+9ses
+3uli
+5us
+2n
+3al
+5s
+4tic
+7al
+9ly
+9ness
+9nesses
+7ise
+9ed
+9es
+9ing
+9m
+9ms
+8ze
+9ed
+9es
+9ing
+7s
+3base
+7s
+4oy
+6s
+3ciable
+5ed
+6r
+7s
+6s
+7t
+5fied
+8s
+6ul
+8ly
+8ness
+9esses
+6y
+7ing
+5less
+6y
+5ness
+9es
+4y
+5ing
+5work
+9s
+3d
+4angle
+9s
+7o
+8es
+8s
+4ed
+4ing
+4om
+6s
+4s
+3e
+4ga
+6da
+8s
+6s
+4s
+3farade
+9s
+6e
+7d
+7s
+6ing
+6on
+8a
+9de
+9ded
+9des
+9ding
+9s
+8s
+4ic
+6s
+4old
+7ed
+7ing
+7s
+3g
+4a
+5s
+4ed
+4ing
+4le
+6d
+6s
+7s
+5ike
+6ng
+4o
+5s
+4s
+3ion
+6s
+3jet
+6s
+3k
+4le
+6d
+6s
+5ing
+4s
+3light
+8s
+5ke
+3ned
+5l
+6l
+7s
+6s
+5r
+6s
+4ied
+6s
+5ng
+7s
+4ying
+3o
+4n
+5s
+4s
+3s
+4ite
+7s
+4ub
+6s
+3tabulous
+5d
+6s
+5il
+7ed
+7s
+5sia
+8s
+7e
+8d
+8s
+7se
+9d
+9r
+9rs
+9s
+8ing
+8t
+9s
+7ze
+9d
+9r
+9rs
+9s
+8ing
+6m
+7al
+9ly
+7ic
+9ally
+7s
+6que
+9s
+6t
+7ic
+9al
+9ality
+9ally
+9alness
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ism
+9isms
+9o
+9oes
+9s
+7ries
+8y
+7s
+6y
+7ing
+7land
+9nds
+4eeg
+7s
+4igue
+8s
+4occini
+5d
+6s
+5m
+6s
+5osh
+3um
+5s
+3wise
+4ort
+7s
+3zine
+7s
+2p
+2qir
+5s
+3uir
+6s
+2r
+3ad
+5aic
+6y
+7s
+5ic
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5s
+4nd
+6ine
+9s
+6ole
+9s
+4way
+7ness
+9sses
+7s
+3borough
+9hs
+3ce
+5d
+5meat
+9s
+5r
+6s
+5s
+5ur
+7s
+6se
+8s
+4i
+5cal
+8ities
+9ty
+8ly
+8ness
+9esses
+5e
+6d
+6s
+5fied
+8s
+6y
+7ing
+5n
+6g
+7s
+6s
+4y
+3d
+4age
+7s
+4ed
+5l
+6s
+5n
+6s
+4ing
+7s
+4s
+3e
+4box
+7es
+4d
+4r
+5s
+4s
+4well
+8ed
+8ing
+8s
+3fal
+6le
+8s
+6s
+4el
+6s
+5t
+6chedness
+3ina
+6ceous
+6s
+5g
+5ha
+7s
+5ose
+8ly
+3kleberries
+9ry
+3l
+4e
+5s
+4s
+3m
+4able
+4ed
+5r
+6ess
+9es
+7tte
+9es
+6ies
+6s
+6y
+4hand
+8s
+5ouse
+9s
+4ing
+7s
+4land
+8s
+4ost
+4s
+5tead
+9s
+4wife
+6ves
+5ork
+8er
+9rs
+8s
+4yard
+8s
+3narkel
+9ed
+9ing
+9ings
+9s
+4esol
+8s
+6s
+7es
+3o
+4lito
+8s
+4s
+4uche
+3raginous
+6o
+7es
+7s
+5nd
+7ine
+9es
+6t
+4ed
+5n
+6s
+4ier
+7ies
+7s
+7y
+5ng
+4ow
+6ed
+6ing
+6s
+4uca
+7s
+3s
+4e
+5d
+5eing
+5s
+4ide
+7s
+5ghted
+9dly
+9dness
+5ng
+3t
+4ed
+5r
+6s
+4hel
+7s
+6r
+7more
+9st
+6st
+5ing
+8ale
+9les
+8land
+9ands
+9ess
+8s
+9worth
+9worths
+4ing
+4lek
+7s
+4s
+2s
+3ces
+4i
+5a
+6e
+6l
+6s
+6te
+8d
+8ly
+7ion
+9ns
+5cle
+8d
+8s
+6ular
+9rly
+9te
+9ted
+9tely
+9tion
+9tions
+8e
+9s
+8i
+8us
+5itis
+9es
+5nate
+9d
+9dly
+9s
+8ing
+9ngly
+9on
+9ons
+9ve
+8or
+9rs
+6e
+7s
+5o
+6la
+8s
+7e
+8s
+7iases
+9sis
+5s
+6m
+7i
+7o
+7s
+6t
+7a
+7i
+8c
+9ally
+7s
+5tis
+8es
+3h
+4ed
+5ries
+6y
+5s
+4ing
+5on
+7ability
+9le
+9leness
+9les
+9ly
+7ed
+8r
+9s
+7ing
+8st
+9ta
+9tas
+9ts
+7monger
+9ngers
+9nging
+7s
+7y
+6us
+8ness
+9esses
+3t
+4back
+8s
+6ll
+8er
+9rs
+8s
+4ed
+5n
+6ed
+7r
+8s
+6ing
+9s
+6s
+5r
+6s
+5st
+4i
+5dious
+9sly
+9sness
+5e
+6s
+5giate
+9ed
+7um
+9s
+5ng
+7s
+5sh
+4ly
+4ness
+8es
+4s
+4uous
+2t
+3al
+5ism
+8s
+7t
+8ic
+9cally
+8s
+6ties
+7y
+5ly
+5ness
+9es
+3back
+7s
+4ird
+7s
+4rained
+3e
+4d
+4ful
+7ly
+7ness
+9sses
+4s
+3head
+7ed
+9ly
+9ness
+9nesses
+7s
+5r
+6ed
+6hood
+9ds
+6ing
+9s
+6land
+9ds
+7ess
+9sness
+7ike
+8ness
+9esses
+7y
+6s
+7hip
+9ps
+4om
+6able
+6ed
+7r
+8s
+7ter
+9rs
+6ing
+6less
+9sly
+9sness
+6s
+3idic
+7al
+9ly
+4gabilities
+9ity
+7le
+9ness
+9nesses
+6te
+8d
+8s
+7ing
+5uable
+9eness
+6e
+7d
+7less
+7s
+6ing
+9ly
+4ng
+4scence
+9es
+8t
+3less
+4ike
+5ng
+7s
+4y
+3ness
+7es
+3s
+4hedera
+9as
+4ia
+6s
+4o
+5es
+5s
+4tock
+8s
+3ted
+5n
+6able
+6ed
+7r
+8s
+6ing
+9s
+6s
+5r
+5st
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+5sh
+6m
+7s
+6t
+7s
+4rels
+4y
+3uities
+6ous
+6y
+4ous
+7ly
+7ness
+9sses
+3wa
+5h
+6ed
+6ing
+6s
+5ing
+5s
+4ood
+7s
+2ubourg
+8s
+3cal
+6s
+4es
+5t
+6s
+4hion
+8s
+5on
+7s
+4ial
+3gh
+3lchion
+9s
+4d
+5s
+4t
+5ed
+5finder
+9ers
+9ing
+9ings
+6ul
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5less
+9ly
+9ness
+9nesses
+6ine
+9s
+5s
+5y
+3n
+4a
+5e
+5l
+6ly
+5s
+4ist
+7ic
+9ally
+7s
+4like
+4s
+4ula
+7e
+6e
+7s
+3r
+4d
+4er
+5st
+3stian
+3t
+4ed
+5uil
+8s
+4ing
+4or
+6s
+4s
+3ve
+5s
+5tte
+8s
+4ism
+7s
+6t
+7s
+3x
+4bourdon
+9ons
+2va
+4s
+3e
+4l
+5a
+6s
+5l
+6a
+7s
+4olate
+4r
+4s
+5t
+3icon
+7s
+4sm
+6s
+3onian
+4r
+5able
+9ness
+9nesses
+8y
+5ed
+7ness
+9sses
+6r
+7s
+5ing
+8ly
+6te
+8s
+7ism
+9ms
+5less
+5s
+4se
+4ur
+6able
+9eness
+9y
+6ed
+8ness
+9esses
+7r
+8s
+6ing
+9ly
+7te
+9s
+8ism
+9sms
+6less
+6s
+5s
+3rile
+7s
+3us
+5es
+2w
+3n
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7ly
+7ness
+9sses
+7s
+4like
+4s
+4y
+3s
+2x
+3ed
+4s
+3ing
+2y
+3alite
+8s
+3ed
+4nce
+7s
+4r
+4st
+3ing
+3ne
+5d
+5s
+4ing
+3re
+5s
+3s
+2ze
+4d
+4nda
+7s
+6eiro
+9os
+4s
+3ing
+1e
+2ague
+6d
+6s
+5ing
+3l
+4ed
+4ing
+4s
+4ties
+5y
+3r
+4e
+5d
+5r
+6s
+5s
+4ful
+7ler
+9st
+8y
+7ness
+9sses
+4ing
+4less
+8ly
+8ness
+9esses
+4naught
+9ts
+5ought
+9ts
+4s
+5ome
+8ly
+8ness
+9esses
+4t
+3sance
+8s
+4e
+5d
+5s
+4ibilities
+9ty
+6le
+8ness
+9esses
+7y
+5ng
+4t
+5ed
+6r
+7s
+5ful
+5ing
+8s
+5less
+5s
+3t
+4ed
+5ous
+8ly
+5r
+5st
+4her
+7bed
+9dded
+9dding
+9ddings
+9ds
+8rain
+9ained
+9ains
+7ed
+9ge
+9ged
+9ges
+9ging
+7head
+9aded
+9ads
+7ier
+9st
+8ness
+9esses
+9g
+9gs
+7less
+8ight
+7s
+8titch
+9itched
+9itches
+7weight
+9ights
+7y
+4ing
+4lier
+7st
+6ness
+9ses
+5y
+4ous
+4s
+4uous
+5re
+7d
+7less
+9ssness
+8y
+7s
+7tte
+9es
+6ing
+3ze
+5d
+5s
+4ing
+2blesse
+8s
+3ricities
+8y
+6ula
+9s
+8e
+9s
+5facient
+9ents
+6erous
+6ic
+6ugal
+8e
+9s
+5le
+6ities
+8y
+2cht
+5er
+7s
+5ing
+5s
+3ial
+6s
+4t
+3ked
+4in
+6g
+4less
+8ly
+8ness
+9esses
+5y
+4s
+3ula
+6e
+6s
+5ence
+9s
+8ies
+8y
+7t
+4nd
+6ate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+9ry
+6ities
+8y
+2d
+3arie
+7s
+4yee
+7n
+3elini
+8s
+4racies
+7y
+6l
+7ese
+9es
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7s
+6rie
+9s
+7y
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+7or
+9s
+4x
+5ed
+6s
+5ing
+3ora
+6s
+3s
+2e
+3b
+4le
+6d
+6minded
+9dedly
+6ness
+9ses
+6r
+6s
+7t
+5ing
+6sh
+5y
+4s
+3d
+4able
+4back
+8s
+6g
+7s
+5ox
+7es
+4er
+6s
+4grain
+9s
+4hole
+8s
+4ing
+7s
+8tuff
+9uffs
+4lot
+7s
+4s
+5tock
+9s
+6uff
+9s
+4through
+9ghs
+4water
+9s
+4yard
+8s
+3ing
+3l
+4bad
+4er
+6s
+5ss
+4good
+4ing
+7less
+8y
+7ness
+9sses
+7s
+4s
+3n
+4s
+3r
+4ed
+4ie
+6s
+5n
+6g
+7s
+6s
+4s
+3s
+4e
+5d
+5s
+4ing
+3t
+4first
+4less
+3ze
+5d
+5s
+4ing
+2g
+3aries
+5y
+3s
+2h
+3m
+4e
+4ic
+3s
+2ign
+5ed
+7ly
+7ness
+9sses
+6r
+7s
+5ing
+8ly
+8s
+5s
+3joa
+6da
+8s
+6s
+3nt
+5ed
+6r
+6st
+5ing
+5s
+3rie
+6r
+6st
+3s
+4eanna
+4t
+5ier
+7st
+6ly
+6ness
+9ses
+5s
+5y
+2lafel
+7s
+3ched
+6s
+3dgrau
+8s
+4schar
+9s
+7er
+9s
+5her
+8s
+5par
+8s
+7th
+9ic
+9oid
+9oids
+9ose
+9s
+3icia
+7s
+6fic
+6tate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7er
+7ies
+7ous
+9sly
+9sness
+7y
+4d
+5s
+4ne
+6ly
+6ness
+9ses
+6s
+5ities
+7y
+3l
+4a
+5ble
+5h
+6een
+6in
+6s
+5s
+5tor
+8s
+6rices
+8x
+9es
+4ed
+5r
+6s
+5st
+4ies
+5ng
+7s
+4monger
+9red
+9ries
+9ring
+9rings
+9rs
+9ry
+4ness
+8es
+4oe
+6s
+5w
+6ed
+6ing
+6ly
+6man
+7en
+6s
+7hip
+9ped
+9ping
+9pped
+9pping
+9ps
+4s
+4y
+3on
+5ies
+6ous
+9ly
+9ness
+9nesses
+5ous
+5ries
+6y
+5s
+5y
+3sic
+5te
+7s
+6ic
+4par
+7s
+6thic
+8oid
+9ids
+9se
+4tone
+8s
+3t
+4ed
+5r
+6ed
+6ing
+6s
+4ier
+6st
+5ng
+7s
+4like
+4s
+4y
+3ucca
+7s
+3wort
+7s
+2m
+3al
+5e
+6ness
+9ses
+6s
+5ities
+7y
+5s
+3e
+4rall
+8s
+4s
+4taries
+7y
+3icidal
+7e
+8s
+4nacies
+7y
+6l
+7ities
+9y
+5eities
+8y
+5ie
+6lities
+9y
+6ne
+8ly
+8ness
+9esses
+8s
+7ism
+9ms
+8ties
+9y
+6sation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8s
+7t
+8ic
+8s
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8s
+7ing
+4ter
+7s
+3me
+5s
+4ier
+6st
+4y
+3ora
+6l
+3s
+3tosecond
+9nds
+3ur
+5s
+2n
+3agle
+7d
+7s
+6ing
+3ce
+5d
+5less
+9ness
+9nesses
+6ike
+5r
+6ow
+8s
+6s
+5s
+4ible
+8s
+5ng
+7s
+3d
+4ed
+5r
+6ed
+6less
+6s
+4ier
+6st
+5ng
+4s
+4y
+3estella
+9ae
+9as
+6ra
+8e
+8l
+9s
+8s
+8te
+9ed
+9ion
+9ions
+3i
+4s
+4tar
+7s
+3ks
+3land
+7s
+3man
+4en
+3nec
+6s
+5l
+6flower
+9wers
+6s
+4ier
+6s
+7t
+5sh
+4y
+3s
+3t
+4anyl
+8s
+4hion
+8s
+4s
+3ugreek
+9s
+4ron
+7s
+2od
+4al
+5ries
+6y
+4s
+3ff
+5ed
+6e
+7s
+6r
+7s
+5ing
+5ment
+9s
+5or
+7s
+5s
+2r
+3acious
+6ties
+7y
+4l
+5ised
+6zed
+5s
+3bam
+6s
+3e
+4r
+4s
+5t
+4tories
+7y
+3ia
+5e
+5l
+5s
+4ne
+4ties
+5y
+3lie
+6d
+6r
+6s
+7t
+4y
+5ing
+3m
+4ata
+7s
+6e
+4ent
+7ability
+9le
+8tion
+9ions
+9ive
+9ively
+7ed
+8r
+9s
+8scible
+7ing
+8tious
+8ve
+7or
+9s
+7s
+4i
+5on
+7ic
+7s
+5s
+5um
+7s
+4s
+3n
+4allies
+7y
+4bird
+8s
+4eries
+6y
+4ier
+6st
+5ng
+7s
+6st
+5tickle
+9les
+8le
+9es
+4less
+5ike
+4s
+5haw
+8s
+4tickle
+9ed
+9es
+7le
+9d
+9s
+4y
+5tickle
+9les
+8le
+9es
+3ocious
+9ly
+9ness
+9nesses
+6ties
+7y
+3randine
+9es
+5te
+7s
+4edoxin
+9ns
+5l
+6ed
+6ing
+6led
+7ing
+6s
+5ous
+5t
+6ed
+7r
+8s
+6ing
+9s
+6s
+6y
+4iage
+8s
+5c
+6yanic
+9ide
+9ides
+9ogen
+9ogens
+5ed
+6s
+5ferous
+5magnet
+9etic
+9etism
+9etisms
+9ets
+5te
+7s
+6ic
+7n
+8s
+4ocene
+9s
+6hrome
+9mes
+9mium
+9miums
+6oncrete
+9retes
+6yanic
+9ide
+9ides
+9ogen
+9ogens
+5electric
+9trics
+5grams
+8phies
+9hy
+5magnesian
+9et
+9etic
+9etism
+9etisms
+9ets
+7nganese
+9aneses
+6olybdenum
+5nickel
+9els
+7ere
+9es
+6niere
+9res
+5prussiate
+9siates
+5silicon
+9cons
+6oferric
+5type
+9d
+9s
+8ing
+5us
+4ugineous
+8ous
+6o
+7s
+5le
+7d
+7s
+6ing
+5m
+6s
+4y
+5boat
+9s
+5ing
+5man
+6en
+3tigate
+9d
+9s
+8ing
+9on
+9ons
+5le
+7ly
+7ness
+9sses
+7r
+7st
+6isable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7ties
+8y
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+3ula
+6ceous
+6e
+6s
+5e
+6d
+6s
+5ing
+3vencies
+7y
+6t
+7er
+8st
+7ly
+7ness
+9sses
+5scent
+4id
+6er
+7st
+6ities
+8y
+6ly
+6ness
+9ses
+4or
+6ous
+6s
+5ur
+7s
+2s
+3cennine
+4ue
+6s
+3s
+4e
+5d
+5s
+4ing
+4wise
+3t
+4a
+5l
+6ly
+6s
+5s
+4er
+6ed
+6ing
+6s
+4ier
+6st
+5logies
+8y
+5nate
+9d
+9ly
+9s
+8ing
+9on
+9ons
+5val
+8goer
+9oers
+8s
+6e
+7ly
+7ness
+9sses
+6ities
+8y
+6ous
+4ologies
+8y
+5on
+7ed
+8ries
+9y
+7ing
+7s
+4s
+5chrift
+9ften
+9fts
+4y
+2t
+3a
+4l
+4s
+4tion
+8s
+3ch
+5ed
+6r
+7s
+6s
+5ing
+8ly
+3e
+4d
+4rita
+8s
+4s
+3ial
+6es
+6is
+6s
+4ch
+6e
+7s
+6ise
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7ze
+9d
+9s
+8ing
+5idal
+7e
+8s
+4d
+5er
+6st
+5ities
+7y
+5ly
+5ness
+9es
+4ng
+4parous
+4sh
+6es
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ically
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+3lock
+7ed
+7s
+3ologies
+8st
+9ts
+7y
+4protein
+9ins
+4r
+5s
+4scope
+9s
+8ies
+8y
+3s
+3t
+4a
+5s
+4ed
+5r
+6ed
+7r
+8s
+6ing
+6less
+7ock
+9ks
+6s
+4ing
+4le
+6d
+6r
+7s
+6s
+5ing
+8s
+4s
+4uccine
+9es
+9i
+6ine
+9s
+8i
+9s
+3us
+5es
+3wa
+5s
+2u
+3ar
+5s
+3d
+4al
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+5ries
+6y
+5tories
+8y
+4ed
+4ing
+7s
+5st
+7s
+4s
+3ed
+3illete
+9s
+8on
+9nism
+9nisms
+9nist
+9nistic
+9nists
+9ns
+4ng
+3s
+3tre
+6d
+6s
+5ing
+2ver
+5ed
+5few
+8s
+5ing
+6sh
+8ly
+8ness
+9esses
+5less
+5ous
+8ly
+5root
+9s
+5s
+5weed
+9s
+6ort
+9s
+2w
+3er
+4st
+3met
+6s
+3ness
+7es
+3s
+3ter
+6ed
+6ing
+6s
+4rils
+2y
+3ed
+4r
+4st
+3ing
+3ly
+3ness
+7es
+3s
+2z
+3es
+3zed
+5s
+4y
+1iacre
+6s
+3ncailles
+5e
+6e
+7s
+6s
+5hetti
+9o
+9oed
+9oes
+9oing
+9os
+3r
+4s
+3schi
+5o
+6es
+6s
+3t
+4ed
+4ing
+4s
+3unt
+6s
+2b
+3bed
+5r
+6ies
+6s
+6y
+4ing
+3er
+5board
+9ds
+5ed
+5fill
+9s
+5glass
+9sed
+9ses
+9sing
+5isation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5less
+6ike
+5s
+6cope
+9es
+3ranne
+8s
+5te
+7s
+4e
+5board
+9ds
+5d
+5fill
+9s
+5glass
+9ses
+5less
+5optic
+5s
+6cope
+9es
+4iform
+5l
+6ar
+6la
+8e
+8r
+9y
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+7iform
+8n
+9s
+7ose
+8us
+6s
+5n
+6ogen
+9nic
+9nous
+9ns
+7id
+9s
+7lyses
+9sin
+9sins
+9sis
+9tic
+7peptide
+9ptides
+7us
+6s
+4o
+5blast
+9tic
+9ts
+5cartilage
+9ilages
+6ement
+9nts
+6ystic
+7te
+9s
+5id
+7s
+6n
+7s
+5line
+9s
+7te
+9s
+5ma
+7s
+7ta
+8ous
+6yalgia
+9gias
+5nectin
+9ins
+5s
+6arcoma
+9omas
+9omata
+6e
+7d
+7s
+6ing
+7s
+7tes
+8ides
+9s
+9ses
+5tic
+5us
+7ly
+7ness
+9sses
+5vascular
+3s
+4ter
+7s
+3ula
+6e
+6r
+6s
+2ce
+4s
+3he
+5s
+4u
+5s
+3in
+5s
+3kle
+6d
+6ness
+9ses
+6r
+6s
+7t
+5ing
+5y
+3o
+4es
+4s
+3tile
+5on
+7al
+9ise
+9ised
+9ises
+9ising
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+9ly
+7eer
+9ring
+9rings
+9rs
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9t
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7s
+5tious
+9sly
+9sness
+5ve
+7ly
+7ness
+9sses
+4or
+6s
+3us
+5es
+2d
+3dious
+8ed
+9s
+8ing
+4le
+6back
+9ks
+6d
+7edee
+8edee
+6head
+9ds
+6neck
+9ks
+6r
+7s
+6s
+7tick
+9cks
+6wood
+9ds
+6y
+7s
+5ier
+7st
+6ng
+5y
+3eicommissa
+9issary
+9issum
+5sm
+7s
+6t
+7ic
+7s
+4lismo
+9s
+7ta
+9s
+6ties
+7y
+4s
+3ge
+5d
+5s
+5t
+6ed
+7r
+8s
+6ier
+8st
+7ness
+9sses
+8g
+9ly
+6s
+6y
+4ing
+3ibus
+7es
+3o
+4s
+3s
+3ucial
+8ly
+7ries
+9ly
+8y
+2e
+3f
+4dom
+7s
+4s
+3ld
+5boots
+5craft
+9ts
+5ed
+6r
+7s
+5fare
+9s
+5ing
+8s
+5mice
+6ouse
+5piece
+9es
+5s
+6man
+7en
+6tone
+9es
+7rip
+9pped
+9pping
+9ps
+9pt
+5vole
+9s
+5ward
+9s
+6ork
+9er
+9ers
+9s
+3nd
+5ish
+8ly
+8ness
+9esses
+5like
+5s
+4t
+5s
+3r
+4ce
+6ly
+6ness
+9ses
+6r
+6st
+4e
+5s
+4ier
+6st
+5ly
+5ness
+9es
+4s
+4y
+3st
+5a
+6s
+2fe
+4d
+4r
+5s
+4s
+3ing
+3teen
+7er
+9s
+7s
+7th
+9ly
+9s
+4h
+5ly
+5s
+4ies
+6th
+8s
+4y
+5ish
+2g
+3eater
+8s
+3ged
+5ries
+6y
+3ht
+5able
+5back
+9s
+5er
+7s
+5ing
+8s
+5s
+3jam
+6s
+3ment
+7s
+3o
+4s
+3s
+3uline
+8s
+4rabilities
+9ity
+7le
+6l
+7ly
+6nt
+8e
+9s
+8s
+6te
+8ly
+7ion
+9ns
+8ve
+9ely
+9eness
+5e
+6d
+7ly
+6head
+9ds
+6less
+6r
+7s
+6s
+6work
+9ks
+5ine
+8s
+7g
+6st
+8s
+3wort
+7s
+2ke
+4d
+4ries
+5y
+4s
+3ier
+5st
+4ng
+4sh
+3y
+2l
+3a
+4beg
+7s
+4ceous
+6r
+7s
+4ggrin
+9s
+5ree
+8d
+8ing
+8s
+4ment
+8ary
+8ous
+8s
+4nder
+8s
+4r
+5ee
+7s
+5ia
+7e
+7l
+7n
+7ses
+8is
+6id
+8s
+4sse
+7s
+4tories
+7y
+5ure
+8s
+4zer
+7s
+3berd
+7s
+6t
+7s
+3ch
+5ed
+6r
+7s
+6s
+5ing
+8ly
+8s
+3e
+4able
+4card
+8s
+4d
+4fish
+8es
+4mot
+7s
+4name
+8s
+4r
+5s
+4s
+4t
+5ed
+5ing
+5s
+3fot
+6s
+3ial
+6ly
+6ness
+9ses
+5te
+7d
+7s
+6ing
+7on
+9s
+4beg
+7s
+5uster
+9red
+9rer
+9rers
+9ring
+9rings
+9rism
+9risms
+9rous
+9rs
+4cidal
+7e
+8s
+6nean
+4form
+4grain
+9s
+7ne
+9s
+6ee
+8d
+8ing
+8s
+4i
+4ng
+6s
+4opietistic
+5que
+8s
+4pendulous
+4ster
+8s
+4us
+3l
+4able
+5gree
+9d
+9ing
+9s
+4e
+5d
+5r
+6s
+5s
+6ter
+9s
+5t
+6ed
+6ing
+6s
+4ibeg
+8s
+5es
+5ng
+7s
+5p
+6ed
+7en
+9s
+6ing
+6s
+5ster
+9s
+4o
+5s
+4s
+4y
+3m
+4able
+4card
+8s
+4dom
+7s
+4ed
+5r
+6s
+4goer
+8s
+6ing
+4i
+5c
+6ally
+5er
+6st
+5ly
+5ness
+9es
+6g
+5s
+6h
+4land
+8s
+5ess
+5ike
+4maker
+9s
+7ing
+9gs
+4ographies
+9hy
+4s
+5et
+7s
+7ter
+9rs
+8ing
+9ngs
+5trip
+9s
+4y
+3o
+4plume
+9s
+5odia
+8um
+4s
+5e
+6lle
+9s
+4virus
+9es
+3s
+3ter
+6abilities
+9lity
+8le
+9eness
+6ed
+7r
+8s
+6ing
+6s
+4h
+5ier
+7st
+6ly
+6ness
+9ses
+5s
+5y
+4rabilities
+9ity
+7le
+6table
+7e
+8d
+8s
+7ing
+8on
+9ns
+5e
+3um
+2mble
+6s
+4ria
+7e
+7l
+7te
+9d
+9s
+8ing
+9on
+9ons
+6llate
+3icolous
+2n
+3able
+7ness
+9sses
+4gle
+7d
+7r
+8s
+7s
+6ing
+4l
+5e
+6s
+5is
+7ation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+8s
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5ly
+5s
+4nce
+7d
+7s
+6ial
+9ist
+9ists
+9ly
+7er
+9ed
+9ing
+9s
+7ng
+9s
+3back
+7s
+3ca
+5s
+4h
+5ed
+6s
+3d
+4able
+4er
+6s
+4ing
+7s
+4ram
+7s
+4s
+3e
+4able
+8ness
+9esses
+4d
+4er
+6ed
+6ing
+6s
+4ish
+4less
+5y
+4ness
+8es
+4r
+5ies
+5s
+5y
+4s
+5pun
+5se
+7d
+7r
+8s
+7s
+6ing
+9s
+5t
+3fish
+7es
+4oot
+7s
+3gan
+6s
+4er
+6board
+9rds
+8wl
+9ls
+7readth
+9adths
+6ed
+7r
+8s
+6glass
+9sses
+7uard
+9rds
+6hold
+9ds
+9e
+9es
+6ings
+6less
+7ike
+8ng
+9gs
+6mark
+9ks
+6nail
+9ls
+6pick
+9ked
+9king
+9kings
+9ks
+7late
+9tes
+7ost
+9ts
+7rint
+9nted
+9nting
+9ntings
+9nts
+6s
+7tall
+9lls
+6tip
+9s
+3i
+4al
+6ed
+6s
+4cal
+7ities
+9y
+7ly
+7ness
+9sses
+5ketier
+9est
+8y
+6ier
+8st
+7n
+8ess
+9sses
+8g
+9s
+6y
+4kin
+7g
+4ng
+6s
+4s
+5es
+5h
+6ed
+7r
+8s
+7s
+6ing
+9s
+4te
+6ly
+6ness
+9ses
+6s
+5ism
+8s
+5o
+5ude
+8s
+3jan
+6s
+3k
+4ed
+4ing
+4s
+3less
+4ike
+3mark
+7s
+3nac
+6k
+7s
+6s
+5n
+6s
+4ed
+5r
+6s
+5sko
+4ickier
+9st
+7y
+5er
+6st
+5ng
+4mark
+8s
+4ochio
+9s
+6k
+7s
+4sko
+4y
+3o
+4cchio
+9s
+5hio
+8s
+4s
+3s
+4ko
+2oratura
+9e
+4d
+5s
+4in
+6s
+5tura
+8e
+2ppence
+8s
+4le
+6s
+2qh
+4s
+3ue
+5s
+2r
+3e
+4able
+5rm
+7ed
+7s
+4back
+8s
+6ll
+8er
+9rs
+8ing
+8s
+6se
+8s
+5ird
+8s
+5oard
+9s
+7t
+8s
+6mb
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+6x
+7es
+5rand
+9s
+7t
+8s
+6eak
+9s
+6ick
+9s
+5ug
+7s
+6sh
+8es
+4clay
+8s
+5racker
+9ers
+6est
+9s
+4d
+5amp
+8s
+5og
+7s
+5ragon
+9ns
+7ke
+9s
+4fang
+8ed
+8ing
+8s
+5ight
+9er
+9ers
+9ing
+9ings
+9s
+5lies
+6oat
+9s
+7od
+9s
+6y
+4guard
+9s
+4hall
+8s
+5ouse
+9s
+4less
+5ight
+9er
+9ers
+9s
+6t
+5ock
+8s
+4man
+7ic
+6rk
+8s
+5en
+4pan
+7s
+5ink
+8s
+5lace
+9d
+9s
+6ug
+8s
+5ot
+7s
+6wer
+9s
+5roof
+9ed
+9ing
+9ings
+9s
+4r
+5oom
+8s
+5s
+4s
+5creen
+9ns
+5hip
+8s
+5ide
+8s
+5tone
+9s
+7rm
+9s
+4thorn
+9s
+5rap
+8s
+6uck
+9s
+4wall
+8ed
+8ing
+8s
+6rden
+9ns
+6ter
+9s
+5eed
+8s
+5oman
+7en
+6od
+8s
+6rk
+8s
+7m
+8s
+3ie
+5s
+4ng
+6s
+3k
+4ed
+4in
+6g
+6s
+4s
+3lot
+6s
+3m
+4ament
+9al
+9s
+5n
+6s
+4ed
+5r
+6s
+5st
+4ing
+4less
+5y
+4ness
+8es
+4s
+4ware
+8s
+3n
+4s
+3rier
+6st
+5ng
+7s
+4y
+3s
+4t
+5born
+9s
+5fruits
+5hand
+5ling
+9s
+6y
+5ness
+9es
+5s
+3th
+5s
+3wood
+7s
+2sc
+4al
+6ist
+9s
+6ly
+6s
+4s
+3gig
+6s
+3h
+4abilities
+9ty
+6le
+4ball
+8s
+5olt
+8s
+6ne
+8s
+6wl
+8s
+5urger
+9rs
+4cake
+8s
+4ed
+5r
+6folk
+6ies
+6man
+7en
+6s
+6woman
+9en
+6y
+5s
+5ye
+7s
+4finger
+9rs
+5ul
+4gig
+7s
+4hook
+8s
+4ier
+6st
+5fied
+8s
+6y
+7ing
+5ly
+5ness
+9es
+6g
+7s
+4kill
+8s
+4less
+5ike
+6ne
+8s
+4meal
+8s
+5onger
+9rs
+4net
+7s
+4plate
+9s
+5ole
+8s
+6nd
+8s
+4skin
+8s
+4tail
+8ed
+8ing
+8s
+4way
+7s
+5ife
+8ly
+6ves
+5orm
+8s
+4y
+5back
+9s
+3k
+4ed
+4ing
+4s
+3nomie
+8s
+3sate
+4icostate
+5le
+6ingual
+7ties
+8y
+5on
+7ability
+9le
+9les
+8l
+7ed
+7ing
+7s
+5palmate
+7rism
+9sms
+9ties
+9ty
+8ous
+9usly
+9usness
+6ed
+8al
+8e
+9s
+8s
+5rostral
+5ve
+4le
+6d
+6s
+5ing
+4ural
+6e
+7d
+7s
+6ing
+3t
+4ed
+4fight
+9s
+5ul
+7s
+4iana
+5c
+6al
+6uff
+9s
+5er
+6st
+4mele
+8s
+4note
+8s
+4s
+4ula
+7e
+7r
+7s
+7te
+6ose
+7us
+4y
+2t
+3ch
+5e
+6e
+6s
+6t
+7s
+6w
+7s
+5y
+3ful
+6ly
+6ness
+9ses
+3lier
+6st
+4y
+3ment
+7s
+3na
+5s
+4ess
+7es
+3s
+3t
+4able
+4e
+5d
+5r
+6s
+5s
+6t
+4ing
+7ly
+7ness
+9sses
+7s
+4s
+2ve
+4finger
+9rs
+5old
+4pence
+9s
+7ny
+5in
+7s
+4r
+5s
+4s
+2x
+3able
+4te
+6d
+6s
+5if
+7s
+6ng
+6on
+8s
+6ve
+8s
+5ure
+8s
+3ed
+5ly
+5ness
+9es
+4r
+5s
+4s
+3ing
+6s
+4t
+5ies
+5y
+4ve
+3t
+4ure
+7less
+7s
+3ure
+6s
+2z
+3gig
+6ged
+7ing
+6s
+3z
+4ed
+5n
+6less
+6s
+5r
+6s
+5s
+4gig
+7s
+4ier
+6st
+5ness
+9es
+6g
+7s
+4le
+6d
+6s
+5ing
+4y
+1jeld
+5s
+2ord
+5ic
+5s
+1lab
+4bergast
+9sted
+9sting
+9sts
+5ier
+7st
+6ly
+6ness
+9ses
+5y
+4ella
+8te
+9ion
+9ions
+7iform
+7um
+9s
+4s
+3ccid
+7er
+8st
+7ities
+9y
+7ly
+7ness
+9sses
+4k
+5ed
+6r
+7ed
+7ies
+8ng
+7s
+7y
+6t
+7s
+5ing
+5s
+4on
+6s
+3ff
+5ed
+6r
+7ed
+7ing
+7s
+5ing
+5s
+3g
+4ella
+8nt
+9tism
+9tisms
+9ts
+8r
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+9ory
+7iferous
+9orm
+8n
+9s
+7omania
+9aniac
+9aniacs
+9anias
+7um
+9s
+5olet
+9s
+4ged
+6r
+7s
+5ier
+7st
+6ness
+9ses
+7g
+8ly
+8s
+5y
+4itate
+9d
+9s
+8ing
+9on
+9ons
+6ious
+9sly
+9sness
+4less
+4man
+5en
+4on
+6s
+4pole
+8s
+4rance
+9s
+8ies
+8y
+7t
+8ly
+8ness
+9esses
+4s
+5hip
+8s
+5taff
+9s
+7ves
+6ick
+9s
+6one
+9s
+3il
+5ed
+5ing
+5s
+4r
+5s
+3k
+4e
+5d
+5r
+6s
+5s
+5y
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+4s
+4y
+3m
+4be
+6au
+8s
+8x
+6e
+7d
+7ing
+7s
+6ing
+6s
+5oyance
+9ces
+9cies
+9cy
+9t
+9te
+9tes
+9tly
+9ts
+4e
+5d
+5less
+7t
+8s
+6ike
+5n
+6co
+8s
+6s
+5out
+8s
+5proof
+9fed
+9fer
+9fers
+9fing
+9fs
+5r
+6s
+5s
+5thrower
+9wers
+4few
+7s
+4ier
+6st
+5nes
+6g
+7ly
+7o
+8es
+8s
+6ical
+4m
+5abilities
+9ity
+7le
+9s
+5ed
+5iferous
+6ng
+5s
+5ulated
+9ion
+9ions
+7e
+8s
+4s
+4y
+3n
+4card
+8s
+5h
+6ed
+7s
+6ing
+9s
+5onade
+9es
+4erie
+8s
+5s
+5ur
+7s
+4ged
+6less
+6r
+7s
+6s
+5ing
+4k
+5ed
+6n
+6r
+7ed
+7ing
+7s
+5ing
+5s
+4nel
+7board
+9ards
+7ed
+8t
+9s
+9te
+9tes
+7graph
+9aphs
+7ing
+7led
+8ing
+8y
+7mouthed
+7s
+6n
+7s
+5ie
+7s
+5y
+4s
+3p
+4doodle
+9es
+4eron
+8s
+4jack
+8s
+4less
+4pable
+5ed
+6r
+7hood
+9ods
+7ish
+7s
+5ier
+7st
+6ng
+8s
+5y
+4s
+4track
+9s
+3re
+5back
+9s
+5d
+5s
+5up
+7s
+4ier
+6st
+5ng
+7ly
+4y
+3ser
+6s
+4h
+5back
+9ed
+9ing
+9s
+6oard
+9ds
+6ulb
+9s
+5card
+9s
+6ube
+9s
+5ed
+6r
+7s
+6s
+7t
+5forward
+5gun
+8s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5lamp
+9s
+6ight
+9ts
+5mobbing
+9ings
+5over
+9s
+5packer
+9ers
+5tube
+9s
+5y
+4k
+5et
+7s
+5s
+3t
+4back
+8s
+5ed
+7s
+5oat
+8s
+5read
+9s
+4cap
+7s
+6r
+7s
+4ette
+8s
+4feet
+5ish
+8es
+5oot
+8ed
+8ing
+8s
+4head
+8s
+4iron
+8s
+4land
+8er
+9rs
+8s
+5et
+7s
+5ine
+8d
+8r
+9s
+8s
+7g
+8s
+7ing
+5ong
+5y
+4mate
+8s
+4ness
+8es
+4pack
+8s
+4s
+5creen
+9ns
+5hare
+9s
+5tick
+4ted
+6n
+7ed
+8r
+9s
+7ing
+7s
+6r
+7able
+7ed
+8r
+9s
+7ies
+8ng
+9gly
+7ous
+9sly
+7s
+7y
+6st
+5ie
+7s
+6ng
+8s
+6sh
+5op
+7s
+5y
+4ulate
+9d
+8ing
+6ence
+9es
+9ies
+9y
+8t
+9ly
+5ous
+5s
+6es
+4ware
+8s
+6sh
+8es
+6ys
+5ise
+5ork
+8s
+7m
+8s
+3ught
+7ed
+8r
+9ed
+9ing
+9s
+7ing
+7s
+4nch
+7ed
+8s
+7ing
+9gs
+5e
+6s
+5t
+6ed
+7r
+8s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9ly
+6s
+6y
+4ta
+6s
+5ist
+8s
+3va
+5nol
+8s
+7ne
+9s
+5s
+4escent
+4in
+6e
+7s
+6s
+5virus
+9ses
+4one
+7s
+6oid
+9s
+7l
+8s
+5protein
+9eins
+6urpurin
+9urins
+5r
+6ed
+7r
+8s
+6ful
+9ly
+6ing
+9s
+7st
+9s
+6less
+6ous
+6s
+7ome
+6y
+5ur
+7dynamics
+7ed
+8r
+9s
+7ful
+9lly
+7ing
+9gs
+7less
+7s
+8ome
+7y
+3w
+4ed
+4ier
+6st
+5ng
+4less
+8ly
+8ness
+9esses
+4n
+5s
+4s
+4y
+3x
+4en
+5s
+4ier
+6st
+4seed
+8s
+4y
+3y
+4ed
+5r
+6s
+4ing
+4s
+5ome
+2ea
+4bag
+7s
+6ne
+8s
+5ite
+8s
+4dh
+6s
+4hopper
+9rs
+4m
+5s
+4pit
+7s
+4s
+5ome
+4wort
+8s
+3che
+6s
+6tte
+9s
+4k
+5ed
+6r
+7ed
+7ing
+7s
+5ier
+7st
+6ng
+5less
+5s
+5y
+4tion
+8al
+8less
+8s
+3d
+4ge
+6d
+6ling
+9gs
+6s
+5ier
+7st
+6ng
+5ling
+9s
+5y
+3e
+4ce
+6d
+6less
+6r
+7s
+6s
+5h
+6ed
+7s
+6ing
+9s
+6ment
+9ts
+5ie
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5y
+4ing
+4r
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5s
+4s
+4t
+5ed
+6r
+6st
+5ing
+8ly
+8ness
+9esses
+5ly
+5ness
+9es
+5s
+3g
+4ged
+5ing
+4s
+3hmen
+7ed
+7ing
+7s
+3ishig
+7k
+3me
+5s
+4ing
+5sh
+7ed
+8s
+7ing
+5t
+3nch
+6ed
+7r
+8s
+7s
+6ing
+4se
+6d
+6r
+7s
+6s
+5ing
+3sh
+5ed
+6r
+7s
+6s
+5hood
+9s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5less
+6ier
+8st
+7ness
+9sses
+8g
+9s
+6y
+5ment
+9s
+6onger
+9ers
+5pot
+8s
+5worm
+9s
+5y
+3tch
+6ed
+7r
+8s
+7s
+6ing
+9s
+4ton
+7s
+3uret
+7s
+7te
+9s
+5on
+7s
+5y
+3w
+4ed
+4s
+3x
+4agon
+8s
+4ecutive
+9ves
+5d
+5s
+4ibilities
+9ty
+6le
+8ness
+9esses
+7y
+5curities
+9ty
+5hours
+5le
+5ng
+5on
+7al
+7less
+7s
+5tarian
+9anism
+9anisms
+9ans
+6ime
+9s
+4o
+5graphic
+9hies
+9hy
+5r
+6s
+5s
+4time
+8r
+9s
+8s
+4uose
+6us
+8ly
+5ral
+6e
+7s
+3y
+4ed
+4ing
+4s
+2ibbert
+8igibbet
+8s
+3c
+4hter
+8ed
+8ing
+8s
+4k
+5able
+5ed
+6r
+7ed
+7ing
+9gly
+7s
+7tail
+9ils
+7y
+5ing
+5s
+4s
+3ed
+4r
+5s
+4s
+5t
+3ght
+6ed
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6less
+6s
+6y
+3m
+4flam
+8med
+9er
+9eries
+9ers
+9ery
+9ing
+8s
+4p
+5ed
+5ing
+5s
+4s
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+5y
+3nch
+6ed
+7r
+8s
+7s
+6ing
+9ly
+9s
+4der
+7s
+8ia
+9as
+4g
+5er
+7s
+5ing
+5s
+4kite
+8s
+4t
+5ed
+5head
+9s
+5ier
+7st
+6fied
+9s
+7y
+8ing
+6ly
+6ness
+9ses
+7g
+5like
+6ock
+9s
+5s
+5y
+3p
+4book
+8s
+4flop
+8ped
+9ing
+8s
+4pancies
+8y
+7t
+8ly
+8ness
+9esses
+5ed
+6r
+7s
+6st
+5ier
+7st
+6ng
+5y
+4s
+5ide
+8s
+3r
+4s
+4t
+5ation
+9ns
+9us
+9usly
+9usness
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8s
+6sh
+5s
+5y
+3sk
+5ed
+5ier
+7st
+6ng
+5s
+5y
+3t
+4ch
+6ed
+7s
+6ing
+4e
+5d
+5s
+4ing
+4s
+4t
+5ed
+6r
+7ed
+7ing
+7mice
+8ouse
+7n
+8s
+7s
+5ing
+8s
+3vver
+7s
+3x
+4ed
+5s
+4ing
+2oat
+5abilities
+9ity
+7le
+6ge
+8s
+6nt
+8s
+6tion
+9ns
+5cut
+5ed
+6l
+7s
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5plane
+9es
+5s
+5y
+3b
+4bed
+5ing
+4s
+3c
+4ced
+5i
+6llation
+9tions
+6ng
+5ose
+5ulant
+9ts
+8r
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7e
+8nce
+9ces
+9cies
+9cy
+9t
+9tly
+8s
+7i
+7us
+6s
+4k
+5ed
+5ier
+7st
+6ng
+8s
+5less
+5s
+5y
+4s
+3e
+4s
+3g
+4gable
+5ed
+6r
+7s
+5ing
+8s
+4s
+3kati
+7s
+3ng
+5s
+3od
+5able
+5ed
+6r
+7s
+5gate
+9s
+5ing
+8s
+5less
+6ight
+9ted
+9ting
+9tings
+9ts
+7t
+5mark
+9s
+5plain
+9ns
+5s
+5tide
+9s
+5wall
+9s
+7ter
+9rs
+7y
+8s
+4ey
+4ie
+4r
+5age
+8s
+5board
+9ds
+5cloth
+9hs
+5ed
+6r
+7s
+5head
+9s
+5ing
+8s
+5less
+5s
+6how
+9s
+5walker
+9ers
+4sie
+7s
+5y
+4zie
+7s
+5y
+3p
+4house
+9s
+4over
+8s
+4ped
+6r
+7s
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5y
+4s
+4tical
+3r
+4a
+5e
+5l
+6ly
+6s
+5s
+4eant
+6t
+7ed
+5nce
+8s
+6tine
+9es
+5scence
+9ces
+9t
+5t
+6s
+4iated
+7ion
+9ns
+5bunda
+9as
+5cane
+9s
+6ultural
+9ure
+9ures
+9urist
+9urists
+5d
+6ean
+9s
+7ous
+7r
+7st
+6ities
+8y
+6ly
+6ness
+9ses
+5er
+6st
+5ferous
+9usness
+6orm
+5gen
+8ic
+8s
+5legia
+9um
+5n
+6s
+5st
+7ic
+9ally
+9s
+7ries
+8y
+7s
+4s
+4uit
+7s
+5la
+7e
+6e
+7s
+4y
+3scular
+7e
+8s
+7ous
+4h
+5es
+4s
+5ed
+6r
+7s
+6s
+5ie
+7r
+7s
+8t
+6ly
+6ng
+8s
+5y
+3ta
+5ge
+7s
+5nt
+5s
+5tion
+9s
+4e
+5l
+6s
+5s
+4illa
+8s
+4sam
+7s
+3unce
+7d
+7s
+6ier
+8st
+7ng
+9s
+6y
+5der
+8ed
+8ing
+8s
+4r
+5ed
+5ier
+7st
+6ng
+6sh
+8ed
+9r
+9rs
+9s
+8ing
+9ngly
+8y
+5less
+5s
+5y
+4se
+6d
+6s
+5h
+6ed
+7s
+6ing
+5ing
+4t
+5ed
+6r
+7s
+5ing
+8ly
+8stock
+9tocks
+5s
+3w
+4age
+7s
+4chart
+9ing
+9ings
+9s
+4ed
+5r
+6age
+9s
+6bed
+9s
+6ed
+7r
+8s
+7t
+8s
+8te
+9es
+6ful
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9s
+6less
+7ike
+6pot
+9s
+6s
+6y
+4ing
+7ly
+7ness
+9sses
+4meter
+9s
+4n
+4s
+5tone
+9s
+3x
+2u
+3ate
+6s
+3b
+4bed
+6r
+7s
+5ing
+4dub
+7s
+4s
+3ctuant
+7te
+9d
+9s
+8ing
+9on
+9onal
+9ons
+3e
+4d
+4gelhorn
+9rns
+4llen
+8s
+6in
+8s
+4nce
+7s
+6ies
+6y
+5t
+6ly
+6ness
+9ses
+6s
+4ric
+7s
+4s
+4work
+8s
+4y
+3ff
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5s
+5y
+3gel
+6horn
+9nist
+9nists
+9ns
+6man
+7en
+6s
+3id
+5al
+7ly
+5extract
+9acts
+5ic
+7s
+6fied
+9s
+7y
+8ing
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5like
+6y
+5ness
+9es
+5ram
+8s
+5s
+4er
+5st
+4sh
+3ke
+5d
+5s
+5y
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4y
+3me
+5d
+5s
+4ing
+4meries
+7y
+5ox
+7ed
+8s
+7ing
+4p
+5ed
+5ing
+5s
+3ng
+4itrazepam
+9epams
+4k
+5ed
+6r
+7s
+6y
+7dom
+9ms
+7ish
+9m
+9ms
+7s
+5ie
+7s
+6ng
+5s
+5y
+6ism
+9s
+3or
+5apatite
+9ites
+5ene
+8s
+6sce
+9d
+9in
+9ine
+9ines
+9ins
+9nce
+9nces
+9nt
+9nts
+9r
+9rs
+9s
+8ing
+5ic
+6d
+7ate
+9ed
+9es
+9ing
+9ion
+9ions
+7e
+8s
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7s
+6meter
+9ers
+9ric
+9ries
+9ry
+6n
+7ate
+9ed
+9es
+9ing
+9ion
+9ions
+7e
+8s
+7s
+6te
+8s
+5oacetate
+9tates
+6carbon
+9bons
+7hrome
+9omes
+6graphic
+9phies
+9phy
+6meter
+9ers
+9ric
+9ries
+9ry
+6phore
+9res
+6scope
+9ped
+9pes
+9pic
+9pies
+9ping
+9pist
+9pists
+9py
+7es
+7is
+6tic
+7ype
+9es
+6uracil
+9cils
+5s
+6par
+9s
+4xetine
+9es
+3phenazine
+9ines
+3rr
+5ed
+5ied
+7s
+6ng
+5s
+5y
+6ing
+3s
+4h
+5able
+5ed
+6r
+7s
+6s
+7t
+5ier
+7st
+6ng
+8s
+5ness
+9es
+5work
+9s
+5y
+4ter
+7ed
+9ly
+7ing
+7ment
+9nts
+7s
+7y
+5rate
+9d
+9s
+8ing
+9on
+9ons
+3te
+5d
+5like
+5mouth
+9hs
+5r
+6s
+5s
+5y
+4ier
+6st
+5na
+7s
+6g
+7s
+5st
+7s
+4ter
+7board
+9ards
+7ed
+8r
+9s
+7ing
+9gly
+7s
+7y
+4y
+3vial
+7ist
+9ts
+6tic
+8le
+5omarine
+4oxamine
+9nes
+3x
+4ed
+5s
+4gate
+8s
+4ing
+5on
+7al
+9ly
+8ry
+7ist
+9ts
+7s
+5ve
+4meter
+9s
+3yt
+5s
+2y
+3able
+4way
+7s
+3back
+7s
+5ne
+7s
+4elt
+7s
+4lew
+5ow
+7ing
+7n
+7s
+4oat
+7s
+5ok
+7s
+5y
+6s
+4ridge
+9s
+4y
+5s
+3catcher
+9rs
+3er
+5s
+4st
+3hand
+7s
+3ing
+6s
+3leaf
+6ves
+5ss
+3maker
+8s
+5n
+4en
+3off
+6s
+4ver
+7s
+3paper
+8s
+5st
+7s
+4e
+5d
+5s
+4ing
+5tch
+8er
+9rs
+9s
+4oster
+9s
+7ing
+9gs
+3rodder
+9s
+3sch
+6es
+5reen
+9s
+4heet
+8s
+4peck
+8ed
+8ing
+8s
+5ray
+8s
+4trike
+9s
+4watter
+9rs
+3te
+5d
+5s
+4ier
+7s
+5ng
+7s
+4rap
+7s
+3way
+6s
+4eight
+9s
+4heel
+8s
+1oal
+4ed
+4foot
+8s
+4ing
+4s
+3m
+4able
+4ed
+5r
+6s
+4flower
+9rs
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7ly
+7s
+4less
+5ike
+4s
+4y
+2b
+3bed
+4ing
+3s
+2caccia
+8s
+4l
+5isation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ly
+3i
+4meter
+9s
+3ometer
+9s
+3us
+5able
+5ed
+6r
+7s
+6s
+5ing
+8s
+5less
+5sed
+7s
+6ing
+2dder
+6ed
+7r
+8s
+6ing
+9s
+6s
+3gel
+2e
+3darie
+8s
+4erati
+8us
+3hn
+5s
+3man
+4en
+3n
+3s
+3tal
+5tion
+9s
+4icidal
+8e
+9s
+5d
+6er
+7st
+6ly
+6ness
+9ses
+5parous
+4or
+6s
+5scopies
+9y
+4us
+6es
+2g
+3ash
+6es
+3bound
+5w
+6s
+3dog
+6s
+3ey
+5dom
+8s
+5ish
+7m
+8s
+5s
+3fruit
+8s
+3gage
+7s
+4ed
+5r
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4y
+3horn
+7s
+3ie
+5s
+3le
+5s
+6s
+3man
+4en
+3ou
+5s
+3ram
+6ite
+9s
+8ies
+8y
+6s
+3s
+3y
+4dom
+7s
+4ish
+6m
+7s
+2h
+3n
+4s
+2ible
+6s
+3d
+4s
+3l
+4able
+4borne
+4ed
+4ing
+7s
+4s
+5man
+6en
+3n
+4ed
+4ing
+7ly
+4s
+3son
+6less
+6s
+4t
+5ed
+6r
+7s
+5ing
+5s
+2lacin
+7s
+4te
+6s
+3d
+4able
+5way
+8s
+4back
+8s
+5oat
+8s
+4ed
+5r
+6ol
+8s
+6s
+4ing
+7s
+4out
+7s
+4s
+4up
+6s
+3ey
+5s
+3ia
+5ceous
+5ge
+7d
+7s
+5r
+5te
+7d
+7s
+6ing
+7on
+9s
+6ure
+9s
+4c
+4e
+5s
+4o
+5ed
+5ing
+5late
+6e
+7s
+6ose
+5s
+6e
+5us
+4um
+6s
+3k
+4ie
+6r
+6s
+7t
+5sh
+7ness
+9sses
+4land
+8s
+5ife
+6ke
+6ves
+5ore
+8s
+7ic
+8sh
+9t
+9tic
+9ts
+4moot
+8s
+6t
+7e
+8s
+7s
+4s
+5ier
+7st
+6ly
+6ness
+9ses
+7ger
+9rs
+8ing
+9ngs
+5ong
+8s
+7omies
+9y
+5y
+4tale
+8s
+5ronica
+9cas
+4way
+7s
+4y
+3les
+4icle
+8s
+6ular
+9te
+9ted
+8in
+9ns
+9tes
+9tides
+9tis
+9tises
+8ose
+9us
+5ed
+6s
+5s
+4ow
+6able
+6ed
+7r
+8s
+9hip
+9hips
+6ing
+9s
+6s
+7hip
+9ps
+6up
+8s
+4y
+5ing
+2ment
+6ation
+9ons
+6ed
+7r
+8s
+6ing
+6s
+4s
+3ite
+6s
+2n
+3ctionnaire
+9aires
+3d
+4a
+5nt
+7s
+5s
+4ed
+5r
+5st
+4ing
+4le
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+5y
+4ness
+8es
+4s
+4u
+5e
+6d
+6ing
+6s
+5ing
+5s
+3e
+3ly
+3ned
+4ing
+3s
+3t
+4al
+5nel
+8le
+9es
+8s
+6ge
+8s
+4iculi
+8us
+5na
+7lis
+9ses
+7s
+4let
+7s
+4s
+2obar
+3d
+4ful
+4ie
+6s
+5sm
+7s
+4less
+8ness
+9esses
+4s
+5tuff
+9s
+4ways
+4y
+3faraw
+8s
+3l
+4begged
+4ed
+5ries
+6y
+4fish
+8es
+4hardier
+9est
+9ly
+9ness
+9nesses
+9se
+9ses
+9ze
+9zes
+8y
+4ing
+7s
+5sh
+7er
+8st
+7ly
+7ness
+9sses
+4proof
+4s
+5cap
+8s
+3sball
+8s
+3t
+4age
+7s
+4bag
+7s
+6ll
+8ene
+9nes
+9r
+9rs
+8ing
+9st
+9sts
+8s
+6r
+7s
+6th
+8s
+5oard
+9s
+6y
+7s
+5rake
+9s
+6eadth
+9ths
+6idge
+9es
+4cloth
+9s
+4dragger
+9ers
+4ed
+5r
+6ed
+6ing
+6s
+4fall
+8s
+6ult
+9ed
+9ing
+9s
+4gear
+8s
+5uards
+4hill
+8s
+5old
+8s
+4ie
+6r
+6s
+7t
+5ng
+7s
+4lambert
+9rts
+5e
+6d
+6r
+7s
+6s
+7s
+8ly
+8ness
+9esses
+5ight
+9s
+6ke
+6ng
+8s
+5ocker
+9rs
+6ose
+4man
+6rk
+8s
+5en
+5uff
+8s
+4note
+8d
+8s
+7ing
+4pace
+8s
+6d
+7s
+6ge
+8s
+6th
+8s
+5late
+9man
+9men
+9s
+9woman
+9women
+5ost
+8s
+5rint
+9s
+5ump
+8s
+4ra
+6ce
+8s
+6s
+5est
+8s
+5ope
+8s
+5ule
+8s
+4s
+5ie
+7s
+5log
+8ged
+9er
+9ers
+9ing
+9ings
+8s
+5ore
+8ness
+9esses
+5talk
+9s
+8l
+9s
+6ep
+8s
+6ock
+9s
+7ne
+9s
+7ol
+9ed
+9s
+5y
+4wall
+8s
+6y
+7s
+5ear
+8s
+8y
+6ll
+8s
+5ork
+8s
+7n
+4y
+3zle
+6d
+6r
+7s
+6s
+5ing
+8s
+2p
+3ling
+7s
+3ped
+5ries
+6y
+4ing
+5sh
+7ly
+7ness
+9sses
+3s
+2r
+3a
+4ge
+6d
+6r
+7s
+6s
+5ing
+4m
+5en
+7s
+5ina
+8l
+8ted
+7ifer
+9era
+9eral
+9eran
+9erans
+9erous
+9ers
+7ous
+5s
+4ne
+4smuch
+4y
+5ed
+6r
+7s
+5ing
+5s
+3b
+4ad
+6e
+5re
+4ear
+7ance
+9ces
+9t
+7er
+9s
+7ing
+9gly
+7s
+4id
+6al
+8s
+6dal
+9s
+8nce
+9ces
+7en
+9ly
+8r
+9s
+7ing
+9gly
+9gness
+9gs
+6s
+4ode
+7d
+7s
+6ing
+5re
+6ne
+4s
+4y
+5e
+3cat
+6s
+4e
+5able
+5d
+6ly
+6ness
+9ses
+5ful
+8ly
+8ness
+9esses
+5less
+5meat
+9s
+5ps
+7es
+7like
+5r
+6s
+5s
+4ibilities
+9ty
+6le
+8ness
+9esses
+7y
+5ng
+7ly
+5pate
+9d
+8ion
+9ons
+6es
+3d
+4able
+4ed
+4id
+5ng
+4less
+4o
+5es
+5ing
+5ne
+6ne
+4s
+3e
+4anent
+5rm
+7ed
+7ing
+7s
+4bay
+7s
+5ear
+8s
+5itt
+8er
+9rs
+8s
+5ode
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ies
+8ng
+9gly
+9gness
+9gs
+7y
+6om
+8s
+5rain
+9s
+5y
+6e
+4cabin
+9s
+6ddie
+9es
+8y
+6r
+7riage
+9ages
+7s
+6st
+8able
+8ed
+9r
+9rs
+8ing
+9ngs
+8le
+9es
+8s
+5heck
+9ed
+9er
+9ers
+9ing
+9s
+6osen
+5losable
+8e
+9d
+9s
+8ing
+8ure
+9res
+7th
+9s
+5ourse
+9es
+8t
+9s
+4damned
+6te
+8d
+8s
+7ing
+5eck
+8s
+5id
+5o
+6es
+6ing
+6ne
+6om
+8ed
+8ing
+8s
+4face
+8s
+6ther
+9rly
+9rs
+5eel
+8ing
+9ngly
+8s
+7t
+6lt
+6nd
+8ed
+8ing
+8s
+5inger
+9rs
+5oot
+5ront
+9s
+4gather
+9red
+9ring
+9rs
+5leam
+9s
+5o
+6er
+8s
+7s
+6ing
+9s
+6ne
+8ness
+9esses
+5round
+9ded
+9ding
+9ds
+5ut
+7s
+4hand
+8ed
+9dly
+9dness
+8ing
+8s
+5ead
+8s
+6nt
+8ing
+8s
+5ock
+8s
+6of
+8s
+7ves
+4ign
+7er
+9s
+7ism
+9ms
+7ly
+7ness
+9sses
+4judge
+9d
+9ment
+9ments
+9s
+8ing
+8ment
+9ents
+4king
+8s
+5new
+6ow
+8able
+8ing
+9ngly
+8ledge
+9edges
+8n
+8s
+4l
+5adies
+7y
+6id
+7n
+6nd
+8s
+6y
+7ing
+7s
+5eg
+7s
+6nd
+8ing
+8s
+7t
+5ie
+7s
+6ft
+8ed
+8ing
+8s
+6mb
+8s
+5ock
+8ed
+8ing
+8s
+5s
+5ying
+4man
+7ship
+9ips
+6st
+8man
+9en
+8s
+5ean
+8ing
+8s
+8t
+6n
+7tioned
+5ilk
+8s
+5ost
+6ther
+9rs
+4name
+8d
+8s
+5ight
+9s
+5oon
+8s
+5sic
+8alities
+9lity
+9lly
+8s
+4ordain
+9ned
+9ning
+9nment
+9nments
+9ns
+7ination
+9ations
+4part
+8s
+6ssed
+7t
+6w
+7s
+6yment
+9nts
+5eak
+8s
+5lan
+8ned
+9ing
+8s
+7y
+8s
+5oint
+9ed
+9ing
+9s
+4quarter
+9ers
+4ran
+7k
+8s
+5each
+9ed
+9es
+9ing
+7d
+8ing
+9ngs
+8s
+5un
+7ner
+9rs
+8ing
+7s
+4s
+5aid
+7l
+8s
+6w
+6y
+7ing
+7s
+5ee
+7ability
+9le
+7ing
+9gly
+7n
+7r
+8s
+7s
+5hadow
+9wed
+9wer
+9wers
+9wing
+9wings
+9ws
+7nk
+9s
+6eet
+9s
+7w
+8ed
+8ing
+8n
+8s
+6ip
+8s
+6ock
+9s
+7re
+9s
+8ten
+9ened
+9ening
+9enings
+9ens
+7w
+8ed
+8ing
+8n
+8s
+5ide
+8s
+6ght
+9ed
+9edly
+9edness
+9ful
+9less
+9s
+7nified
+9fies
+9fy
+9fying
+5kin
+8s
+7rt
+9s
+5lack
+9ed
+9ing
+9s
+6ow
+8ed
+8ing
+8s
+5pake
+6eak
+9ing
+9s
+7nd
+9ing
+9s
+8t
+6oke
+9n
+5t
+6age
+9s
+7ir
+9s
+7l
+8l
+9ed
+9er
+9ers
+9ing
+9ings
+9ment
+9ments
+9s
+8ment
+9ents
+7tion
+9ons
+7y
+8s
+9ail
+9ails
+6eal
+7d
+7r
+8s
+6ial
+7ne
+8g
+6land
+9ds
+7ess
+6ries
+7y
+6s
+5wear
+9ing
+9s
+6ore
+8n
+4taste
+9d
+9s
+8ing
+6ught
+5each
+9es
+9ing
+6eth
+6ll
+8er
+9rs
+8ing
+8s
+5hink
+9er
+9ers
+9ing
+9s
+6ought
+9htful
+9hts
+5ime
+8s
+5oken
+9ed
+9ing
+9ings
+9s
+6ld
+6oth
+6p
+7man
+9st
+9sts
+8en
+7s
+5riangle
+9gles
+4ver
+7more
+7ness
+9sses
+7s
+5ouched
+4ward
+8s
+7n
+8ed
+9r
+9rs
+8ing
+9ngly
+9ngs
+8s
+5eigh
+9ed
+9ing
+9s
+6nt
+5ind
+8s
+7g
+8s
+5oman
+7en
+6rd
+8s
+7n
+4x
+5es
+4yard
+8s
+3fair
+7ed
+7ing
+7n
+7s
+6ter
+9s
+7ing
+9gs
+5ult
+8s
+4eit
+7able
+7ed
+8r
+9s
+7ing
+7s
+7ure
+9es
+5nd
+7ed
+7ing
+7s
+5uchen
+5x
+6es
+4icate
+6ulate
+4ochen
+5ughen
+8ten
+3gat
+6her
+9ed
+9ing
+9s
+5ve
+4e
+5abilities
+9ity
+7le
+5d
+5man
+6en
+5r
+6ies
+6s
+6y
+5s
+5t
+6ful
+9ly
+9ness
+9nesses
+6ive
+6s
+6table
+7er
+9ies
+9s
+9y
+7ing
+9gly
+9gs
+4ing
+7s
+5vable
+9y
+6e
+7n
+8ess
+9sses
+7r
+8s
+7s
+6ing
+9ly
+9ness
+9nesses
+4o
+5er
+7s
+6s
+5ing
+5ne
+5t
+6ten
+9ness
+9nesses
+3haile
+8d
+8s
+7ing
+4ent
+7ing
+7s
+4oo
+6ed
+6ie
+8d
+8ing
+8s
+7ng
+6s
+5w
+6ed
+6ing
+6s
+3insec
+8al
+5t
+6s
+4sfamiliate
+9liated
+9liates
+3jaskit
+4eskit
+4udge
+8d
+8s
+7ing
+7ment
+9nts
+3k
+4ball
+8s
+4ed
+6ly
+6ness
+9ses
+5r
+6s
+4ful
+7s
+4head
+8s
+4ier
+6st
+5ness
+9es
+6g
+4less
+5ift
+8ed
+8ing
+8s
+6ke
+4s
+5ful
+4tail
+8s
+4y
+3lana
+7s
+4end
+7ing
+7s
+6t
+4orn
+7er
+8st
+7ly
+7ness
+9sses
+7s
+3m
+4abilities
+9ty
+6le
+7y
+5l
+6dehyde
+9ydes
+6in
+8s
+7sable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ically
+9s
+7ter
+8ies
+8y
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ly
+6ness
+9ses
+6s
+5mide
+9s
+5nt
+7s
+5t
+6e
+7d
+7s
+6ing
+7on
+9al
+9s
+7ve
+9ly
+9ness
+9nesses
+9s
+6s
+6ted
+8r
+9s
+7ing
+4e
+5d
+5e
+5r
+6ly
+6s
+5s
+4fitting
+5ul
+4iate
+8s
+5c
+6a
+7nt
+7ria
+9es
+9um
+8y
+7s
+7te
+9d
+9s
+8ing
+9on
+9ons
+5dabilities
+9lity
+8le
+9eness
+9y
+5ng
+7s
+4less
+8ly
+8ness
+9esses
+4ol
+6s
+4s
+4ula
+7e
+7ic
+9ally
+7r
+8ies
+9sation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9stic
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8y
+7s
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6ise
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7ze
+9d
+9s
+8ing
+4work
+8s
+4yl
+6s
+3nenst
+6t
+4ical
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+8ress
+9esses
+6es
+5x
+3pet
+6s
+4ine
+7d
+7s
+6ing
+5t
+6s
+3rad
+6er
+5rder
+5y
+6ed
+6ing
+6s
+4en
+4it
+3said
+5ke
+7n
+8ly
+8ness
+9esses
+7r
+8s
+7s
+6ing
+9s
+5y
+6ing
+6s
+4lack
+8ed
+8ing
+8s
+5oe
+7d
+7ing
+7s
+6w
+7ed
+7ing
+7s
+4ook
+6th
+4peak
+8ing
+8s
+6nd
+8ing
+8s
+7t
+5oke
+8n
+4terite
+9es
+4watt
+5ear
+8er
+9rs
+8ing
+8s
+5ink
+8ed
+8ing
+8s
+5onck
+6re
+7n
+8ness
+9esses
+5unk
+4ythia
+9s
+3t
+4alice
+9s
+4e
+5d
+5pianist
+9ists
+9o
+9os
+5s
+4h
+5came
+6ome
+9s
+8ing
+9ngness
+5going
+9gs
+5ink
+8ing
+8s
+5ought
+5right
+9tly
+9tness
+9ts
+5with
+5y
+4ies
+6th
+8s
+5fiable
+7cation
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+9gly
+5lage
+9s
+5ng
+5s
+6simi
+9o
+9os
+8ssimo
+5tude
+9s
+8inous
+4let
+7s
+4night
+9lies
+9ly
+9s
+4ress
+8ed
+9s
+8ing
+8like
+4s
+4uities
+8sm
+9ms
+9t
+9ts
+7ous
+9sly
+9sness
+7y
+5nate
+9ly
+9ness
+9nesses
+9s
+6e
+7d
+7less
+7s
+7teller
+9llers
+9lling
+9llings
+6ing
+7ze
+9d
+9s
+8ing
+4y
+5ish
+3um
+5s
+3wander
+9ed
+9ing
+9s
+5rd
+7ed
+8r
+9s
+8st
+7ing
+9gs
+7ly
+7ness
+9sses
+7s
+6n
+7ed
+7ing
+7s
+5ste
+8d
+8s
+7ing
+4earied
+9s
+7y
+8ing
+5nt
+4hy
+4orn
+3za
+5ndi
+7o
+8s
+5ti
+6o
+7s
+4e
+2scarnet
+9s
+3s
+4a
+5e
+5s
+5te
+4e
+5d
+5s
+5tte
+8s
+4ick
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5l
+6iferous
+7sable
+9tion
+9tions
+8e
+9d
+9s
+8ing
+7zable
+9tion
+9tions
+8e
+9d
+9s
+8ing
+6s
+4or
+6ial
+6s
+4ula
+7e
+7te
+3ter
+6age
+9s
+6ed
+7r
+8s
+6ing
+9s
+6ling
+9gs
+6s
+4ress
+8es
+2ther
+6ed
+6gilla
+9las
+6ing
+6s
+2u
+3at
+5s
+3d
+4rie
+7s
+5oyant
+4s
+3er
+4st
+4t
+5s
+5te
+7s
+3gade
+7s
+5sse
+8s
+4ht
+6en
+6ier
+8st
+6y
+3l
+4ard
+7s
+4brood
+9s
+4der
+7ed
+7ing
+7s
+4e
+5d
+5r
+5s
+6t
+4ie
+6s
+5ng
+7s
+4ly
+4mart
+8s
+5outhed
+4ness
+8es
+4s
+3mart
+7s
+3nd
+5ation
+9nal
+9nally
+9nary
+9ner
+9ners
+9nless
+9ns
+5ed
+6r
+7ed
+7ing
+7ous
+7s
+5ing
+8s
+5ling
+9s
+5ress
+9es
+6ies
+6y
+5s
+4t
+5ain
+8ed
+8head
+9eads
+8ing
+8less
+8s
+5ful
+5s
+3r
+4ball
+8s
+4chee
+7tte
+9es
+4drinier
+9ers
+4eyed
+4fold
+8ness
+9esses
+4gon
+7s
+4pence
+9s
+7nies
+8y
+5lay
+8s
+6ex
+8es
+4ragere
+9es
+4s
+5core
+8th
+5es
+5ome
+8s
+5quare
+9ely
+9eness
+4teen
+8er
+9rs
+8s
+8th
+9hly
+9hs
+5h
+6ly
+6s
+3s
+4sa
+6s
+4tier
+7st
+5y
+3ter
+6ed
+6ing
+6s
+4h
+5s
+4ra
+6s
+5e
+6d
+6s
+5ing
+2vea
+5e
+5l
+5s
+5te
+7d
+4iform
+4ola
+7e
+7r
+7s
+7te
+9d
+6e
+7s
+7t
+8s
+2wl
+4ed
+5r
+6s
+4ing
+7s
+4pox
+7es
+4s
+3th
+5s
+2x
+3berries
+7y
+3ed
+4s
+3fire
+7s
+5sh
+7es
+3glove
+8s
+3hole
+7s
+5und
+8s
+4unt
+7ed
+8r
+9s
+7ing
+9gs
+7s
+3ie
+5r
+5s
+6t
+4ly
+4ness
+8es
+5g
+6s
+3like
+3shark
+8s
+5ip
+7s
+4kin
+7s
+3tail
+7s
+4rot
+7s
+7ted
+8ing
+3y
+2y
+3boat
+7s
+3er
+5s
+3le
+5d
+5s
+4ing
+3ne
+5d
+5s
+4ing
+3s
+2zier
+5st
+4ness
+8es
+3y
+1ra
+3b
+4bed
+5ing
+6t
+4jous
+8ly
+4s
+3cas
+6es
+4k
+5ing
+8s
+4t
+5al
+7ities
+9y
+7s
+5ed
+5i
+6ng
+6on
+8al
+9lise
+9lised
+9lises
+9lising
+9lism
+9lisms
+9list
+9lists
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9ry
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+8ed
+8ing
+9sation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8let
+9ets
+8s
+7us
+9ly
+9ness
+9nesses
+5ocumuli
+9ulus
+6graphies
+9phy
+6strati
+9atus
+5s
+5ur
+7able
+8l
+7e
+8d
+8r
+9s
+8s
+7ing
+7s
+6s
+3e
+4na
+5um
+7s
+3g
+4ged
+5ing
+8s
+4ile
+7ly
+7ness
+9sses
+7r
+7st
+6ities
+8y
+4ment
+8al
+9lly
+9rily
+9riness
+9ry
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+8ed
+8ing
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+8s
+4or
+6s
+4rance
+9d
+9s
+8ies
+9ng
+8y
+7t
+8ly
+8ness
+9esses
+4s
+3icheur
+9s
+4l
+5er
+6st
+5ish
+5ly
+5ness
+9es
+5s
+5tee
+8s
+6ies
+6y
+4m
+5s
+4se
+6d
+6s
+5ing
+3ktur
+7s
+3mable
+4besia
+9s
+5oesia
+9as
+6ise
+9s
+4e
+5able
+5d
+5less
+5r
+6s
+5s
+6hift
+9ts
+5work
+9s
+4ing
+7s
+4pal
+5ler
+8s
+5old
+3nc
+5hise
+9d
+9e
+9es
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+8or
+9rs
+5isation
+9ions
+7e
+8d
+8s
+7ing
+6um
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5o
+6lin
+9s
+6mania
+9ias
+6phil
+9le
+9les
+9ls
+8obe
+9bes
+9bia
+9bias
+9ne
+9nes
+5s
+4ger
+7s
+5ibilities
+9ity
+7le
+9ness
+9nesses
+6pane
+9es
+9i
+9is
+9ni
+5lais
+4ion
+7s
+4k
+5able
+6lmoign
+9igns
+5ed
+6r
+7s
+6st
+5fort
+9s
+6urt
+9er
+9ers
+9s
+5incense
+9nses
+7g
+5lin
+8ite
+9tes
+8s
+6y
+5ness
+9es
+5pledge
+9ges
+5s
+4seria
+9s
+4tic
+7ally
+7ly
+7ness
+9sses
+4zier
+7st
+5y
+3p
+4e
+4pant
+5e
+6d
+6e
+6s
+5ing
+4s
+3s
+4cati
+8s
+4s
+5es
+3t
+4ch
+6es
+7ty
+6ier
+8st
+7ng
+6y
+4e
+5r
+6ies
+6nal
+9ism
+9isms
+9ly
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+6s
+6y
+4i
+4ricidal
+9e
+9es
+6es
+5y
+4s
+3u
+4d
+5ful
+8ly
+5s
+6man
+7en
+6ter
+9s
+5ulence
+9ces
+9cies
+9cy
+9t
+9tly
+9tness
+4ghan
+8s
+6t
+7age
+9es
+7ed
+8r
+8st
+7ing
+7s
+4lein
+8s
+4s
+4tage
+8s
+3wzey
+7s
+3xinella
+9as
+3y
+4ed
+4ing
+7s
+4s
+3zil
+6s
+4zle
+7d
+7s
+6ing
+2eak
+5ed
+6ries
+7y
+5ful
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+6sh
+8ly
+8ness
+9esses
+5out
+8s
+5s
+5y
+3ckle
+7d
+7s
+6ier
+8st
+7ng
+9s
+6y
+3daine
+8s
+3e
+4base
+8d
+8r
+9s
+8s
+7ing
+5ee
+7s
+5ie
+7s
+5oard
+9s
+6ot
+8ed
+9r
+9ries
+9rs
+9ry
+8ies
+9ng
+9ngs
+8s
+8y
+6rn
+4cooling
+9ngs
+5ycle
+9d
+9s
+8ing
+4d
+5iver
+9s
+7ing
+9gs
+5man
+6en
+5om
+7s
+5woman
+8en
+4form
+4gan
+7ism
+9ms
+7s
+4hand
+8ed
+9dly
+9dness
+5earted
+9edly
+5old
+8er
+9rs
+8s
+4ing
+4lance
+9d
+9r
+9rs
+9s
+8ing
+5oad
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+5y
+4man
+6rtin
+9ns
+6son
+9ic
+9ries
+9ry
+9s
+5en
+4ness
+8es
+4phone
+9s
+4r
+5ide
+8s
+5s
+4s
+5heet
+9s
+5ia
+7s
+5t
+6anding
+6one
+9s
+6yle
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+4t
+5hinker
+9ers
+9ing
+9ings
+5ier
+7st
+5s
+5y
+4ware
+8s
+6y
+7s
+5heel
+9ed
+9er
+9ers
+9ing
+9ingly
+9ings
+9s
+5ill
+5oman
+7en
+5rite
+9s
+8ing
+9ngs
+8ten
+6ote
+4zable
+5e
+6r
+7s
+6s
+5ing
+8ly
+8s
+3ight
+7age
+9es
+7ed
+8r
+9s
+7ing
+7less
+7s
+4t
+5ier
+7st
+5s
+5y
+3md
+5s
+4escence
+9ces
+9t
+4it
+6s
+6us
+8es
+3na
+4ch
+6ed
+7s
+6ification
+9ed
+9es
+8y
+9ing
+7ng
+4etic
+8al
+9lly
+8ism
+9sms
+8ness
+9esses
+8s
+4ne
+6s
+4ula
+7r
+6um
+8s
+5m
+6s
+4zical
+6ed
+8ly
+7s
+6ly
+5y
+6ing
+3quence
+9s
+8ies
+8y
+7t
+8able
+9tion
+9tions
+9tive
+9tives
+8ed
+9r
+9rs
+9st
+8ing
+8ly
+8ness
+9esses
+8s
+3re
+5s
+3scade
+8s
+5o
+6ed
+7r
+8s
+7s
+6ing
+9s
+7st
+9s
+6s
+4h
+5ed
+6n
+7ed
+8r
+9s
+7ing
+7s
+6r
+7dom
+9ms
+7s
+6s
+7t
+6t
+7s
+5ie
+7s
+6ng
+6sh
+5ly
+5man
+8ship
+9hips
+6en
+5ness
+9es
+5water
+9rs
+4nel
+7s
+3t
+4board
+9s
+4ful
+7ly
+7ness
+9sses
+4less
+4s
+5aw
+7s
+5ome
+4ted
+6r
+7s
+5ier
+7st
+6ng
+8s
+5y
+4work
+8s
+2iabilities
+9y
+5le
+7ness
+9sses
+4nd
+6e
+7s
+6s
+4r
+5bird
+9s
+5ies
+5ly
+5s
+5y
+3b
+4ble
+7d
+7r
+8s
+7s
+6ing
+7sh
+4s
+3cadel
+8s
+5ndeau
+9us
+9ux
+7o
+8es
+5ssee
+9d
+9ing
+9s
+5tive
+9s
+4ht
+6ed
+6ing
+6s
+4king
+4tion
+8al
+9lly
+8less
+9essly
+8s
+3dge
+6d
+6s
+5ing
+3ed
+5cake
+9s
+4nd
+6ed
+6ing
+9s
+6less
+9sness
+7ier
+9s
+9st
+8ly
+8ness
+9esses
+7y
+6s
+7hip
+9ps
+4r
+5s
+4s
+4ze
+6d
+6like
+6s
+5ing
+3g
+4ate
+7s
+6oon
+9s
+4es
+4ged
+6r
+7s
+5ing
+8s
+4ht
+6ed
+7n
+8ed
+9r
+9rs
+8ing
+9ngly
+8s
+6ful
+9ly
+9ness
+9nesses
+6ing
+6s
+7ome
+4id
+6aria
+9um
+6er
+7st
+6ities
+8y
+6ly
+6ness
+9ses
+4orific
+9co
+9cos
+5t
+6s
+4s
+3jol
+6e
+7s
+3kkadel
+9s
+3ll
+5ed
+6r
+7s
+5ier
+7s
+8t
+6ness
+9ses
+7g
+8s
+5s
+5y
+3nge
+6d
+6less
+6s
+5ier
+7st
+6llaceous
+8id
+9form
+9ne
+6ng
+5y
+3pon
+6nerie
+9ies
+6s
+4per
+7er
+9s
+7ies
+7s
+7y
+6t
+7s
+3s
+4bee
+7s
+4e
+5e
+6s
+5s
+5tte
+8s
+5ur
+7s
+4k
+5a
+6s
+5ed
+6r
+7s
+6t
+7s
+5ful
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+8s
+5s
+5y
+4son
+7s
+4t
+5ed
+5ing
+5s
+4ure
+7s
+3t
+4es
+4flies
+6y
+4h
+5borh
+9s
+5s
+6oken
+9ns
+6tool
+9ls
+4illaria
+9ias
+9ies
+9y
+4s
+4t
+5ata
+8s
+5ed
+6r
+7ed
+8r
+9s
+7ing
+7s
+5ing
+5s
+4ure
+7s
+4z
+5es
+3vol
+6ed
+7r
+8s
+6ing
+7ties
+8y
+6led
+8r
+9s
+7ing
+6ous
+9ly
+9ness
+9nesses
+6s
+3z
+4e
+5d
+5r
+6s
+5s
+5tte
+8s
+4ing
+4z
+5ante
+5ed
+6r
+7s
+6s
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5le
+7d
+7r
+8s
+7s
+6ier
+8st
+7ness
+9sses
+8g
+6y
+5y
+2o
+3ck
+5ed
+5ing
+8s
+5less
+5s
+3e
+4s
+3g
+4bit
+7s
+4eye
+7d
+7s
+4fish
+8es
+4ged
+6ries
+7y
+5ier
+7st
+6ng
+8s
+5y
+4hopper
+9rs
+4let
+7s
+5ike
+6ng
+8s
+4man
+6rch
+9ed
+9es
+9ing
+5en
+5outh
+9s
+4s
+5pawn
+9s
+3ideur
+8s
+4ng
+6s
+4se
+6s
+3lic
+6ked
+8r
+9s
+7ing
+7y
+6s
+7ome
+9ely
+9eness
+3m
+4age
+7s
+4enties
+7y
+3nd
+5age
+8s
+5ed
+6nt
+6scence
+9nces
+9nt
+6ur
+8s
+5iferous
+5less
+5ose
+6us
+5s
+4s
+4t
+5age
+8r
+9s
+8s
+6l
+7ities
+9y
+7ly
+7s
+5bencher
+9hers
+5court
+9ts
+5ed
+6nis
+9es
+6r
+6s
+5ier
+8ed
+8ing
+8s
+9man
+9men
+9woman
+9women
+6ng
+6spiece
+9eced
+9eces
+9ecing
+5less
+9ly
+7t
+8s
+6ine
+9s
+7st
+9s
+5man
+6en
+5ogeneses
+9esis
+9etic
+6lyses
+9is
+6n
+7s
+6on
+8s
+5page
+9d
+9s
+8ing
+5runner
+9ers
+9ing
+9ings
+5s
+5ward
+9s
+7ys
+6ise
+3re
+5n
+4n
+5e
+4y
+3s
+4h
+5es
+4t
+5bit
+8e
+9s
+8ing
+9ngs
+8ten
+6ound
+5ed
+7s
+5fish
+9es
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5less
+6ike
+7ne
+9s
+5nip
+8s
+5s
+5work
+9s
+5y
+3th
+5ed
+6r
+7ies
+7s
+7y
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5less
+5s
+5y
+4tage
+8s
+5eur
+8s
+3ufrou
+8s
+4ghier
+8st
+6y
+4nce
+7d
+7s
+6ing
+4zier
+7st
+6ness
+9ses
+5y
+3w
+4ard
+7ly
+7ness
+9sses
+7s
+4ie
+6r
+6st
+4n
+5ed
+6r
+7s
+5ing
+8ly
+5s
+4s
+5ier
+7st
+6ness
+9ses
+5t
+6ed
+7r
+8s
+6ier
+8st
+7ness
+9sses
+8g
+6s
+6y
+5y
+4y
+4zier
+7st
+6ly
+6ness
+9ses
+5y
+3ze
+5n
+6ly
+6ness
+9ses
+2uctan
+7s
+5ed
+5iferous
+9ously
+7ication
+9ations
+8ed
+9r
+9rs
+9s
+7y
+8ing
+6ve
+7orous
+5ose
+8s
+5uaries
+8y
+7te
+9d
+9s
+8ing
+9on
+9ons
+6ous
+9ly
+9ness
+9nesses
+3g
+4al
+6ist
+9s
+7ties
+8y
+6ly
+6ness
+9ses
+4ged
+5ing
+4iferous
+5vore
+9s
+8ous
+4s
+3ict
+6s
+4t
+5age
+8s
+6rian
+9nism
+9nisms
+9ns
+5cake
+9s
+5ed
+6r
+7er
+9s
+8ss
+9ses
+7ies
+7s
+7y
+5ful
+8ler
+9est
+9y
+8ness
+9esses
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+6on
+8s
+6ve
+5less
+9ly
+9ness
+9nesses
+7t
+8s
+6ike
+5s
+5wood
+9s
+5y
+3mentaceous
+8rious
+8tion
+9ions
+7ies
+7y
+4p
+5ed
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+6sh
+8ly
+8ness
+9esses
+5le
+7d
+7s
+6ing
+5s
+5y
+3semide
+9s
+4h
+5ed
+6s
+5ing
+4t
+5a
+5rate
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+9on
+9ons
+5s
+5ule
+8s
+6m
+7s
+3tescence
+9ces
+9t
+5x
+4ices
+6ose
+5fied
+8s
+6y
+7ing
+2y
+3able
+3bread
+8s
+3er
+5s
+3ing
+6s
+3pan
+6s
+1ub
+3ar
+3bed
+5ries
+6y
+4ier
+6st
+5ng
+4y
+3s
+4ier
+6st
+4y
+2chsia
+7s
+6n
+7e
+8s
+7s
+6te
+8s
+3i
+4vorous
+3oid
+6al
+6s
+4se
+6s
+4us
+4xanthin
+9ins
+3us
+5ed
+6s
+2d
+3dies
+4le
+6d
+6r
+7s
+6s
+5ing
+8s
+4y
+3ge
+5d
+5s
+4ing
+3s
+2ehrer
+7s
+3l
+4ed
+5r
+6s
+4ing
+4led
+6r
+7s
+5ing
+4s
+4wood
+8s
+3ro
+5s
+2ff
+4ed
+4ier
+6st
+5ng
+4s
+4y
+2g
+3acious
+9ly
+9ness
+9nesses
+6ties
+7y
+4l
+5ly
+4to
+6s
+3ged
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4y
+3hetta
+8s
+3ie
+5s
+4o
+5s
+4tation
+9ns
+5ive
+8ly
+8ness
+9esses
+8s
+5ometer
+9ers
+3le
+5d
+5man
+6en
+5s
+4ier
+6st
+5ng
+4y
+3s
+3u
+4e
+5d
+5like
+5s
+4ing
+5st
+7s
+4s
+2hrer
+6s
+2ji
+4s
+2lcra
+6te
+5um
+7s
+3fil
+6l
+7ed
+8r
+9s
+7ing
+9gs
+7ment
+9nts
+7s
+6ment
+9ts
+6s
+3gencies
+7y
+6t
+7ly
+4id
+4or
+6ous
+6s
+5ur
+7s
+4ural
+7nt
+7te
+9d
+9s
+8ing
+9on
+9ons
+6ite
+9s
+6ous
+3ham
+6s
+3iginosities
+9ity
+8us
+9sly
+9sness
+3l
+4age
+7s
+5m
+6s
+5n
+6s
+4back
+8s
+5lood
+9s
+4ed
+5r
+6ed
+7ne
+9s
+6ide
+9s
+7es
+7ng
+7te
+9s
+6s
+6y
+5st
+4face
+8s
+4ing
+5sh
+4mouthed
+4ness
+8es
+4s
+4y
+3mar
+6s
+4inant
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+9ry
+6e
+7d
+7ous
+7s
+6ic
+7ng
+6ous
+3ness
+7es
+3some
+7ly
+7ness
+9sses
+7r
+7st
+3vid
+4ous
+2m
+3ado
+6es
+6s
+4ge
+6s
+4rase
+8s
+6te
+8s
+5ic
+5ole
+8s
+7ic
+4toria
+8es
+8um
+9ms
+7y
+3ble
+6d
+6r
+7s
+6s
+5ing
+8ly
+8ness
+9esses
+3e
+4d
+4less
+5ike
+4r
+5ole
+8s
+5s
+4s
+4t
+5s
+5te
+7s
+6i
+6o
+3ier
+5st
+4gant
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+9y
+4ng
+6ly
+4tories
+7y
+3osities
+7y
+4us
+3s
+3uli
+5us
+3y
+2n
+3ambulate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+9tory
+8ism
+9sms
+9st
+9sts
+3board
+8s
+3ckia
+7s
+4tion
+8al
+9lism
+9lisms
+9list
+9listic
+9lists
+9lities
+9lity
+9lly
+9ls
+9ries
+9ry
+9te
+9ted
+9tes
+9ting
+8ed
+8ing
+8less
+8s
+5or
+7s
+3d
+4able
+5ment
+9al
+9alism
+9alisms
+9alist
+9alists
+9ality
+9ally
+9alness
+9als
+9s
+4ed
+5r
+6s
+4holder
+9rs
+8ing
+9ngs
+4i
+5c
+5e
+6s
+5ng
+7s
+5s
+4less
+4raise
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+4s
+4us
+4y
+3ebral
+6e
+6ial
+4ral
+7s
+6ry
+5eal
+8ly
+4st
+3fair
+7s
+4est
+7s
+3g
+4al
+6s
+4i
+5bilities
+9ty
+6le
+8s
+5c
+6idal
+9lly
+8e
+9s
+5form
+5stat
+9ic
+9ically
+9s
+4o
+5es
+5id
+7al
+7s
+5sities
+8y
+5us
+4s
+4us
+6es
+3house
+8s
+3icle
+7s
+5ular
+9s
+8te
+7i
+7us
+3k
+4ed
+5r
+6s
+4hole
+8s
+4ia
+6s
+5er
+6st
+5ly
+5ness
+9es
+6g
+4s
+5ter
+8s
+4y
+3ned
+5l
+6ed
+6form
+6ing
+6led
+7ing
+6s
+5r
+5st
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+4y
+5man
+6en
+3plex
+7es
+3s
+4ter
+7s
+2r
+3acious
+9ness
+9nesses
+6ties
+7y
+4l
+5dehyde
+9des
+5s
+4n
+5e
+6s
+5ose
+8s
+7ide
+9es
+5s
+4zolidone
+9ones
+3bearer
+9s
+5low
+8ed
+8ing
+8s
+4ish
+7ed
+8r
+9s
+8s
+7ing
+3ca
+5e
+5l
+5te
+7d
+7ly
+7s
+6ing
+7on
+9s
+4iferous
+4raea
+8s
+4ula
+7e
+7r
+6um
+3der
+3eur
+6s
+3fair
+7s
+4ur
+6aceous
+9ously
+7l
+8dehyde
+9ehydes
+8s
+7n
+8s
+6es
+6ol
+8e
+9s
+8s
+7us
+6s
+3ibund
+4es
+4osities
+8y
+6o
+7s
+5us
+7ly
+7ness
+9sses
+3kid
+6s
+3l
+4able
+5na
+7s
+4ed
+5r
+6s
+5ss
+4ing
+4ong
+7s
+5ugh
+8ed
+8ing
+8s
+4s
+3menties
+7y
+5ties
+6y
+4ities
+6y
+3nace
+7d
+7s
+6ing
+4iment
+9s
+5sh
+7ed
+8r
+9s
+8s
+7ing
+9gs
+7ment
+9nts
+5ture
+9s
+3ol
+5e
+6s
+5s
+4r
+5e
+6s
+5s
+4semide
+9es
+3phies
+5y
+3r
+4ed
+4ier
+7ies
+7s
+7y
+6s
+7t
+5ly
+5ner
+8s
+7ss
+9es
+6g
+7s
+4ow
+6ed
+7r
+8s
+6ing
+6less
+6s
+6y
+4s
+4y
+3s
+4hlugginer
+3th
+5coming
+9ngs
+5er
+7ance
+9ces
+7ed
+8r
+9s
+7ing
+7more
+9st
+7s
+8ome
+6st
+4ive
+7ly
+7ness
+9sses
+3uncle
+8s
+6ular
+8oses
+9sis
+9us
+3y
+3ze
+5s
+4ier
+6st
+4y
+2sain
+6s
+4ria
+6um
+5ol
+7e
+8s
+7s
+3ball
+7s
+3c
+4ous
+3e
+4d
+4e
+5s
+4l
+5age
+8s
+5ess
+5ike
+5s
+4s
+3hion
+7less
+7s
+3ibilities
+9y
+5le
+7ness
+9sses
+6y
+4dic
+4form
+4l
+5e
+6er
+8s
+5ier
+8s
+5lade
+9d
+9s
+8ing
+7tion
+9ons
+6i
+7s
+5s
+4ng
+4on
+6al
+6ism
+9s
+8t
+9s
+6less
+6s
+3s
+4ball
+8s
+5udget
+9ts
+9ty
+4ed
+5r
+6s
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4pot
+7s
+4y
+3t
+4anella
+9as
+9e
+9es
+4ed
+5t
+6s
+4ian
+7ist
+9ts
+8ze
+9ed
+9es
+9ing
+7s
+5c
+6s
+5er
+6st
+5gate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+9ry
+5larian
+9ans
+6irian
+9ans
+6lirian
+9ians
+6ugs
+6y
+5ness
+9es
+6g
+4oc
+6s
+4s
+4y
+3ulinid
+9s
+4ma
+2tchel
+7s
+3harc
+7s
+6k
+7s
+4orc
+7s
+6k
+7s
+3ile
+6ly
+6ness
+9ses
+6r
+6st
+5itarian
+9ianism
+9ians
+7ies
+7y
+3on
+5s
+3sal
+6s
+3tock
+7s
+3ural
+5e
+6less
+9sness
+6s
+5ism
+8s
+7t
+8ic
+9cally
+9cs
+8s
+6ties
+8on
+9ns
+7y
+5ological
+9ies
+9ist
+9ists
+9y
+3z
+4ed
+5s
+4ing
+2ze
+4d
+4e
+5s
+4s
+3il
+5s
+4ng
+3z
+4box
+7es
+4ed
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4le
+6d
+6s
+5ing
+4tone
+8s
+4y
+1y
+2ce
+4s
+2ke
+4d
+4s
+3ing
+2le
+4s
+3fot
+6s
+2nbos
+6es
+2rd
+4s
+2tte
+5s
+0gab
+3apentin
+9ns
+4rdine
+9s
+3ba
+5rd
+7s
+6t
+7s
+5s
+4ed
+5r
+6s
+4ier
+6st
+5ness
+9es
+6g
+4le
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8s
+4ro
+6ic
+7d
+7tic
+6s
+4y
+3elle
+7d
+7r
+8s
+7s
+4rdine
+9s
+5lunzie
+9ies
+3fest
+7s
+3ies
+4on
+6ade
+9s
+7ge
+9s
+6ed
+6nade
+9es
+6s
+3le
+5d
+5like
+5s
+5t
+6s
+4ing
+3nash
+7es
+3oon
+6s
+3s
+3y
+2d
+3about
+8s
+4rene
+3ded
+5r
+6s
+4i
+5ng
+5s
+3e
+4s
+3flies
+5y
+3ge
+5s
+5t
+6eer
+9s
+6ries
+7y
+6s
+6y
+4ie
+6s
+3i
+4d
+5s
+4s
+3je
+5s
+4o
+3ling
+7s
+3oid
+6s
+4linic
+8te
+9es
+8um
+9ms
+3roon
+7ed
+7ing
+9gs
+7s
+3s
+4man
+5en
+4o
+3wall
+7s
+3zookeries
+9y
+7s
+2e
+3d
+3ing
+3licise
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+3n
+3s
+2ff
+4e
+5d
+5r
+6s
+5s
+4ing
+7s
+4s
+5ail
+8s
+2g
+3a
+4ku
+6s
+3e
+4able
+7y
+4d
+4r
+5s
+4s
+3ged
+5r
+6ies
+6s
+6y
+4ing
+4le
+6d
+6s
+5ing
+8s
+3ing
+3man
+4en
+3s
+4ter
+7s
+2hnite
+7s
+2id
+4s
+3eties
+5y
+3jin
+3llard
+8e
+8ia
+9as
+4y
+3n
+4able
+4ed
+5r
+6s
+5st
+4ful
+7ly
+7ness
+9sses
+4giving
+9gs
+4ing
+7s
+4less
+8ness
+9esses
+5ier
+7st
+6ness
+9ses
+5y
+4s
+5aid
+6y
+7er
+9s
+7ing
+9gs
+7s
+5t
+6rive
+9ed
+9en
+9es
+9ing
+7ove
+3r
+4fowl
+8s
+4s
+3t
+4a
+5s
+4ed
+5r
+6ed
+6less
+6s
+4ing
+4s
+4t
+5s
+2jo
+4s
+2k
+3s
+2l
+3a
+4bea
+7h
+8s
+7s
+5ia
+7h
+8s
+7s
+6eh
+8s
+6ya
+8h
+9s
+8s
+4ctagogue
+9gues
+6ic
+6ometer
+9ters
+9tries
+9try
+7phorous
+8oieses
+9iesis
+9ietic
+9ietics
+7rrhea
+9heas
+9hoea
+9hoeas
+7saemia
+9emias
+9mine
+9mines
+8e
+9mia
+9mias
+9mic
+9s
+8idase
+9dases
+9de
+9des
+8yl
+9ls
+4ge
+6s
+5o
+6s
+4h
+5s
+4nga
+7l
+8s
+7s
+5t
+6amine
+9nes
+6ine
+9s
+6y
+4pago
+8s
+4s
+4tea
+7s
+4vant
+8ed
+8ing
+8s
+4x
+5es
+5ies
+5y
+3banum
+8s
+3dragon
+9s
+3e
+4a
+5e
+5s
+5te
+7d
+4iform
+4na
+6s
+5gale
+9s
+5ic
+7al
+9s
+6te
+8s
+5oid
+4opithecine
+9ecoid
+4re
+6s
+4s
+4tte
+7s
+3ilee
+7s
+4matias
+9ses
+4ngale
+9s
+4ongee
+9s
+5t
+6s
+4pot
+7s
+4vant
+8ed
+8ing
+8s
+3l
+4abea
+8h
+9s
+8s
+6ia
+8h
+9s
+8s
+7eh
+9s
+7ya
+9h
+9hs
+9s
+8eh
+9hs
+5mine
+9s
+5nt
+7ed
+8r
+8st
+7ing
+7ly
+7ness
+9sses
+7ries
+8y
+7s
+5te
+7s
+4bladder
+9ers
+4eass
+8es
+5d
+5in
+7s
+5on
+7s
+5ria
+8s
+7ed
+8s
+7st
+9s
+6y
+7goer
+9ers
+7ing
+8te
+9es
+5t
+6a
+7s
+6ed
+6ing
+6s
+5y
+6s
+4flies
+6y
+4iambic
+9cs
+6rd
+8ise
+9ses
+8s
+6ss
+8es
+5c
+6a
+7n
+7s
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+5ed
+6s
+5gaskins
+5maufries
+9ry
+5nacean
+9ans
+9ous
+7zo
+9s
+6g
+7ly
+6ipper
+9ers
+6ule
+9s
+5ot
+7s
+5pot
+8s
+5se
+7d
+7s
+6ing
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+5um
+7s
+5vant
+9ed
+9ing
+9s
+7t
+8s
+5wasp
+9s
+5ze
+7d
+7s
+6ing
+4nut
+7s
+4ock
+5glass
+9ses
+5n
+6age
+9s
+6s
+5on
+7ed
+7s
+6t
+7s
+5p
+6ade
+9d
+9s
+8ing
+6ed
+7r
+8s
+6ing
+6s
+5us
+5w
+6ed
+6glass
+9sses
+6ing
+6s
+7es
+7ness
+9sses
+4s
+5ickness
+9esses
+5tone
+9s
+4umph
+8ed
+8ing
+8s
+5s
+6ed
+7s
+4y
+5gaskins
+5ing
+3oche
+7d
+7s
+6ing
+4ot
+6s
+4p
+5ade
+8s
+5ed
+5in
+7g
+7s
+5ped
+6ing
+5s
+4re
+6s
+4sh
+6e
+7d
+7s
+6ing
+4wses
+3ravage
+9d
+9s
+8ing
+6itch
+9hed
+9hes
+9hing
+3s
+3tonia
+8s
+3umph
+7ed
+8r
+9s
+7ing
+7s
+4t
+5h
+6s
+5s
+3vanic
+8al
+9lly
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ometer
+9ters
+9tric
+9trical
+9tries
+9try
+7plastic
+9asties
+9asty
+7scope
+9opes
+9opic
+9opies
+9opy
+7tropic
+9opism
+9opisms
+4o
+5s
+3yac
+6s
+5k
+6s
+2m
+3a
+4huche
+9d
+9s
+8ing
+4ruche
+9d
+9s
+8ing
+4s
+5h
+6es
+4y
+5s
+3b
+4a
+5de
+7s
+6o
+7ed
+8s
+7ing
+7s
+5s
+4e
+5s
+6on
+8s
+5t
+6s
+6ta
+8s
+4ia
+6s
+5er
+7s
+5r
+6s
+5st
+7s
+5t
+6ed
+6ing
+6s
+4le
+6d
+6r
+7s
+6s
+5ing
+8s
+4o
+5es
+5ge
+7s
+6ian
+7c
+5l
+6ed
+6ing
+6led
+7ing
+6s
+4rel
+7s
+5oon
+8s
+4s
+4usia
+8s
+3e
+4breaker
+9ers
+4cock
+8s
+4d
+4keeper
+9rs
+8ing
+9ngs
+4lan
+7s
+5ike
+5y
+4ness
+8es
+4play
+8s
+4r
+5s
+4s
+5ier
+7st
+5man
+8ship
+9hips
+6en
+5ome
+8ly
+8ness
+9esses
+5t
+6er
+8s
+5y
+4tal
+6ngia
+9al
+9um
+5e
+6s
+5ic
+7ally
+5ocyte
+9es
+6geneses
+9esis
+9ic
+9ies
+9ous
+9y
+6phore
+9res
+9ric
+8yte
+9tes
+9tic
+4y
+5ness
+9es
+3gee
+3ic
+4er
+5st
+4fication
+6ed
+5y
+4ly
+4n
+5e
+6rie
+9s
+6s
+7que
+7s
+8es
+5g
+6s
+5s
+3ma
+5dia
+7on
+5s
+5t
+6ia
+7on
+6s
+4e
+5d
+5r
+6s
+7tang
+9ngs
+5s
+4ier
+6st
+5ng
+4ock
+7ed
+7ing
+7s
+5n
+6ed
+7r
+8s
+6ing
+9s
+6s
+4y
+3odeme
+8s
+4geneses
+9is
+8tic
+9ical
+9ically
+4ne
+6s
+4petalous
+5hyllous
+4sepalous
+4tropic
+9sm
+9sms
+3p
+4ish
+4s
+3s
+3ut
+5s
+3y
+4ness
+8es
+2n
+3ache
+7s
+3ch
+5ed
+6s
+5ing
+3der
+6ed
+6ing
+7sm
+9s
+6s
+4y
+3e
+4f
+5s
+4v
+5s
+3g
+4board
+9s
+5uster
+9rs
+8ing
+9ngs
+4ed
+5r
+6s
+4ing
+7s
+4land
+8s
+5ia
+7l
+7r
+7te
+9d
+6er
+7st
+6form
+6ng
+6on
+8ated
+8ic
+8s
+7side
+9des
+5y
+4plank
+9s
+6ow
+8s
+4rel
+7s
+6ne
+8d
+8s
+7ing
+7ous
+4s
+5man
+6en
+5ta
+7s
+6er
+8dom
+9oms
+8ish
+9sm
+9sms
+8land
+9ands
+8s
+4ue
+6s
+4way
+7s
+3ister
+8s
+3ja
+5h
+6s
+5s
+3ned
+5t
+6ries
+7y
+6s
+4ing
+5ster
+9s
+3of
+5s
+4id
+6s
+5n
+6e
+7s
+6s
+3s
+4ey
+6s
+3t
+4ed
+5lope
+9s
+4ing
+4let
+7ed
+7ing
+7s
+5ine
+8s
+5ope
+8s
+4ries
+5y
+4s
+3ymede
+8s
+2ol
+4bird
+8s
+5reak
+9s
+4ed
+5r
+6ess
+9es
+6s
+4ing
+4less
+4s
+2p
+3e
+4d
+4r
+5s
+4s
+5eed
+8s
+4worm
+8s
+3ier
+5st
+4ng
+6ly
+6s
+3less
+3o
+4s
+5is
+7es
+3ped
+5r
+6s
+4ier
+6st
+5ng
+7s
+4y
+3s
+3y
+2r
+3age
+6d
+6man
+7en
+6s
+6y
+5ing
+8s
+6st
+8e
+9s
+8s
+3b
+4age
+7man
+8en
+7s
+7y
+6y
+5nzo
+8s
+4e
+5d
+5s
+4ing
+4le
+6d
+6r
+7s
+6s
+7s
+5ing
+8s
+4o
+5ard
+8s
+5il
+7s
+5logies
+9st
+9sts
+8y
+5s
+4s
+4ure
+7s
+3cinia
+8s
+4on
+6s
+3da
+5i
+5nt
+7s
+4en
+6ed
+7r
+8s
+6ful
+9s
+6ia
+8s
+7ng
+9s
+6less
+6s
+5robe
+9s
+4yloo
+8s
+3e
+4fowl
+8s
+3fish
+7es
+3ganey
+8s
+6tua
+9n
+9s
+5rise
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+4et
+6s
+6y
+4le
+6d
+6r
+7s
+6s
+5ing
+4oyle
+8d
+8s
+7ism
+9ms
+3i
+4al
+6s
+4baldi
+9s
+4gue
+7s
+4s
+5h
+6ed
+7s
+6ing
+6ly
+6ness
+9ses
+3jan
+6s
+3land
+7age
+9es
+7ed
+7ing
+7less
+7ries
+8y
+7s
+4ic
+6ked
+7ier
+9st
+8ng
+7y
+6s
+3ment
+7ed
+7ing
+7less
+7s
+7ure
+9es
+3ner
+6ed
+6ing
+6s
+5t
+6iferous
+6s
+4i
+5erite
+9es
+5sh
+7ed
+8e
+9d
+9ing
+9ment
+9ments
+9s
+8r
+9s
+8s
+7ing
+9gs
+7ment
+9nts
+7ries
+8y
+5ture
+9s
+3ote
+6d
+6s
+5ing
+5te
+7d
+7r
+8s
+7s
+6ing
+9s
+4upa
+7s
+3pike
+7s
+3ran
+6s
+4e
+5d
+5s
+5t
+6ed
+7er
+9s
+6s
+4igue
+8s
+5ng
+5son
+8ed
+8ing
+8s
+4on
+6s
+5t
+6e
+7d
+7r
+8s
+7s
+6ing
+6s
+6te
+8d
+8r
+9s
+8s
+7ing
+9gs
+4ulities
+8y
+6ous
+9ly
+9ness
+9nesses
+4ya
+6s
+5owen
+9s
+3s
+3t
+4er
+6ed
+6ing
+6s
+4h
+5s
+3uda
+6s
+4m
+5s
+3vey
+6s
+4ie
+6s
+4ock
+7s
+2s
+3ahol
+7s
+4lier
+8s
+3bag
+6ged
+7ing
+6s
+3con
+6ade
+9d
+9r
+9rs
+9s
+8ing
+6ism
+9s
+6s
+3eities
+6y
+4lier
+8s
+4ous
+7ness
+9sses
+4s
+3field
+8s
+3h
+4ed
+5r
+5s
+6t
+4ful
+4ing
+4liness
+9ses
+5y
+4older
+9s
+5use
+8s
+3ifiable
+6cation
+9ions
+6ed
+7r
+8s
+7s
+5orm
+5y
+6ing
+3ket
+6s
+4in
+6g
+7s
+6s
+3less
+4ight
+8s
+5t
+3man
+4en
+3ogene
+8s
+4hol
+7s
+4lene
+8s
+5ier
+8s
+6ne
+8s
+7ic
+4meter
+9s
+7ric
+9cal
+9es
+8y
+3p
+4ed
+5r
+6eau
+9s
+9x
+6s
+4ier
+6st
+5ness
+9es
+6g
+7ly
+7s
+4s
+4y
+3sed
+5r
+6s
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4y
+3t
+4ed
+5r
+6opod
+9dous
+9ds
+6s
+4full
+4ight
+8ness
+9esses
+5ng
+4ness
+8e
+9s
+4raea
+8s
+7um
+9s
+6l
+7gia
+9as
+9c
+5ea
+7s
+6ctomies
+9my
+5ic
+6n
+7s
+6tic
+8des
+8s
+9es
+5ocnemii
+9mius
+7olic
+6duodenal
+6enteric
+9eritic
+9eritis
+6lith
+9hs
+7oger
+9ers
+9ical
+9ies
+9ist
+9ists
+9y
+6mancies
+9cy
+6nome
+9er
+9ers
+9es
+9ic
+9ical
+9ically
+9ics
+9ies
+9ist
+9ists
+9y
+6pod
+9an
+9ans
+9ous
+9s
+7ub
+9s
+6scope
+9pes
+9pic
+9pies
+9pist
+9pists
+9py
+7oph
+9her
+9hers
+9hies
+9hs
+9hy
+7tomies
+9my
+6tomies
+9y
+7rich
+9chs
+6vascular
+5ula
+8e
+8r
+8s
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+4s
+3works
+2t
+3e
+4au
+6s
+6x
+4crash
+9ed
+9er
+9ers
+9es
+9ing
+4d
+4fold
+8s
+4house
+9s
+4keeper
+9rs
+8ing
+4leg
+6ss
+5ike
+4man
+5en
+4post
+8s
+4r
+5s
+4s
+4way
+7s
+3h
+4er
+6able
+6ed
+7r
+8s
+6ing
+9s
+6s
+4s
+3ing
+6s
+3ling
+3or
+5s
+3s
+3vol
+2u
+3che
+6ly
+6ness
+9ses
+6r
+7ie
+9s
+6sco
+7t
+5o
+6s
+4ie
+6r
+6st
+4y
+3d
+4eamus
+9es
+5d
+5ries
+6y
+4gie
+7s
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+4s
+4y
+3fer
+6s
+4fer
+7ed
+7ing
+9gs
+7s
+4re
+6s
+3ge
+5able
+8y
+5d
+5r
+6s
+5s
+4ing
+7s
+3je
+5s
+3leiter
+9s
+4t
+5er
+7s
+5heria
+9as
+5s
+3m
+4ed
+4ier
+6st
+5ng
+4less
+4s
+4y
+3n
+4ch
+6ed
+7s
+6ing
+4t
+5ed
+6r
+6st
+5ing
+5let
+8ed
+8ing
+8s
+6y
+5ness
+9es
+5ree
+8s
+6ies
+6y
+5s
+3p
+4ed
+5r
+6s
+4ing
+4s
+4us
+6es
+3r
+4s
+3s
+4s
+5es
+5ian
+5meter
+9rs
+3ze
+5like
+5s
+4ier
+6st
+5ly
+5ness
+9es
+4y
+2vage
+6s
+3e
+4l
+5ed
+5ing
+5kind
+9s
+5led
+6ing
+5man
+6en
+5ock
+8s
+5s
+3ial
+6oid
+6s
+3ot
+5s
+5te
+7d
+7s
+6ing
+2w
+3cier
+6st
+4y
+3d
+4s
+3k
+4ed
+5r
+6s
+4ier
+6s
+7t
+5hood
+9s
+5ly
+5ness
+9es
+6g
+5sh
+7ly
+7ness
+9sses
+4s
+4y
+3p
+4ed
+5r
+6s
+4ing
+4s
+4us
+6es
+3s
+4ie
+6r
+6st
+4y
+2y
+3al
+5s
+3dar
+6s
+3er
+4st
+4ties
+5y
+3ly
+3ness
+7es
+3s
+4ome
+3wings
+2zabo
+6es
+6s
+4l
+5s
+4nia
+7s
+4r
+5s
+3e
+4bo
+6es
+6s
+4d
+4ful
+4hound
+9s
+4lle
+7s
+4ment
+8s
+4r
+5s
+4s
+4tte
+7d
+7er
+9ed
+9ing
+9ish
+9s
+7s
+6ing
+3ier
+5st
+4llion
+9aire
+9aires
+9s
+4ng
+6s
+3ogene
+8s
+4n
+5s
+4o
+5ka
+7s
+5n
+6s
+5s
+3pacho
+8s
+3ump
+6ed
+7r
+8s
+6ing
+6s
+4nder
+8ed
+9r
+9rs
+8ing
+8s
+3y
+1eal
+4ed
+4ing
+4ous
+7ies
+7y
+4s
+3n
+4s
+4ticlinal
+9ne
+9nes
+3r
+4box
+7es
+4case
+8s
+5hange
+9es
+4e
+5d
+5s
+4head
+8s
+4ing
+7s
+4less
+4s
+5hift
+9s
+4wheel
+9s
+3son
+3t
+4s
+2bur
+5s
+2ck
+4ed
+4ing
+4o
+5es
+5s
+4s
+2d
+3act
+6s
+3dit
+3eckt
+7s
+3s
+2e
+3bag
+6s
+4ung
+7s
+3chee
+7s
+3d
+3gaw
+6s
+3ing
+3k
+4dom
+7s
+4ed
+4ier
+6st
+5ness
+9es
+4s
+5peak
+9s
+4y
+3lbek
+7s
+3p
+4ound
+8s
+4s
+3s
+4e
+4t
+5s
+3z
+4ah
+6s
+4er
+6s
+2filte
+3uffle
+8d
+8s
+7ing
+4llte
+2genschein
+9ins
+3gie
+6s
+2hlenite
+9s
+2isha
+6s
+4t
+5s
+3t
+4onogamies
+9mous
+9my
+4s
+2l
+3able
+4da
+6s
+4nde
+7sprung
+9rungs
+5t
+6s
+4stic
+4te
+6d
+6s
+5i
+6n
+7ate
+9ed
+9es
+9ing
+9ion
+9ions
+7e
+8s
+7g
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7oid
+9ds
+8us
+9sly
+9sness
+7s
+6on
+8s
+6s
+5o
+6s
+3cap
+6s
+3d
+4ed
+5r
+6s
+4ing
+7s
+4s
+3ee
+5s
+3id
+5er
+6st
+5ities
+7y
+5ly
+5ness
+9es
+4gnite
+9s
+3lant
+7s
+4ed
+4ies
+5flowre
+9res
+5ng
+4y
+3osies
+5y
+3s
+4emia
+7ne
+9s
+8ine
+9nes
+7um
+9s
+3t
+4s
+2m
+3atria
+8s
+3clip
+7s
+3einschaft
+9aften
+9afts
+4l
+5s
+3fibrozil
+9ils
+5sh
+7es
+3inal
+7ly
+6te
+8d
+8ly
+8s
+7ing
+8on
+9ns
+5i
+6es
+5ous
+5y
+3like
+3ma
+5ceous
+5e
+5n
+5te
+7d
+7s
+6ing
+7on
+9s
+7ve
+4ed
+5n
+5ous
+5ries
+6y
+4ier
+6st
+5ferous
+5ly
+5ness
+9es
+6g
+5parous
+9usly
+4ological
+9es
+9st
+9sts
+8y
+4ulation
+9ons
+6e
+7s
+4y
+3ological
+8es
+8st
+9ts
+7y
+4ny
+4t
+5e
+6s
+5s
+3s
+4bok
+7s
+5uck
+8s
+4horn
+8s
+4tone
+8s
+3utlich
+9keit
+9keits
+2n
+3a
+4l
+4ppe
+7s
+4s
+3darme
+8rie
+9ies
+9y
+8s
+4er
+6ed
+6ing
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6less
+6s
+3e
+4alogic
+9cal
+9cally
+9es
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+8y
+4cologies
+9y
+4ra
+6ble
+6l
+7ate
+9es
+7cies
+8y
+7e
+7ia
+8sable
+9ation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9simo
+9simos
+9t
+9ts
+8ties
+9y
+8zable
+9ation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7led
+8ing
+8y
+7ness
+9sses
+7s
+8hip
+9ips
+6nt
+8s
+6te
+8d
+8s
+7ing
+8on
+9nal
+9nally
+9nism
+9nisms
+9ns
+8ve
+7or
+9s
+7rices
+9x
+5ic
+7al
+9ly
+7ness
+9sses
+7s
+5osities
+9y
+6us
+8ly
+8ness
+9esses
+4s
+5es
+5is
+4t
+5hliac
+9cal
+9cally
+9con
+9cons
+9cs
+9logic
+9logies
+9logy
+5ic
+7al
+9ly
+7ist
+9ts
+7s
+5otrophic
+5rices
+7x
+8es
+5s
+5te
+7s
+4va
+6s
+5rette
+9es
+3ial
+6ise
+9d
+9s
+8ing
+7ties
+8y
+7ze
+9d
+9s
+8ing
+6ly
+6ness
+9ses
+4c
+5ally
+5ular
+8te
+9ed
+9ely
+9es
+9ing
+9ion
+9ions
+4e
+5s
+4i
+4p
+5ap
+7s
+5s
+4sta
+7s
+6ein
+9s
+4tal
+7ia
+9l
+8c
+7ly
+5ival
+9ly
+7e
+8ly
+8s
+5or
+7s
+6urinary
+5rices
+7x
+8es
+5ure
+8s
+4us
+6es
+4zah
+7s
+5ot
+7h
+3lock
+7s
+3naker
+8s
+4ed
+5l
+6s
+5t
+6s
+4ies
+5ng
+4y
+3oa
+5s
+4cidaire
+9res
+8l
+7e
+8s
+4gram
+8s
+4ise
+7s
+4m
+5e
+6s
+5ic
+7s
+5s
+4phobia
+9as
+4toxic
+5ype
+8s
+7ic
+9al
+9ally
+9ities
+9ity
+4uillere
+9res
+3re
+5s
+4o
+5s
+3s
+4darmes
+4eng
+7s
+3t
+4amicin
+9ns
+4eel
+7er
+8st
+7ise
+9ed
+9es
+9h
+9ing
+9m
+9ms
+8ze
+9ed
+9es
+9ing
+7ly
+7ness
+9sses
+5s
+4ian
+7aceous
+7ella
+9las
+7s
+5er
+6st
+5l
+6e
+7s
+8se
+9es
+6homme
+6ic
+7se
+9d
+9s
+8h
+8ing
+8m
+9s
+7tial
+9an
+9es
+9ous
+8y
+7ze
+9d
+9s
+8ing
+6shommes
+4le
+6d
+6folk
+9ks
+6hood
+9ds
+6man
+9hood
+9hoods
+9like
+9liness
+9ly
+9ship
+9ships
+7en
+6ness
+9se
+9ses
+6person
+9sons
+6r
+6s
+7t
+6woman
+9anly
+9en
+5ing
+5y
+4oo
+6s
+4rice
+8s
+6es
+6fication
+9ations
+8ed
+9r
+9rs
+9s
+7y
+8ing
+5y
+4s
+4y
+3u
+4a
+4flect
+9ed
+9ing
+9ion
+9ions
+9or
+9ors
+9s
+7xion
+9ons
+4ine
+7ly
+7ness
+9sses
+4s
+5es
+2o
+3botanic
+9cal
+9es
+9st
+9sts
+8y
+3caching
+9gs
+5rpic
+8es
+7y
+4entric
+9cal
+9cally
+9cism
+9cisms
+4hemical
+9ally
+8st
+9tries
+9try
+9ts
+5ronologic
+9logies
+9logist
+9logy
+4orona
+9e
+9s
+3de
+5mographics
+5s
+6ic
+8al
+8s
+7es
+7st
+9s
+6y
+5tic
+8al
+9lly
+8s
+4ic
+4uck
+7s
+4ynamic
+9cal
+9cist
+9cists
+9cs
+3fact
+7s
+3genies
+6y
+4noses
+7ies
+8s
+7t
+8ic
+9cal
+9cally
+8s
+7y
+4onic
+7es
+6y
+4rapher
+9rs
+8ic
+9cal
+9cally
+9es
+8y
+3hydrologic
+9ogies
+9ogist
+9ogists
+9ogy
+3id
+5al
+5s
+3latries
+7y
+4inguistics
+4oger
+8s
+6ian
+9s
+7c
+8al
+9lly
+7es
+7se
+9d
+9s
+8ing
+8t
+9s
+7ze
+9d
+9s
+8ing
+6y
+3magnetic
+9ically
+9ism
+9isms
+9ist
+9ists
+5ncer
+9s
+7ies
+7y
+6t
+7ic
+7s
+4echanics
+5dical
+8ine
+9nes
+5ter
+8s
+6ric
+9al
+9ally
+9ian
+9ians
+9s
+8d
+9s
+8es
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9t
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7y
+4orphic
+8ogenic
+9genies
+9genist
+9geny
+9logic
+9logies
+9logist
+9logy
+4yoid
+3phagia
+9s
+8es
+8sm
+9ms
+9t
+9ts
+7ous
+7y
+5ilic
+7ous
+5one
+8s
+5ysical
+9ally
+9ist
+9ists
+9s
+6te
+8s
+7ic
+4olitical
+9cally
+9cian
+9cians
+9cs
+5nic
+8al
+8s
+4ressured
+5obe
+8s
+3rgette
+9s
+5ic
+7al
+7s
+3s
+4cience
+9es
+8tific
+9ist
+9ists
+4patial
+5here
+9s
+4tatic
+9s
+8onary
+5rategic
+9gical
+9gies
+9gist
+9gists
+9gy
+6ophic
+9ically
+4ynchronous
+7linal
+9ne
+9nes
+3tactic
+9al
+9ally
+5g
+6ged
+7ing
+6s
+5xes
+6is
+4echnic
+9cal
+9cs
+8ologies
+9logy
+6tonic
+9ically
+9ics
+5xtile
+9es
+4herm
+8al
+9lly
+8ic
+8ometer
+9meters
+8s
+4ropic
+9ally
+8sm
+9ms
+2r
+3ah
+5s
+4niaceous
+7l
+8s
+6ol
+8s
+6um
+8s
+4rdia
+8s
+4tological
+9ies
+9ist
+9ists
+9y
+3be
+5ra
+7s
+5s
+4il
+6le
+8s
+6s
+3e
+4nt
+6s
+5uk
+7s
+4s
+3falcon
+9s
+3iatric
+9ian
+9ians
+9s
+8st
+9ts
+3le
+5s
+3m
+4ain
+7e
+8s
+7s
+5n
+6der
+9s
+6e
+7ly
+7ness
+9sses
+6ic
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7te
+9s
+7um
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ous
+6s
+4ed
+5n
+6s
+4free
+4icidal
+8e
+9s
+5er
+6st
+5n
+6a
+7bilities
+9lity
+8le
+7l
+8ly
+7nt
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+6ess
+9es
+6g
+6s
+4like
+4plasm
+9s
+5roof
+4s
+4y
+3ne
+5d
+5s
+4ing
+3onimo
+5tic
+6ocracies
+9acy
+9at
+9atic
+9ats
+7logic
+9gical
+9gies
+9gist
+9gists
+9gy
+7morphic
+7phil
+9ile
+9iles
+9ilia
+9ilias
+9ils
+9obe
+9obes
+9obia
+9obias
+4piga
+8s
+3rymander
+9ered
+9erer
+9erers
+9ering
+9erings
+9ers
+3s
+3t
+4cha
+3und
+6ial
+7val
+8e
+9ly
+9s
+6s
+2sellschaft
+9aften
+9afts
+3neria
+8d
+9s
+8s
+3samine
+9s
+4e
+5d
+5s
+4ing
+4o
+5ed
+6s
+3t
+4alt
+7en
+7ism
+9ms
+9t
+9ts
+7s
+5nt
+5po
+7s
+5te
+7d
+7s
+6ing
+7on
+9al
+9s
+7ve
+6orial
+8y
+4e
+5s
+4ic
+6al
+6ulant
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+9tory
+4s
+4ural
+8ly
+6e
+7d
+7r
+8s
+7s
+6ing
+3undheit
+2t
+3a
+4ble
+4s
+4table
+4way
+7s
+3s
+3table
+4er
+6ed
+6ing
+9s
+6s
+4ing
+7s
+3up
+5s
+2um
+4s
+2wgaw
+6ed
+6s
+3urztraminer
+9miners
+2y
+3an
+3er
+4st
+3ser
+6ite
+9s
+6s
+1harial
+7s
+4ri
+6es
+6s
+5y
+3st
+5ed
+5ful
+8ly
+5ing
+5lier
+8st
+7ness
+9sses
+6y
+5ness
+9es
+5s
+3t
+4s
+3ut
+5s
+3zal
+6s
+4el
+6s
+4i
+5es
+5s
+2ee
+4s
+3rao
+6ed
+7s
+6ing
+6s
+4kin
+7s
+3sse
+6d
+6s
+5ing
+4t
+3tto
+6ed
+7s
+6ing
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+2i
+3bli
+6s
+3lgai
+7s
+4lie
+7d
+7s
+5ying
+3s
+2ost
+5ed
+5ier
+7st
+6ng
+8s
+5lier
+8st
+7ke
+7ness
+9sses
+6y
+5s
+5write
+9er
+9ers
+9es
+9ing
+9ten
+7ote
+5y
+3ul
+5ie
+7s
+6sh
+8ly
+8ness
+9esses
+5s
+2relin
+7s
+2ubar
+2yll
+5s
+1i
+2ambeux
+3nt
+5ess
+8es
+5hood
+9s
+5ism
+8s
+5lier
+8st
+7ke
+6y
+5ries
+6y
+5s
+6hip
+9s
+3our
+6s
+3rdia
+7s
+8es
+8is
+2b
+3bed
+5r
+6ed
+7llic
+9in
+9ins
+6ing
+7sh
+9es
+6s
+5t
+6ed
+6ing
+6s
+6ted
+7ing
+4ing
+4on
+6s
+5se
+6ities
+8y
+5us
+7ly
+7ness
+9sses
+4site
+8s
+3e
+4d
+4l
+5s
+4r
+5s
+4s
+3ing
+6ly
+3let
+6s
+4i
+5s
+3s
+4on
+6s
+3us
+5es
+2d
+3dap
+5y
+4ied
+6r
+6s
+7t
+5ly
+5ness
+9es
+4up
+4y
+5ap
+5ing
+5up
+3gee
+6s
+3jee
+6s
+3s
+2e
+3d
+3ing
+3n
+3s
+2f
+3t
+4able
+8s
+4ed
+6ly
+6ness
+9ses
+5e
+6s
+4ing
+4less
+4s
+5hop
+8s
+4ware
+8s
+5rap
+8ped
+9ing
+8s
+2g
+3a
+4bit
+7s
+5yte
+8s
+4cycle
+9s
+4flop
+8s
+4hertz
+9es
+4ntean
+7sque
+6ic
+8ally
+8ide
+9des
+8ness
+9esses
+7sm
+9s
+6ologies
+9gy
+7machia
+9chias
+9chies
+9chy
+4s
+4ton
+7s
+4watt
+8s
+3ged
+4ing
+5t
+6ed
+6ing
+6s
+4le
+6d
+6r
+7s
+6s
+7ome
+5ier
+7st
+6ng
+8ly
+8s
+5y
+3he
+3let
+6s
+4ot
+6s
+3man
+6ities
+8y
+4en
+3olo
+6s
+4t
+5s
+3s
+3ue
+5s
+2la
+4s
+3bert
+7s
+3cup
+6s
+3d
+4ed
+5n
+5r
+6s
+4hall
+8s
+4ing
+7s
+4s
+5man
+6en
+5woman
+8en
+3et
+5s
+3gai
+6s
+4ie
+6s
+3l
+4aroo
+8s
+4ed
+5r
+6s
+5t
+6s
+4flirt
+9s
+4ie
+6d
+6s
+5flower
+9ers
+5ng
+5on
+7s
+4net
+7s
+7ted
+9r
+9rs
+8ing
+4ravage
+9ed
+9es
+9ing
+7itch
+9ched
+9ches
+9ching
+4s
+4y
+5flower
+9ers
+5ing
+5vor
+8s
+3pey
+6s
+4ies
+4y
+3ravage
+9d
+9r
+9rs
+9s
+8ing
+6itch
+9hed
+9hes
+9hing
+3sonite
+9s
+3t
+4cup
+7s
+4head
+8s
+4s
+4wood
+2mbal
+6ed
+6ing
+6led
+7ing
+6s
+3crack
+8eries
+9ry
+8s
+3el
+5s
+3let
+6ed
+6ing
+6s
+3mal
+6led
+6s
+4e
+5r
+6s
+5s
+4ick
+7ed
+7ier
+9st
+8ng
+7ries
+8y
+7s
+7y
+5e
+6s
+4or
+6s
+3p
+4ed
+4ier
+6st
+5ng
+4s
+4y
+2n
+3g
+4al
+6l
+7s
+6s
+4e
+5ley
+8s
+6i
+7es
+7s
+6li
+8es
+8s
+7y
+6y
+5r
+6ade
+9s
+6bread
+9aded
+9ads
+9ady
+6ed
+6ing
+6liness
+9esses
+7y
+6ous
+6root
+9ts
+6s
+7nap
+9ps
+6y
+5s
+4ham
+7s
+4ili
+7s
+6li
+8s
+5va
+7e
+7l
+6ectomies
+9omy
+6ites
+8ides
+9s
+9ses
+4ko
+6es
+6s
+4le
+6s
+5imoid
+5ymi
+7us
+4s
+3house
+8s
+3k
+4go
+6es
+6s
+4s
+3n
+4ed
+5l
+6s
+5r
+6ies
+6s
+6y
+4ier
+6st
+5ng
+7s
+4y
+3ormous
+3s
+4eng
+7s
+4hop
+7s
+3zo
+5es
+2o
+3coso
+3s
+2p
+3on
+5s
+3ped
+5r
+6s
+4ies
+5ng
+4o
+5es
+5s
+4y
+3s
+4en
+6s
+4ied
+6s
+4y
+5dom
+8s
+5hood
+9s
+5ing
+6sh
+5wort
+9s
+2raffe
+7s
+6id
+7ne
+7sh
+6oid
+4ndola
+9s
+8e
+9s
+4sol
+7e
+8s
+7s
+3d
+4ed
+5r
+6s
+4ing
+7ly
+7s
+4le
+6cake
+9es
+6d
+6r
+7s
+6s
+7cone
+9nes
+7tead
+9ads
+5ing
+4s
+3kin
+6s
+3l
+4friend
+9ds
+4hood
+8s
+4ie
+6r
+6s
+7t
+5sh
+7ly
+7ness
+9sses
+4ond
+7s
+4s
+4y
+3n
+4ed
+5l
+6s
+5r
+6s
+4ie
+6r
+6st
+5ng
+4s
+3o
+4lle
+7s
+4n
+5ic
+5ny
+5s
+4s
+5ol
+7s
+3r
+4s
+3sh
+5es
+3t
+4ed
+4h
+5ed
+5ing
+5line
+9s
+5s
+4ing
+4line
+8s
+4s
+2s
+3arme
+7s
+3m
+4o
+5logies
+8y
+5s
+4s
+3t
+4s
+2t
+3ana
+6s
+5o
+6s
+3e
+4s
+3s
+3tarone
+9s
+4ed
+5rn
+7ed
+7ing
+7s
+4in
+6g
+2ust
+5ed
+5ing
+5o
+5s
+2vable
+3e
+4able
+5way
+8s
+4back
+8s
+4d
+4n
+5ness
+9es
+5s
+4r
+5s
+4s
+3ing
+6s
+2zmo
+5logies
+8y
+5s
+3z
+4ard
+7s
+4en
+6ed
+6ing
+6s
+5s
+1jetost
+7s
+2u
+3s
+1labella
+8e
+8r
+4rate
+5escent
+5ous
+8ness
+9esses
+3ce
+5ed
+5ing
+5s
+4ial
+7ist
+9ts
+7ly
+7s
+6te
+8d
+8s
+7ing
+8on
+9ns
+5er
+7ed
+7s
+5ologic
+9ical
+9ies
+9ist
+9ists
+9y
+5s
+6es
+3d
+4ded
+6n
+7ed
+8r
+9s
+7ing
+7s
+6r
+6st
+5ie
+7s
+6ng
+5on
+7s
+4e
+5like
+5s
+4ful
+7ness
+9sses
+4iate
+7or
+9ial
+9ian
+9s
+9ship
+9ships
+9y
+5er
+6st
+5ola
+8r
+8s
+7e
+8s
+7i
+7us
+9es
+5us
+7es
+4lier
+7st
+5y
+4ness
+8es
+4s
+5ome
+8ly
+8ness
+9esses
+8r
+8st
+5tone
+9s
+4wrap
+8ped
+9ing
+8s
+4y
+3ik
+5et
+7ness
+9sses
+5it
+7ness
+9sses
+5s
+4r
+5e
+6d
+6ous
+6s
+5ier
+7st
+6n
+7ess
+9ses
+7g
+7s
+5s
+5y
+4ve
+6d
+6s
+3m
+4med
+5ier
+7st
+6ng
+5y
+4or
+6ed
+6ing
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ous
+9ly
+9ness
+9nesses
+6s
+5ur
+7ed
+7ing
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7less
+7ous
+9sly
+9sness
+7puss
+9sses
+7s
+4ping
+8s
+4s
+3nce
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+4d
+5ered
+7ous
+7s
+6s
+5iferous
+7orm
+5less
+6ike
+5s
+5ular
+9ly
+7e
+8s
+7iferous
+7ous
+9sly
+4s
+3re
+5al
+5d
+5less
+5ous
+5s
+4ier
+6st
+5ness
+9es
+6g
+7ly
+7ness
+9sses
+4y
+3snost
+8ian
+9c
+8s
+4s
+5blower
+9ers
+9ing
+9ings
+5ed
+6n
+6s
+5ful
+8s
+5house
+9es
+5ie
+7r
+7s
+8t
+6fied
+9s
+7y
+8ing
+6ly
+6ne
+8s
+9s
+9ses
+7g
+5less
+6ike
+5maker
+9rs
+8ing
+9ngs
+7n
+6en
+5paper
+9red
+9ring
+9rs
+5ware
+9s
+6ork
+9er
+9ers
+9s
+8m
+9s
+8t
+9s
+5y
+6headed
+3uberite
+9es
+4cescence
+9nces
+9nt
+5oma
+8s
+8tous
+6nite
+9es
+9ic
+6us
+8ly
+8ness
+9esses
+4m
+5ed
+5ing
+5s
+4r
+5ier
+7st
+5s
+5y
+3ze
+5d
+5n
+5r
+6s
+5s
+4ier
+7ies
+7s
+7y
+6st
+5ly
+5ness
+9es
+6g
+7s
+4y
+2eam
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5s
+5y
+4n
+5able
+5ed
+6r
+7s
+5ing
+8s
+5s
+4ve
+6s
+3ba
+5e
+4e
+5less
+5s
+4ier
+6st
+4ous
+4y
+3d
+4e
+5s
+4ge
+6d
+6s
+5ing
+4s
+3e
+4d
+5s
+4ful
+7ly
+7ness
+9sses
+4ing
+4k
+5ed
+5ing
+5s
+4maiden
+9ns
+6n
+5en
+4nie
+7s
+4s
+5ome
+4t
+5ed
+5ier
+7st
+6ng
+5s
+5y
+3g
+4ger
+6st
+4ly
+4ness
+8es
+3i
+4s
+5ation
+9ns
+4zation
+9ns
+3n
+4doveer
+9rs
+4garries
+8y
+4like
+4oid
+7al
+7s
+4s
+4t
+5ed
+5ing
+5s
+3y
+4ed
+4ing
+7s
+4s
+2ia
+4din
+7e
+8s
+7s
+4l
+4s
+3b
+4bed
+6r
+7y
+6st
+5ing
+4ly
+4ness
+8es
+4s
+3d
+4der
+7y
+6st
+4e
+5d
+5path
+9s
+5r
+6s
+5s
+4ing
+7ly
+7s
+3ff
+5ing
+8s
+5s
+4t
+5s
+3ke
+5s
+3m
+4e
+5d
+5s
+4ing
+4mer
+7ed
+7ing
+9gly
+9gs
+7s
+7y
+4pse
+7d
+7r
+8s
+7s
+6ing
+4s
+3nt
+5ed
+5ier
+7st
+6ng
+5s
+5y
+3oblastoma
+9omas
+9omata
+4ma
+6s
+6ta
+7oses
+9is
+8us
+4ses
+5is
+3sk
+5s
+4sade
+8d
+8r
+9s
+8s
+7ing
+6ndi
+8o
+9s
+4ten
+7ed
+7ing
+9gly
+7s
+6r
+7ed
+7ing
+9gly
+7s
+3t
+4ch
+6es
+6ier
+8st
+6y
+4s
+4ter
+7and
+8ti
+7ed
+7ier
+9st
+8ng
+9gly
+9gs
+7s
+7y
+4z
+5ed
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5y
+2oam
+5ing
+8s
+5s
+4t
+5ed
+6r
+7s
+5ing
+8ly
+5s
+3b
+4al
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+5te
+7d
+4bier
+7st
+5y
+4e
+5d
+5fish
+9es
+6lower
+9ers
+5like
+5s
+6ities
+8y
+5trot
+9s
+9ted
+9ter
+9ters
+9ting
+9tings
+4i
+5gerina
+9nae
+9nas
+5n
+6g
+6s
+4oid
+7s
+5se
+7ly
+7ness
+9sses
+6ities
+8y
+5us
+4s
+4ular
+8ities
+9ty
+8ly
+8ness
+9esses
+8s
+6e
+7s
+7t
+8s
+6iferous
+7n
+8s
+7te
+9s
+6ous
+5s
+4y
+3chid
+7ia
+9te
+8um
+7s
+4kenspiel
+9iels
+3de
+3gg
+5s
+3ire
+6s
+3m
+4era
+7te
+9d
+9s
+8ing
+9on
+9ons
+6ular
+9te
+8e
+9s
+8i
+8us
+4med
+5ing
+4s
+4us
+3noin
+7s
+3om
+5ed
+5ful
+8ly
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5less
+5s
+5y
+4p
+5ed
+5ier
+7st
+6ng
+5s
+5y
+3p
+4ped
+5ier
+7st
+6ng
+5y
+4s
+3ria
+6s
+5ed
+6s
+5fiable
+7cation
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5ole
+8s
+6sa
+8s
+6us
+8ly
+8ness
+9esses
+4y
+5ing
+3ss
+5a
+6e
+6l
+6rial
+9lly
+8es
+8st
+9ts
+7y
+6s
+6tor
+9s
+5ectomies
+9my
+6d
+6me
+8s
+6r
+7s
+6s
+5ier
+7s
+8t
+6ly
+6na
+8s
+7ess
+9ses
+7g
+8ly
+6st
+8s
+6tic
+8s
+9es
+5less
+5odynia
+9ias
+6grapher
+9phers
+9phical
+9phies
+9phy
+6lalia
+9ias
+9ist
+9ists
+7ogical
+9ies
+9ist
+9ists
+9y
+5y
+4t
+5s
+3ttal
+5ic
+6dean
+8s
+6s
+7es
+5ogonic
+6logies
+9y
+3ut
+5ed
+5ing
+5s
+3ve
+5d
+5less
+5r
+6s
+5s
+4ing
+7s
+3w
+4ed
+5r
+6ed
+6ing
+9ly
+6s
+4flies
+6y
+4ing
+7ly
+4lamp
+8s
+4s
+5tick
+9s
+4worm
+8s
+3xinia
+8s
+3ze
+5d
+5s
+4ing
+7s
+2ucagon
+8s
+5n
+6s
+4ina
+7s
+6ic
+7um
+9s
+6um
+8s
+4ocorticoid
+9icoids
+5kinase
+9ses
+5nate
+9s
+6eogeneses
+9enesis
+9enic
+5phore
+9es
+6rotein
+9eins
+5samine
+9nes
+6e
+7s
+6ic
+7dal
+9se
+9ses
+8e
+9s
+8ic
+6uria
+9as
+9c
+4uronidase
+9dases
+9de
+9des
+3e
+4ball
+8s
+4d
+4ing
+4like
+4pot
+7s
+4r
+5s
+4s
+4y
+5ness
+9es
+3g
+4gable
+5ed
+5ing
+4s
+3hwein
+8s
+3ier
+5st
+4ly
+4ness
+8es
+5g
+4sh
+3m
+4aceous
+4e
+5like
+6la
+8s
+5s
+4iferous
+4ly
+4mer
+6st
+4ness
+8es
+4pier
+7st
+6ly
+6sh
+5s
+5y
+4s
+3nch
+6ed
+7s
+6ing
+3on
+5s
+3rge
+6s
+3t
+4aeal
+6i
+6us
+5mate
+9s
+6ic
+7nase
+9ses
+8e
+9s
+8ic
+5raldehyde
+9ehydes
+5thione
+9nes
+4e
+5al
+5i
+5lin
+8s
+5n
+6in
+8s
+6ous
+6s
+5s
+5thimide
+9ides
+5us
+4inosities
+9ty
+7us
+9ly
+9ness
+9nesses
+4s
+4ted
+5ing
+8ly
+5on
+7ies
+8se
+9ed
+9es
+9h
+9ing
+8ze
+9ed
+9es
+9ing
+7ous
+9sly
+9sness
+7s
+7y
+2ycaemia
+9s
+8c
+5n
+6s
+5tion
+9s
+4emia
+8s
+7c
+5raldehyde
+9ehydes
+6ia
+8s
+7c
+7de
+9s
+8ic
+7n
+8ate
+9ted
+9tes
+9ting
+8e
+9s
+8s
+6ol
+8s
+6yl
+8s
+4in
+6e
+7s
+6s
+4ocoll
+9s
+5gen
+8eses
+9sis
+9tic
+8ic
+8olyses
+9lysis
+9lytic
+8s
+5l
+6ic
+7pid
+9ds
+6lic
+6s
+6yses
+8is
+7tic
+5neogeneses
+9enesis
+6ic
+8s
+5peptide
+9ides
+6hyte
+9es
+9ic
+6rotein
+9eins
+5se
+7s
+6idase
+9ses
+8e
+9s
+8ic
+9cally
+6uria
+9as
+9c
+6yl
+8ate
+9ted
+9tes
+9ting
+9tion
+9tions
+8s
+4yl
+6s
+3oxaline
+9es
+3ph
+5ic
+5ograph
+9pher
+9phers
+9phic
+9phical
+9phies
+9phs
+9phy
+5s
+4tal
+7s
+5ic
+7s
+5odont
+9ts
+6grapher
+9phers
+9phic
+9phical
+9phies
+9phy
+6theca
+9cae
+1melinite
+9s
+1namma
+3phalium
+9ms
+3r
+4l
+5ed
+5ier
+7st
+6ng
+5s
+5y
+4r
+5ed
+5ing
+5s
+4s
+3sh
+5ed
+6r
+7s
+6s
+5ing
+8ly
+8s
+3t
+4catcher
+9ers
+4hal
+5ic
+6on
+8s
+6te
+8s
+5onic
+9al
+9ally
+6stomatous
+9me
+9mes
+4like
+6ng
+8s
+4s
+4tier
+7st
+5y
+4wren
+8s
+3w
+4able
+4ed
+5r
+6s
+4ing
+7ly
+7s
+4n
+4s
+2eiss
+6es
+6ic
+7tic
+6oid
+7se
+3tophyte
+9es
+2occhi
+3mae
+4e
+5like
+5s
+4ic
+6al
+8ly
+5sh
+6t
+7s
+4on
+6ic
+8al
+9lly
+8s
+6ologies
+9gy
+6s
+3seologies
+9y
+5s
+4iologies
+9y
+5s
+4tic
+7al
+9ly
+7ism
+9ms
+7s
+3tobiological
+9ogies
+9ogy
+8ses
+9is
+8te
+9es
+9ic
+9ically
+9ics
+3w
+4s
+2u
+3s
+1o
+2a
+3d
+4ed
+4ing
+4like
+4s
+5man
+6en
+5ter
+8s
+3f
+4s
+3l
+4ball
+8s
+4ed
+4ie
+6s
+5ng
+4keeper
+9rs
+8ing
+9ngs
+5icker
+9rs
+8ing
+9ngs
+4less
+4mouth
+9s
+4post
+8s
+4s
+4tender
+9rs
+8ing
+9ngs
+4ward
+8s
+3nna
+6s
+3ry
+3s
+3t
+4ee
+6d
+6s
+4fish
+8es
+4herd
+8s
+4ier
+6st
+5sh
+7ly
+7ness
+9sses
+4like
+6ng
+8s
+4s
+5beard
+9ds
+5kin
+8s
+5ucker
+9rs
+4weed
+8s
+4y
+2b
+3an
+5g
+6s
+5s
+4r
+3bed
+5line
+9s
+5t
+6s
+4i
+5er
+6st
+5ng
+4le
+6d
+7egook
+9ooks
+7ygook
+9ooks
+6r
+7s
+6s
+5ing
+4o
+4y
+3i
+4es
+4id
+6s
+4oid
+7s
+4s
+3let
+6s
+4in
+6s
+3o
+4es
+4nee
+5y
+4s
+3s
+4macked
+4topper
+9rs
+3urra
+7s
+3y
+2d
+3child
+8ren
+3damnedest
+6s
+5ughter
+9ers
+4ed
+5n
+6s
+5ss
+7es
+7hood
+9ods
+4ing
+3et
+5ia
+7s
+5s
+3father
+9ed
+9ing
+9s
+4orsaken
+3head
+7s
+4ood
+7s
+3less
+7ly
+7ness
+9sses
+4ier
+6st
+5ke
+7ness
+9sses
+5ly
+5ness
+9es
+6g
+7s
+4y
+3mother
+9ed
+9ing
+9s
+3own
+6s
+3parent
+9s
+3roon
+7ed
+7ing
+9gs
+7s
+3s
+4end
+7s
+4hip
+7s
+4lot
+7s
+4o
+5n
+6s
+4peed
+8s
+4quad
+8s
+3ward
+7s
+4it
+6s
+2e
+3l
+4s
+3r
+4s
+3s
+4t
+3th
+5ite
+8s
+4ic
+5es
+4y
+3y
+2fer
+5s
+3f
+4ed
+5r
+6ed
+6ing
+9s
+6s
+4ing
+4s
+2gga
+5s
+4le
+6box
+9es
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5y
+3let
+6s
+3o
+4s
+2honzon
+8s
+2ier
+4st
+3ng
+5s
+3ter
+6ed
+6s
+4re
+6d
+6s
+5ogen
+9ic
+9icity
+9s
+6us
+2ji
+4s
+2lconda
+8s
+3d
+4arn
+7s
+4beater
+9rs
+5rick
+9ed
+9ing
+9s
+5ug
+7s
+4crest
+9s
+4en
+6berries
+9ry
+6ed
+7r
+7st
+7ye
+9s
+6ing
+6ly
+6ness
+9ses
+6rod
+9s
+6s
+7eal
+9ls
+5r
+5st
+5ye
+7s
+4field
+9s
+6nch
+9es
+7nies
+8y
+6sh
+8es
+4ier
+6st
+5locks
+9ses
+5sh
+4less
+4miner
+9s
+4s
+5innies
+8y
+6ze
+8s
+5mith
+9eries
+9ery
+9ries
+9ry
+9s
+5pink
+9s
+5tick
+9s
+6one
+9s
+4tail
+5hread
+9ds
+5one
+4urn
+7s
+4work
+8s
+4y
+3e
+4m
+5s
+4s
+3f
+4ed
+5r
+6s
+4iana
+8s
+5ng
+7s
+4s
+3gotha
+8s
+3iard
+7eries
+9y
+7ic
+8es
+7s
+7y
+5s
+6ed
+7s
+6ing
+5th
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7s
+3lan
+6d
+7s
+6s
+5r
+6ed
+6ing
+6s
+4er
+6ed
+6ing
+6s
+4ied
+6s
+5wog
+8g
+9s
+8s
+4op
+6ed
+7r
+8s
+6ing
+6s
+4y
+5ing
+5wog
+8s
+3omynka
+9s
+4ptious
+4sh
+6e
+7d
+7s
+6ing
+6oes
+3p
+4e
+5s
+4s
+3uptious
+2mbeen
+7ism
+9ms
+7s
+4o
+5s
+4ro
+6on
+8s
+6s
+3er
+5al
+7s
+5el
+7s
+5il
+7s
+5s
+3oku
+6s
+3pa
+5s
+4hoses
+7is
+3uti
+6s
+5o
+6s
+2n
+3ad
+5al
+5ectomies
+9mised
+9mized
+9my
+5ial
+6c
+5otrophic
+9phin
+9phins
+9pic
+9pin
+9pins
+5s
+3delay
+8s
+4ola
+7s
+6ier
+9s
+3e
+4f
+5s
+4ness
+8es
+4r
+5s
+3falon
+8ier
+9ers
+8s
+5non
+8s
+3g
+4ed
+4ing
+4like
+4oristic
+4s
+5ter
+8s
+4yo
+6s
+3ia
+5tite
+9s
+8oid
+9ids
+4dia
+7l
+6c
+6um
+4f
+5f
+6s
+5s
+4moblast
+9sts
+4ometer
+9rs
+8ric
+9ical
+9ically
+9ies
+9y
+5n
+5scope
+9es
+4um
+3k
+4s
+3na
+3ococcal
+8i
+9c
+8oid
+8us
+5yte
+8s
+4duct
+8s
+4f
+5s
+4ph
+6ore
+9s
+8ic
+8ous
+6s
+5od
+7s
+6re
+8s
+4rrhea
+9l
+9s
+8ic
+7oea
+9al
+9as
+9ic
+4some
+8s
+3s
+3ys
+5es
+3zo
+2o
+3ber
+6s
+4ies
+4y
+3d
+4by
+6e
+7s
+6s
+4faced
+5ella
+9s
+8ow
+9ws
+9wship
+9wships
+4ie
+6r
+6s
+7t
+5ness
+9es
+5sh
+4lier
+7st
+6head
+9ds
+6ness
+9ses
+5y
+6head
+9ds
+4man
+5en
+4ness
+8es
+5ight
+9s
+4s
+5ire
+8s
+4time
+4wife
+6ll
+8ed
+8s
+6ves
+4y
+5ear
+8s
+3ey
+5ness
+9es
+3f
+4ball
+8s
+4ed
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4s
+4y
+3g
+4le
+6d
+6s
+6whack
+9cks
+5ies
+6ng
+5y
+4ol
+6plex
+9xes
+6s
+4s
+3ier
+5st
+4ly
+4ness
+8es
+3k
+4s
+4y
+3l
+4d
+5s
+4ey
+6s
+4ie
+6s
+4s
+4y
+3mbah
+7s
+6y
+7s
+3n
+4da
+6s
+4ey
+6bird
+9ds
+6s
+4ie
+6r
+6s
+7t
+4s
+4y
+3p
+4ed
+4ier
+6st
+5ness
+9es
+4s
+4y
+3r
+4al
+6s
+4ie
+6s
+4oo
+6s
+4s
+4y
+3s
+4ander
+9s
+4e
+5berries
+9y
+5d
+5fish
+9es
+6lesh
+9hes
+6oot
+9s
+5gob
+8s
+7g
+8s
+6rass
+9ses
+5herd
+9s
+5neck
+9ed
+9s
+5ries
+6y
+5s
+5y
+6s
+4ier
+6s
+7t
+5ness
+9es
+6g
+4y
+2pak
+5s
+3her
+6ed
+6ing
+6s
+6wood
+9ds
+3ik
+5s
+3ura
+6m
+7s
+6s
+2r
+3a
+4l
+5s
+4mies
+5y
+4s
+3bellies
+7y
+4limey
+9s
+7ies
+7y
+3cock
+7s
+4row
+7s
+3dita
+7s
+3e
+4d
+4hound
+9s
+4s
+3ge
+5able
+5d
+6ly
+5ous
+8ly
+8ness
+9esses
+5r
+6in
+8s
+6s
+5s
+5t
+6ed
+6s
+4ia
+6s
+5ng
+5o
+6s
+4on
+6eia
+8on
+6ian
+9s
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6s
+3hen
+6s
+3i
+4er
+5st
+4lla
+7gram
+9ams
+7s
+6ian
+7ne
+6oid
+5y
+4ness
+8es
+5g
+6s
+4s
+3m
+4and
+7ise
+9ed
+9er
+9ers
+9es
+9ing
+9ings
+9m
+9ms
+8ze
+9ed
+9er
+9ers
+9es
+9ing
+9ings
+7s
+4ed
+4ier
+6st
+5ng
+4less
+4s
+4y
+3p
+4ed
+4ing
+4s
+3se
+5dd
+7s
+5s
+4ier
+6st
+4oon
+7s
+4y
+3y
+2s
+3h
+4awk
+7s
+4t
+5s
+3larite
+9s
+4et
+6s
+4ing
+7s
+3pel
+6er
+8s
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6led
+8r
+9s
+7ing
+9gs
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7y
+6s
+4oda
+7r
+8s
+6in
+5rt
+7s
+3s
+4amer
+8s
+8y
+5n
+6s
+4e
+5d
+5s
+4ib
+6s
+5ng
+5p
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6monger
+9gers
+6ped
+8r
+9s
+7ing
+6ries
+7y
+6s
+6y
+4oon
+7s
+4ypine
+6ol
+8s
+3ter
+6ed
+6ing
+6s
+2t
+3cha
+6s
+3h
+4ic
+6ally
+6ise
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+6s
+5te
+7s
+4s
+3ta
+4en
+2uache
+7s
+3ch
+5ed
+6s
+5ing
+3ge
+5d
+5r
+6e
+7s
+6s
+5s
+4ing
+3jeers
+4on
+6s
+3k
+4s
+3lash
+7es
+3ra
+5mi
+7es
+7s
+5s
+4d
+5e
+6s
+5ier
+7st
+6ness
+9ses
+5like
+5s
+5y
+4mand
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+8s
+5et
+7s
+3stier
+7st
+5rous
+5y
+3t
+4flies
+6y
+4ier
+6st
+5ly
+5ness
+9es
+4s
+4te
+6s
+4weed
+8s
+5ort
+8s
+4y
+3vernante
+9tes
+2v
+3ern
+6abilities
+9lity
+8le
+9eness
+7ll
+9s
+7nce
+9es
+8te
+9es
+6ed
+7ss
+9ed
+9es
+9ing
+9y
+6ing
+6ment
+9tal
+9talise
+9talism
+9talist
+9talize
+9tally
+9tese
+9teses
+9ts
+6or
+8ate
+9tes
+8s
+9hip
+9hips
+6s
+3s
+2wan
+5ed
+5s
+5y
+3d
+4er
+5st
+4s
+5pink
+9s
+3f
+4ed
+5r
+6s
+4ing
+4s
+3k
+4s
+3l
+4an
+6d
+7s
+6s
+4ed
+4ing
+4s
+3n
+4boy
+7s
+4ed
+4ing
+4man
+5en
+4s
+5man
+6en
+3pen
+6ful
+9s
+6s
+2x
+3es
+2y
+3im
+4sch
+5h
+3le
+5s
+3s
+2zzan
+6s
+1raal
+5s
+3b
+4bable
+5ed
+6r
+7s
+5ier
+7st
+6ng
+5le
+7d
+7r
+8s
+7s
+6ing
+5y
+4en
+6s
+4s
+3ce
+5d
+5ful
+8ler
+9est
+9y
+8ness
+9esses
+5less
+9ly
+9ness
+9nesses
+5s
+4ile
+7ness
+9sses
+7s
+6is
+7ties
+8y
+5ng
+5osities
+9y
+7o
+8s
+6us
+8ly
+8ness
+9esses
+4kle
+7s
+3d
+4abilities
+9ty
+6le
+8ness
+9esses
+8s
+5te
+7d
+7s
+6im
+7ng
+7on
+9al
+9ally
+9ed
+9s
+6ory
+4dan
+7ed
+7ing
+7s
+4e
+5d
+5less
+6ier
+8st
+6y
+5r
+6s
+5s
+4ient
+8er
+9rs
+8s
+5n
+6e
+7s
+6g
+7s
+6i
+6o
+6s
+5ometer
+9ers
+4s
+4ual
+7ism
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+7ly
+7ness
+9sses
+7s
+6nd
+8s
+6te
+8d
+8s
+9hip
+9hips
+7ing
+8on
+9ns
+7or
+9s
+5s
+6es
+3ecise
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+3ff
+5ed
+5ing
+6ti
+8ed
+8ing
+8ng
+8s
+9t
+9ts
+7o
+5s
+4t
+5age
+8s
+5ed
+6r
+7s
+5ing
+8s
+5s
+3ham
+6s
+3il
+5e
+6s
+5s
+4n
+5age
+8s
+5e
+6d
+6r
+7s
+6s
+5field
+9ds
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5less
+5s
+5y
+4p
+5s
+4th
+6ed
+6ing
+6ly
+6s
+3kle
+6s
+3llatorial
+5och
+8ed
+8ing
+8s
+3m
+4a
+5ries
+6y
+7e
+8s
+5s
+6h
+7es
+4e
+5rcies
+7y
+5s
+4icidin
+9ns
+5naceous
+6eous
+6icolous
+7vorous
+6ologies
+9gy
+4ma
+6ge
+8s
+6logue
+9ues
+6r
+7ian
+9ns
+7less
+7s
+6s
+6tic
+9al
+9ality
+9ally
+9alness
+9aster
+9asters
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ize
+9ized
+9izes
+9izing
+8st
+9ts
+7ologies
+9ogist
+9ogists
+9ogy
+5e
+6s
+4oche
+8s
+5phone
+9es
+9ic
+9ically
+9ies
+9ist
+9ists
+9y
+4p
+5a
+6s
+5s
+5us
+7es
+4s
+3n
+4a
+5dilla
+9as
+5ries
+6y
+4d
+5ad
+7dies
+8y
+7s
+6m
+7e
+8s
+7s
+6unt
+9s
+5babies
+8y
+5child
+9dren
+5dad
+8dies
+9y
+8s
+7m
+8s
+7ughter
+9hters
+5e
+6e
+7s
+8hip
+9ips
+6r
+6st
+6ur
+8s
+5father
+9ered
+9ering
+9erly
+9ers
+5iflora
+9rae
+9ras
+6loquence
+9uences
+9uent
+9uently
+9uous
+6ose
+9ly
+9ness
+9nesses
+8ities
+9ty
+8o
+5kid
+8s
+5ly
+5ma
+7ma
+9s
+8ma
+9as
+7s
+8ter
+9ers
+6other
+9erly
+9ers
+5nephew
+9ews
+7ss
+9es
+6iece
+9es
+5pa
+7pa
+9s
+7rent
+9ntal
+9nthood
+9nts
+7s
+5s
+6ir
+8e
+9s
+8s
+6on
+8s
+6tand
+9ded
+9der
+9ders
+9ding
+9ds
+7ood
+5uncle
+9es
+4fer
+7s
+4ge
+6r
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7s
+6s
+4ita
+7s
+6e
+7like
+7s
+7ware
+9res
+6ic
+7fication
+8orm
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7te
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6oid
+5vore
+9s
+8ous
+4nam
+7s
+5ie
+7d
+7ing
+7s
+5om
+7s
+5y
+6ing
+7sh
+4odiorite
+9ites
+9itic
+5la
+7s
+6ith
+9ic
+9ics
+9s
+5phyre
+9es
+9ic
+4s
+4t
+5able
+5ed
+6e
+7s
+6r
+7s
+5ing
+5or
+7s
+5s
+6man
+9ship
+9ships
+7en
+4ular
+8ities
+9ty
+8ly
+8y
+7te
+9d
+9r
+9rs
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+6e
+7s
+6iferous
+8orm
+7te
+9s
+8ic
+9sation
+9zation
+6ocyte
+9tes
+9tic
+7ma
+9s
+9ta
+9tous
+7se
+9s
+8is
+7us
+5m
+3pe
+5d
+5fruit
+9ts
+5less
+6ice
+7ke
+6ouse
+5ries
+6y
+5s
+6eed
+9s
+6hot
+9s
+6tone
+9es
+5tree
+9s
+5vine
+9s
+5y
+4h
+5ed
+6me
+8s
+7ic
+9ally
+9s
+6ne
+8s
+5ic
+7acies
+9y
+8l
+9ly
+9ness
+9nesses
+7ly
+7ness
+9sses
+7s
+6ng
+6te
+8s
+7ic
+8sable
+9ation
+9ations
+9e
+9ed
+9es
+9ing
+8zable
+9ation
+9ations
+9e
+9ed
+9es
+9ing
+7oid
+6um
+8s
+5olect
+9ts
+7ogic
+9ical
+9ies
+9ist
+9ists
+9y
+6mania
+9ias
+7otor
+6phobia
+9bias
+5s
+4ier
+6st
+5ness
+9es
+6g
+4le
+6ment
+9ts
+6s
+5in
+7e
+8s
+7s
+4nel
+7s
+4pa
+6s
+5le
+7d
+7r
+8s
+7s
+6ing
+9s
+4tolite
+9es
+9ic
+4y
+3sp
+5able
+5ed
+6r
+7s
+5ing
+8ly
+8ness
+9esses
+5less
+5s
+4s
+5bird
+9s
+5ed
+6r
+7s
+6s
+5finch
+9hes
+5hook
+9s
+7pper
+9ers
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5land
+9s
+6ess
+6ike
+5plot
+9s
+5quit
+9s
+5root
+9s
+5um
+7s
+5wrack
+9ks
+5y
+4te
+3t
+4e
+5d
+5ful
+8ler
+9est
+9y
+8ness
+9esses
+5less
+5r
+6s
+5s
+4iculation
+9tions
+8e
+9s
+5fication
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+9gly
+5llities
+9y
+5n
+6ate
+9d
+9s
+8ing
+6e
+7e
+8d
+8ing
+8s
+6g
+7ly
+7s
+6s
+5s
+5tude
+9s
+4toir
+8s
+4uities
+7ous
+9sly
+9sness
+7y
+5lant
+7te
+9d
+9s
+8ing
+9on
+9ons
+8ory
+3unch
+7ed
+8r
+9s
+8s
+7ing
+4pel
+7s
+3v
+4adlax
+9es
+5men
+8s
+6ina
+4e
+5d
+5l
+6ed
+7ss
+6ike
+7ng
+7sh
+6led
+7ing
+7y
+6s
+6y
+5n
+6ess
+9es
+5olent
+5r
+6s
+5s
+6ide
+9s
+7te
+9s
+6t
+7one
+9es
+5ward
+5yard
+9s
+4id
+6a
+7e
+7s
+6ities
+8y
+6ly
+6ness
+9ses
+5es
+5meter
+9rs
+8ric
+9ical
+9ically
+9ies
+9y
+5ng
+7s
+5perception
+5s
+5tas
+8es
+7te
+9d
+9r
+9rs
+9s
+8ing
+9on
+9onal
+9onally
+9ons
+9ve
+6ies
+7no
+9s
+6ometer
+9ters
+7n
+8s
+6y
+4laks
+6x
+7es
+4s
+4ure
+7s
+4y
+3y
+4back
+8s
+5eard
+9ed
+9s
+4ed
+5r
+5st
+4fish
+8es
+5lies
+6y
+4hound
+9s
+4ing
+5sh
+4lag
+7s
+5e
+6s
+5ing
+8s
+5y
+4mail
+8s
+4ness
+8es
+4out
+7s
+4s
+5cale
+4wacke
+9s
+6ter
+9s
+3zable
+4e
+5able
+5d
+5r
+6s
+5s
+4ier
+7s
+5ng
+7ly
+7s
+5oso
+2ease
+6ball
+9ls
+8nd
+9ds
+7ush
+9hes
+6d
+6less
+6paint
+9nts
+7roof
+9ofs
+6r
+7s
+6s
+6wood
+9ds
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5y
+4t
+5coat
+9ed
+9s
+5en
+7ed
+7ing
+7s
+6r
+6st
+8s
+5hearted
+9tedly
+5ly
+5ness
+9es
+5s
+4ve
+6d
+6s
+5ing
+3be
+5s
+4o
+5s
+3ce
+5s
+4ian
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7s
+5se
+7d
+7s
+6ing
+5ze
+7d
+7s
+6ing
+4que
+7s
+3e
+4bo
+6es
+4ce
+6s
+4d
+5ier
+7st
+6ly
+6ness
+9ses
+5less
+5s
+6ome
+5y
+4gree
+8s
+4ing
+4k
+5ed
+5ing
+8s
+4n
+5back
+9er
+9ers
+9ism
+9isms
+9s
+6elt
+9s
+6one
+9s
+7ttle
+9les
+6rier
+9rs
+6ug
+8s
+5cloth
+9hs
+5ed
+6r
+7ies
+7s
+7y
+6st
+6ye
+8s
+5field
+9ds
+7nch
+9hes
+6lies
+7y
+5gage
+9s
+6rocer
+9eries
+9ers
+9ery
+5hand
+9s
+6ead
+9s
+8rt
+9ts
+6orn
+9s
+7use
+9es
+5ie
+7r
+7s
+8t
+6ng
+8s
+6sh
+8ness
+9esses
+5keeper
+9ers
+5let
+8s
+6ight
+9ted
+9ting
+9ts
+7ng
+9s
+7t
+6y
+5mail
+9ed
+9er
+9ers
+9ing
+9s
+5ness
+9es
+5ockite
+9tes
+5room
+9s
+5s
+6and
+9s
+6hank
+9ks
+6ick
+9ness
+9nesses
+6keeper
+9pers
+6ome
+9s
+6peak
+9ks
+6tick
+7one
+9es
+7uff
+9fs
+6ward
+9ds
+5th
+7s
+5wash
+9ed
+9es
+9ing
+7y
+8s
+6eed
+9s
+6ing
+9s
+6ood
+9s
+5y
+4s
+5e
+6s
+5ing
+8s
+4t
+5e
+6d
+6r
+7s
+6s
+5ing
+8s
+5s
+3ffier
+8s
+3gale
+7s
+5rian
+9ism
+9isms
+7ne
+9s
+8ian
+7ous
+9sly
+9sness
+5tim
+4e
+4o
+5s
+3ige
+6s
+4n
+5ed
+5ing
+5s
+4sen
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7s
+5ly
+3mial
+7s
+4lin
+7s
+4mie
+7s
+5y
+4olata
+9s
+3n
+4ache
+8s
+5de
+7s
+6ier
+9s
+7lla
+9as
+7ne
+9s
+4ned
+5ing
+4s
+3se
+5s
+4sing
+8s
+5orial
+8ous
+3ve
+5s
+4illea
+9s
+3w
+4ed
+4hound
+9s
+4ing
+4s
+5ome
+8r
+8st
+3x
+4es
+3y
+4back
+8s
+5eard
+9ed
+9s
+4ed
+5r
+5st
+4hen
+7s
+5ound
+9s
+4ing
+7s
+5sh
+4lag
+7s
+5ist
+8ed
+8ing
+8s
+5y
+4ness
+8es
+4s
+5cale
+9s
+5tone
+9s
+4wacke
+9s
+5ether
+9rs
+2ibble
+7s
+3ce
+5d
+5r
+6s
+5s
+4ing
+7s
+3d
+4ded
+6r
+7s
+5le
+7bread
+9eads
+7cake
+9kes
+7d
+7s
+6ing
+4e
+5d
+5lin
+8s
+5s
+4ing
+5ron
+8ed
+8ing
+8s
+4lock
+8ed
+8ing
+8s
+4s
+3ece
+6d
+6s
+4f
+5er
+7s
+5ful
+5less
+5s
+4sie
+5ly
+5y
+4vance
+9s
+7t
+8s
+5e
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+5ous
+8ly
+8ness
+9esses
+3ff
+5e
+6s
+5in
+7ish
+9m
+9ms
+7s
+5on
+7s
+5s
+4t
+5ed
+6r
+7s
+5ing
+5s
+3g
+4ged
+5ing
+4ri
+6s
+4s
+3ke
+5s
+3ll
+5ade
+8s
+6ge
+8s
+5e
+6d
+6r
+7ies
+7s
+7y
+6s
+5ing
+8s
+6on
+8s
+5room
+9s
+5s
+6teak
+9ks
+5work
+9s
+4se
+6s
+3m
+4ace
+7d
+7r
+8s
+7s
+6ing
+9ly
+5lkin
+9s
+4e
+5d
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4looked
+5y
+4mer
+6st
+4ness
+8es
+4oire
+8s
+4y
+3n
+4ch
+6es
+4d
+5ed
+6lia
+9s
+6r
+7ies
+7s
+7y
+5house
+9es
+5ing
+8ly
+8s
+5s
+6tone
+9es
+4ga
+6s
+5o
+6s
+4ned
+6r
+7s
+5ing
+8ly
+8s
+4s
+3ot
+5s
+3p
+4e
+5d
+5r
+6s
+5s
+5y
+4ier
+6st
+5ng
+7ly
+4le
+4man
+5en
+4pe
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8ly
+5le
+7s
+5y
+4s
+5ack
+8s
+4t
+5ape
+8s
+4y
+3s
+4aille
+9s
+4e
+5d
+5ly
+5ofulvin
+9vins
+6us
+5s
+5tte
+8s
+4gris
+4ing
+4kin
+7s
+4led
+5ier
+7s
+8t
+6ness
+9ses
+5y
+4on
+6s
+4sini
+7o
+4t
+5er
+7s
+5le
+7s
+6ier
+8st
+7ness
+9sses
+6y
+5mill
+9s
+5s
+4y
+3t
+4h
+5s
+4less
+4s
+5tone
+9s
+4ted
+6r
+7s
+6st
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5y
+3vation
+9s
+4et
+6s
+3ze
+5s
+4zle
+7d
+7r
+8s
+7s
+6ier
+8s
+9t
+7ng
+6y
+2oan
+5ed
+6r
+7s
+5ful
+5ing
+8ly
+8s
+5s
+4t
+5s
+6worth
+9ths
+3cer
+6ies
+6s
+6y
+5teria
+9as
+4ked
+5ing
+5le
+7s
+3dier
+6st
+4y
+3g
+4ged
+6ries
+7y
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5y
+4ram
+7s
+4s
+5hop
+8s
+3in
+5ed
+5ing
+8s
+5s
+3k
+4ed
+4ing
+4ked
+5ing
+4s
+3ma
+5s
+4et
+6s
+4met
+7ed
+7ing
+7s
+4well
+8s
+3ne
+5d
+5full
+5s
+4ing
+3of
+5s
+4lier
+7st
+5y
+4m
+5ed
+6r
+7s
+5ing
+8s
+5s
+6man
+7en
+4ve
+6d
+6less
+7ike
+6r
+7s
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5y
+3ped
+5r
+6s
+5s
+4ing
+7ly
+3sbeak
+8s
+4chen
+8s
+4er
+6s
+6t
+7s
+5t
+6s
+4grain
+9s
+4s
+5art
+8s
+5ed
+6r
+7s
+6s
+7t
+5ierete
+9tes
+6ng
+5ly
+5ness
+9es
+5ular
+9ite
+9ites
+9s
+4z
+5e
+5y
+3t
+4esque
+9ly
+9ness
+9nesses
+9r
+9rie
+9ries
+9ry
+9s
+9st
+4s
+4tier
+7st
+6ness
+9ses
+5o
+6ed
+7s
+6s
+5y
+3uch
+6ed
+7s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6y
+4f
+5s
+4gh
+6s
+4nd
+6age
+9s
+6bait
+9ted
+9ting
+9ts
+7reaker
+9akers
+9aking
+9akings
+7urst
+9sts
+6ed
+8ly
+7n
+7r
+8s
+6fish
+9hes
+6hog
+9s
+6ing
+9s
+6less
+9sly
+9sness
+7ing
+9gs
+6man
+8ss
+9ses
+7en
+6nut
+9s
+6out
+9s
+6plot
+9ts
+7rox
+9xes
+6s
+7el
+9l
+9ls
+9s
+7hare
+9red
+9res
+9ring
+8eet
+9ets
+7ill
+9ls
+7keeper
+9epers
+7man
+8en
+7peed
+9eds
+7well
+9lls
+6water
+9ers
+7ood
+9ds
+8rk
+9ks
+4p
+5able
+6ge
+8s
+5ed
+6r
+7s
+5ie
+7s
+6ng
+8s
+6st
+8s
+5let
+8s
+5oid
+8s
+5s
+5think
+9ks
+5uscule
+9les
+5ware
+9s
+6ork
+9s
+5y
+4se
+6d
+6like
+6r
+7s
+6s
+7t
+5ing
+4t
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8s
+5s
+5y
+3ve
+5d
+5l
+6ed
+7r
+8s
+7ss
+6ing
+9ly
+6led
+8r
+9s
+7ing
+9gly
+9gs
+6s
+5s
+5t
+6s
+3w
+4able
+4er
+6s
+4ing
+7ly
+7s
+4l
+5ed
+6r
+7ies
+7s
+7y
+5ier
+7st
+6ness
+9ses
+7g
+8ly
+8s
+5s
+5y
+4n
+5up
+7s
+4s
+4th
+6ier
+8st
+7ness
+9sses
+7st
+9s
+6s
+6y
+3yne
+6s
+3zing
+2rl
+4s
+3rl
+5s
+2ub
+4bed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5le
+7d
+7s
+6ing
+5y
+4s
+5take
+9d
+9r
+9rs
+9s
+8ing
+4worm
+8s
+3dge
+6d
+6ful
+6less
+6r
+7s
+6s
+5ing
+8ly
+8s
+3e
+4d
+4ing
+4l
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5led
+7r
+8s
+6ing
+9ly
+9s
+5s
+4s
+5ome
+8ly
+8ness
+9esses
+8r
+8st
+3fe
+5s
+4f
+5ed
+6r
+6st
+5ier
+7st
+6ly
+6ng
+6sh
+5ly
+5ness
+9es
+5s
+5y
+4ted
+3gru
+6s
+3iform
+4ng
+3m
+4ble
+7d
+7r
+8s
+7s
+6ier
+8st
+7ng
+9ly
+9s
+6y
+4e
+5s
+4ly
+4mer
+6st
+6t
+7ed
+7ing
+7s
+4ness
+8es
+4ose
+5us
+4p
+5ed
+5h
+6ed
+6ie
+8s
+7ng
+6s
+6y
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+6sh
+8ly
+8ness
+9esses
+5s
+5y
+3nd
+5ies
+5le
+7s
+4ge
+6r
+7s
+6s
+6y
+5ier
+7st
+5y
+4ion
+7s
+4t
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5le
+7d
+7s
+6ing
+5s
+3ppetti
+8o
+3shie
+3tch
+6ed
+7s
+6ing
+4ten
+3yere
+7s
+2yce
+5s
+3de
+5d
+5s
+4ing
+3esy
+3fon
+6s
+3ke
+5s
+3pe
+5s
+4hon
+7s
+4t
+3sbok
+7s
+4ely
+4ie
+1u
+2acamole
+9s
+4hamole
+9es
+6ro
+8es
+8s
+4o
+5s
+3iac
+6ol
+8s
+6s
+6um
+8s
+4ocum
+8s
+3n
+4a
+5bana
+9s
+5co
+7s
+5s
+6e
+7s
+5y
+6s
+5zolo
+9s
+4ethidine
+9ines
+4go
+6s
+4idin
+8e
+9s
+8s
+5ferous
+5n
+6e
+7s
+6s
+4o
+5s
+6ine
+9s
+4s
+4xi
+6s
+4ylic
+3r
+4ana
+7s
+6i
+7es
+7s
+6tee
+9d
+9ing
+9s
+7ied
+9s
+7or
+9s
+7y
+8ing
+4d
+5able
+6ge
+8s
+6nt
+8s
+5dog
+8s
+5ed
+7ly
+7ness
+9sses
+6e
+7s
+6r
+7s
+5house
+9es
+5ian
+8s
+9hip
+9hips
+6ng
+5less
+6ike
+5rail
+9s
+6oom
+9s
+5s
+6hip
+9s
+6man
+7en
+4ish
+7ed
+8s
+7ing
+4s
+3va
+5s
+3yabera
+9s
+4ule
+7s
+2b
+3bah
+6s
+4ed
+4ing
+6s
+7es
+3ernacula
+9lar
+9lum
+7tion
+9ons
+8or
+9rial
+9rs
+6iya
+9s
+3s
+2ck
+4ier
+6st
+4s
+4y
+2ddle
+6d
+6s
+5ing
+3e
+4man
+5en
+4s
+5ire
+8s
+4wife
+6ves
+3geon
+7ed
+7ing
+7s
+2e
+3lder
+3non
+6s
+3rdon
+7ed
+8r
+9s
+7ing
+7s
+4eza
+7s
+4idon
+8s
+5lla
+8ism
+9sms
+8s
+5te
+7s
+4nsey
+8s
+4rilla
+9ism
+9isms
+9s
+8ero
+9ros
+3s
+4s
+5able
+5ed
+6r
+7s
+6s
+5ing
+8ly
+8s
+5timate
+9ted
+9tes
+9ting
+5work
+9s
+4t
+5book
+9s
+5ed
+6n
+7ed
+7ing
+7s
+5house
+9es
+5imate
+9ed
+9es
+9ing
+6ng
+5s
+5wise
+2ff
+4aw
+6ed
+6ing
+6s
+4ie
+6s
+4s
+2ga
+4s
+3gle
+6d
+6s
+5ing
+3let
+6s
+2ichet
+7s
+3d
+4able
+5ge
+7s
+5nce
+8s
+4e
+5book
+9s
+5d
+5less
+6ine
+9s
+5post
+9s
+5r
+6s
+5s
+6hip
+9s
+5way
+8s
+6ord
+9s
+4ing
+7s
+4on
+6s
+4s
+4willie
+3ld
+5er
+7s
+5hall
+9s
+5ries
+6y
+5s
+6hip
+9s
+6man
+7en
+6woman
+9en
+4e
+5d
+5ful
+8ly
+8ness
+9esses
+5less
+9ly
+9ness
+9nesses
+5r
+6s
+5s
+4ing
+4lemet
+9s
+7ot
+9s
+5oche
+9d
+9s
+8ing
+6tine
+9ed
+9er
+9ers
+9es
+9ing
+4t
+5ed
+5ier
+7st
+6ly
+6ness
+9ses
+5less
+9ly
+9ness
+9nesses
+5s
+5y
+3mbard
+8s
+4p
+5e
+6d
+6s
+5ing
+5s
+3nea
+6s
+3pure
+7s
+3ro
+5s
+3sard
+7s
+4e
+5d
+5r
+6s
+5s
+4ing
+7s
+3tar
+6fish
+9hes
+6ist
+9s
+6s
+4guit
+8s
+3zer
+6s
+2l
+3a
+4g
+5s
+4r
+4s
+3ch
+5ed
+6s
+5ing
+3den
+6s
+3e
+4s
+4t
+5s
+3f
+4ed
+4ier
+6st
+5ng
+4like
+4s
+4weed
+8s
+4y
+3l
+4able
+7y
+4ed
+5r
+6ies
+6s
+6y
+5t
+6s
+5y
+6ed
+6ing
+6s
+4ibilities
+9ty
+6le
+7y
+5ed
+6s
+5ng
+5sh
+4s
+4wing
+4y
+5ing
+3osities
+7y
+3p
+4ed
+5r
+6s
+4h
+5s
+4ier
+6st
+5ng
+7ly
+4s
+4y
+3s
+3y
+2m
+3ball
+7s
+4o
+5il
+7s
+5ot
+7s
+5s
+5til
+8s
+3drop
+7s
+3lands
+4ess
+4ike
+5ne
+7s
+3ma
+5s
+5ta
+6ous
+4ed
+5r
+6s
+4ier
+6s
+7t
+5ferous
+5ly
+5ness
+9es
+6g
+7s
+5te
+7s
+4ose
+7s
+6is
+7ties
+8y
+5us
+4y
+3nut
+6s
+3p
+4ed
+4hion
+8s
+4ing
+4s
+4tion
+8s
+7us
+3s
+4hield
+9s
+5oe
+7d
+7ing
+7s
+4ucker
+9s
+3tree
+7s
+3weed
+7s
+4ood
+7s
+2n
+3boat
+7s
+3cotton
+9s
+3dies
+4og
+6s
+4y
+3fight
+8er
+9rs
+8ing
+9ngs
+8s
+5re
+7s
+4lint
+8s
+4ought
+3g
+4e
+5d
+5s
+4ier
+6st
+5ng
+4y
+3house
+8s
+3ite
+6s
+3k
+4hole
+8d
+8s
+7ing
+4ier
+6st
+4s
+4y
+3layer
+8s
+4ess
+4ock
+7s
+3maker
+8s
+5n
+6ship
+9ps
+4en
+5tal
+8s
+3nage
+7s
+4ed
+5l
+6s
+5n
+5r
+6a
+7s
+6ies
+6s
+7hip
+9ps
+6y
+4ies
+5ng
+7s
+4y
+5bag
+8s
+5sack
+9s
+3paper
+8s
+4lay
+7s
+4oint
+8s
+5rt
+7s
+5wder
+9s
+9y
+3room
+7s
+4unner
+9s
+7ing
+9gs
+3s
+4el
+6s
+4hip
+7s
+5ot
+7s
+4ight
+8s
+4linger
+9rs
+8ing
+9ngs
+4mith
+8ing
+9ngs
+8s
+4tick
+8s
+5ock
+8s
+6ne
+8s
+3ter
+6s
+3wale
+7s
+3yah
+6s
+2p
+3pies
+4y
+3s
+2qin
+5s
+2r
+3ami
+6s
+3dwara
+8s
+3ge
+5d
+5s
+4ing
+5tation
+9ons
+4le
+6d
+6s
+6t
+7s
+5ing
+4oyle
+8s
+3jun
+6s
+3l
+4ed
+5t
+6s
+4ier
+6st
+5ng
+4s
+4y
+3n
+4ard
+7s
+4ed
+5t
+6s
+5y
+6s
+4ing
+4s
+3rah
+6s
+4ier
+7s
+6s
+4y
+3s
+4h
+5es
+3u
+4dom
+7s
+4ism
+7s
+4s
+5hip
+8s
+2s
+3h
+4ed
+5r
+6s
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7ly
+4y
+3la
+5r
+6s
+5s
+4e
+5s
+4i
+5s
+3set
+6ed
+6ing
+9s
+6s
+4ie
+6d
+6s
+4y
+5ing
+3t
+4able
+8s
+5tion
+9s
+7ve
+6orily
+8y
+4ed
+4ful
+4ie
+6r
+6st
+5ly
+5ness
+9es
+6g
+4less
+4o
+5es
+5s
+4s
+4y
+2t
+3bucket
+9s
+3cher
+7s
+3ful
+6s
+3less
+7ly
+7ness
+9sses
+4ike
+3rot
+6s
+3s
+4ed
+5r
+6s
+5s
+4ful
+7s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4y
+3ta
+5e
+5s
+5te
+7d
+7s
+6ing
+7on
+9s
+4ed
+5r
+6blood
+9ods
+6ed
+6ing
+9s
+6s
+7nipe
+9pes
+9pish
+6y
+4ier
+6s
+7t
+5ferous
+5ng
+4le
+6d
+6r
+7s
+6s
+5ing
+4ural
+8isation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8ness
+9esses
+8s
+4y
+3zer
+6s
+2v
+3s
+2y
+3ed
+3ing
+3le
+5d
+5r
+6s
+5s
+4ine
+7r
+8s
+7s
+6g
+3ot
+5s
+3s
+4e
+5s
+2zzle
+6d
+6r
+7s
+6s
+5ing
+1weduc
+6k
+7s
+6s
+2ine
+4iad
+7s
+2yniad
+7s
+1yal
+4s
+2be
+4d
+4s
+3ing
+2eld
+5s
+2lden
+2m
+3bal
+6s
+3khana
+8s
+3mal
+6s
+3nasia
+8l
+8rch
+9chs
+8st
+9ts
+7c
+7en
+7um
+9s
+6t
+7ic
+9al
+9ally
+9s
+7s
+4ic
+4orhinal
+5soph
+9ies
+9ist
+9ists
+9s
+9y
+6perm
+9mies
+9mous
+9ms
+9my
+3p
+4ed
+4ie
+6s
+5ng
+4s
+3s
+4lip
+7s
+2nae
+5cea
+7um
+9s
+6ia
+7um
+6ocracies
+9acy
+9atic
+7id
+7logic
+9gical
+9gies
+9gist
+9gists
+9gy
+7mast
+9stia
+9stias
+9sties
+9sts
+9sty
+5s
+4ndries
+8sm
+9ms
+7omorph
+9orphic
+9orphs
+9orphy
+8us
+7y
+4rchic
+8es
+7y
+3ecia
+6c
+6um
+5ocracies
+9cy
+9tic
+6id
+6logic
+9ical
+9ies
+9ist
+9ists
+9y
+6mastia
+9tias
+3iatrics
+8es
+7y
+4e
+5s
+4olatries
+9y
+3ney
+6s
+4ies
+4y
+3ocracies
+8y
+7tic
+4dioecious
+9ism
+9isms
+4ecia
+7um
+4geneses
+9is
+8tic
+4monoecious
+9cism
+9cisms
+4phobe
+9s
+8ia
+9as
+9c
+9cs
+7re
+9s
+8ic
+4stemia
+9um
+3y
+2oza
+5s
+2p
+3lure
+7s
+3ped
+5r
+6s
+4ie
+6s
+5ng
+4o
+5s
+4y
+3s
+4eian
+5ous
+4ied
+6s
+5ferous
+4ophila
+9as
+4ter
+7s
+4um
+6s
+4y
+5dom
+8s
+5hood
+9s
+5ing
+6sh
+7m
+8s
+5wort
+9s
+2ral
+5ly
+4nt
+4se
+6s
+4te
+6d
+6s
+5ing
+6on
+8al
+8s
+5or
+7s
+7y
+3e
+4d
+4ne
+6s
+4s
+3falcon
+9s
+3i
+4ng
+3o
+4car
+7s
+5ompass
+9sses
+6pter
+9rs
+4dyne
+8s
+4frequencies
+9ency
+4idal
+4lite
+8s
+4magnetic
+9tism
+9tisms
+6ncies
+8y
+4n
+5ic
+5ny
+5s
+4pilot
+9s
+5lane
+9s
+4s
+5cope
+9s
+8ic
+9cally
+9cs
+5e
+5tabiliser
+9lisers
+9lizer
+9lizers
+7t
+8ic
+9cally
+9cs
+8s
+4us
+4vague
+9s
+3us
+5es
+2te
+4s
+3rash
+7es
+3tja
+6s
+2ve
+4d
+4s
+3ing
+0ha
+2af
+4s
+3nepoot
+9s
+3r
+4s
+2banera
+8s
+7o
+8s
+3dabs
+5lah
+8s
+3erdasher
+9eries
+9ers
+9ery
+6ine
+9s
+5geon
+9s
+3ilable
+6tory
+5e
+5iment
+9ts
+6tate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+4t
+5abilities
+9ity
+7le
+9ness
+9nesses
+8y
+6n
+7s
+7t
+8s
+6t
+7ion
+9nal
+9ns
+7s
+6unce
+9es
+5ed
+5ing
+5s
+5ual
+8ly
+8ness
+9esses
+8s
+7te
+9d
+9s
+8ing
+9on
+9ons
+6de
+8s
+7inal
+6e
+7s
+6s
+3le
+3oob
+6s
+3u
+4s
+2cek
+5s
+4ndado
+9s
+3his
+4ure
+7d
+7s
+6ing
+3ienda
+8do
+9os
+8s
+3k
+4able
+5more
+9s
+4berries
+8y
+5olt
+8s
+5ut
+7eer
+9rs
+7s
+7ter
+9rs
+4ed
+5e
+6s
+5r
+6ies
+6s
+6y
+5tte
+8s
+4ie
+6s
+5ng
+7s
+4le
+6d
+6r
+7s
+6s
+6t
+7s
+5ier
+7st
+6ng
+5y
+4man
+6tack
+9ks
+5en
+4ney
+7ed
+7ing
+8sm
+9ms
+7man
+8en
+7s
+4s
+5aw
+7ed
+7ing
+7n
+7s
+4work
+8s
+3queton
+9s
+2d
+3al
+4rim
+4way
+3den
+5st
+4ie
+6s
+5ng
+4ock
+7s
+3e
+4d
+5ah
+7s
+4s
+3ing
+4th
+6s
+3j
+4ee
+6s
+5s
+4i
+5s
+3rome
+7s
+5n
+6ic
+6s
+5saur
+9s
+9us
+9uses
+3s
+4t
+2e
+3cceities
+8y
+3d
+3ing
+3m
+4achrome
+9mes
+6ytometer
+9meters
+5gglutinate
+9tinin
+9tinins
+6ogue
+9es
+5l
+5ngioma
+9mas
+9mata
+5tal
+6ein
+9s
+7meses
+9sis
+6ic
+8s
+7n
+8ic
+9cs
+8s
+7te
+9s
+8ic
+6oblast
+9astic
+9asts
+7cele
+9les
+8rit
+9its
+9yal
+7geneses
+9nesis
+9netic
+9nic
+9nous
+7id
+7logic
+9gical
+9gies
+9gist
+9gists
+9gy
+8yses
+9sis
+7ma
+9s
+9ta
+7phagous
+8oieses
+9iesis
+9ietic
+7ses
+8is
+7thermal
+7xylic
+9lin
+9lins
+9lon
+9lons
+7zoa
+9on
+6uria
+9as
+9c
+4ic
+5n
+6s
+4ochrome
+9mes
+6oel
+9s
+7nia
+9as
+6yanin
+9ins
+7te
+9s
+8ometer
+9meters
+5dialyser
+9ysers
+9yses
+9ysis
+9yzer
+9yzers
+5flagellate
+5globin
+9ins
+9inuria
+5id
+5lyses
+8in
+9ns
+9s
+7tic
+5nies
+6y
+5phile
+9es
+9ia
+9iac
+9iacs
+9ias
+9ic
+9ioid
+6oieses
+9sis
+9tic
+6tyses
+9is
+5rrhage
+9ged
+9ges
+9gic
+9ging
+8oid
+9idal
+9ids
+5stases
+9ia
+9ias
+9is
+8t
+9ic
+9ics
+9s
+4s
+3n
+3redes
+5mai
+8s
+5s
+3s
+3t
+4s
+2ff
+4et
+6s
+4it
+6s
+4lin
+7s
+4s
+3is
+4z
+5es
+3nium
+7s
+3t
+4ara
+7h
+8s
+7s
+6ot
+8h
+4ed
+5r
+6s
+4ing
+4orah
+8s
+6os
+7t
+8h
+4s
+2g
+3adic
+6st
+8s
+3berries
+7y
+4olt
+7s
+5rn
+4ush
+7es
+5t
+6eer
+9s
+6s
+6ter
+9s
+3den
+6s
+4on
+6s
+5wn
+7s
+3fish
+7es
+3g
+4ada
+7h
+8s
+7s
+6ic
+8al
+7st
+9ic
+9s
+6ot
+8h
+5rd
+7ly
+7ness
+9sses
+7s
+4ed
+4ing
+5s
+6es
+6h
+7ly
+7ness
+9sses
+4le
+6d
+6r
+7s
+6s
+5ing
+4s
+3iarchies
+8y
+4ocracies
+9y
+5grapher
+9hers
+9hic
+9hical
+9hies
+9hist
+9hists
+9hy
+5later
+9rs
+8ries
+9ous
+9y
+6ogic
+9cal
+9es
+9st
+9sts
+8y
+5scope
+9es
+9ic
+3let
+6s
+4ike
+3ridden
+6e
+7r
+8s
+7s
+6ing
+4ode
+3s
+2h
+3a
+4s
+3nium
+7s
+3s
+2ick
+5s
+3duk
+6s
+3k
+4a
+5i
+4s
+4u
+5s
+3l
+4ed
+5r
+6s
+4ier
+6st
+5ng
+4s
+5hot
+8s
+5tone
+9s
+7rm
+9s
+4y
+3mish
+3n
+4ch
+6ed
+7s
+6ing
+4ed
+4ing
+7s
+4s
+4t
+5s
+3que
+6s
+3r
+4ball
+8s
+6nd
+8s
+5ell
+8s
+5rained
+6eadth
+9ths
+6ush
+9es
+4cap
+7s
+5loth
+9s
+5ut
+7s
+7ter
+9rs
+8ing
+9ngs
+4do
+6s
+5resser
+9ers
+9ing
+9ings
+6ier
+9s
+6yer
+9s
+4ed
+4grip
+8s
+4ier
+6st
+5f
+6s
+5ness
+9es
+6g
+4less
+8es
+8ness
+9esses
+5ike
+6ne
+8s
+5ock
+8s
+4net
+7s
+4piece
+9s
+6n
+7s
+4s
+5breadth
+9dths
+5plitter
+9ters
+9ting
+9tings
+6ray
+9s
+7ing
+9gs
+5t
+6ed
+6ing
+6reak
+9ks
+6s
+6yle
+9s
+8ing
+9ngs
+9st
+9sts
+4tail
+8s
+4weaving
+9ngs
+5ork
+8s
+7m
+8s
+4y
+5back
+9s
+3th
+2j
+3es
+3i
+4s
+3j
+4ah
+6s
+4es
+4i
+5s
+2ka
+4m
+5s
+4ri
+6s
+4s
+3e
+4a
+5s
+4em
+6s
+4s
+3im
+5s
+3u
+4s
+2lacha
+7s
+6ic
+7st
+9s
+6ot
+8h
+4kah
+7s
+5ha
+7h
+8s
+7s
+6ic
+7st
+9s
+6ot
+8h
+5ic
+6st
+8s
+5oth
+4l
+5a
+6h
+7s
+6s
+5led
+6ing
+5s
+4tion
+8s
+4vah
+7s
+4zone
+8s
+3berd
+7ier
+9rs
+7s
+6t
+7s
+3cyon
+7ian
+8c
+7s
+3e
+4d
+4ness
+8es
+4r
+5s
+5u
+4s
+5t
+3f
+4a
+5s
+4back
+8s
+5eak
+8s
+4en
+6deale
+4hearted
+9edly
+9edness
+4life
+6n
+7g
+8s
+7s
+6ves
+4ness
+8es
+4pace
+8s
+5ence
+7nies
+8y
+9worth
+9worths
+5ipe
+8s
+4s
+5eriously
+4time
+8s
+5one
+8s
+5rack
+9s
+4way
+5it
+7s
+7ted
+9dly
+9dness
+3ibut
+7s
+4core
+8s
+4d
+5e
+6s
+5om
+7e
+8s
+7s
+5s
+4eutic
+9s
+4mot
+7e
+8s
+7s
+4ng
+4otis
+4plankton
+9tons
+4te
+6s
+5oses
+7is
+6tic
+6us
+5us
+7es
+3l
+4ah
+6s
+5l
+6i
+7s
+6led
+7ing
+6oo
+8s
+6s
+5n
+6s
+4eflinta
+9tas
+5l
+6s
+6uiah
+9hs
+7jah
+9hs
+4ian
+7s
+6rd
+8s
+5ng
+7s
+5on
+7s
+4mark
+8ed
+8ing
+8s
+4o
+5a
+6ed
+6ing
+6s
+5ed
+6s
+5ing
+5o
+6ed
+6ing
+6s
+5s
+5t
+6h
+5umi
+8s
+5w
+6ed
+8ness
+9esses
+7r
+8s
+6ing
+6s
+5ysite
+9es
+4s
+5tand
+9s
+4ucal
+6es
+6inate
+9ted
+9tes
+9ting
+9tion
+9tional
+9tions
+9tive
+9tor
+9tors
+9tory
+8ogen
+9genic
+9genics
+9gens
+9ses
+9sis
+9sises
+5x
+4way
+7s
+4yon
+7s
+3m
+4a
+5s
+4s
+3o
+4biont
+9ic
+9s
+7tic
+4carbon
+9ns
+5line
+9s
+4ed
+5s
+4gen
+7ate
+9ed
+9es
+9ing
+9ion
+9ions
+7oid
+8us
+7s
+6ton
+9s
+4id
+6s
+5ng
+4like
+4morphic
+4n
+5s
+4peridol
+9ols
+5hile
+9s
+8ic
+9es
+8ous
+8y
+6obe
+9s
+6yte
+9s
+8ic
+9sm
+9sms
+4s
+5ere
+8s
+4thane
+9s
+4umi
+7s
+3se
+5d
+5r
+6s
+5s
+4ing
+3t
+4ed
+5r
+6break
+9aking
+9aks
+8oke
+9ken
+6e
+7d
+7s
+6ing
+6neck
+9ks
+6s
+4ing
+7ly
+7ness
+9sses
+7s
+4less
+4s
+3utz
+6im
+3va
+5h
+6s
+5s
+4e
+5d
+5r
+6s
+5s
+4ing
+3yard
+7s
+2m
+3ada
+6s
+5ryad
+9es
+9s
+8s
+9es
+4l
+5s
+4melidaceous
+8s
+9es
+4ntasch
+9hen
+4rthritis
+9tises
+6ia
+8s
+7ologies
+9ogy
+4te
+6s
+4ul
+6s
+3ba
+4le
+6d
+6s
+5ing
+4one
+7d
+7s
+6ing
+4urg
+7er
+9s
+7s
+3e
+4d
+4s
+5ucken
+9ns
+4with
+3fatter
+9ed
+9ing
+9s
+3ing
+3let
+6s
+3mada
+7s
+5l
+6s
+5m
+6s
+4ed
+5r
+6cloth
+9ths
+6ed
+7r
+8s
+6head
+9ded
+9ds
+6ing
+9s
+6kop
+9s
+6less
+7ock
+9ks
+6man
+7en
+6s
+7tone
+9nes
+6toe
+9s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4ock
+7s
+4y
+3ose
+4us
+3per
+6ed
+8ness
+9esses
+7r
+8s
+6ing
+6s
+4ster
+8s
+3s
+4hackle
+9ed
+9es
+9ing
+4ter
+7s
+5ring
+9ed
+9ing
+9s
+6ung
+3ular
+6te
+5i
+5ose
+6us
+5us
+3za
+5h
+6s
+5s
+2n
+3ap
+5er
+7s
+5s
+3ce
+5s
+4h
+5ed
+6s
+5ing
+3d
+4ax
+6es
+4bag
+7ged
+8ing
+9ngs
+7s
+6ll
+8ed
+9r
+9rs
+8ing
+8s
+6rrow
+9ws
+6sket
+9ts
+5ell
+8s
+5ill
+8s
+5lown
+5ook
+8s
+5rake
+9s
+6eadth
+9ths
+4car
+7s
+7t
+8s
+5lap
+8s
+7sp
+9s
+5raft
+9ed
+9ing
+9s
+9sman
+9smen
+5uff
+8ed
+8ing
+8s
+4ed
+6ness
+9ses
+5r
+6s
+4fast
+8ed
+8ing
+9ngs
+8s
+5ed
+6ed
+8ing
+8s
+5ul
+7s
+4grip
+8s
+5un
+7s
+4held
+8s
+5old
+8ing
+9ngs
+8s
+4icap
+8ped
+9er
+9ers
+9ing
+8s
+6raft
+9ter
+9ters
+9ts
+9tsman
+9tsmen
+6uffs
+5er
+6st
+5ly
+5ness
+9es
+6g
+5sm
+7s
+5work
+9s
+4jar
+7s
+4kercher
+9ers
+9ief
+9iefs
+9ieves
+5nit
+8s
+4langer
+9rs
+5e
+6able
+6bar
+9s
+6d
+6less
+6r
+7s
+6s
+7s
+5ike
+6ng
+8s
+6st
+8s
+5oom
+8s
+4made
+6id
+8en
+9ns
+8s
+4off
+7s
+5ut
+7s
+5ver
+8s
+4pass
+8ed
+9s
+8ing
+5hone
+9s
+5ick
+8ed
+8ing
+8s
+5lay
+8s
+5ress
+9es
+6int
+9s
+4rail
+8ing
+9ngs
+8s
+5oll
+8s
+4s
+5aw
+7s
+5breadth
+9dths
+5el
+7ed
+7ing
+7led
+8ing
+7s
+6t
+7s
+6wn
+5ful
+5hake
+9s
+8ing
+9ngs
+5ome
+8ly
+8ness
+9esses
+8r
+8s
+9t
+5pike
+9s
+6ring
+9gs
+5taff
+9s
+7mp
+9ed
+9ing
+9s
+7nd
+9s
+7ves
+6roke
+9es
+6urn
+9s
+4towel
+9s
+4wheel
+9s
+5ork
+8ed
+9r
+9rs
+8s
+6ven
+5ringer
+9ers
+9ing
+9ings
+7t
+8e
+9s
+8ing
+9ngs
+8ten
+6ote
+7ught
+4y
+5man
+6en
+5person
+9ons
+5work
+9s
+3epoot
+8s
+3g
+4abilities
+9ty
+6le
+5r
+6ed
+6ing
+6s
+4bird
+8s
+4dog
+7s
+4ed
+5r
+6s
+4fire
+8s
+4i
+5ng
+7s
+5s
+4man
+5en
+4nail
+8s
+5est
+8s
+4out
+7s
+5ver
+8s
+4s
+4tag
+7s
+4ul
+5p
+6s
+3iwa
+3jar
+6s
+3k
+4ed
+5r
+6ed
+7r
+8s
+6ing
+9s
+6s
+4ie
+6s
+5ng
+4s
+4y
+3sa
+5rdise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+5s
+4e
+5atic
+5l
+6ed
+6ing
+6led
+7ing
+6s
+5s
+4om
+6s
+3t
+4avirus
+9ses
+4ed
+4ing
+4le
+6s
+4s
+3ukiah
+8s
+4man
+7s
+2o
+3le
+5s
+3ma
+5s
+3s
+2p
+3ax
+5anthic
+9ous
+5es
+3hazard
+9ly
+9ness
+9nesses
+9ries
+9ry
+9s
+4tara
+8h
+9s
+8s
+7ot
+9h
+3kido
+7s
+3less
+7ly
+7ness
+9sses
+4ite
+7s
+6ic
+4obiont
+9tic
+9ts
+5graphies
+9hy
+5id
+7ic
+8es
+7s
+7y
+5logic
+9es
+8y
+5nt
+7ic
+7s
+5pia
+8s
+5ses
+6is
+6temonous
+5type
+9s
+4y
+3ped
+5n
+6chance
+9nces
+6ed
+6ing
+9s
+6s
+7tance
+9nces
+4ied
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+4y
+5ing
+3s
+3ten
+6e
+7s
+6ic
+6s
+5ron
+8s
+4ic
+6al
+6s
+4oglobin
+9ins
+5tropic
+9ism
+9isms
+3u
+4ka
+6s
+5u
+6s
+4s
+2queton
+8s
+2rakeke
+8s
+4m
+5bee
+8s
+5da
+7s
+6i
+7s
+5s
+5zada
+9s
+8i
+9s
+4ngue
+8d
+8r
+9s
+8s
+7ing
+4ss
+6ed
+8ly
+7r
+8s
+7s
+6ing
+9ly
+9s
+6ment
+9ts
+3binger
+9ed
+9ing
+9s
+4or
+6age
+9s
+6ed
+7r
+8s
+6ful
+9s
+6ing
+6less
+6master
+9ters
+6ous
+6s
+7ide
+5ur
+7age
+9es
+7ed
+8r
+9s
+7ing
+7less
+7s
+3d
+4ass
+7es
+4back
+8ed
+8s
+6ke
+8s
+6ll
+8s
+5eam
+8s
+5oard
+9s
+6ot
+8s
+6und
+9s
+4case
+5ourt
+6ver
+9s
+4edge
+8s
+5n
+6ed
+7r
+8s
+6ing
+9s
+6s
+5r
+5st
+4face
+8s
+5isted
+4goods
+5rass
+9es
+4hack
+8s
+6nded
+9dness
+6t
+7s
+5ead
+8ed
+9dly
+9dness
+8s
+7rted
+9edly
+9edness
+4ier
+6s
+7t
+5head
+9s
+6ood
+9s
+5ly
+5ment
+9s
+5ness
+9es
+6ggrass
+9asses
+5sh
+4line
+8r
+9s
+5y
+4man
+5en
+5outhed
+4ness
+8es
+5ose
+8d
+8s
+4oke
+7s
+4pack
+8s
+6n
+7s
+6rts
+4rock
+8s
+4s
+5crabble
+5et
+5hell
+6ip
+8s
+5tand
+9ing
+9ings
+9s
+4tack
+8s
+6il
+8s
+5op
+7s
+4ware
+8man
+9en
+8s
+5ire
+8d
+8s
+7ing
+5ood
+8s
+6rking
+4y
+3e
+4bell
+8s
+5rained
+4d
+4em
+6s
+4ld
+6s
+5ike
+6p
+7ped
+7s
+4m
+5s
+4s
+5tail
+9s
+4wood
+8s
+3iana
+7s
+4cot
+7s
+4galds
+7s
+4jan
+7s
+4m
+5s
+4ng
+4olate
+9d
+9s
+8ing
+9on
+9ons
+4ra
+6s
+4sh
+5sa
+7s
+3k
+4ed
+5n
+6ed
+7r
+8s
+6ing
+6s
+4ing
+4s
+3l
+4ed
+5quin
+9ade
+9ades
+9ed
+9ing
+9s
+4ing
+7s
+4ot
+6ries
+7y
+6s
+4s
+3m
+4ala
+7s
+6in
+8e
+9s
+8s
+5n
+6s
+5ttan
+9s
+4doing
+9s
+4ed
+5l
+6s
+5r
+6s
+4ful
+7ly
+7ness
+9sses
+4in
+6e
+7s
+6g
+6s
+4less
+8ly
+8ness
+9esses
+4olodic
+9cs
+5nic
+8a
+9l
+9lly
+9s
+8hord
+9ords
+8ist
+9sts
+8on
+9ns
+8s
+7es
+7ous
+9sly
+9sness
+7phon
+9one
+9ones
+9ons
+7sable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8t
+9ic
+9ically
+9s
+7um
+9ist
+9ists
+9s
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ogram
+9ams
+9aph
+9aphs
+7meter
+9ters
+6y
+5st
+7ies
+7s
+7y
+5tome
+9s
+4s
+3n
+4ess
+7ed
+8r
+9s
+8s
+7ing
+7less
+4s
+3o
+4s
+5et
+7h
+8s
+7s
+3p
+4ed
+5r
+6s
+4ies
+5n
+6g
+7s
+6s
+5st
+7s
+4oon
+7ed
+8er
+9rs
+8r
+9s
+7ing
+7s
+4s
+5ichord
+9rdist
+9rdists
+9rds
+4y
+5like
+3quebus
+9e
+9es
+9ier
+9iers
+9s
+9ses
+3ridan
+8s
+5ed
+6r
+7s
+6s
+4ow
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6ment
+9ts
+6s
+4umph
+8ed
+8ing
+8s
+4y
+5ing
+3sh
+5ed
+6n
+7ed
+7ing
+7s
+6r
+6s
+7t
+5ing
+5ly
+5ness
+9es
+4let
+7s
+3t
+4al
+6s
+4bees
+8es
+8t
+9s
+4ebeest
+9ts
+5ly
+5n
+6ed
+6ing
+6s
+4lesse
+4s
+5horn
+9s
+3umph
+7ed
+7ing
+7s
+4spex
+6ical
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+8es
+8ies
+8y
+3vest
+7able
+7ed
+8r
+9s
+7ing
+9gs
+7less
+7man
+8en
+7s
+7time
+9mes
+2s
+3bian
+7s
+3enpfeffer
+9fers
+3h
+4ed
+5esh
+8es
+5s
+4head
+8s
+4ier
+6st
+5ng
+7s
+5sh
+7es
+4mark
+8s
+4tag
+7ged
+8ing
+7s
+4y
+3k
+4s
+3let
+6s
+3p
+4ed
+4ing
+4s
+3s
+4ar
+6s
+4el
+6s
+5s
+4ium
+7s
+4le
+6d
+6s
+5ing
+4ock
+7s
+7y
+3t
+4a
+5te
+7d
+7ly
+4e
+5d
+5ful
+8ly
+5n
+6ed
+7r
+8s
+6ing
+6s
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4y
+2t
+3able
+3band
+7s
+4ox
+6es
+4rush
+8es
+3ch
+5abilities
+9ity
+7le
+5back
+9s
+5eck
+8s
+6d
+6l
+7ed
+7ing
+7led
+9r
+9rs
+8ing
+7s
+6r
+7ies
+7s
+7y
+6s
+6t
+7s
+7tite
+9tes
+7y
+5ing
+8s
+5ling
+9s
+5ment
+9s
+5way
+8s
+3e
+4able
+4d
+4ful
+7ly
+7ness
+9sses
+4less
+8ness
+9esses
+4monger
+9rs
+4r
+5ent
+8s
+5s
+4s
+4worthy
+3ful
+6s
+3guard
+8s
+3h
+4a
+3ing
+3less
+7ness
+9sses
+4ike
+3maker
+8s
+3peg
+6s
+4in
+6s
+3rack
+7s
+4ed
+6s
+3s
+4ful
+4tand
+8s
+3ted
+5r
+6ed
+6ia
+8s
+7ng
+6s
+4ing
+7s
+4ock
+7s
+2ubergeon
+9ns
+6k
+7s
+4ois
+3d
+4ing
+4s
+3f
+4s
+3gh
+5s
+5t
+6ier
+8st
+7ly
+7ness
+9sses
+6y
+3l
+4age
+7s
+4d
+5s
+4ed
+5r
+6s
+4ier
+7s
+5ng
+4m
+5ier
+7st
+5s
+5y
+4s
+5t
+4t
+4yard
+8s
+3nch
+6ed
+7s
+6ing
+4t
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5s
+3riant
+5ent
+3se
+5d
+5n
+6s
+5s
+4frau
+8en
+8s
+4ing
+4smannise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+4tella
+9te
+8um
+5oria
+9l
+8um
+3t
+4bois
+6y
+7s
+4e
+5ur
+7s
+3yne
+6s
+2varti
+7s
+3dalah
+8s
+4oloh
+8s
+3e
+4lock
+8s
+4n
+5ed
+5ing
+5less
+5s
+4our
+7s
+4r
+5ed
+6l
+7s
+5ing
+8s
+5s
+6ack
+9s
+6ine
+9s
+4s
+3ildar
+8s
+4ng
+6s
+4or
+6s
+5ur
+7s
+3oc
+5ked
+7r
+8s
+6ing
+5s
+2w
+3ala
+6s
+3buck
+7s
+3ed
+3finch
+8es
+3ing
+3k
+4bell
+8s
+5ill
+8s
+6t
+7s
+4ed
+5r
+6s
+5y
+6ed
+6s
+4ie
+6s
+5ng
+7s
+5sh
+7ly
+7ness
+9sses
+5t
+4like
+4moth
+8s
+4nose
+8s
+4s
+5beard
+9ds
+6ill
+9s
+5haw
+8s
+4weed
+8s
+3m
+4ed
+4ing
+4s
+3s
+4e
+5d
+5hole
+9s
+5pipe
+9s
+5r
+6s
+5s
+4ing
+3thorn
+8s
+8y
+2y
+3band
+7s
+4ox
+6es
+3cock
+7s
+3ed
+4r
+5s
+4y
+3field
+8s
+4ork
+7s
+3ier
+5st
+4ng
+6s
+3lage
+7s
+4e
+5s
+4oft
+7s
+3maker
+8s
+6ing
+9s
+4ow
+6s
+3rack
+7s
+5ke
+7s
+4ick
+7s
+5de
+7s
+3s
+4eed
+7s
+5l
+6s
+4tack
+8s
+3ward
+7s
+4ire
+7s
+2zan
+5im
+5s
+4rd
+6able
+6ed
+7r
+8s
+6ing
+7ze
+9s
+6ous
+9ly
+9ness
+9nesses
+6ries
+7y
+6s
+3e
+4d
+4l
+5hen
+8s
+5ly
+5nut
+8s
+5s
+4r
+5s
+4s
+3ier
+5st
+4ly
+4ness
+8es
+5g
+6s
+3mat
+6s
+3y
+3zan
+6im
+6s
+1e
+2ad
+4ache
+8s
+8y
+7ier
+9st
+7y
+5ge
+7s
+4band
+8s
+7g
+8ed
+8ing
+9ngs
+8s
+5oard
+9s
+6rough
+9ghs
+4case
+8s
+5hair
+9s
+6eese
+9es
+5loth
+9s
+5ount
+9s
+4dress
+9es
+4ed
+5nd
+7s
+5r
+6s
+4fast
+8s
+5irst
+6sh
+8es
+5oremost
+5rame
+9s
+5ul
+7s
+4gate
+8s
+5ear
+8s
+5uard
+9s
+4hunt
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4lamp
+8s
+6nd
+8s
+5ease
+9s
+6ss
+8ness
+9esses
+5ight
+9s
+6ke
+6ne
+8d
+8r
+9s
+8s
+7ing
+5ock
+8s
+6ng
+4man
+6rk
+8s
+6ster
+9rly
+9rs
+9rship
+9rships
+5en
+5istress
+9esses
+9essy
+5ost
+4note
+8s
+4peace
+9s
+5hone
+9s
+5iece
+9s
+6n
+7s
+4quarter
+9ered
+9ering
+9ers
+4race
+8s
+6il
+8s
+5each
+9ed
+9es
+9ing
+6st
+8s
+5ig
+7s
+6ng
+8s
+5oom
+8s
+6pe
+8s
+4s
+5ail
+8s
+5carf
+8ves
+5et
+7s
+5hake
+9s
+6eets
+6ip
+8s
+6ot
+8s
+6rinker
+9kers
+5man
+6en
+5pace
+9s
+6ring
+9gs
+5quare
+9es
+5tall
+9s
+7nd
+9s
+7y
+8s
+6ick
+9s
+6ock
+9s
+7ne
+9s
+6ream
+9ms
+7ong
+9gly
+9gness
+4waiter
+9rs
+6ll
+8s
+6rd
+8s
+6ter
+9s
+6y
+7s
+5ind
+8s
+5ord
+8s
+7k
+8er
+9rs
+8s
+4y
+3l
+4able
+4d
+5ed
+5ing
+5s
+4ed
+5e
+6s
+5r
+6s
+4ing
+7ly
+7s
+4s
+5ome
+4th
+6care
+9es
+6ful
+9ly
+9ness
+9nesses
+6ier
+8st
+7ly
+7ness
+9sses
+7sm
+9s
+6less
+9sness
+6s
+7ome
+6y
+3me
+3p
+4ed
+5r
+6s
+4ier
+6st
+5ng
+4s
+5tead
+9s
+4y
+3r
+4able
+4d
+5s
+4e
+5r
+6s
+5s
+4ie
+5ng
+7s
+4ken
+7ed
+8r
+9s
+7ing
+7s
+4s
+5ay
+7s
+5e
+6d
+6s
+5ier
+7st
+6ng
+5y
+4t
+5ache
+9s
+5beat
+9s
+6reak
+9ker
+9kers
+9king
+9kingly
+9ks
+7oke
+9en
+9enly
+9enness
+6urn
+9ing
+9ings
+9s
+5ed
+6n
+7ed
+8r
+9s
+7ing
+9gly
+7s
+5felt
+6ree
+5h
+6rug
+9s
+6s
+7tone
+9nes
+5ier
+7s
+8t
+6kin
+9s
+6ly
+6ness
+9ses
+7g
+5land
+9s
+6ess
+9ly
+9ness
+9nesses
+7t
+8s
+6ing
+9s
+6y
+5pea
+8s
+5rending
+9ingly
+5s
+6ease
+9es
+7ed
+9s
+6ick
+9ness
+9nesses
+7nk
+9s
+6ome
+9ly
+9ness
+9nesses
+7re
+6tring
+9ngs
+5throb
+9bs
+5warming
+7ter
+9rs
+6ood
+9s
+7rm
+9s
+5y
+3st
+5e
+6s
+5s
+3t
+4able
+4ed
+6ly
+6ness
+9ses
+5r
+6s
+4h
+5berries
+9y
+6ird
+9s
+5cock
+9s
+5en
+7dom
+9ms
+7esse
+9ses
+7ise
+9ed
+9es
+9h
+9hly
+9hness
+9ing
+9m
+9ms
+8ze
+9ed
+9es
+9ing
+7ness
+9sses
+7ries
+8y
+7s
+6r
+7ed
+7ier
+9st
+7s
+7y
+5fowl
+9s
+5ier
+7st
+5land
+9s
+6ess
+6ike
+5s
+5y
+4ing
+7s
+4less
+4proof
+4s
+5pot
+8s
+5troke
+9es
+4wave
+8s
+3ume
+6s
+3ve
+5d
+5n
+6lier
+9st
+8ness
+9esses
+7y
+6s
+6ward
+9ds
+5r
+6s
+5s
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+4y
+5hearted
+9tedly
+5set
+5weight
+9hts
+2bdomad
+8al
+9lly
+9r
+9ries
+9rs
+9ry
+8er
+9rs
+8s
+3e
+4n
+5on
+7s
+5s
+4phrenia
+9iac
+9iacs
+9ias
+9ic
+9ics
+4s
+4tant
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+5ic
+5ude
+8s
+7inosity
+9ous
+3ona
+6s
+3raisation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+2catomb
+8s
+3h
+4t
+5ing
+5s
+3k
+4elphone
+9nes
+4le
+6d
+6r
+7s
+6s
+5ing
+8s
+4s
+3ogenin
+9s
+3tare
+7s
+4ic
+6al
+8ly
+6ly
+6s
+4ocotyli
+9lus
+5gram
+9me
+9mes
+9s
+8ph
+9hed
+9hic
+9hies
+9hing
+9hs
+9hy
+5liter
+9rs
+8re
+9es
+5meter
+9rs
+8re
+9es
+5r
+6ed
+7r
+8s
+6ing
+9ly
+9s
+7sm
+9s
+6ly
+6s
+7hip
+9ps
+5stere
+9es
+2ddle
+6d
+6s
+5ing
+3er
+5a
+6l
+6s
+6ted
+5s
+3ge
+5bill
+9s
+5d
+5hog
+8s
+7p
+8ped
+9er
+9ers
+9ing
+9ings
+8s
+5pig
+8s
+5r
+6ow
+8s
+6s
+5s
+4ier
+6st
+5ng
+7ly
+7s
+4y
+3onic
+7ally
+7s
+6sm
+8s
+7t
+8ic
+9cally
+8s
+3yphane
+9s
+2ed
+4ed
+5r
+6s
+4ful
+7ly
+7ness
+9sses
+4iness
+9es
+6g
+4less
+8ly
+8ness
+9esses
+4s
+4y
+3haw
+6ed
+6ing
+6s
+3l
+4ball
+8s
+6r
+7s
+4ed
+5r
+6s
+4ing
+7s
+4less
+4piece
+9s
+5late
+9s
+5ost
+8s
+4s
+4tap
+7s
+3ze
+5d
+5s
+4ie
+6s
+5ng
+2ft
+4e
+5d
+5r
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4s
+4y
+2gari
+6s
+3emon
+7ial
+8c
+9al
+8es
+8sm
+9ms
+9t
+9ts
+7s
+7y
+3ira
+6s
+3umen
+7e
+8s
+7ies
+7oi
+8s
+9es
+7s
+7y
+2h
+3s
+2id
+4s
+3fer
+6s
+3gh
+5t
+6en
+8ed
+9r
+9rs
+8ing
+8s
+6h
+7s
+6ism
+9s
+6s
+3l
+4ed
+4ing
+4s
+3mish
+3nie
+6s
+4ous
+7ly
+7ness
+9sses
+3r
+4dom
+7s
+4ed
+5ss
+7es
+4ing
+4less
+5oom
+8s
+4s
+5hip
+8s
+3shi
+4t
+5ed
+6r
+7s
+5ing
+5s
+3tiki
+7s
+2jab
+5s
+3ira
+6s
+3ra
+5s
+2ketara
+8s
+3tare
+7s
+4ogram
+9s
+2lcoid
+3d
+4entenor
+9ors
+3e
+4d
+4nium
+8s
+4s
+3iac
+6al
+8ly
+5nthemum
+9mums
+8us
+9ses
+5st
+7s
+4borne
+5us
+7es
+7ses
+4cal
+7ly
+6se
+8s
+5es
+5hrysum
+9ums
+5ities
+7y
+5line
+9s
+5ograph
+9phs
+6id
+8al
+9lly
+8s
+6n
+7ia
+9s
+7s
+6pt
+8ed
+9r
+9red
+9ring
+9rs
+8ing
+8s
+5tite
+9s
+4deck
+8s
+5rome
+9s
+4lift
+8ed
+8ing
+8s
+4man
+5en
+4ng
+4o
+5centric
+9ricism
+9ricity
+6hrome
+9mes
+9mic
+9mies
+9my
+5dor
+8s
+5gram
+9s
+8ph
+9hed
+9her
+9hers
+9hic
+9hical
+9hies
+9hing
+9hs
+9hy
+8vure
+9ures
+5later
+9rs
+8ries
+9ous
+9y
+6ithic
+6ogies
+8y
+5meter
+9rs
+8ric
+9ical
+9ically
+9ies
+9y
+5pause
+9es
+6hilous
+7obic
+7yte
+9es
+5s
+6ciophyte
+9phytes
+7ope
+9es
+9ic
+6es
+6is
+6phere
+9res
+6tat
+9ic
+9s
+5tactic
+7xes
+8is
+6herapies
+9apy
+6rope
+9es
+9ic
+9ical
+9ically
+9ies
+9in
+9ins
+9ism
+9isms
+9y
+6ype
+9d
+9s
+8ic
+9es
+9ng
+8y
+5zoan
+9s
+7ic
+4pad
+7s
+5ilot
+9s
+5ort
+8s
+4spheric
+9ical
+5top
+8s
+4um
+6s
+4x
+5es
+3lacious
+9sly
+4bender
+9rs
+7t
+5ox
+7es
+5roth
+9s
+4cat
+7s
+4diver
+9s
+4ebore
+9s
+8ine
+9nes
+5d
+5nisation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+5r
+6i
+7es
+7s
+6s
+6y
+4fire
+8s
+4gramite
+9tes
+8mite
+9ites
+4hole
+8s
+6und
+9s
+4icat
+8s
+5er
+7s
+5ng
+5on
+7s
+5sh
+7ly
+7ness
+9sses
+4kite
+8s
+4o
+5ed
+6s
+5ing
+5s
+5va
+4s
+4uva
+4ward
+8s
+3m
+4ed
+5r
+6s
+5t
+6ed
+6ing
+6like
+6s
+4ing
+6th
+8iases
+9asis
+9c
+9cs
+8oid
+9logic
+9logies
+9logist
+9logy
+9us
+8s
+4less
+4s
+5man
+8ship
+9hips
+6en
+3o
+4phyte
+9s
+4s
+4t
+5age
+8s
+5ism
+8s
+5ries
+6y
+5s
+3p
+4able
+4desk
+8s
+4ed
+5r
+6s
+4ful
+7ly
+7ness
+9sses
+4ing
+7s
+4less
+8ly
+8ness
+9esses
+5ine
+8s
+4mate
+8s
+5eet
+8s
+4s
+3ve
+5d
+5s
+5tium
+9s
+4ing
+2m
+3achrome
+9es
+5ytometer
+9eters
+4gglutinate
+9inated
+9inates
+9inin
+9inins
+5og
+7s
+7ue
+9s
+4l
+4ngioma
+9as
+9ata
+4tal
+5ein
+8s
+6meses
+9is
+5ic
+7s
+6n
+7e
+8s
+7ic
+9s
+7s
+6te
+8s
+7ic
+5oblast
+9stic
+9sts
+6cele
+9es
+7rit
+9ts
+8yal
+6geneses
+9esis
+9etic
+9ic
+9ous
+6id
+6logic
+9ical
+9ies
+9ist
+9ists
+9y
+7yses
+9is
+6ma
+8s
+8ta
+6phagous
+7oieses
+9esis
+9etic
+8rphyrin
+6ses
+7is
+6thermal
+6xylin
+9ins
+6zoa
+8on
+5uria
+9s
+8c
+3e
+4lytra
+9l
+8on
+8um
+4ralopia
+9ias
+9ic
+5ocallis
+9lises
+5ythrin
+9ins
+4s
+3iacetal
+9ls
+5lgia
+9s
+5nopia
+9as
+8sia
+9ias
+8tic
+4c
+5ellulose
+9loses
+5hordate
+9ates
+5rania
+9as
+6yptophyte
+7stalline
+5ycle
+9s
+8ic
+4elytra
+9al
+9on
+4hedral
+8ies
+9sm
+9sms
+8on
+9ns
+8y
+5ydrate
+9ted
+9tes
+4metabolous
+5orphic
+9ies
+9ism
+9isms
+9ite
+9ites
+9y
+4n
+5a
+6s
+5s
+4ola
+7s
+6ia
+8s
+7c
+5ne
+7s
+6us
+8es
+5pia
+8s
+7c
+6sia
+9s
+4parasite
+9ites
+9itic
+5legia
+9as
+9c
+9cs
+5od
+7e
+8s
+7s
+5ter
+8al
+9n
+9ns
+8on
+9ns
+9us
+8s
+4space
+9s
+6here
+9es
+9ic
+9ical
+9oid
+9oidal
+9oids
+5tich
+9al
+9s
+4terpene
+9nes
+5ropal
+8e
+9s
+8ic
+9es
+9sm
+9sms
+8ous
+8y
+4zygous
+3line
+7s
+4ock
+7s
+3med
+5r
+6s
+4ing
+3ochromatoses
+9atosis
+9e
+9es
+5oel
+8s
+5yanin
+9ns
+6te
+8s
+7ometer
+9eters
+4dialyses
+9sis
+6lution
+9ions
+5ynamic
+9ically
+9ics
+4flagellate
+9llates
+4globin
+9ns
+9nuria
+9nurias
+9nuric
+4id
+4lymph
+9s
+6se
+8d
+8s
+7in
+9g
+9s
+8s
+6tic
+6ze
+8d
+8s
+7ing
+4phile
+9s
+8ia
+9ac
+9acs
+9as
+9c
+9cs
+9oid
+5oieses
+9is
+8tic
+5rotein
+9ins
+5tyses
+8is
+4rrhage
+9ed
+9es
+9ic
+9ing
+7oid
+9dal
+9dals
+9ds
+4siderin
+9ins
+5tases
+8ia
+9as
+9s
+7t
+8ic
+9cs
+8s
+4toxic
+8n
+9s
+3p
+4en
+4ie
+6r
+6s
+7t
+4like
+4s
+5eed
+8s
+4weed
+8s
+4y
+3s
+4titch
+9ed
+9er
+9ers
+9es
+9ing
+2n
+3bane
+7s
+4it
+6s
+3ce
+5forth
+8ward
+9ards
+4hman
+6en
+5person
+9ons
+5woman
+8en
+4oop
+7s
+3d
+4ecagon
+9nal
+9ns
+7hedra
+9dron
+9drons
+7syllabic
+9llable
+5d
+4iadys
+9es
+5ng
+4s
+3equen
+8s
+6in
+8s
+3ge
+5s
+3house
+8s
+3iquen
+8s
+6in
+8s
+3ley
+6s
+4ike
+3na
+5ed
+5ing
+5s
+4ed
+5r
+6ies
+6s
+6y
+4ier
+6s
+7t
+5n
+6g
+6s
+5sh
+7ly
+4y
+3otheism
+9ms
+9t
+9tic
+9ts
+5ic
+3peck
+7ed
+8ries
+9y
+7ing
+7s
+3ries
+4y
+5s
+3s
+3t
+4ed
+4ing
+4s
+2ortological
+9ies
+9ist
+9ists
+9y
+2p
+3ar
+5in
+7ised
+8zed
+7oid
+7s
+5s
+4tectomies
+9mised
+9mized
+9my
+5ic
+7a
+8e
+8l
+8s
+7ological
+9ogies
+9ogist
+9ogists
+9ogy
+7s
+6sation
+9ions
+7e
+8d
+8s
+7ing
+6te
+8s
+7ides
+8s
+9es
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ocellular
+7yte
+9es
+6genous
+6logies
+9ist
+9ists
+9y
+6ma
+8s
+8ta
+7egalies
+9aly
+6pancreas
+6scopies
+9py
+6toxic
+9icity
+3cat
+6s
+3hthemimer
+9meral
+9mers
+3per
+5st
+3s
+4ter
+7s
+3t
+4achlor
+9rs
+7ord
+9ds
+5d
+6ecanoic
+6s
+5gon
+8al
+8s
+6ynous
+5hedra
+9al
+9on
+9ons
+5merous
+7ter
+9rs
+8rical
+5ndrous
+6e
+7s
+6gular
+5podic
+9es
+8y
+5rch
+8al
+8ic
+9es
+9st
+9sts
+8s
+8y
+5stich
+9hs
+6yllabic
+5thlete
+9tes
+8on
+9ns
+6onic
+5valent
+4ose
+7s
+2r
+3ald
+6ed
+6ic
+8ally
+7ng
+7st
+9s
+6ries
+7y
+6s
+7hip
+9ps
+3b
+4aceous
+9sly
+5ge
+7d
+7s
+5l
+6ism
+9s
+8t
+9s
+6s
+5r
+6ia
+8l
+8n
+9s
+7es
+7um
+9s
+6s
+6y
+4ed
+5let
+8s
+4icidal
+9lly
+8e
+9s
+5er
+6st
+5st
+7s
+5vora
+8e
+9s
+8ies
+8ous
+9usly
+9usness
+8y
+4less
+6t
+7s
+5ike
+4ologies
+8y
+5risation
+9tions
+8e
+9d
+9s
+8ing
+8t
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+5se
+5us
+4s
+4y
+3cogamies
+8ous
+8y
+4ulean
+7s
+8es
+4ynite
+9s
+3d
+4boy
+7s
+4ed
+5n
+6s
+5r
+6s
+5ss
+7es
+4ic
+6s
+5ng
+4like
+4man
+5en
+4s
+5man
+6en
+4wick
+8s
+3e
+4about
+9s
+5fter
+9s
+5t
+5way
+8s
+4by
+4des
+5itability
+9le
+9ly
+8ment
+9ents
+8rian
+9ianism
+9ianist
+9ians
+9ily
+9iness
+9y
+7ies
+8st
+9ts
+7y
+4from
+4in
+6above
+7fter
+6before
+8low
+6to
+4ness
+8es
+4of
+5n
+4s
+5iarch
+9hs
+6es
+6ographer
+9aphers
+9aphies
+9aphy
+7logies
+9gist
+9gists
+9gy
+5thetic
+9ical
+9ician
+9icians
+9ics
+5y
+4tic
+7al
+9ly
+8te
+9ed
+9es
+9ing
+7s
+5o
+6fore
+9es
+5rices
+7x
+8es
+4under
+6to
+5pon
+4with
+3ied
+5s
+4ot
+6able
+6s
+4sse
+6on
+8s
+4tabilities
+9ity
+7le
+8y
+6ge
+8s
+5or
+7s
+5ress
+9es
+6ices
+7x
+8es
+3kogamies
+8y
+3l
+4ing
+7s
+4s
+3m
+4a
+5e
+6an
+5i
+5ndad
+9s
+5phrodite
+9dites
+9ditic
+9ditism
+5typic
+4eneutic
+9ical
+9ically
+9ics
+9ist
+9ists
+5tic
+8al
+9lly
+8ism
+9sms
+9ties
+9ty
+8s
+7sm
+9s
+8t
+9s
+4it
+6age
+9s
+6ess
+9es
+6ic
+8al
+9lly
+7sm
+9s
+6ries
+7y
+6s
+4s
+3n
+4ia
+6e
+6l
+6s
+6te
+8d
+8s
+7ing
+8on
+9ns
+5orrhaphies
+9aphy
+6tomies
+9y
+4s
+5haw
+8s
+3o
+4es
+4ic
+6al
+8ly
+8ness
+9esses
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6ly
+6ness
+9ses
+6omic
+9cal
+6s
+5n
+6e
+7s
+6ism
+9s
+6s
+5se
+7d
+7s
+6ing
+6m
+7s
+5ze
+7d
+7s
+6ing
+4n
+5ries
+6y
+5s
+6ew
+8s
+6haw
+9s
+4on
+6s
+4s
+5hip
+8s
+3pes
+6es
+6virus
+9uses
+5tic
+8s
+6ofauna
+9unae
+9unas
+7id
+7logic
+9gical
+9gies
+9gist
+9gists
+9gy
+4tile
+3renvolk
+9ks
+4ied
+6s
+5ment
+9s
+5ng
+7bone
+9ned
+9nes
+9ning
+7er
+9s
+7s
+4y
+5ing
+5ment
+9s
+3s
+4all
+7s
+4e
+5d
+5lf
+5s
+4hip
+7s
+4tories
+7y
+3tz
+5es
+3y
+4e
+5d
+5s
+4ing
+2s
+3itance
+9s
+8ies
+8y
+7t
+8ly
+6te
+8d
+8r
+9s
+8s
+7ing
+9gly
+8on
+9ns
+8ve
+7or
+9s
+9y
+3p
+4ed
+5rid
+8ia
+9n
+9ns
+9um
+9ums
+8s
+4ing
+4s
+3sian
+7s
+5te
+7s
+4onite
+9s
+3t
+4ernal
+4s
+2t
+3aera
+7e
+7s
+6ic
+7sm
+9ic
+9s
+8t
+9ic
+9s
+4ira
+7i
+7s
+6ia
+8s
+7c
+7sm
+9ic
+9s
+8t
+9ic
+9s
+3e
+4rarchies
+9y
+6uxeses
+9sis
+5o
+6atom
+9ms
+7uxin
+9ins
+6blastic
+9sties
+9sty
+6carpous
+7ercal
+9cality
+9cies
+9cy
+7hromatic
+9omatin
+9omous
+9onic
+9onies
+9onism
+9onisms
+9onous
+9ony
+7lite
+9tes
+9tic
+9tous
+7ont
+9ts
+7ycle
+9les
+9lic
+9lics
+8st
+9tous
+9ts
+6dactyl
+9tylous
+9tyls
+7ont
+8x
+9ies
+9y
+7uplex
+9lexes
+7yne
+9ed
+9es
+9ing
+6ecious
+9sm
+9sms
+6flexible
+9xibles
+6gamete
+9etes
+9etic
+9eties
+9ety
+9ies
+9ous
+9y
+7eneities
+9eity
+9eous
+9eously
+9eses
+9esis
+9etic
+9ic
+9ies
+9ous
+9y
+7onic
+9ies
+9ous
+9ously
+9y
+7raft
+9fts
+9phic
+9phical
+9phies
+9phy
+7ynous
+6karyon
+9yons
+9yoses
+9yosis
+9yotic
+7ont
+9tan
+9ts
+6lecithal
+7ogies
+9ous
+9ously
+9y
+7yses
+9is
+8tic
+6merous
+7orphic
+9phies
+9phism
+9phisms
+9phous
+9phy
+6nomies
+9ous
+9ously
+9y
+7ym
+9ous
+9ously
+9s
+6ousian
+9ians
+6phil
+9le
+8onies
+9ny
+8yllies
+9llous
+9lly
+7lasia
+9sias
+9stic
+9sties
+9sty
+8oid
+9idies
+9ids
+9idy
+7od
+9s
+8lar
+9arity
+7teran
+9rans
+9rous
+6s
+7cedastic
+8ian
+9ans
+7es
+8xism
+9isms
+9ist
+9ists
+9ual
+9uality
+9ually
+9uals
+7is
+7ocial
+9iality
+8matous
+7pecific
+8ories
+9rous
+9ry
+7trophic
+9ophies
+9ophy
+8yled
+9lies
+9lism
+9lisms
+9lous
+9ly
+6tactic
+9tous
+8xes
+9ia
+9ias
+9ic
+9ies
+9is
+9y
+7hallic
+9llies
+9llism
+9llisms
+9lly
+8ermal
+7ic
+7opia
+9ias
+9ic
+9ies
+9ous
+9y
+7roph
+9phic
+9phies
+9phs
+9phy
+7ypic
+9ical
+6usian
+9ans
+6zygoses
+9osis
+9osity
+9ote
+9otes
+9ous
+4s
+3h
+4er
+6ward
+4s
+3ing
+3man
+6ate
+9s
+6s
+7hip
+9ps
+3s
+3tie
+6s
+2uch
+5era
+8s
+5s
+3gh
+5s
+3landite
+9es
+3reka
+7s
+5tic
+8s
+4ism
+7s
+6tic
+9ally
+9s
+2vea
+5s
+2w
+3able
+3ed
+4r
+5s
+3gh
+3ing
+6s
+3n
+3s
+2x
+3achlorethane
+9ide
+9ides
+9ophane
+9ophene
+6ord
+9s
+5osanoic
+5t
+6inal
+8ellid
+9llids
+6s
+4d
+5actylic
+9lous
+5e
+6cane
+9es
+9oic
+7imal
+9als
+6s
+5ic
+5s
+4emeric
+8on
+9ns
+4fluoride
+9ides
+5oil
+8s
+4gon
+7al
+9ly
+7s
+5ram
+8moid
+9oids
+8s
+5ynian
+7ous
+4hedra
+9l
+8on
+9ns
+6meric
+9on
+9ons
+5ydrate
+9ted
+9tes
+4meral
+7ism
+9ms
+7ous
+6ter
+9s
+7honium
+9niums
+7ral
+8ic
+9cal
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+5ine
+8s
+4ndrian
+7ous
+5e
+6s
+5gular
+5oic
+4pla
+7r
+8ian
+9c
+7s
+6oid
+9ies
+9s
+9y
+5od
+7al
+7ic
+8es
+7s
+7y
+4rch
+7ies
+7y
+4stich
+9al
+9ic
+9on
+9ons
+9s
+6yle
+9s
+4teuchal
+4valent
+3ed
+4ne
+6s
+4r
+5ei
+7s
+5s
+4s
+3ing
+6s
+3obarbital
+9tals
+4kinase
+9es
+4ne
+6s
+4saminidase
+9idases
+6n
+7s
+5e
+6s
+3yl
+5ene
+8s
+5ic
+5resorcinol
+5s
+2y
+3day
+6s
+4ey
+6s
+4uck
+7s
+3ed
+3ing
+3s
+1i
+2ant
+3tal
+4us
+6es
+2bachi
+7s
+4kusha
+9s
+3ernacle
+9es
+8ula
+9lum
+7l
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6icise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+3iscus
+8es
+2c
+3atee
+7s
+3catee
+8s
+4ough
+8ed
+8ing
+8s
+4up
+6ed
+6ing
+6ped
+7ing
+6s
+6y
+3k
+4ey
+6s
+4ie
+6s
+5sh
+4ories
+6y
+4s
+4wall
+8s
+4ymal
+8s
+2d
+3able
+4ge
+6s
+4lga
+7s
+6o
+7ish
+9m
+9ms
+7s
+3den
+6ite
+9s
+6ly
+6most
+6ness
+9ses
+5r
+6s
+3e
+4away
+8s
+4bound
+4d
+4less
+4osities
+8y
+5us
+7ly
+7ness
+9sses
+6t
+7s
+4r
+5s
+4s
+3ing
+6s
+3ling
+7s
+6s
+3roses
+6is
+5tic
+8s
+2e
+3d
+3ing
+3laman
+8s
+5nd
+3mal
+4s
+3racium
+9s
+6osphinges
+9hinx
+9hinxes
+5rch
+8al
+8ic
+9cal
+9cally
+9es
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+8s
+8y
+5tic
+8a
+9l
+9lly
+9s
+8s
+4ocracies
+9y
+8t
+9ic
+9ical
+9s
+5dule
+9s
+8ic
+5glyph
+9hed
+9hic
+9hical
+9hics
+9hing
+9hist
+9hists
+9hs
+6ram
+9mat
+9mate
+9mates
+9matic
+9matist
+9mats
+9s
+8ph
+9her
+9hers
+9hic
+9hical
+9hies
+9hs
+9hy
+5latries
+9y
+6ogic
+9cal
+9es
+9st
+9sts
+8y
+5mancies
+9y
+5phant
+9tic
+9ts
+7obia
+9ias
+9ic
+5scopies
+9y
+4urgical
+8es
+7y
+3s
+2falutin
+2ggle
+6d
+6r
+7s
+6s
+5ing
+8s
+3h
+4ball
+8ed
+8ing
+8s
+5inder
+9rs
+5looded
+5orn
+6y
+7s
+5red
+6ow
+8ed
+8ism
+9sms
+8s
+5ush
+4chair
+9s
+4ed
+5r
+6ed
+6ing
+6most
+6s
+5st
+4falutin
+9ing
+9ings
+9ins
+5lier
+9s
+6yer
+9s
+4handed
+9dly
+9dness
+4ing
+5sh
+4jack
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+4land
+8er
+9rs
+8s
+5ife
+8s
+6ght
+9ed
+9er
+9ers
+9ing
+9s
+5y
+4man
+5en
+5ost
+4ness
+8es
+4rise
+8s
+5oad
+8s
+4s
+5pot
+8s
+4t
+5ail
+8ed
+8ing
+8s
+5ed
+5h
+6s
+5ing
+5op
+7s
+5s
+4veld
+8s
+4way
+7man
+8en
+7s
+5rought
+2jab
+5s
+4ck
+6ed
+7r
+8s
+6ing
+9s
+6s
+3inks
+3ra
+5h
+6s
+5s
+2ke
+4d
+4r
+5s
+4s
+3ing
+3oi
+5ed
+5ing
+5s
+2la
+4r
+5ious
+9ly
+9ness
+9nesses
+6ties
+7y
+3ch
+5ed
+6s
+5ing
+3d
+4ing
+7s
+3i
+3l
+4billies
+8y
+4crest
+9s
+4ed
+5r
+6s
+4folk
+6rt
+8s
+4ier
+6st
+5ness
+9es
+6g
+7s
+4men
+4o
+5a
+6ed
+6ing
+6s
+5ck
+7ed
+7s
+7y
+5ed
+6s
+5ing
+5s
+4s
+5ide
+8s
+5lope
+9s
+4top
+7s
+4walker
+9rs
+8ing
+9ngs
+4y
+3t
+4ed
+4ing
+4less
+4s
+3um
+4s
+2m
+3atia
+6on
+8s
+3bo
+5s
+3s
+4elf
+2n
+3ahina
+8s
+4u
+5s
+3d
+4berries
+8y
+5rain
+9s
+4cast
+8ed
+8ing
+8s
+4er
+6ance
+9es
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6land
+9ds
+9s
+7ings
+9s
+6most
+6s
+4feet
+5oot
+6remost
+4gut
+7s
+4head
+8s
+4leg
+7s
+4most
+4quarter
+9ers
+4rance
+9s
+4s
+5hank
+9s
+5ight
+9s
+4ward
+5ing
+8s
+3g
+4e
+5d
+5less
+6ike
+5r
+6s
+5s
+4ing
+4s
+3kier
+6st
+4y
+3nied
+6s
+4y
+5ing
+3s
+3t
+4ed
+5r
+6land
+9ds
+6s
+4ing
+7ly
+7s
+4s
+2oi
+4s
+2p
+3bone
+7s
+3hugger
+3less
+4ike
+5ne
+7s
+4y
+3ness
+7es
+3parch
+8s
+4eastrum
+9ums
+5d
+5n
+6s
+5r
+5st
+4iatric
+9cs
+9es
+9st
+9sts
+8y
+5c
+5e
+6dom
+9s
+6ish
+6ness
+9ses
+6r
+6s
+7t
+5n
+6ess
+9es
+6g
+7s
+6s
+5sh
+4o
+5campal
+9i
+9us
+6entaur
+9aurs
+6ras
+9es
+7epian
+5dame
+9s
+8ist
+9sts
+8ous
+6rome
+9es
+9ic
+5griff
+9fs
+7yph
+9hs
+5logies
+9st
+9sts
+8y
+5manes
+5phagies
+9ist
+9ists
+9ous
+9y
+7ile
+9es
+7obe
+9es
+6otami
+9mian
+9mic
+9mus
+9muses
+5s
+4uric
+7te
+9s
+8ic
+5s
+6es
+4y
+5dom
+8s
+3s
+4hot
+4ter
+7ism
+9ms
+7s
+3t
+2rable
+4gana
+8s
+5e
+6s
+3cine
+4ocervus
+9uses
+5sities
+8y
+3e
+4able
+5ge
+7s
+4d
+4e
+5s
+4ling
+8s
+4r
+5s
+4s
+3ing
+6s
+3ling
+7s
+3ple
+6d
+6s
+5ing
+3rient
+8s
+3sel
+6ed
+6ing
+6led
+7ing
+6s
+4le
+6d
+6s
+5ing
+4tie
+4ute
+7ness
+9sses
+6ism
+9s
+3udin
+7ean
+9ns
+7oid
+8us
+7s
+4ndine
+2s
+3h
+4ed
+5s
+4ing
+3n
+3panicise
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+7dad
+9ds
+7olise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+7sm
+9s
+4id
+6ities
+8y
+3s
+4ed
+5lf
+5r
+6s
+5s
+4ier
+6s
+7t
+5ng
+7ly
+7s
+4y
+3t
+4amin
+8ase
+9ses
+8e
+9rgic
+9s
+8ic
+8s
+4ed
+4idin
+8e
+9s
+8s
+5e
+5ng
+5ocyte
+9es
+9ic
+6id
+6logies
+9y
+6phoroid
+4oblast
+9ts
+5chemical
+9ically
+9ist
+9istry
+9ists
+6ompatible
+5gen
+8eses
+9sis
+9tic
+8ic
+9cally
+9es
+8s
+8y
+6ram
+9s
+5id
+5logic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+6yses
+8is
+7tic
+9cally
+5ne
+7s
+5pathologic
+9ology
+6hysiology
+6lasmoses
+9mosis
+5rian
+9s
+8ted
+7c
+8al
+9lly
+9lness
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9ties
+9ty
+9ze
+9zed
+9zes
+9zing
+7ed
+8s
+8tte
+9tes
+7fied
+9es
+8y
+9ing
+7ographer
+9raphic
+9raphy
+8logies
+9ogy
+7sm
+9s
+6y
+7ing
+4rio
+7n
+8ic
+9cal
+9cally
+9cism
+9cisms
+9cs
+9sm
+9sms
+8s
+7s
+4s
+2t
+3ch
+5ed
+6r
+7s
+6s
+5hike
+9d
+9r
+9rs
+9s
+8ing
+5ier
+7st
+6ly
+6ng
+5y
+3he
+5r
+6ed
+6ing
+6most
+6s
+7ide
+9es
+6to
+6ward
+9ds
+5s
+3less
+3man
+4en
+3s
+3table
+4er
+6s
+4ing
+2ve
+4d
+4less
+5ike
+4r
+5s
+4s
+4ward
+8s
+3ing
+2ya
+2zen
+5s
+3z
+4ed
+5s
+4ing
+4oner
+8s
+1m
+2m
+1o
+2a
+3ctzin
+8es
+8s
+3ed
+3gie
+6s
+4y
+3ing
+3rd
+5ed
+6r
+7s
+5ing
+8s
+5s
+4ed
+4frost
+9s
+4head
+8s
+5ound
+9s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4s
+5e
+6ly
+6n
+7ed
+8ss
+9ses
+7ing
+7s
+6r
+6st
+4y
+3s
+4t
+5ed
+5ing
+5man
+6en
+5s
+3tching
+4zin
+7es
+7s
+3x
+4ed
+5r
+6s
+5s
+4ing
+2b
+3bed
+5r
+6s
+4ies
+5ng
+5sh
+5t
+6ries
+7y
+6s
+4le
+6bush
+9hes
+6d
+7ehoy
+9oydom
+9oydoms
+9oyhood
+9oyish
+9oyism
+9oyisms
+9oys
+6r
+7s
+6s
+5ing
+8ly
+8s
+4y
+5horse
+9ed
+9es
+9ing
+5ism
+8s
+7t
+8s
+5less
+3day
+6ed
+6ing
+6s
+3goblin
+9ism
+9isms
+9ries
+9ry
+9s
+3job
+6bed
+8r
+9s
+7ing
+9gs
+6s
+3like
+3nail
+7ed
+7ing
+7s
+4ob
+6bed
+8r
+9s
+7ing
+7y
+6s
+3o
+4dom
+7s
+4ed
+5s
+4ing
+5sm
+7s
+4s
+3s
+2c
+3hmagandies
+9dy
+3k
+4ed
+5r
+6s
+5y
+6s
+4ing
+4le
+6d
+6s
+5ing
+4s
+5hop
+8s
+3us
+5ed
+6s
+5ing
+5sed
+7s
+6ing
+2d
+3ad
+5dies
+6y
+5s
+3ded
+5n
+6s
+4in
+6g
+6s
+4le
+6d
+6s
+5ing
+3gepodge
+9es
+3iernal
+3ja
+5s
+3man
+6dod
+9s
+4en
+3ograph
+9ic
+9s
+4meter
+9s
+7ries
+8y
+4scope
+9s
+3s
+2e
+3cake
+7s
+3d
+4own
+7s
+3ing
+3like
+3rs
+3s
+2g
+3an
+5s
+3back
+7s
+3en
+5s
+3fish
+7es
+3g
+4ed
+5r
+6el
+8s
+6ies
+6s
+6y
+5t
+6s
+4in
+6g
+7s
+6s
+5sh
+7ly
+7ness
+9sses
+4s
+3h
+4ood
+7s
+4s
+3like
+3manay
+8s
+6e
+7s
+4enay
+8s
+3nose
+7d
+7s
+4ut
+6s
+3s
+4head
+8s
+3tie
+6d
+6ing
+6s
+4ying
+3ward
+7s
+5sh
+7es
+4eed
+7s
+2h
+3a
+3ed
+3ing
+3s
+2i
+3ck
+5ed
+5ing
+5s
+6ed
+7s
+6ing
+3den
+6ed
+6ing
+7sh
+9ness
+9nesses
+6s
+3k
+4ed
+4ing
+4s
+3ng
+3se
+5d
+5s
+4in
+6g
+6s
+4t
+5ed
+6r
+7s
+5ing
+8s
+5man
+6en
+5s
+5way
+8s
+2jatoleslam
+9lams
+7islam
+9lams
+2ka
+4s
+3e
+4d
+4s
+4y
+5ness
+9es
+5pokey
+9ys
+3i
+4er
+5st
+4ly
+4ness
+8es
+5g
+4s
+3ku
+3onui
+7s
+3um
+5s
+3ypokies
+7y
+2landric
+4rchies
+7y
+5d
+6s
+3d
+4able
+5ll
+7s
+4back
+8s
+4down
+8s
+4en
+5r
+6bat
+9s
+6s
+7hip
+9ps
+4fast
+8s
+4ing
+7s
+4out
+7s
+5ver
+8s
+4s
+4up
+6s
+3e
+4d
+4less
+4s
+5om
+7e
+4y
+5er
+6st
+3ibut
+7s
+4day
+7ed
+8r
+9s
+7ing
+7maker
+9kers
+7s
+4er
+5s
+6t
+4ly
+4ness
+8es
+5g
+6s
+4sm
+6s
+5t
+6ic
+8ally
+6s
+3k
+4ed
+4ing
+4s
+3la
+5ed
+5ing
+5nd
+7aise
+9ses
+7s
+5s
+4er
+6ed
+6ing
+6s
+4idam
+8s
+5es
+4o
+5a
+6ed
+6ing
+6s
+5ed
+6s
+5ing
+5o
+6ed
+6ing
+6s
+5s
+5w
+6are
+9s
+6ed
+7r
+7st
+6ing
+6ly
+6ness
+9ses
+6s
+6ware
+9es
+4y
+5hock
+9s
+3m
+4ia
+6s
+5c
+5um
+7s
+4s
+3obenthic
+5lastic
+9ically
+4caust
+9al
+9ic
+9s
+5ene
+5rine
+6ystalline
+4discus
+9ses
+4enzyme
+9es
+4gamies
+7y
+5ram
+8s
+7ph
+9ed
+9er
+9ers
+9ic
+9ically
+9ies
+9ing
+9s
+9y
+5ynic
+8es
+7y
+4hedra
+9l
+8ism
+9sms
+8on
+9ns
+4metabolic
+9olism
+9olisms
+9olous
+5orphic
+4n
+5ic
+5s
+4photal
+8e
+9s
+6rase
+9es
+9tic
+6yte
+9s
+8ic
+9sm
+9sms
+5lankton
+9tons
+5tic
+4steric
+4thurian
+9ans
+5ype
+8s
+7ic
+4zoic
+3p
+4en
+3s
+4tein
+8s
+6r
+7ed
+7ing
+7s
+3t
+4s
+3y
+4dam
+7e
+8s
+7s
+6y
+7s
+4stone
+9d
+9s
+8ing
+4tide
+8s
+2m
+3a
+4ge
+6d
+6r
+7s
+6s
+5ing
+4lographic
+6id
+8al
+8s
+4s
+3bre
+6s
+4urg
+7s
+3e
+4birth
+9s
+5odies
+7y
+6und
+6y
+7s
+5red
+8s
+7w
+8s
+5uilt
+6yer
+9s
+4comer
+9s
+7ing
+9gs
+5raft
+9s
+4d
+4felt
+4girl
+8s
+5rown
+4land
+8s
+5ess
+8ness
+9esses
+5ier
+7st
+6ke
+6ly
+6ness
+9ses
+5y
+6n
+7s
+4made
+6ker
+9s
+7ing
+9gs
+4obox
+8es
+5meric
+9es
+8ous
+8y
+6orph
+9hic
+9hies
+9hism
+9hisms
+9hous
+9hs
+9hy
+5path
+9ic
+9ically
+9ies
+9ist
+9ists
+9s
+9y
+5ses
+6is
+6tases
+9is
+8tic
+5teleuton
+9utons
+6herm
+9mal
+9mic
+9mies
+9mous
+9ms
+9my
+6ic
+6ypic
+9cal
+5wner
+9s
+9ship
+9ships
+4page
+8s
+5lace
+9s
+5ort
+8ed
+8ing
+8s
+4r
+5ed
+5ic
+6ng
+5oom
+8s
+5s
+4s
+5chool
+9led
+9ler
+9lers
+9ling
+9ls
+6reetch
+9tches
+5horing
+9ngs
+5ick
+8ness
+9esses
+6te
+8s
+5ourcing
+9ings
+5pun
+8s
+5tall
+9s
+7nd
+9s
+7y
+8s
+6ead
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+6retch
+9ches
+4town
+8s
+4ward
+8s
+7e
+8s
+5ork
+8er
+9rs
+8ing
+9ngs
+8s
+4y
+5ness
+9es
+5s
+3icidal
+9ly
+7e
+8s
+4e
+5r
+5s
+6t
+4letic
+9al
+9ally
+9s
+5ies
+6st
+8s
+5y
+4nes
+7s
+8es
+5g
+6s
+5ian
+8s
+6d
+7s
+6es
+6n
+7e
+7s
+6sation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5oid
+8s
+5y
+3me
+5s
+4ock
+7s
+5s
+6es
+3oblastic
+9ies
+9y
+4centric
+9ically
+6rcal
+8ies
+8y
+5hlamydeous
+6romatic
+9atism
+9atisms
+9ies
+9ous
+9y
+5yclic
+6steine
+9ines
+4dont
+5yne
+4eobox
+6meric
+9ies
+9ous
+9y
+7orph
+9phic
+9phies
+9phism
+9phisms
+9phous
+9phs
+9phy
+6path
+9hic
+9hies
+9hist
+9hists
+9hs
+9hy
+6ses
+7is
+7tases
+9sis
+9tic
+6teleuton
+9eutons
+7hermal
+9rmic
+9rmous
+7ic
+7ypic
+9ical
+5rotisms
+4gametic
+7ic
+8es
+7ous
+7y
+5enate
+9es
+7eities
+9ty
+8ous
+9usly
+9usness
+8ses
+9is
+8tic
+9ical
+7ies
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7ous
+7y
+5onies
+7ous
+9sly
+7y
+5raft
+9s
+7ph
+9ic
+9s
+4iomerous
+6therm
+9rmal
+9rmic
+9rmies
+9rms
+9rmy
+6usian
+9ans
+4log
+7ate
+9ed
+9es
+9ing
+9ion
+9ions
+7ic
+9al
+9ally
+8es
+8se
+9ed
+9er
+9ers
+9es
+9ing
+8ze
+9ed
+9er
+9ers
+9es
+9ing
+7oumena
+9s
+7raphic
+7s
+7ue
+9s
+8mena
+7y
+6sine
+5yses
+7is
+6tic
+4morph
+9ic
+9ies
+9ism
+9isms
+9oses
+9osis
+9ous
+9s
+9y
+4nuclear
+5ym
+7ic
+8es
+8ties
+9y
+7ous
+9sly
+7s
+7y
+4ousian
+9ns
+4phile
+9s
+6obe
+9s
+8ia
+9as
+9c
+7ne
+9s
+8ic
+9cally
+9es
+8ous
+8y
+6ylies
+8lic
+8y
+5lasies
+8mies
+9y
+8tic
+9ically
+9ies
+9y
+8y
+5olar
+9ities
+9ity
+7ymer
+9eric
+9ers
+5teran
+9ns
+8ous
+4rganic
+4s
+5cedastic
+5ex
+7es
+7ual
+9lism
+9lisms
+9list
+9lists
+9lities
+9lity
+9lly
+9ls
+5ocial
+9lities
+9lity
+5pories
+8ous
+8y
+5tylies
+8y
+4taxes
+7ial
+9lly
+8c
+8s
+5hallic
+9ies
+9ism
+9isms
+9y
+6ermal
+9ic
+9ies
+9ous
+9y
+5onic
+8es
+7ous
+7y
+5ransplant
+9plants
+5ypal
+7e
+8s
+7ic
+8es
+7y
+4usian
+9s
+4zygoses
+9is
+9ities
+9ity
+8te
+9es
+9ic
+8us
+9sly
+3s
+3uncle
+8s
+6ular
+8e
+9s
+8i
+8us
+3y
+2n
+3an
+5s
+3cho
+6ed
+6ing
+6s
+3d
+4a
+5s
+4le
+6d
+6s
+5ing
+4s
+3e
+4d
+4r
+5s
+4s
+5t
+6er
+7st
+6ies
+6ly
+6ness
+9ses
+6y
+4wort
+8s
+4y
+5bee
+8s
+6un
+8ch
+9hes
+8s
+5comb
+9ed
+9ing
+9ings
+9s
+6reeper
+9pers
+5dew
+8ed
+8s
+5eater
+9rs
+6d
+7ly
+5ful
+5guide
+9es
+5ing
+5less
+5month
+9hed
+9hing
+9hs
+7on
+9ed
+9er
+9ers
+9ing
+9s
+5pot
+8s
+5s
+6ucker
+9ers
+9le
+9led
+9les
+5trap
+9s
+3g
+4i
+5ed
+6s
+5ing
+5ng
+5s
+4s
+3ied
+6ly
+4ng
+3k
+4ed
+5r
+6s
+5ys
+4ie
+6s
+5ng
+4s
+4y
+3or
+5abilities
+9ity
+7le
+9ness
+9nesses
+8y
+6nd
+8s
+6ria
+8es
+8ly
+8um
+9ms
+7y
+5ed
+6e
+7s
+6r
+7s
+5ific
+9al
+9ally
+9s
+6ng
+5less
+5s
+4ur
+6able
+9eness
+9y
+6ed
+7e
+8s
+7r
+8s
+6ing
+6less
+6s
+3s
+2o
+3ch
+5es
+5ie
+7s
+3d
+4ed
+6ness
+9ses
+4ia
+6s
+5e
+6r
+6s
+7t
+5ng
+4less
+5ike
+5um
+7ish
+9m
+9ms
+7s
+4man
+5en
+5old
+8s
+4oo
+6ed
+6ing
+7sm
+9s
+6s
+4s
+4wink
+8ed
+9r
+9rs
+8ing
+8s
+4y
+3ey
+5s
+3f
+4beat
+8s
+5ound
+4ed
+5r
+6s
+4ing
+4less
+5ike
+4print
+9s
+4rot
+7s
+4s
+3k
+4a
+5h
+6s
+5s
+4check
+9s
+4ed
+6ness
+9ses
+5y
+6s
+4ier
+6s
+7t
+5ng
+4less
+6t
+7s
+5ike
+4nose
+8d
+8s
+4s
+4up
+6s
+4worm
+8s
+4y
+3lachan
+9s
+4ey
+6s
+4ican
+8s
+5e
+6r
+6s
+7t
+5gan
+8ism
+9sms
+8s
+4ock
+7s
+4y
+3n
+4ed
+4ing
+4s
+3p
+4ed
+5r
+6s
+4ing
+4la
+6s
+5ess
+5ike
+4oe
+6s
+5o
+6s
+4s
+5kirt
+9s
+5ter
+8s
+3r
+4ah
+6ed
+6ing
+6s
+5y
+6ed
+6ing
+6s
+4d
+5s
+4oo
+4s
+3segow
+8s
+4gow
+7s
+4h
+5ed
+6s
+5ing
+3t
+4anannie
+9ies
+9y
+4ch
+6es
+4ed
+5nannie
+9ies
+9y
+5r
+6s
+4ier
+6st
+5ng
+4nannie
+9es
+8y
+4s
+4y
+3ve
+5d
+5n
+5r
+6ed
+6ing
+6s
+5s
+4ing
+2p
+3bind
+7s
+6e
+7s
+3dog
+6s
+3e
+4d
+4ful
+7ly
+7ness
+9sses
+7s
+4less
+8ly
+8ness
+9esses
+4r
+5s
+4s
+3head
+7s
+3ing
+6ly
+3lite
+7s
+6ic
+4ologies
+9st
+9sts
+8y
+3ped
+5r
+6car
+9s
+6s
+4ier
+6st
+5ng
+7s
+4le
+6d
+6r
+7s
+6s
+5ing
+4us
+4y
+3s
+4ack
+7ing
+9gs
+7s
+4cotch
+9ed
+9es
+9ing
+3toad
+7s
+2ra
+4h
+5s
+4l
+4ry
+4s
+3de
+5d
+5in
+7s
+5ola
+7um
+5s
+4ing
+4ock
+7s
+3ehound
+9s
+3i
+4atiki
+9s
+4s
+4zon
+7al
+7less
+7s
+7tal
+9lities
+9lity
+9lly
+9lness
+9ls
+3key
+6s
+3licks
+3me
+5s
+6es
+6is
+5tic
+4ic
+4ogonia
+9um
+5nal
+8ly
+6e
+7like
+7s
+6ic
+3n
+4bag
+7s
+5eak
+8s
+7m
+8s
+5ill
+8s
+5lende
+9es
+9ic
+5ook
+8s
+5ug
+7s
+4ed
+6ness
+9ses
+5r
+6s
+5t
+6s
+4fels
+5ul
+7s
+4geld
+8s
+4ing
+7s
+5sh
+6t
+7s
+5to
+7s
+4less
+8ness
+9esses
+6t
+7s
+5ike
+4pipe
+8s
+5out
+8s
+4s
+5tone
+9s
+5woggle
+9led
+9les
+9ling
+4tail
+8s
+4work
+8s
+7m
+8s
+7t
+8s
+5rack
+9s
+4yhead
+9s
+5wink
+9s
+3oeka
+7s
+4grapher
+9ers
+9ies
+9y
+4kaka
+8s
+4loge
+8r
+9s
+8s
+7ia
+8c
+9al
+8es
+8on
+9ns
+8st
+9ts
+8um
+9ms
+7y
+4metrical
+9es
+8y
+4pito
+8s
+5ter
+8s
+4scope
+9s
+8ic
+9es
+9st
+9sts
+8y
+3rendous
+9sly
+9sness
+6t
+4ible
+8ness
+9esses
+8s
+7y
+5d
+6er
+7st
+6ly
+6ness
+9ses
+5fic
+8ally
+9tion
+9tions
+7ed
+8s
+6y
+7ing
+9gly
+5pilant
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+5sonant
+8ous
+4or
+6s
+3s
+4e
+5back
+9s
+6ean
+9s
+6ox
+8es
+5car
+8s
+5d
+5feathers
+6lesh
+9hes
+7ies
+7y
+5hair
+9s
+6ide
+9s
+5laugh
+9hs
+6eech
+9hes
+7ss
+6ike
+5man
+8ship
+9hips
+6eat
+9s
+7n
+6int
+9s
+5play
+9er
+9ers
+9s
+6ond
+9s
+7wer
+9rs
+7x
+8es
+5race
+9s
+7dish
+9shes
+5s
+6hod
+8e
+9d
+9ing
+9ings
+9r
+9rs
+9s
+5tail
+9s
+5way
+8s
+6eed
+9s
+6hip
+9ped
+9per
+9pers
+9ping
+9s
+6oman
+8en
+5y
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4on
+6s
+4t
+5e
+6s
+5s
+4y
+3tation
+9s
+7ve
+9ly
+6orily
+8y
+4icultural
+9urally
+9ure
+9ures
+9urist
+9urists
+2s
+3anna
+7ed
+7h
+8s
+7ing
+7s
+3e
+4d
+4l
+5ike
+5s
+4man
+5en
+4n
+4pipe
+8s
+4r
+5s
+4s
+4y
+5ed
+5ing
+5s
+3ier
+6ies
+6s
+6y
+4ng
+3pice
+7s
+5table
+9eness
+9y
+7ge
+9s
+7l
+8e
+9r
+9rs
+9s
+8isation
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ler
+9ers
+8s
+6ia
+7um
+4odar
+8s
+3s
+4es
+3t
+4a
+5ge
+7s
+5s
+4ed
+5l
+6ed
+7r
+8s
+6ing
+9s
+6led
+8r
+9s
+7ing
+9gs
+6ries
+7y
+6s
+5ss
+7ed
+8s
+7ing
+4ie
+6s
+5le
+7ly
+7s
+6ities
+8y
+5ng
+7s
+4ler
+7s
+6sse
+5y
+4ries
+5y
+4s
+2t
+3bed
+6s
+4lood
+8s
+4ox
+6es
+3cake
+7s
+4h
+5ed
+6s
+5ing
+5pot
+8ch
+9hes
+8s
+3dog
+6ged
+8r
+9s
+7ing
+6s
+3e
+4l
+5dom
+8s
+5ier
+8s
+6ng
+8s
+5ling
+9s
+5man
+6en
+5s
+4n
+3foot
+7ed
+7ing
+7s
+3head
+7ed
+9ly
+9ness
+9nesses
+7s
+4ouse
+8d
+8s
+7ing
+9gs
+3line
+7s
+6k
+7s
+4y
+3ness
+7es
+3plate
+8s
+4ot
+6s
+4ress
+8ed
+9s
+8ing
+3rod
+6s
+3s
+4hot
+7s
+4pot
+7s
+5ur
+7s
+3ted
+5ntot
+9s
+5r
+6ed
+6ing
+6s
+5st
+4ie
+6s
+5ng
+7s
+5sh
+4y
+2udah
+6s
+5n
+6s
+3f
+4ed
+4f
+5ed
+5ing
+5s
+4ing
+4s
+3gh
+5ed
+5ing
+5magandie
+9ndies
+5s
+3here
+7s
+3mmos
+7es
+4ous
+7es
+4us
+6es
+3nd
+5ed
+6r
+7s
+5fish
+9es
+5ing
+5s
+6tooth
+4gan
+7s
+3r
+4glass
+9es
+4i
+5s
+4less
+5ies
+5ong
+5y
+4plate
+9s
+4s
+3se
+5boat
+9er
+9ers
+9s
+7und
+7y
+8s
+6reak
+9ker
+9kers
+9king
+9kings
+9ks
+7oke
+9en
+5carl
+9s
+6lean
+9ned
+9ning
+9nings
+9ns
+6oat
+9s
+6raft
+9ts
+5d
+6ress
+9ses
+5father
+9ers
+6lies
+7y
+6ront
+9ts
+6ul
+8s
+5guest
+9ts
+5hold
+9er
+9ers
+9ership
+9s
+6usband
+9ands
+5keep
+9er
+9ers
+9ing
+9ings
+9s
+7pt
+5l
+6ed
+7ek
+9s
+7ss
+9ness
+9nesses
+6ights
+7ne
+9s
+8g
+6led
+7ing
+9gs
+6s
+5maid
+9s
+7n
+7ster
+9ers
+7te
+9s
+6en
+6istress
+9resses
+6other
+9ers
+5painter
+9ters
+7rent
+9nts
+6erson
+9ons
+6lant
+9ts
+5r
+6oom
+9s
+6s
+5s
+6at
+6it
+8s
+8ting
+5top
+8s
+5wares
+8ming
+9ings
+6ife
+9liness
+9ly
+9ries
+9ry
+9ship
+9ships
+9skep
+9skeps
+9y
+7ves
+6ork
+9er
+9ers
+9s
+5y
+4ier
+6st
+5ng
+7s
+4ling
+4tonia
+9s
+3t
+4ed
+4ing
+7s
+4s
+2ve
+4a
+5s
+4d
+4l
+5ed
+5ing
+5led
+7r
+8s
+6ing
+5s
+4n
+4r
+5craft
+9ts
+5ed
+6r
+7s
+5flies
+7y
+5ing
+8ly
+5port
+9s
+5s
+5train
+9ns
+4s
+3ing
+2w
+3be
+5it
+3dah
+6s
+4ie
+6d
+6s
+4y
+5ing
+3e
+4s
+4ver
+3f
+4ed
+4f
+5ed
+5ing
+5s
+4ing
+4s
+3itzer
+8s
+3k
+4ed
+5r
+6s
+4ing
+4s
+3l
+4back
+8s
+4ed
+5r
+6s
+5t
+6s
+4ing
+7ly
+7s
+4round
+9s
+4s
+3re
+5s
+3s
+4o
+5ever
+3towdie
+9s
+3zat
+4it
+2x
+3ed
+4s
+3ing
+2y
+3a
+4s
+3den
+6ed
+6hood
+9ds
+6ing
+7sh
+9ness
+9nesses
+8m
+9s
+6s
+3ed
+3ing
+3le
+5s
+3s
+1ryvna
+6s
+5ia
+7s
+5ya
+7s
+1uanaco
+7s
+3quero
+8s
+3rache
+8s
+7o
+8s
+2b
+3bies
+4ly
+4ub
+6oo
+8s
+6s
+4y
+3cap
+6s
+3ris
+6es
+6tic
+9ally
+3s
+2ck
+4aback
+9s
+4ed
+5ry
+4ing
+4le
+6berries
+9ry
+9rying
+9ryings
+7one
+9es
+6d
+6s
+5ing
+4s
+5ter
+8age
+9ges
+8ed
+9ss
+9sses
+8ies
+9ng
+9sm
+9sms
+8s
+8y
+6ress
+9ses
+2dden
+4le
+6d
+6r
+7s
+6s
+5ing
+4up
+3ibrastic
+3na
+5s
+3ud
+5s
+2e
+3d
+3less
+3r
+4s
+3s
+2ff
+4ed
+5r
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+5sh
+7ly
+7ness
+9sses
+4kin
+7s
+4s
+4y
+2g
+3e
+4ly
+4ness
+8es
+4ous
+7ly
+7ness
+9sses
+4r
+4st
+3gable
+4ed
+5r
+6s
+4ier
+6st
+5ng
+4y
+3s
+3y
+2h
+3u
+4s
+2i
+3a
+4s
+3c
+3pil
+6es
+6s
+3s
+4ache
+8s
+4sier
+8s
+3tain
+7s
+2la
+4s
+3e
+4s
+3k
+4ed
+4ier
+6st
+5ng
+4s
+4y
+3l
+4aballoo
+9oos
+8oo
+9os
+4ed
+5r
+6s
+4ier
+6st
+5ng
+4o
+5a
+6ed
+6ing
+6s
+5ed
+6s
+5ing
+5o
+6ed
+6ing
+6s
+5s
+4s
+4y
+2m
+3a
+4n
+5e
+6ly
+6ness
+9ses
+6r
+6st
+5hood
+9s
+5isation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+9cally
+8s
+6tarian
+9ianism
+9ianist
+9ians
+7ies
+7y
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5kind
+9s
+5like
+6y
+5ness
+9es
+5oid
+8s
+5s
+4s
+4te
+6s
+3ble
+6bee
+9s
+6d
+6ness
+9ses
+6r
+7s
+6s
+7se
+9s
+7t
+5ing
+8ly
+8s
+5y
+4ucker
+9s
+5g
+6gable
+7ed
+8r
+9ies
+9s
+9y
+7ing
+6s
+5zz
+7es
+3dinger
+9s
+4rum
+7ness
+9sses
+7s
+4udgeon
+9ns
+3ect
+6ant
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+6ed
+6ing
+7ve
+9s
+6s
+4fied
+7s
+5y
+6ing
+4ral
+7s
+5i
+5us
+3f
+4ed
+4ing
+4s
+3gruffian
+9ans
+9n
+9ns
+3hum
+6s
+3ic
+5ole
+8s
+7ous
+4d
+5er
+6st
+6x
+7es
+5ices
+6fication
+9ations
+8ed
+9r
+9rs
+9s
+7y
+8ing
+6stat
+9ts
+6ties
+7y
+5ly
+5ness
+9es
+5or
+7s
+4fication
+9ions
+6ed
+7s
+5y
+6ing
+4liant
+7te
+9d
+9s
+8ing
+9ngly
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+6ties
+7y
+4nt
+6s
+4te
+6s
+5ure
+8s
+3lie
+6s
+3mable
+5um
+7s
+4ed
+5l
+6led
+8r
+9s
+7ing
+6s
+5r
+6s
+4ing
+7bird
+9rds
+7s
+4le
+4ock
+7ed
+7ing
+7s
+7y
+4um
+6s
+5s
+6es
+3ogen
+7s
+4ngous
+4r
+5al
+7ism
+9ms
+9t
+9ts
+7ly
+5ed
+6sk
+8s
+7que
+9es
+5ful
+5ing
+6st
+8ic
+8s
+5less
+9ly
+9ness
+9nesses
+5ous
+8ly
+8ness
+9esses
+5s
+6ome
+4ur
+6ed
+6ful
+6ing
+6less
+9sness
+6s
+7ome
+9eness
+5s
+3p
+4back
+8ed
+8s
+4ed
+5n
+6s
+5r
+6s
+4h
+5ed
+5ing
+5s
+4ier
+6s
+7t
+5ness
+9es
+4less
+5ike
+4s
+4ties
+5y
+4y
+3s
+4trum
+8s
+3ungous
+4s
+5es
+5y
+3vee
+6s
+2n
+3ch
+5back
+9ed
+9s
+5ed
+6s
+5ing
+3dred
+7er
+9s
+7fold
+9lds
+7or
+9s
+7s
+7th
+9s
+7weight
+9ights
+3g
+4an
+6s
+4er
+6ed
+6ful
+6ing
+9ly
+6ly
+6s
+4over
+4rier
+7st
+6ly
+6ness
+9ses
+5y
+3h
+3k
+4er
+6ed
+6ing
+6s
+5y
+6s
+4ie
+6r
+6s
+7t
+4s
+5es
+4y
+3nish
+3s
+3t
+4able
+5way
+8s
+4ed
+6ly
+5r
+6s
+4iegowk
+9ks
+5ng
+7s
+4ress
+8es
+4s
+5man
+8ship
+9hips
+6en
+2p
+3aithric
+3iro
+6s
+3pah
+6s
+4ed
+4ing
+4ot
+6h
+3s
+2rcheon
+8s
+3den
+6s
+4ies
+4le
+6d
+6r
+7s
+6s
+5ing
+8s
+4s
+3l
+4barrow
+9ws
+6t
+7s
+4ed
+5r
+6s
+5y
+6s
+4ies
+5ng
+7s
+4s
+4y
+3ra
+5ed
+5h
+6ed
+6ing
+6s
+5ing
+5s
+5y
+6ed
+6ing
+6s
+4icane
+9s
+8o
+9es
+5ed
+7ly
+7ness
+9sses
+6r
+7s
+6s
+4y
+5ing
+8ly
+8s
+3st
+5s
+3t
+4er
+6s
+4ful
+7ly
+7ness
+9sses
+4ing
+4le
+6berries
+9ry
+6d
+6s
+7s
+8ly
+8ness
+9esses
+5ing
+4s
+2sband
+7age
+9es
+7ed
+8r
+9s
+7ing
+7land
+9nds
+8ess
+8ike
+8y
+7man
+8en
+7ries
+8y
+7s
+3h
+4abied
+8s
+6y
+7ing
+4ed
+6ly
+5r
+6ed
+6ing
+6s
+5s
+4ful
+4ier
+6st
+5ng
+4puppies
+8y
+4y
+3k
+4ed
+5r
+6s
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+4like
+4s
+4y
+3o
+4s
+3s
+4ar
+6s
+4es
+4ies
+5f
+6s
+4y
+3tings
+4le
+6d
+6r
+7s
+6s
+5ing
+8s
+3wife
+7s
+5ves
+2t
+3ch
+5ed
+6s
+5ie
+7s
+6ng
+3ia
+5s
+3like
+3ment
+7s
+3s
+3ted
+4ing
+7s
+3zpa
+6h
+7s
+6s
+2zoor
+6s
+3za
+5ed
+5h
+6ed
+6ing
+6s
+5ing
+5s
+4ies
+4y
+1wan
+2yl
+4s
+1yacine
+7s
+6th
+8ine
+8s
+3ena
+6s
+5ic
+3lin
+6e
+7s
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+5te
+7s
+4ogen
+8s
+5id
+7s
+5melan
+9ne
+9nes
+9ns
+5nema
+9s
+5phane
+9es
+6lasm
+9mic
+9ms
+4uronic
+9dase
+9dases
+2brid
+6isable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9s
+7ties
+8y
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6oma
+9s
+7us
+6s
+5s
+6es
+6tic
+2dantoin
+9s
+4thode
+9s
+5id
+7iform
+7s
+5oid
+3nocarpate
+9ates
+9ic
+3ra
+5cid
+8s
+5e
+6mia
+9s
+5gog
+8s
+8ue
+9es
+5lazine
+9nes
+5ngea
+9s
+6t
+7h
+8s
+7s
+5rgyral
+9ia
+9ias
+9ic
+9ism
+9isms
+9um
+9ums
+6throses
+9osis
+5s
+6e
+7s
+6tine
+9es
+9ine
+9ines
+8s
+9es
+5te
+7d
+7s
+6ing
+7on
+9s
+6or
+8s
+5ulic
+9ally
+9ked
+9king
+9s
+5zide
+9s
+7ne
+9s
+6oic
+4emia
+8s
+4ia
+6e
+5c
+6ally
+5d
+6e
+7s
+6s
+5lla
+8s
+5odic
+4o
+5acoustics
+5biological
+9ogies
+9ogist
+9ogists
+9ogy
+6romic
+5carbon
+9ons
+7st
+9s
+6ele
+9s
+8lulose
+9uloses
+7phalic
+9alics
+9alies
+9aloid
+9alous
+9alus
+9aluses
+9aly
+6hloric
+9ride
+9rides
+7ore
+9es
+9ic
+6odone
+9nes
+7lloid
+9oidal
+9oids
+7ral
+9lline
+9llines
+9ls
+8tisone
+9isones
+6rack
+9ked
+9ker
+9kers
+9king
+9kings
+9ks
+6yanic
+5dynamic
+9mical
+9micist
+9mics
+5elastic
+7ectric
+6xtractor
+9actors
+5fluoric
+6oil
+9s
+7rming
+9ings
+5gel
+8s
+7n
+8ase
+9ses
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8olyses
+9lysis
+9us
+8s
+7ological
+9ogies
+9ogist
+9ogists
+9ogy
+6raph
+9her
+9hers
+9hic
+9hical
+9hies
+9hs
+9hy
+5id
+7s
+5kinetic
+9tical
+9tics
+5lase
+9s
+6ogic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+6ysable
+9te
+9tes
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+9s
+7te
+9s
+8ic
+9cally
+7zable
+9te
+9tes
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+5ma
+7gnetic
+9etics
+7ncer
+9ers
+9ies
+9y
+8ia
+9as
+8tic
+7s
+7ta
+6echanical
+9anics
+7dusa
+9sae
+9san
+9sans
+9sas
+9soid
+9soids
+7l
+8s
+7tallurgy
+8eor
+9ors
+9r
+9rs
+8ric
+9ical
+9ically
+9ies
+9y
+6orphic
+5naut
+9s
+6ephroses
+9rosis
+9rotic
+6ic
+8ally
+7um
+9s
+5path
+9ic
+9ical
+9ically
+9ics
+9ies
+9ist
+9ists
+9s
+9y
+6eroxide
+9xides
+6hane
+9es
+9ous
+7ile
+9es
+9ic
+9icity
+9ies
+9ite
+9ites
+9ous
+9y
+7obia
+9ias
+9ic
+9icity
+9ous
+8ne
+9es
+7yte
+9es
+9ic
+9on
+9ons
+9ous
+6ic
+6lane
+9ed
+9es
+9ing
+6neumatic
+6olyp
+9ps
+7nic
+9cally
+9cs
+7wer
+9rs
+6s
+7es
+7ies
+7y
+6tic
+6ult
+9s
+5quinol
+9ols
+9one
+9ones
+5s
+6cope
+9es
+9ic
+9ical
+6ere
+9s
+6ki
+8s
+6ol
+8ic
+8s
+7ma
+9l
+9ta
+9tous
+8e
+9s
+6pace
+9es
+7here
+9res
+9ric
+6tat
+9ic
+9ical
+9ically
+9ics
+9s
+6ulphate
+9hates
+9hide
+9hides
+9hite
+9hites
+9huric
+9hurous
+5tactic
+7xes
+8is
+6heca
+9ae
+8rapic
+9apies
+9apist
+9apists
+9apy
+9mal
+9mally
+7oraces
+9acic
+9ax
+9axes
+6ropic
+9ically
+9ism
+9isms
+5us
+5vane
+9s
+5xide
+9s
+6onium
+9ums
+6y
+7apatite
+9atites
+7butyrate
+7l
+8amine
+9mines
+9patite
+9se
+9ses
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+8ic
+8s
+7proline
+9olines
+7urea
+9eas
+7zine
+9nes
+5zincite
+9ites
+6oa
+8n
+9s
+7on
+3yne
+6s
+2e
+3d
+3ing
+3n
+4a
+5s
+4ic
+5ne
+4oid
+4s
+3s
+3tal
+4ograph
+9hic
+9hical
+9hies
+9hs
+9hy
+5logies
+8y
+5meter
+9rs
+8rograph
+2geist
+7s
+3ieist
+8s
+5ne
+7s
+6ic
+8ally
+8s
+7st
+9s
+3ristor
+9s
+4ochasies
+9tic
+9y
+5deik
+9s
+5graph
+9hic
+9hical
+9hs
+5logies
+8y
+5ma
+7s
+7ta
+6eter
+9rs
+8ric
+9ical
+9ically
+9ies
+9y
+5phil
+9e
+9es
+9ous
+7obe
+7yte
+9es
+9ic
+5scope
+9es
+9ic
+9ical
+9ically
+9icity
+6tat
+9s
+2ing
+2ke
+4s
+2la
+4s
+3ding
+7s
+3e
+4g
+5s
+4s
+3ic
+5ism
+8s
+7t
+8s
+4sm
+6s
+5t
+6s
+3obate
+8s
+4geneses
+9is
+4ist
+7s
+4morphic
+9ism
+9isms
+4pathism
+9sms
+9st
+9sts
+5hagous
+6yte
+9s
+4theism
+9ms
+9t
+9ts
+5omous
+4zoic
+8al
+7sm
+9s
+8t
+9ic
+9ically
+9s
+2men
+5aeal
+8n
+6l
+5eal
+8ly
+8s
+7n
+5ia
+7l
+6um
+8s
+5ophore
+9res
+7lasties
+9sty
+7tera
+9ran
+9rans
+9ron
+9rons
+9rous
+5s
+3n
+4al
+6s
+5ries
+6y
+4book
+8s
+4ed
+4ic
+5ng
+5st
+7s
+4less
+5ike
+4odical
+7es
+7st
+9s
+6y
+5grapher
+9hers
+9hies
+9hy
+5logic
+9cal
+9es
+9st
+9sts
+8y
+4s
+2nde
+5s
+2oid
+5al
+5ean
+5s
+3plastra
+9al
+9on
+3scine
+8s
+5yamine
+9nes
+8us
+9ses
+2p
+3abyssal
+9lly
+4esthesia
+9sias
+9sic
+5thral
+8on
+9ns
+4lgesia
+9as
+9c
+6ia
+8s
+5lactic
+7ge
+9s
+4nthia
+9l
+8um
+4te
+6s
+3e
+4d
+4r
+5acid
+9ities
+9ity
+7tion
+9ons
+9ve
+9ves
+9vities
+9vity
+7uities
+9ty
+8ses
+9is
+8te
+9eness
+6drenalism
+6emia
+9as
+9c
+7sthesia
+9hesias
+9hesic
+9hetic
+6ggressive
+6lert
+7gesia
+9sias
+9sic
+6rid
+7ousal
+9sals
+6ware
+9eness
+5baric
+9cally
+7tic
+9cally
+8on
+9ns
+6ola
+9e
+9s
+8e
+9s
+8ic
+9cal
+9cally
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+8oid
+9idal
+9ids
+7rean
+9ans
+5calcaemia
+9aemias
+9emia
+9emias
+9emic
+7pnia
+9ias
+9ic
+7rbia
+9ias
+7tabolism
+9lectic
+9lexes
+9lexis
+7utious
+6harge
+9ged
+9ges
+9ging
+6ivilised
+9lized
+6oagulable
+7lour
+9urs
+7mplex
+7nscious
+7rrect
+9ection
+9ectly
+6ritic
+9ical
+9ically
+9icise
+9icised
+9icises
+9icism
+9icisms
+9icize
+9icized
+9icizes
+9ics
+6ube
+9s
+5dactyl
+9ylies
+9yly
+6orian
+6ulia
+9as
+9c
+9cal
+5efficient
+6meses
+9is
+8tic
+7ia
+9s
+8c
+7otional
+6ndemic
+7ergetic
+6sthesia
+9esias
+9etic
+6utectic
+9ctoid
+6xcitable
+9ted
+9tement
+8retion
+9etions
+7tend
+9nded
+9nding
+9nds
+9nsion
+9nsions
+5fastidious
+6ine
+6ocal
+6unction
+9tional
+9tions
+5gamies
+8ous
+8y
+6eometric
+6lycaemia
+9aemias
+9aemic
+9emia
+9emias
+9emic
+6ol
+8ic
+9cally
+8s
+5hidroses
+9osis
+5icin
+9s
+7um
+9s
+6droses
+9sis
+6mmune
+9nise
+9nised
+9nises
+9nising
+9nize
+9nized
+9nizes
+9nizing
+6nflated
+9ation
+9ations
+7oses
+9is
+8tic
+7sulinism
+7tense
+7volution
+6rritable
+5keratoses
+9tosis
+9totic
+6ineses
+9sia
+9sias
+9sis
+9tic
+5link
+9ed
+9ing
+9s
+7pemia
+9mias
+9mic
+8idaemia
+9demia
+9demias
+6ydian
+5mania
+9as
+9c
+7rket
+9ets
+8t
+9s
+7sculine
+6edia
+9as
+7tabolic
+9bolism
+8er
+9rs
+8ric
+9ical
+9opia
+9opias
+9opic
+9opical
+9opies
+9opy
+6iling
+9ngs
+6nesia
+9ias
+9ic
+6obilities
+9lity
+7dern
+9rnist
+9rnists
+6utability
+9ble
+5natraemia
+9aemias
+6ova
+9e
+9s
+6ym
+8ies
+8s
+8y
+5on
+7s
+6pe
+8s
+7ia
+9s
+8c
+6rexia
+9ias
+6smia
+9as
+7toses
+9sis
+9tic
+5parasite
+9sites
+9sitic
+9sitism
+6hagia
+9ias
+9ic
+7rygian
+7ysical
+9ically
+6igmented
+7tuitary
+6lane
+9es
+8sia
+9ias
+9tic
+7oid
+9dies
+9ds
+9dy
+6nea
+9s
+8ic
+7oea
+9as
+6olarise
+9rised
+9rises
+9rising
+9rize
+9rized
+9rizes
+9rizing
+7wer
+9rs
+6roducer
+9ucers
+9uction
+8sexia
+9exias
+6ure
+6yretic
+9xia
+9xial
+9xias
+5rational
+6eactive
+9tivity
+9tor
+9tors
+8l
+9ism
+9isms
+9ist
+9istic
+9ists
+9ities
+9ity
+9s
+7sponsive
+6omantic
+9ntics
+5s
+6aline
+9nities
+9nity
+9vation
+7rcoma
+9omas
+9omata
+9oses
+9osis
+6ecretion
+9etions
+7nsitise
+9itised
+9itises
+9itive
+9itize
+9itized
+9itizes
+9ual
+7xual
+9ality
+6omnia
+9ias
+9olence
+7nic
+9cally
+9cs
+6pace
+9es
+8tial
+6tatic
+7hene
+9nes
+9nia
+9nias
+9nic
+9nite
+9nites
+7imulate
+9ulated
+9ulates
+7ress
+9sses
+6urface
+9aces
+5tense
+9ion
+9ions
+9ive
+9ives
+7xt
+9s
+6hermal
+9mia
+9mias
+9mic
+9mies
+9my
+7ymia
+9ias
+8roid
+9oidism
+9oids
+6onia
+9as
+9c
+9cities
+9city
+6rophic
+9hical
+9hied
+9hies
+9hous
+9hy
+9hying
+6ypical
+5urbanism
+9nisms
+7icemia
+9emias
+5velocities
+9city
+7ntilate
+9ilated
+9ilates
+6igilance
+9lances
+9lant
+7rulent
+7scosity
+4s
+5ter
+8s
+6hesia
+9ias
+9ic
+4thral
+3ha
+5e
+5l
+4emia
+8s
+5n
+6ate
+9d
+9s
+8ing
+9on
+9ons
+6ed
+6ic
+7ng
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6less
+6s
+4ies
+4y
+3ing
+6s
+5oses
+7is
+3nagogic
+4ic
+6s
+4oanalyses
+9ysis
+9ytic
+5birthing
+9hings
+5geneses
+9sis
+9tic
+8ic
+9es
+8ous
+8y
+6ogic
+5id
+7al
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+5logic
+9cal
+9es
+9st
+9sts
+8y
+5ne
+7s
+5paedia
+9ias
+6ompic
+5ses
+6is
+5tee
+8s
+6herapies
+9apist
+9apists
+9apy
+6ic
+8ally
+8s
+7sability
+9ble
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7zability
+9ble
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6oid
+4um
+6s
+3o
+4acid
+8ities
+9ty
+5eolian
+5llergenic
+4baric
+5last
+9ic
+9s
+5ole
+8s
+4calcemia
+9mias
+9mic
+6ust
+9s
+5enter
+9rs
+8ral
+9e
+9es
+5hlorite
+9ites
+9ous
+6ondria
+9riac
+9riacal
+9riacs
+9rias
+9riases
+9riasis
+9riasm
+9riasms
+9riast
+9riasts
+9rium
+5ist
+8s
+5orism
+9ma
+9mas
+9ms
+9tic
+9tical
+6tyl
+9ous
+9s
+5risies
+8y
+7te
+9s
+8ic
+9cal
+9cally
+6ystalline
+5ycloid
+9idal
+9ids
+4derm
+8a
+9l
+9s
+8ic
+9cally
+9cs
+9s
+9ses
+8s
+5iploid
+9idies
+9idy
+5orian
+4ed
+5utectic
+9toid
+4gaea
+8l
+8n
+7ous
+7um
+6stria
+9ic
+9ium
+5ea
+7l
+7n
+6ne
+7ic
+7ous
+6ous
+6um
+5lossal
+9als
+6ycaemia
+9emias
+9emic
+8emia
+9mias
+9mic
+9mics
+5nathism
+9isms
+9ous
+5ynies
+7ous
+7y
+4id
+5ng
+4kalemia
+9ias
+9ic
+4limnia
+9on
+9ons
+5ydian
+4magnesaemia
+9semia
+9semias
+6nia
+9s
+8c
+9s
+5enorrhea
+9rheas
+9rhoea
+9rhoeas
+5ixolydian
+5orph
+9ic
+9s
+4nastic
+9cally
+9es
+8y
+6traemia
+9emias
+5ea
+7s
+5itrite
+9tes
+8ous
+5oia
+8s
+5ym
+7ies
+7s
+7y
+4pharynges
+9nx
+9nxes
+6osphate
+9hates
+9hite
+9hites
+9horic
+9horous
+6rygian
+6yge
+9s
+7seal
+9ctomy
+9s
+8ial
+9s
+5ituitarism
+9tary
+5lasia
+9as
+8tic
+9ies
+9ra
+9ron
+9y
+6oid
+9ies
+9s
+9y
+5nea
+8s
+7ic
+6oea
+9s
+5yon
+8s
+4s
+5ensitise
+9tised
+9tises
+9tising
+9tize
+9tized
+9tizes
+9tizing
+5padias
+9ases
+5tases
+8is
+9sation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+7tic
+9cal
+9cally
+9sation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+6henia
+9ias
+9ic
+6ome
+9s
+6ress
+9ses
+7ophe
+9hes
+6yle
+9s
+5ulphate
+9ates
+9ite
+9ites
+9uric
+9urous
+4tactic
+6xes
+7is
+5ension
+9ons
+9ve
+9ves
+7use
+9es
+5halami
+9mic
+9mus
+6ec
+8a
+9e
+9ry
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+8s
+7nuse
+9ses
+7rmal
+9ia
+9ias
+9ic
+7ses
+8is
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+7tic
+9cal
+9cally
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+6ymia
+9as
+7roid
+9idism
+9idisms
+9ids
+5onia
+9s
+8c
+9ities
+9ity
+5rochoid
+9oids
+5yposes
+9is
+4ventilation
+4xaemia
+9as
+9c
+6nthine
+9ines
+5emia
+9s
+8c
+5ia
+7s
+6c
+3ped
+4ing
+3s
+4ochrome
+9mes
+9mic
+5graphic
+9hical
+9hies
+9hy
+5meter
+9rs
+8ric
+9ical
+9ically
+9ies
+9ist
+9ists
+9y
+5phobe
+9es
+9ia
+9ias
+7yll
+9lary
+9ls
+3ural
+2races
+5oid
+8ean
+9ans
+8s
+4x
+5es
+2son
+5s
+3sop
+6s
+3teranthous
+6ectomies
+9omise
+9omised
+9omises
+9omize
+9omized
+9omizes
+9omy
+7ses
+8ial
+9s
+7tic
+9cally
+6ia
+8s
+7c
+8al
+9lly
+8ky
+8s
+7tis
+9ses
+6ogenic
+9nies
+9ny
+7id
+9al
+7mania
+9nias
+7tomies
+9my
+4ricomorph
+9orphic
+9orphs
+2te
+3he
+5s
+0iamb
+4i
+5c
+6ally
+6s
+5st
+7s
+4ographer
+9hers
+4s
+4us
+6es
+2nthine
+2tric
+6al
+4ochemical
+9ist
+9istry
+9ists
+5genic
+9cally
+9cities
+9city
+9es
+8y
+1badah
+5t
+2eris
+6es
+3x
+4es
+2ices
+3dem
+3s
+4es
+2ogaine
+8s
+2rik
+5s
+2uprofen
+9s
+1ce
+3ball
+7s
+4erg
+7s
+4link
+8s
+4oat
+7er
+9s
+7ing
+9gs
+7s
+5und
+5x
+6es
+4reaker
+9rs
+8ing
+3cap
+6ped
+6s
+3d
+3fall
+7s
+4ield
+8s
+3house
+8s
+3khana
+8s
+3less
+4ike
+3maker
+8s
+5n
+4en
+3pack
+7s
+3r
+4s
+3s
+4tone
+8s
+3wine
+7s
+2h
+3abod
+3ed
+4s
+3ing
+3neumon
+9s
+4ite
+7s
+4ofossil
+9ils
+5graphic
+9hical
+9hies
+9hy
+5lite
+9s
+6ogical
+9es
+8y
+3or
+5ous
+5s
+3s
+3thic
+5yic
+6ocolla
+9llas
+7dorulite
+9rylite
+7fauna
+9unae
+9unal
+9unas
+7id
+9al
+9s
+7latries
+9trous
+9try
+8ite
+9tes
+9tic
+8ogic
+9gical
+9gies
+9gist
+9gists
+9gy
+7phagies
+9agist
+9agists
+9agous
+9agy
+8sid
+9idan
+9idans
+9ids
+7rnis
+9ises
+7saur
+9uri
+9urian
+9urians
+9urs
+9urus
+9uruses
+8es
+8is
+7tic
+6s
+7es
+2icle
+6d
+6s
+3er
+4st
+3ly
+3ness
+7es
+4g
+5s
+2k
+3er
+5s
+3ier
+5st
+4ly
+4ness
+8es
+3le
+5r
+5st
+3y
+2on
+4es
+4ic
+6al
+8ly
+6ities
+8y
+5fied
+8s
+6y
+7ing
+5se
+7d
+7s
+6ing
+5ze
+7d
+7s
+6ing
+4oclasm
+9ms
+9t
+9tic
+9ts
+5grapher
+9hers
+9hic
+9hical
+9hies
+9hy
+5later
+9rs
+8ries
+9ous
+9y
+6ogical
+9es
+9st
+9sts
+8y
+5machies
+9ist
+9ists
+9y
+7tic
+9cism
+9cisms
+6eter
+9rs
+8ries
+9y
+5philism
+9isms
+9ist
+9ists
+5scope
+9es
+6tas
+9es
+9is
+4s
+3sahedra
+9al
+9on
+9ons
+5ndrian
+8ous
+4itetrahedra
+2tal
+3eric
+7al
+9s
+7s
+6d
+7s
+6ne
+6tious
+5us
+7es
+3ic
+3us
+5es
+2y
+1d
+2ant
+5s
+2e
+3a
+4ed
+4l
+5ess
+5isation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+9cally
+8s
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5less
+6y
+5ness
+9es
+5ogies
+7ue
+9s
+7y
+5s
+4s
+4ta
+5e
+6d
+6s
+5ing
+6on
+8al
+9lly
+8s
+6ve
+5um
+3e
+4s
+3m
+4potencies
+9cy
+9t
+9ts
+3nt
+5ic
+7al
+9ly
+9ness
+9nesses
+6fiable
+9bly
+8cation
+9ations
+8ed
+9r
+9rs
+9s
+7y
+8ing
+6kit
+9s
+6ties
+7y
+5s
+3ogram
+8ic
+8matic
+9ic
+8s
+7ph
+9ic
+9ical
+9ically
+9ies
+9s
+9y
+4logic
+9al
+9ally
+8es
+8se
+9ed
+9es
+9ing
+9t
+9ts
+8ze
+9ed
+9es
+9ing
+7ue
+9s
+7y
+4motor
+4phone
+9s
+5olis
+9es
+5raxist
+9sts
+3s
+2ioblast
+9ic
+9s
+4cies
+5y
+4glossia
+9ias
+5ram
+8s
+7ph
+9ic
+9s
+4lect
+8al
+8ic
+8s
+4m
+5atic
+9al
+9ally
+9alness
+9ness
+9nesses
+5orphic
+9ically
+9ism
+9isms
+5s
+4pathic
+9cally
+9es
+8y
+5hone
+9s
+8ic
+5lasm
+9atic
+9ic
+9s
+4rhythmic
+5rhythmic
+4syncrasies
+9asy
+9atic
+9atical
+4t
+5cies
+6y
+5hermous
+5ic
+7al
+9ly
+9ness
+9nesses
+7on
+9s
+6sh
+7m
+8s
+5s
+5ype
+8s
+7ic
+2le
+4d
+4hood
+8s
+4ness
+8es
+4r
+5s
+4s
+5se
+7s
+5t
+3ing
+3y
+2ocrase
+8s
+3l
+4a
+5ter
+8s
+6or
+8s
+6ress
+9ses
+7ies
+8se
+9ed
+9er
+9ers
+9es
+9ing
+8ze
+9ed
+9er
+9ers
+9es
+9ing
+7ous
+9sly
+9sness
+7y
+4isation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+6m
+7s
+6t
+7s
+5zation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+4oclast
+9ts
+5n
+4s
+4um
+3neities
+7y
+5ous
+3xuridine
+9nes
+2s
+2yl
+4ist
+7s
+4l
+5ian
+6c
+7ally
+6st
+8s
+5s
+4s
+1f
+2f
+3ier
+5st
+4ness
+8es
+3y
+2s
+2tar
+5s
+1gad
+3po
+5s
+3rape
+7s
+2g
+3ed
+3ing
+3s
+2loo
+5s
+3u
+4s
+2naro
+6es
+6s
+4tia
+7s
+3eous
+4scent
+9s
+3ified
+7s
+5y
+6ing
+4mbrite
+9es
+4potent
+4tabilities
+9ity
+7le
+5e
+6d
+6r
+7s
+6s
+5ibilities
+9ity
+7le
+6ng
+6on
+8s
+5or
+7s
+5ron
+8s
+3obilities
+9y
+5le
+7ness
+9sses
+7r
+7st
+6y
+4mies
+6nies
+8ous
+9usly
+9usness
+7y
+5y
+4rable
+6mi
+7us
+9es
+6nce
+9s
+7t
+8ly
+8ness
+9esses
+8s
+6tion
+9ns
+5e
+6d
+6r
+7s
+6s
+5ing
+2uana
+6s
+5ian
+8s
+6d
+7s
+5odon
+9s
+1hram
+5s
+1jtihad
+7s
+1kan
+4s
+3t
+4s
+2ebana
+7s
+2on
+4s
+1lea
+4c
+4l
+3itides
+6s
+7es
+3ostomies
+8y
+3um
+4s
+5es
+3x
+4es
+2ia
+4c
+5us
+7es
+4d
+5s
+4l
+3ces
+3um
+2k
+3a
+4day
+7s
+3s
+2l
+3apse
+7d
+7s
+6ing
+4queable
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+4tion
+8s
+6ve
+8ly
+8s
+4udable
+9y
+4warra
+9s
+3egal
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7s
+5ibilities
+9ity
+7le
+9ness
+9nesses
+8y
+6timacies
+9acy
+9ate
+9ated
+9ately
+9ates
+9ating
+9ation
+9ations
+4r
+4st
+3iad
+6s
+4beral
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+9ly
+9ness
+9nesses
+4cit
+7ly
+7ness
+9sses
+4mitability
+9le
+9leness
+9ly
+8tion
+9ions
+7ed
+4nium
+8s
+4pe
+6s
+4quation
+9ons
+6id
+8ities
+9ty
+4sion
+8s
+4te
+6racies
+9y
+8te
+9ely
+9eness
+9es
+6s
+5ic
+3ness
+7es
+3ocution
+9nary
+9ns
+4gic
+7al
+9ities
+9ity
+9ly
+9ness
+9nesses
+7s
+3s
+3th
+5s
+3ude
+6d
+6s
+5ing
+4me
+6d
+6s
+5inable
+8nce
+9ces
+9t
+9ts
+8te
+9ed
+9es
+9i
+9ing
+9ingly
+9ion
+9ional
+9ions
+9ive
+9o
+9or
+9ors
+7e
+8d
+8r
+9s
+8s
+7g
+7ing
+8sm
+9ms
+9t
+9ts
+4pi
+6s
+4sion
+8al
+9ry
+8ed
+8ism
+9sms
+9st
+9stic
+9sts
+8s
+6ve
+8ly
+8ness
+9esses
+5orily
+8ness
+9esses
+7y
+5tratable
+9e
+9ed
+9eds
+9es
+9ing
+9ion
+9ional
+9ions
+9ive
+9ively
+9or
+9ors
+9ory
+7ious
+9usly
+9usness
+8ssimo
+4via
+7l
+7te
+9d
+9s
+8ing
+9on
+9ons
+6um
+8s
+3y
+2menite
+8s
+1mage
+5able
+5d
+5less
+5r
+6ies
+6s
+6y
+5s
+4inable
+9eness
+9y
+7l
+7ries
+9ly
+9ness
+9nesses
+8y
+7tion
+9onal
+9ons
+9ve
+9vely
+9veness
+6e
+7d
+7er
+9ed
+9ing
+9s
+7r
+8s
+7s
+6g
+7s
+6ing
+9s
+7st
+9s
+5sm
+7s
+6t
+7ic
+9ally
+7s
+4o
+5es
+5s
+3m
+4ate
+7s
+4s
+3ret
+6s
+4i
+5s
+3um
+5s
+2balance
+9d
+9s
+5m
+6ed
+7r
+8s
+6ing
+6s
+4r
+5k
+6ed
+6ing
+6s
+5red
+6ing
+5s
+4se
+6d
+6s
+5ing
+4the
+7d
+7s
+6ing
+3ecile
+8ly
+8s
+7ic
+9ally
+8ties
+9y
+4d
+5ded
+6ing
+5s
+3ibe
+6d
+6r
+7s
+6s
+5ing
+6tion
+9nal
+9ns
+4tter
+8ed
+8ing
+8s
+4zo
+6s
+3laze
+7d
+7s
+6ing
+3odied
+7s
+5y
+6ing
+4lden
+8ed
+8ing
+8s
+4rder
+8ed
+8ing
+8s
+4sk
+6ed
+6ing
+6s
+5om
+7ed
+7ing
+7s
+5s
+6ed
+7s
+6ing
+4wer
+7ed
+7ing
+7s
+3rangle
+9d
+9s
+8ing
+5st
+4ex
+4icate
+9d
+9ly
+9s
+8ing
+9on
+9ons
+6es
+4occata
+9as
+5glio
+9s
+5wn
+7ed
+7ing
+7s
+4ue
+6d
+6ment
+9ts
+6s
+5ing
+5te
+7d
+7s
+6ing
+3ue
+5d
+5ment
+9s
+5s
+4ing
+4rse
+7d
+7s
+6ing
+2id
+4azole
+9s
+4e
+5s
+4ic
+4o
+4s
+3nazole
+9s
+4e
+5s
+4o
+5urea
+9s
+3pramine
+9es
+3tabilities
+9ty
+6le
+8ness
+9esses
+5ncies
+7y
+6t
+7s
+5te
+7d
+7s
+6ing
+7on
+9al
+9s
+7ve
+9ly
+9ness
+9nesses
+6or
+8s
+2maculacies
+9y
+8te
+9ely
+9eness
+4nacle
+9d
+9s
+8ing
+6tion
+9ns
+5e
+6ly
+6nce
+9s
+8ies
+8y
+7t
+8al
+8ism
+9sms
+9st
+9stic
+9sts
+8ly
+5ities
+7y
+5tle
+8d
+8s
+7ing
+4rcescible
+5ginate
+4sk
+6ed
+6ing
+6s
+4terial
+9lise
+9lised
+9lises
+9lising
+9lism
+9lisms
+9list
+9lists
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9lness
+5ure
+8ly
+8ness
+9esses
+8s
+7ities
+9y
+3easurability
+9ble
+9bly
+8ed
+4diacies
+8y
+7te
+9ly
+9ness
+9nesses
+8ism
+9sms
+6cable
+9leness
+9ly
+4morial
+9lly
+4nse
+7ly
+7ness
+9sses
+7r
+7st
+6ities
+8y
+6urability
+9ble
+4rge
+7d
+7nce
+9es
+7s
+6ing
+5itous
+5se
+7d
+7r
+8s
+7s
+6ible
+7ng
+7on
+9ism
+9isms
+9ist
+9ists
+9s
+7ve
+4sh
+6ed
+7s
+6ing
+4thodical
+9cally
+4w
+5ed
+5ing
+5s
+3ies
+4grant
+9s
+7te
+9d
+9s
+8ing
+9on
+9onal
+9ons
+8or
+9rs
+9ry
+4nence
+9s
+8ies
+8y
+7t
+8ly
+8ness
+9esses
+5gle
+8d
+8s
+7ing
+5ute
+7ion
+9ns
+4scibilities
+9lity
+8le
+9y
+5eration
+9ions
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5sion
+9s
+4t
+5igability
+9le
+9ly
+5s
+5tance
+9es
+6ed
+6ing
+4x
+5ed
+6s
+5ing
+5ture
+9s
+3obile
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+4deracies
+9y
+8te
+9ely
+9eness
+9ion
+9ions
+6st
+8ies
+8ly
+8y
+4late
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+4ment
+8ous
+4ral
+7ism
+9ms
+9t
+9ts
+8ties
+9y
+7ly
+5tal
+8isation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9ties
+9ty
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8ly
+8s
+6elle
+9es
+4tile
+7ities
+9y
+4vabilities
+9ity
+7le
+9ness
+9nesses
+9s
+8y
+5eabilities
+9lity
+8le
+9eness
+9es
+9y
+3une
+6s
+5ifacient
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5oassay
+9ayable
+9ayist
+9ayists
+9ays
+6blot
+9ts
+9tting
+9ttings
+6chemical
+9mist
+9mistry
+9mists
+7ompetent
+9plex
+9plexes
+6deficient
+7iagnoses
+9gnosis
+8ffusion
+6gen
+9eses
+9esis
+9etic
+9etical
+9etics
+9ic
+9ically
+9icity
+9s
+7lobulin
+9bulins
+6logic
+9ical
+9ically
+9ies
+9ist
+9ists
+9y
+6modulator
+6pathology
+7horeses
+9resis
+6reaction
+9ctions
+9ctive
+6sorbent
+9bents
+7uppress
+6therapies
+9rapy
+7oxic
+9in
+9ins
+4re
+6d
+6ment
+9ts
+6s
+5ing
+4tabilities
+9ity
+7le
+9ness
+9nesses
+8y
+3y
+2p
+3acable
+5t
+6ed
+7r
+8s
+6ful
+6ing
+7on
+9s
+7te
+9s
+7ve
+6or
+8s
+6s
+4int
+7ed
+7ing
+7s
+5r
+6able
+6ed
+7r
+8s
+6ing
+9s
+6ment
+9ts
+6s
+4la
+6s
+5e
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+5pabilities
+9lity
+8le
+9y
+5udism
+9ms
+4nate
+7ion
+9ns
+5el
+7ed
+7ing
+7led
+8ing
+7ment
+9nts
+7s
+5nel
+8led
+9ing
+8s
+4radise
+9ed
+9es
+9ing
+5idigitate
+6pinnate
+6syllabic
+6ties
+7y
+5k
+6ation
+9ons
+6ed
+6ing
+6s
+5l
+6ance
+9es
+6ed
+6ing
+6s
+5t
+6able
+7tion
+9ons
+6ed
+7r
+8s
+6ial
+9ities
+9ity
+9ly
+9ness
+9nesses
+7bilities
+9lity
+8le
+9y
+7ng
+6ment
+9ts
+6s
+4ssabilities
+9lity
+8le
+9eness
+9y
+6e
+7s
+6ibilities
+9lity
+8le
+9eness
+9y
+7on
+9ate
+9ed
+9edly
+9edness
+9ing
+9s
+7ve
+9ly
+9ness
+9nesses
+8ities
+9ty
+5tation
+9ons
+6e
+7d
+7s
+6ing
+6o
+7ed
+7s
+4tience
+9es
+8s
+8t
+9ly
+4ve
+6d
+6s
+5id
+7ly
+6ng
+4wn
+6ed
+6ing
+6s
+3each
+7ability
+9le
+7ed
+8r
+9s
+8s
+7ing
+7ment
+9nts
+5rl
+7ed
+7ing
+7s
+4ccabilities
+9lity
+8le
+9y
+7ncies
+9y
+8t
+5uniosities
+9sity
+9us
+9usly
+9usness
+4d
+5ance
+9s
+5e
+6d
+6r
+7s
+6s
+5iment
+9ta
+9tal
+9tary
+9ts
+6ng
+8ly
+6tive
+5or
+7s
+4l
+5led
+7nt
+9s
+7r
+8s
+6ing
+6or
+8s
+5s
+4nd
+6ed
+7nce
+9es
+9ies
+9y
+8t
+6ing
+6s
+5etrability
+9ble
+9bly
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+5itence
+9ces
+9cies
+9cy
+9t
+9tly
+9tness
+9ts
+5nate
+4ratival
+9e
+9ely
+9eness
+9es
+7or
+9ial
+9ially
+9s
+9ship
+9ships
+5ceable
+7ivable
+7ptible
+9ibly
+9ion
+9ions
+9ive
+9ively
+9ivity
+6ipience
+9ences
+9ent
+9ently
+5fect
+9ible
+9ion
+9ions
+9ive
+9ively
+9ives
+9ly
+9ness
+9nesses
+9s
+6orable
+9te
+9ted
+9tion
+9tions
+5ia
+7l
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9stic
+9sts
+9ties
+9ty
+9ze
+9zed
+9zes
+9zing
+8ly
+8ness
+9esses
+8s
+6l
+7ed
+7ing
+7led
+8ing
+7ment
+9nts
+7s
+6ous
+9ly
+9ness
+9nesses
+6shability
+9ble
+9bles
+9bly
+6um
+8s
+5manence
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+6eability
+9le
+9leness
+9ly
+6issible
+9ibly
+5scriptible
+6everant
+6istent
+6onal
+9lise
+9lised
+9lises
+9lising
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+5tinence
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+6urbable
+9ably
+9ation
+9ations
+5viability
+9le
+9leness
+7ous
+9sly
+9sness
+4ticos
+9sed
+9ses
+9sing
+6gines
+9ous
+7o
+8s
+5rate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+5uosities
+9ty
+7us
+9ly
+9ness
+9nesses
+6s
+7es
+3hee
+6s
+3i
+4ctured
+4erceable
+5s
+5ties
+6y
+4gnorate
+9ted
+9tes
+9ting
+9tion
+9tions
+4ng
+6e
+7d
+7ment
+9nts
+7nt
+7r
+8s
+7s
+6ing
+6s
+4ous
+7ly
+7ness
+9sses
+4s
+5h
+6ly
+6ness
+9ses
+3lacabilities
+9lity
+8le
+9eness
+9y
+6ental
+5nt
+7able
+8tion
+9ions
+7ed
+8r
+9s
+7ing
+7s
+5te
+7d
+7s
+6ing
+5usibility
+9le
+9leness
+9ly
+4each
+8ed
+9s
+8ing
+6d
+7able
+7ed
+8r
+9s
+7ing
+7s
+5d
+6ge
+8d
+8s
+7ing
+5ment
+9al
+9ation
+9ations
+9ed
+9er
+9ers
+9ing
+9or
+9ors
+9s
+5te
+7d
+7s
+6ing
+7on
+9s
+5x
+6es
+6ion
+9s
+6uous
+4icate
+9d
+9s
+8ing
+9on
+9onal
+9ons
+9ve
+9vely
+9veness
+8ure
+9res
+6it
+8ies
+8ly
+8ness
+9esses
+8y
+5ed
+7ly
+6s
+4ode
+7d
+7nt
+9s
+7s
+6ing
+5ration
+9ons
+8or
+9rs
+9ry
+6e
+7d
+7r
+8s
+7s
+6ing
+9ly
+5sion
+9s
+7ve
+9ly
+9s
+4unge
+8d
+8s
+7ing
+5via
+7um
+4y
+5ing
+3ocket
+8ed
+8ing
+8s
+4lder
+8ed
+8ing
+8s
+5icies
+7y
+6te
+8ly
+8ness
+9esses
+8r
+8st
+7ic
+9al
+9ally
+9ly
+9ness
+9nesses
+4nderabilia
+9bility
+9ble
+9bles
+9bly
+8ous
+5e
+6d
+6nt
+8s
+6s
+5ing
+4rous
+5t
+6abilities
+9lity
+8le
+7nce
+9es
+9ies
+9y
+8t
+9ly
+7tion
+9ons
+6ed
+7r
+8s
+6ing
+9s
+6s
+6unacies
+9cy
+9te
+9tely
+9teness
+8e
+9d
+9ly
+9r
+9rs
+9s
+8ing
+9ngs
+9ties
+9ty
+4sable
+5e
+6d
+6r
+7s
+6s
+6x
+7es
+5ing
+8ly
+8ness
+9esses
+6tion
+9ns
+5sibilism
+9lisms
+9list
+9lists
+9lities
+9lity
+8le
+9eness
+9es
+9y
+5t
+6ed
+7r
+8s
+6humate
+9ated
+9ates
+9ating
+9ation
+9ations
+9e
+9ed
+9es
+6ing
+6or
+8ous
+8s
+6rous
+6s
+6umate
+9ted
+9tes
+9ting
+9tion
+9tions
+8e
+9d
+9s
+7re
+9s
+8ous
+4t
+5ence
+9s
+8ies
+8y
+7t
+8ly
+8ness
+9esses
+8s
+5s
+4und
+7able
+8ge
+9es
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+4verish
+9hed
+9her
+9hers
+9hes
+9hing
+9hment
+9hments
+4wer
+7ed
+7ing
+7s
+3racticable
+9ably
+9al
+9ality
+9ally
+9alness
+4ecate
+9d
+9s
+8ing
+9on
+9ons
+8ory
+6ise
+9ly
+9ness
+9nesses
+8ion
+9ons
+5dicative
+5gn
+7ability
+9le
+9leness
+9ly
+8nt
+9ts
+8table
+9e
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7ed
+7ing
+7s
+5sa
+7ri
+9o
+9os
+7s
+6criptible
+9ptibly
+6e
+7s
+6s
+7e
+8d
+8r
+9s
+8s
+7ibility
+9le
+8ng
+8on
+9nable
+9nal
+9nally
+9nism
+9nisms
+9nist
+9nistic
+9nists
+9ns
+8ve
+9ely
+9eness
+7ment
+9nts
+7ure
+9es
+6t
+7s
+4imatur
+9rs
+6is
+5nt
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5son
+8able
+8ed
+9r
+9rs
+8ing
+8ment
+9ents
+8s
+4obabilities
+9lity
+8le
+9eness
+9y
+7tion
+9ons
+6ities
+8y
+5mptu
+9s
+5per
+8ly
+8ness
+9esses
+6riate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+8eties
+9ty
+5v
+6abilities
+9lity
+8le
+9eness
+9y
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+6idence
+9nces
+9nt
+9ntly
+7ng
+9ly
+7sate
+9ted
+9tes
+9ting
+9tion
+9tional
+9tions
+9tor
+9tore
+9tores
+9tori
+9torial
+9tors
+9tory
+9trices
+9trix
+9trixes
+8e
+9d
+9r
+9rs
+9s
+8ing
+8or
+9rs
+6s
+6visatore
+9atores
+9atrice
+4udence
+9es
+8t
+9ly
+3s
+4onite
+9s
+3udence
+9s
+8ies
+8y
+7t
+8ly
+8ness
+9esses
+5icities
+9y
+4gn
+6able
+7tion
+9ons
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4issance
+9ces
+9t
+4lse
+7d
+7s
+6ing
+7on
+9s
+7ve
+9ly
+9ness
+9nesses
+8ities
+9ty
+4ndulu
+9s
+5ities
+7y
+4re
+6ly
+6ness
+9ses
+6r
+6st
+5ities
+7y
+5ple
+8d
+8s
+7ing
+4tabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6tion
+9ns
+8ve
+9ely
+5e
+6d
+6r
+7s
+6s
+5ing
+2shi
+4y
+1n
+2abilities
+8y
+4stinence
+9nces
+3ccessibility
+9ble
+9bly
+5uracies
+9y
+8te
+9ely
+9eness
+4tion
+8s
+6vate
+9ed
+9es
+9ing
+9ion
+9ions
+7e
+8ly
+8ness
+9esses
+7ities
+9y
+3daptable
+8tion
+9ions
+7ive
+4equacies
+9y
+8te
+9ely
+9eness
+9es
+4missibility
+9ble
+9bly
+4vertence
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+5isability
+9le
+9leness
+9ly
+3idable
+3lienability
+9le
+9leness
+9ly
+4terability
+9le
+9leness
+9ly
+3morata
+9s
+8o
+9s
+3ne
+5ly
+5ness
+9es
+5r
+5s
+6t
+4ga
+6s
+4imate
+9ly
+9ness
+9nesses
+8ion
+9ons
+5ties
+7on
+9s
+6y
+3pparent
+9tly
+5easable
+6llable
+6tence
+9ces
+9cies
+9cy
+9t
+5licability
+9ble
+9bly
+5osite
+9ely
+9eness
+5reciable
+9ably
+9ation
+9ations
+9ative
+7hensible
+9nsion
+9nsions
+9nsive
+6oachable
+9hably
+7priate
+9iately
+4t
+5itude
+9es
+5ly
+5ness
+9es
+3rable
+4ch
+6ed
+7s
+6ing
+4guable
+9y
+4m
+5ed
+5ing
+5s
+4ticulacies
+9acy
+9ate
+9ately
+9ates
+9ation
+9ations
+6ficial
+9ially
+6stic
+9cally
+3smuch
+3ttention
+9ons
+9ve
+9vely
+9veness
+3udibilities
+9ity
+7le
+9ness
+9nesses
+8y
+4gural
+9s
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+9ory
+4rate
+4spicious
+9ously
+4thentic
+9icity
+2being
+7s
+4nt
+3oard
+7s
+4rn
+4und
+7ed
+7ing
+7s
+4x
+5es
+3reak
+7s
+6the
+9d
+9s
+8ing
+5d
+6s
+5ed
+7er
+9s
+7ing
+9gs
+7s
+4ing
+7ing
+9gs
+7s
+4ought
+3uilt
+4rning
+5st
+7s
+3y
+4e
+2cage
+6d
+6s
+5ing
+4lculability
+9ble
+9bly
+5escence
+9nces
+9nt
+4ndesce
+9ed
+9ence
+9ences
+9encies
+9ency
+9ent
+9ently
+9ents
+9es
+9ing
+5t
+6ation
+9onal
+9ons
+8or
+9rs
+9ry
+6ed
+6ing
+6s
+4pabilities
+9ity
+7le
+9ness
+9nesses
+9s
+8y
+6cious
+9usness
+8tant
+9ants
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ies
+9y
+5sulate
+9ted
+9tes
+9ting
+9tion
+9tions
+4rcerate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+5dinate
+9ted
+9tes
+9ting
+9tion
+9tions
+5nadine
+9ned
+9nes
+9ning
+7te
+9d
+9s
+8ing
+9on
+9ons
+5villea
+9eas
+4se
+6d
+6ment
+9ts
+6s
+5ing
+4tenation
+9ions
+4ution
+9s
+8us
+9sly
+9sness
+4ve
+6d
+6s
+5i
+6ng
+5o
+3ede
+6d
+6s
+5ing
+8ly
+4ndiaries
+9ism
+9isms
+9y
+7vities
+9ty
+5sation
+9ons
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+6or
+8ies
+8s
+8y
+5t
+6ed
+7r
+8s
+6ing
+7ve
+9ly
+9s
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+6re
+8s
+6s
+4pt
+6ed
+6ing
+7on
+9s
+7ve
+9ly
+9s
+6or
+8s
+6s
+4rtain
+9ties
+9ty
+6itude
+9des
+4ssancies
+9y
+8t
+9ly
+9ness
+9nesses
+3h
+4aritable
+5se
+7d
+7s
+6ing
+4ed
+5r
+6s
+5s
+4ing
+4meal
+4oate
+8d
+8ly
+8ness
+9esses
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+9es
+4pin
+7s
+4worm
+8s
+3idence
+9s
+7t
+8al
+9lly
+9lness
+9ls
+8s
+4nerate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+4pience
+9es
+9ies
+9y
+8t
+9ly
+6t
+7s
+4sal
+5e
+6d
+6s
+5iform
+6ng
+6on
+8s
+6ve
+8ly
+8ness
+9esses
+5or
+7ial
+7s
+7y
+5ural
+7e
+8s
+4table
+6nt
+8s
+6tion
+9ns
+8ve
+9es
+5e
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+4vil
+7ities
+9y
+6sm
+8s
+3lasp
+7ed
+7ing
+7s
+4e
+5mencies
+9y
+8t
+9ly
+9ness
+9nesses
+5s
+4inable
+9eness
+7tion
+9onal
+9ons
+8oria
+9rium
+9ry
+6e
+7d
+7r
+8s
+7s
+6ing
+9s
+6ometer
+9ters
+5p
+6ped
+7ing
+6s
+4osable
+6e
+7d
+7r
+8s
+7s
+6ing
+6ure
+9s
+4udable
+6e
+7d
+8ness
+9esses
+7s
+6ible
+7ng
+5sion
+9s
+7ve
+9ly
+9ness
+9nesses
+8ities
+9ty
+3oagulable
+4ercible
+4g
+5itability
+9le
+8ncies
+9cy
+9t
+8tive
+5nisable
+9nce
+9nces
+9nt
+7ta
+9s
+8o
+9s
+7zable
+9nce
+9nces
+9nt
+5s
+4herence
+9ces
+9cies
+9cy
+9t
+9tly
+9tness
+4mbustible
+9ibles
+9ibly
+5e
+6r
+7s
+6s
+5ing
+8s
+5mensurable
+9urably
+9urate
+6iscible
+6ode
+9d
+9s
+8ing
+9ous
+9ously
+9ties
+9ty
+6unicable
+9cably
+9cado
+9cative
+7tability
+9ble
+9bly
+5pact
+7rability
+9ble
+9bly
+8ed
+7tibility
+9ble
+9bles
+9bly
+6etence
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9nts
+6lete
+9ely
+9eness
+9ion
+9ions
+7iance
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+6osed
+8ite
+8sible
+6rehension
+9ensive
+8ssible
+9sibly
+6utability
+9ble
+9bly
+5unicado
+4nceivable
+9ables
+9ably
+6innities
+9ity
+9ous
+6lusion
+9ions
+9ive
+9ively
+5densable
+9ible
+6ite
+9ly
+5formities
+9ity
+5gruence
+9nces
+9nt
+9ntly
+8ities
+9ty
+8ous
+9usly
+9usness
+5ie
+5nu
+7e
+8s
+7s
+5scient
+9ntly
+8onable
+9us
+6ecutive
+9tively
+7quence
+9ences
+9ent
+9ential
+9ently
+6iderable
+9rably
+9rate
+9rately
+9ration
+7stence
+9ences
+9encies
+9ency
+9ent
+9ently
+6olability
+9ble
+9bly
+7nance
+9nces
+9nt
+9ntly
+6picuous
+9uously
+6tancies
+9cy
+9t
+9tly
+7ruable
+6umable
+9bly
+5testable
+9ably
+6iguous
+9ously
+7nence
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+6rollable
+9lably
+5venience
+9enced
+9ences
+9encies
+9encing
+9ency
+9ent
+9ently
+7rsable
+9ant
+8tible
+9ibly
+6incible
+9ibly
+5y
+4ordinate
+9ation
+9ations
+4ronate
+9ed
+9ion
+9ions
+5porable
+9l
+9ll
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+8eal
+9ality
+9ally
+9ities
+9ity
+6se
+8d
+8s
+7ing
+5rect
+9ly
+9ness
+9nesses
+6igibility
+9ble
+9bles
+9bly
+6odible
+7sible
+6upt
+9ed
+9ible
+9ibles
+9ibly
+9ion
+9ions
+9ive
+9ly
+9ness
+9nesses
+3rassate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+4easable
+7e
+8d
+9ly
+8ful
+8r
+9s
+8s
+7ing
+9gly
+9gs
+6te
+8ly
+5dibilities
+9lity
+8le
+9eness
+9y
+6ulities
+9ty
+8ous
+9usly
+9usness
+5mate
+9d
+9s
+8ing
+9on
+9ons
+6ent
+9al
+9alism
+9alisms
+9alist
+9alists
+9ally
+9als
+9ed
+9ing
+9s
+5scent
+5tion
+9ary
+9s
+6ory
+4iminate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+9tory
+4oss
+7bred
+9eds
+9eed
+9eeding
+9eeds
+7ed
+8s
+7ing
+4ust
+7ant
+9ts
+8tion
+9ions
+7ed
+7ing
+7s
+3ubate
+8d
+8s
+7ing
+8on
+9nal
+9ns
+8ve
+7or
+9s
+9y
+5i
+5ous
+5us
+7es
+4dal
+6te
+5es
+4lcate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+5pabilities
+9lity
+8le
+9eness
+9y
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8ory
+5t
+4mbencies
+9y
+8t
+9ly
+9s
+7r
+8ed
+8ing
+9ngly
+8s
+6rance
+9ces
+4nable
+9s
+7ula
+9ar
+9ist
+9ists
+9um
+4r
+5abilities
+9ity
+7le
+9ness
+9nesses
+9s
+8y
+5iosities
+9ty
+7us
+9ly
+9ness
+9nesses
+5rable
+6ed
+7nce
+9es
+8t
+6ing
+5s
+6ion
+9s
+7ve
+5vate
+9d
+9s
+8ing
+9on
+9ons
+8ure
+9res
+6e
+7d
+7s
+6ing
+7ties
+8y
+4s
+5e
+6d
+6s
+5ing
+4t
+2daba
+6s
+4gate
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+9y
+4min
+7e
+8s
+7s
+4pamide
+9es
+4rt
+6ed
+6ing
+6s
+3ebted
+8ness
+9esses
+4cencies
+8y
+7t
+8er
+9st
+8ly
+5iduate
+8ous
+6pherable
+9rably
+6sion
+9ns
+8ve
+9ely
+9eness
+5linable
+9bly
+5omposable
+6rous
+9sly
+9sness
+7um
+9s
+4ed
+4fatigable
+9ably
+5easibility
+9ble
+9bly
+6ctibility
+9ble
+9bly
+6nsibility
+9ble
+9bly
+5inability
+9le
+9leness
+9les
+9ly
+7ite
+9ely
+9eness
+9es
+4hiscence
+9nces
+9nt
+4libilities
+9ity
+7le
+9ness
+9nesses
+8y
+6cacies
+9y
+8te
+9ely
+9eness
+4mnification
+9ed
+9er
+9ers
+9es
+8y
+9ing
+7ties
+8y
+5onstrable
+9rably
+4ne
+6s
+5t
+6ation
+9ons
+6ed
+7r
+8s
+6ing
+7on
+9s
+6or
+8s
+6s
+6ure
+9d
+9s
+9ship
+9ships
+8ing
+4pendence
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9nts
+4scribable
+9ables
+9ably
+5ignate
+5tructible
+9tibly
+4tectable
+8ible
+6rminable
+9nably
+9nacies
+9nacy
+9nate
+9nately
+9nation
+9ned
+9nism
+9nisms
+9nist
+9nistic
+9nists
+4vout
+4w
+5ed
+5ing
+5s
+4x
+5able
+6l
+6tion
+9ns
+5ed
+6r
+7s
+6s
+5ical
+9s
+6ng
+8s
+5less
+5terities
+9ty
+3ia
+5s
+4can
+7s
+7t
+8s
+6table
+7e
+8d
+8s
+7ing
+8on
+9nal
+9ns
+8ve
+9ely
+9es
+7or
+9s
+9y
+5es
+5ia
+7l
+7s
+6um
+8s
+5olite
+9es
+5t
+6able
+9y
+6ed
+7e
+8s
+7r
+8s
+6ing
+7on
+9al
+9s
+6ment
+9ts
+6or
+8s
+6s
+4e
+5s
+4fference
+9nces
+9ncies
+9ncy
+9nt
+9ntism
+9ntisms
+9ntist
+9ntists
+9ntly
+9nts
+4gen
+7ce
+9s
+8ies
+8y
+7e
+8s
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ous
+9sly
+9sness
+7s
+7t
+8ly
+8s
+6st
+8ed
+8ibility
+9ble
+9bles
+9bly
+9on
+9ons
+9ve
+8s
+5n
+6ance
+9es
+8t
+9ly
+7tion
+9ons
+6ified
+9es
+8y
+9ing
+7ties
+8y
+6ly
+5o
+6es
+6id
+8s
+6lite
+9es
+6s
+6tic
+8n
+9s
+4navir
+9s
+4rect
+8ion
+9ons
+8ly
+8ness
+9esses
+5ubin
+9s
+4scernible
+9ibly
+8ptible
+6iplinable
+9ine
+9ined
+9ines
+6overable
+6reet
+9tly
+9tness
+8te
+9ely
+9eness
+9ion
+9ionary
+9ions
+7iminate
+5pensable
+9ables
+9ably
+6ose
+9d
+9dness
+9s
+8ing
+9tion
+9tions
+6utability
+9ble
+9bly
+5sociable
+9ably
+7lubility
+9ble
+9bly
+8vable
+6uadable
+9ably
+5tinct
+9tion
+9tions
+9tive
+9tively
+9tly
+9tness
+6ributable
+4te
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+4um
+6s
+4vertible
+9bly
+5idable
+7ua
+9l
+9lise
+9lised
+9liser
+9lisers
+9lises
+9lising
+9lism
+9lisms
+9list
+9listic
+9lists
+9lities
+9lity
+9lize
+9lized
+9lizer
+9lizers
+9lizes
+9lizing
+9lly
+9ls
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+8um
+6sibility
+9le
+9leness
+9les
+9ly
+3ocible
+6le
+7ities
+9y
+5trinate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ator
+9ators
+4l
+5e
+6acetic
+6butyric
+6nce
+9s
+8ies
+8y
+7t
+8ly
+6s
+5s
+4methacin
+9cins
+5itability
+9le
+9leness
+9ly
+4or
+6s
+4phenol
+9ls
+4rsable
+6e
+7d
+7e
+8s
+7ment
+9nts
+7r
+8s
+7s
+6ing
+6or
+8s
+4w
+5ed
+5ing
+5s
+4xyl
+7s
+3raft
+7s
+5ught
+9s
+5wn
+4ench
+8ed
+9s
+8ing
+4i
+5s
+6es
+3ubious
+6tability
+9le
+9leness
+9ly
+4ce
+6d
+6ment
+9ts
+6r
+7s
+6s
+5iae
+6bilities
+9ity
+7le
+6ng
+5t
+6ance
+9es
+6ed
+7e
+8s
+6ile
+8ities
+9ty
+7ng
+7on
+9al
+9s
+7ve
+9ly
+9ness
+9nesses
+8ities
+9ty
+6or
+8s
+6s
+4e
+5d
+5s
+4ing
+4lge
+7d
+7nce
+9ed
+9es
+9ies
+9ing
+9y
+8t
+9ly
+7r
+8s
+7s
+6ing
+9ly
+5in
+7e
+8s
+7s
+5t
+6s
+4menta
+8um
+9ms
+4na
+6s
+4plicate
+9ted
+9tion
+9tions
+4rate
+8d
+8s
+7ing
+8on
+9ns
+8ve
+4sia
+7l
+7te
+6um
+5trial
+9lise
+9lised
+9lises
+9lising
+9lism
+9lisms
+9list
+9lists
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9ls
+8es
+8ous
+9usly
+9usness
+7y
+8wide
+4viae
+7l
+7te
+3well
+7er
+9s
+7ing
+9gs
+7s
+6t
+2earth
+7ed
+7ing
+7s
+3briant
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+6eties
+8y
+6ous
+3dibilities
+9ty
+6le
+7y
+5ta
+6ed
+4ucabilities
+9lity
+8le
+3ffabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6ceability
+9ble
+9bly
+5ective
+9vely
+9veness
+8ual
+9ality
+9ally
+9alness
+5icacies
+9ious
+9iously
+9ities
+9ity
+9y
+7iencies
+9ncy
+9nt
+9ntly
+9nts
+3galitarian
+3laborate
+9tely
+5stic
+9ally
+9ities
+9ity
+4egance
+9es
+9ies
+9y
+8t
+9ly
+4igibilities
+9lity
+8le
+9eness
+9es
+9y
+4oquence
+9ces
+9t
+9tly
+4uctability
+9le
+9ly
+5dibilities
+9lity
+8le
+9y
+3narrable
+3pt
+5er
+6st
+5itude
+9es
+5ly
+5ness
+9es
+3quable
+6lities
+9y
+6tion
+9ns
+5ipotent
+6table
+9leness
+9ly
+7ies
+7y
+6valve
+9ved
+3radicability
+9ble
+9bly
+5sable
+9y
+6ible
+9y
+4m
+5ous
+4rabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6ncies
+8y
+7t
+4t
+5er
+6st
+5ia
+7e
+7l
+8ly
+7s
+5ly
+5ness
+9es
+5s
+4udite
+3scapable
+9ly
+5ulent
+6tcheon
+9eons
+4sential
+9ality
+9als
+5ive
+8s
+4timability
+9le
+9leness
+9ly
+3vitabilities
+9lity
+8le
+9eness
+9es
+9y
+3xact
+7itude
+9udes
+7ly
+7ness
+9sses
+4citable
+5usability
+9le
+9leness
+9ly
+4ecrable
+6utable
+8ion
+9ons
+4hausted
+9ible
+9ibly
+9ive
+4istant
+7ence
+9ces
+9cies
+9cy
+9t
+4orabilities
+9lity
+8le
+9eness
+9y
+4pansible
+5ectancies
+9ncy
+9nt
+9tion
+9tions
+6dience
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+6nsive
+9vely
+9veness
+6rience
+9nced
+9nces
+7t
+8ly
+8ness
+9esses
+8s
+5iable
+9eness
+9y
+5lainable
+9ably
+6icability
+9ble
+9bly
+8it
+9tly
+9tness
+5ressible
+9ibles
+9ibly
+9ive
+9ively
+5ugnability
+9ble
+9bly
+6ngible
+4tended
+7sibility
+9ble
+9on
+9ons
+5irpable
+5ricability
+9ble
+9bly
+2fall
+6ibilism
+9lisms
+9list
+9lists
+9lities
+9lity
+8le
+9eness
+9es
+9y
+7ng
+6s
+4me
+6d
+6s
+5ies
+6ng
+6se
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5onise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+6us
+8ly
+8ness
+9esses
+5y
+4ncies
+6y
+5gthief
+9efs
+5t
+6a
+7s
+6e
+7s
+6hood
+9ds
+6icidal
+9de
+9des
+7le
+8isation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+7ne
+6ries
+7y
+8man
+9en
+6s
+4rct
+7ed
+7ion
+9ns
+7s
+5e
+6s
+4tuate
+9d
+9dly
+9s
+8ing
+9on
+9ons
+4una
+7e
+7l
+7s
+5st
+3easibilities
+9lity
+8le
+9eness
+4ct
+6ant
+6ed
+7r
+8s
+6ing
+7on
+9s
+8us
+9sly
+9sness
+7ve
+9ly
+9ness
+9nesses
+8ities
+9ty
+6or
+8s
+6s
+5und
+8ities
+9ty
+4ft
+6ed
+6ing
+6ment
+9ts
+6s
+4licities
+9ous
+9ously
+9y
+5t
+4off
+7ed
+7ing
+7s
+4r
+5able
+8y
+5e
+6nce
+9s
+8ing
+9ngs
+7tial
+9ally
+5iae
+6ble
+6or
+8ities
+9ty
+8ly
+8s
+5nal
+8ities
+9ty
+8ly
+6o
+7s
+5rable
+6ed
+7r
+8s
+6ible
+7ng
+5s
+5tile
+9ly
+8ities
+9ty
+4st
+6ant
+9s
+7tion
+9ons
+6ed
+7r
+8s
+6ing
+6s
+4udation
+9ons
+3ibulate
+9ed
+9es
+9ing
+9ion
+9ions
+4cete
+4del
+7ic
+8ties
+9y
+7s
+4eld
+7er
+9s
+7s
+8man
+9en
+4ght
+7er
+9s
+7ing
+9gs
+7s
+4ll
+6ed
+6ing
+9s
+6s
+5trate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+4ma
+5um
+7s
+4nitant
+8ry
+8te
+9ed
+9es
+9ing
+7e
+8ly
+8ness
+9esses
+8s
+9imal
+9imally
+9imals
+7ies
+8val
+9ally
+9e
+9ely
+9es
+7ude
+9es
+7y
+4rm
+6arer
+9rs
+8ian
+9ans
+9es
+8y
+6ed
+7r
+7st
+6ing
+7ties
+8y
+6ly
+6ness
+9ses
+6s
+4x
+5ation
+9ns
+5ed
+6s
+5ing
+6on
+8s
+3lamable
+6e
+7d
+7r
+8s
+7s
+6ing
+9ly
+6mability
+9le
+9leness
+9les
+9ly
+8tion
+9ions
+9orily
+9ory
+5table
+9es
+6e
+7d
+8ly
+8ness
+9esses
+7r
+8s
+7s
+6ing
+9ly
+7on
+9ary
+9ism
+9isms
+9ist
+9ists
+9s
+7ve
+6or
+8s
+6us
+8es
+4ect
+7able
+7ed
+9ness
+9nesses
+7ing
+8on
+9nal
+9nally
+9nless
+9ns
+8ve
+7or
+9s
+7s
+5xed
+6ibilities
+9lity
+8le
+9eness
+9y
+7on
+9al
+9ally
+9less
+9s
+6ure
+9s
+4ict
+7able
+7ed
+8r
+9s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+7s
+5ght
+4orescence
+9ences
+9ent
+5w
+6ing
+9s
+6s
+4uence
+9able
+9d
+9r
+9rs
+9s
+8ing
+7t
+8ial
+9ally
+9als
+8s
+7za
+9l
+9s
+5x
+6es
+6ion
+9s
+3o
+4bahn
+8s
+4ld
+6ed
+7r
+8s
+6ing
+9s
+6ment
+9ts
+6s
+4mania
+9s
+5ercial
+9als
+4preneurial
+4rce
+7d
+7s
+6ing
+5m
+6able
+7l
+8ities
+9ty
+8ly
+7nt
+9s
+7tician
+9cians
+9cs
+9on
+9onal
+9onally
+9ons
+9ve
+9vely
+9veness
+8orily
+9ry
+6ed
+8ly
+7r
+8s
+6idable
+7ng
+9ly
+6s
+5tune
+9s
+4s
+5phere
+9es
+4tainment
+9ents
+5ech
+8s
+4ught
+3ra
+5costal
+6t
+7ed
+7ing
+8on
+9ns
+7or
+9s
+7s
+5grant
+5human
+9ns
+5lapsarian
+9arians
+5maxillary
+5ngibility
+9le
+9leness
+9ly
+5orbital
+5posed
+8ition
+9tions
+5red
+8s
+5sonic
+7und
+9ds
+6pecific
+6tructural
+9cture
+9ctures
+4equence
+9ces
+9cies
+9cy
+9t
+9tly
+4inge
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+4uctuous
+9usly
+5gal
+3ula
+6e
+4ndibula
+9lar
+9late
+9liform
+9lum
+4riate
+9d
+9ly
+9s
+8ing
+9ngly
+9on
+9ons
+4scate
+9d
+5e
+6d
+6r
+7s
+6s
+5ibilities
+9ity
+7le
+9ness
+9nesses
+6ng
+6on
+8ism
+9sms
+9st
+9sts
+8s
+6ve
+5oria
+9l
+9n
+9ns
+7y
+2g
+3an
+5s
+4te
+6s
+5her
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+3eminate
+9ed
+9es
+9ing
+9ion
+9ions
+4ner
+7ate
+9ed
+9es
+9ing
+9ion
+9ions
+7s
+5ious
+9ly
+9ness
+9nesses
+6um
+8s
+5u
+6e
+7s
+6ities
+8y
+6ous
+9ly
+9ness
+9nesses
+6s
+4st
+6a
+6ed
+6ible
+7ng
+7on
+9s
+7ve
+6s
+3ine
+6s
+3le
+5neuk
+9s
+6ook
+9s
+5s
+4obe
+7d
+7s
+6ing
+5rious
+9sly
+9sness
+4uvial
+7es
+3o
+4es
+4ing
+7s
+4t
+5ed
+5ing
+5s
+3raft
+7ation
+9ions
+7ed
+7ing
+7ment
+9nts
+7s
+5in
+7ed
+9ly
+9ness
+9nesses
+8r
+9s
+7ing
+7s
+5m
+5te
+7ful
+7ly
+7s
+6iate
+9ed
+9es
+9ing
+9ingly
+9ion
+9ions
+9ory
+7tude
+9des
+5vescence
+9ences
+9ent
+4edient
+9ts
+5ss
+7es
+7ion
+9ns
+8ve
+9eness
+9es
+4oove
+8d
+8s
+7ing
+5ss
+7ed
+8s
+7ing
+5und
+6p
+7s
+5wing
+6n
+7ness
+9sses
+6th
+8s
+4um
+3s
+3uinal
+4lf
+6ed
+6ing
+6ment
+9ts
+6s
+5ph
+7ed
+7ing
+7s
+4rgitate
+9ted
+9tes
+9ting
+9tion
+9tions
+2habit
+7ability
+9le
+8nce
+9ces
+9cies
+9cy
+9t
+9ts
+8tion
+9ions
+7ed
+8r
+9s
+7ing
+8veness
+7or
+9s
+7ress
+9sses
+7s
+4lant
+8s
+6tion
+9nal
+9ns
+7or
+9ium
+9iums
+9s
+5e
+6d
+6r
+7s
+6s
+5ing
+4rmonic
+9cal
+9cities
+9city
+9es
+9ous
+9ously
+8y
+4ul
+6er
+8s
+6s
+5st
+7ed
+7ing
+7s
+3earse
+8d
+8s
+7ing
+4rce
+7d
+7s
+6ing
+5e
+6d
+6nce
+9s
+8ies
+8y
+7t
+8ly
+6s
+5ing
+6t
+7ability
+9le
+9leness
+9ly
+8nce
+9ces
+7ed
+7ing
+7or
+9s
+7ress
+9sses
+8ices
+9x
+9xes
+7s
+4sion
+8s
+3ibin
+7s
+6t
+7able
+7ed
+9ly
+8r
+9s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+9y
+7s
+3older
+8s
+6ing
+9s
+4mogeneities
+9eity
+9eous
+4op
+6ed
+6ing
+6s
+4spitable
+9bly
+9lities
+9lity
+3uman
+7e
+8ly
+7ities
+9y
+7ly
+7ness
+9sses
+6te
+8d
+8s
+7ing
+8on
+9ns
+5e
+6d
+6r
+7s
+6s
+5ing
+2ia
+3mical
+8ities
+9ty
+8ly
+8ness
+9esses
+6itious
+5tabilities
+9lity
+8le
+9eness
+9y
+3on
+5s
+3quities
+7ous
+9sly
+9sness
+7y
+3sle
+6d
+6s
+5ing
+3tial
+7ed
+8r
+9s
+7ing
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7led
+9r
+9rs
+8ing
+8y
+7ness
+9sses
+7s
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+9es
+7or
+9ies
+9s
+9y
+7ress
+9sses
+8ices
+9x
+9xes
+2ject
+6able
+9es
+7nt
+9s
+6ed
+6ing
+7on
+9s
+7ve
+6or
+8s
+6s
+4llied
+8s
+6y
+7ing
+4ra
+6s
+3oint
+7ed
+7ing
+7s
+3udicial
+9lly
+8ous
+9usly
+9usness
+4nct
+7ed
+7ing
+8on
+9ns
+8ve
+9ely
+7s
+4rable
+5e
+6d
+6r
+7s
+6s
+5ies
+6ng
+6ous
+9ly
+9ness
+9nesses
+5y
+4stice
+9s
+2k
+3berries
+7y
+4lot
+7s
+3ed
+4r
+5s
+3holder
+9s
+5rn
+7s
+5si
+7s
+3ier
+5st
+4ness
+8es
+5g
+3jet
+3le
+5d
+5s
+6s
+4ike
+5ng
+7s
+3osi
+6s
+3pad
+6s
+4ot
+6s
+3s
+4pot
+7s
+4tand
+8s
+5one
+8s
+3well
+7s
+4ood
+7s
+3y
+2lace
+6d
+6s
+5ing
+4id
+4nd
+6er
+8s
+6s
+4y
+5er
+7s
+5ing
+8s
+5s
+3et
+5s
+5ting
+3ier
+6s
+3ock
+6ed
+6ing
+6s
+3y
+4ing
+2marriage
+9es
+4te
+6s
+3esh
+6ed
+7s
+6ing
+3igrant
+9s
+3ost
+2n
+3age
+6s
+4rds
+4te
+6ly
+6ness
+9ses
+5ive
+4vigable
+9ly
+3ed
+4r
+5ly
+5most
+9s
+5ness
+9es
+5s
+6ole
+9s
+6pring
+5vate
+9d
+9s
+8ing
+9on
+9ons
+6e
+7d
+7s
+6ing
+5wear
+9s
+3ing
+6s
+4t
+3keeper
+9s
+3less
+3ocence
+9s
+8ies
+8y
+7t
+8er
+9st
+8ly
+8s
+5uities
+8y
+6ous
+9ly
+9ness
+9nesses
+4minable
+9les
+8te
+4vate
+8d
+8s
+7ing
+8on
+9nal
+9nist
+9nists
+9ns
+8ve
+9ely
+9eness
+7or
+9s
+9y
+4xious
+9ly
+9ness
+9nesses
+3s
+3uendo
+8ed
+9s
+8ing
+8s
+4merability
+9le
+9leness
+9ly
+8cies
+9y
+8te
+9es
+7ous
+4trient
+7tion
+9ons
+9ous
+3yard
+7s
+2obedience
+9ces
+9t
+9tly
+4servable
+9nce
+9nces
+9nt
+9ntly
+9tion
+9tions
+4trusive
+9vely
+9veness
+3ccupation
+9ions
+4ula
+7bilities
+9lity
+8le
+7nt
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+6um
+8s
+3dorous
+9ly
+9ness
+9nesses
+3ffensive
+9vely
+9veness
+5icious
+9usly
+9usness
+3perabilities
+9lity
+8le
+9eness
+9y
+7tive
+9veness
+6culate
+9ates
+4inate
+4portune
+9nely
+9neness
+9nities
+9nity
+3rb
+5ed
+5ing
+5s
+4dinacies
+9y
+8te
+9ely
+9eness
+9ion
+9ions
+4ganic
+9ally
+8sation
+9ations
+9ed
+8zation
+9ations
+9ed
+4nate
+3sculate
+9ed
+9es
+9ing
+9ion
+9ions
+4ine
+7s
+5te
+7s
+6ol
+8s
+3tropic
+2patient
+9s
+4yment
+9s
+3hase
+3our
+6ed
+6ing
+9s
+6s
+3ut
+5s
+5ted
+7r
+8s
+6ing
+2qilab
+7s
+3uere
+7d
+7s
+6ing
+5st
+7s
+4iet
+7ed
+7ing
+7ly
+7s
+7ude
+9es
+5line
+9s
+8ic
+9cs
+9sm
+9sms
+9ties
+9ty
+8ous
+5nate
+9d
+9s
+8ing
+9on
+9ons
+5ration
+9ons
+6e
+7d
+7ndo
+9os
+7r
+8s
+7s
+6ies
+7ng
+9ly
+6y
+5sition
+9onal
+9onist
+9onists
+9ons
+9ve
+9vely
+9veness
+8or
+9rial
+9rially
+9rs
+8ress
+9esses
+8urient
+4orate
+2ro
+4ad
+6s
+3un
+5s
+4sh
+6es
+6ing
+9s
+2s
+3alivate
+9ed
+9es
+9ing
+9ion
+9ions
+5ubrious
+9ously
+9ties
+9ty
+6tary
+4ne
+6ly
+6ness
+9ses
+6r
+6st
+5ie
+7s
+6tariness
+9y
+8tion
+9ions
+7ies
+7y
+4tiabilities
+9lity
+8le
+9eness
+9y
+7te
+9ly
+9ness
+9nesses
+6eties
+8y
+3cape
+7s
+4ience
+9s
+7t
+4once
+8d
+8s
+7ing
+4ribable
+9leness
+7e
+8d
+8r
+9s
+8s
+7ing
+6ption
+9onal
+9ons
+9ve
+9vely
+5oll
+8ed
+8ing
+8s
+5utability
+9le
+9leness
+9ly
+4ulp
+7ed
+7ing
+7s
+7t
+8ure
+9red
+9res
+9ring
+3eam
+6ed
+6ing
+6s
+4ct
+6an
+7ries
+9um
+9ums
+8y
+6ean
+6icidal
+9dally
+9de
+9des
+7form
+8uge
+9ges
+7le
+7on
+9s
+7vore
+9res
+9rous
+6ologies
+9gist
+9gists
+9gy
+6s
+5ure
+8ly
+8ness
+9esses
+7ities
+9y
+4em
+6ed
+6ing
+6s
+4lberg
+9e
+9s
+4minate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+4nsate
+9ly
+9ness
+9nesses
+6ibilities
+9lity
+8le
+9eness
+9y
+7tive
+9vely
+9veness
+9vities
+9vity
+6uous
+5tience
+9ces
+9cies
+9cy
+9t
+4parability
+9le
+9leness
+9les
+9ly
+8te
+4rt
+6able
+6ed
+7r
+8s
+6ing
+7on
+9al
+9s
+6s
+4ssorial
+4t
+5s
+5ted
+7r
+8s
+6ing
+4verable
+3hallah
+4eath
+8e
+9d
+9s
+8ing
+8s
+5ll
+7ed
+7ing
+7s
+6ter
+9ed
+9ing
+9s
+4ip
+6ped
+7ing
+6s
+4ore
+4rine
+8d
+8s
+7ing
+3ide
+6r
+7s
+6s
+5ious
+9ly
+9ness
+9nesses
+4ght
+7ful
+9lly
+7s
+5ne
+6ia
+8s
+7ficance
+9cances
+9cancy
+9cant
+9cantly
+9cative
+4ncere
+9ly
+8ities
+9ty
+5ew
+7ed
+7ing
+7s
+5uate
+9d
+9s
+8ing
+9ngly
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+4pid
+7ities
+9y
+7ly
+7ness
+9sses
+6ence
+9es
+8t
+9ly
+4st
+6ed
+7nce
+9es
+9ies
+9y
+8t
+9ly
+7r
+8s
+6ing
+9ly
+6s
+3nare
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+3obrieties
+9y
+4ciabilities
+9lity
+8le
+9y
+4far
+4late
+8d
+8s
+7ing
+8on
+9ns
+5e
+6nce
+9s
+7t
+8ly
+8s
+6s
+5idities
+9y
+5ubilise
+9ised
+9ises
+9ising
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+7le
+9ness
+9nesses
+9s
+8y
+5vabilities
+9lity
+8le
+9y
+6encies
+9y
+8t
+9s
+4mnia
+8c
+9s
+8s
+7ous
+6olence
+9nces
+5uch
+4oth
+4uciance
+9ces
+9t
+9tly
+5l
+6ed
+6ing
+6ment
+9ts
+6s
+5rce
+8d
+8s
+7ing
+9gs
+3pan
+6ned
+7ing
+6s
+4ect
+7able
+7ed
+7ing
+9gly
+8on
+9nal
+9ns
+8ve
+7or
+9al
+9ate
+9ates
+9ial
+9s
+9ship
+9ships
+7s
+4here
+8d
+8s
+7ing
+4irable
+7tion
+9onal
+9onally
+9onism
+9onisms
+9onist
+9onists
+9ons
+9ve
+8or
+9rs
+9ry
+6e
+7d
+7r
+8s
+7s
+6ing
+9ly
+7t
+8ed
+9r
+9rs
+8ing
+9ngly
+8ment
+9ents
+8s
+5ssate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+3tabilities
+9ty
+6le
+5l
+6l
+7ant
+9ts
+8tion
+9ions
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+6ment
+9ts
+6s
+5nce
+8d
+8s
+7ies
+8ng
+7y
+6t
+7aneities
+9eity
+9eous
+9eously
+7er
+7ial
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+7ly
+7ness
+9sses
+7s
+5r
+6red
+7ing
+6s
+5te
+7d
+7ment
+9nts
+7s
+6ing
+5uration
+9ions
+9or
+9ors
+4ead
+5p
+6s
+4igate
+9d
+9s
+8ing
+9ngly
+9on
+9ons
+9ve
+8or
+9rs
+5l
+6l
+7ation
+9ions
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+6ment
+9ts
+6s
+5nct
+8ive
+9vely
+9vities
+9vity
+8s
+8ual
+9ally
+5torial
+6ute
+9d
+9r
+9rs
+9s
+8ing
+9on
+9onal
+9onally
+9onary
+9ons
+9st
+9sts
+9ve
+9vely
+8or
+9rs
+4reaming
+9ngs
+6ss
+8ed
+9s
+8ing
+5oke
+8s
+5uct
+8ed
+8ible
+9ng
+9on
+9onal
+9ons
+9ve
+9vely
+9veness
+8or
+9rs
+9rship
+9rships
+8ress
+9esses
+8s
+6ment
+9tal
+9talism
+9talist
+9tality
+9tally
+9tals
+9tation
+9ted
+9ting
+9ts
+3ubjection
+9ions
+5ordinate
+9nately
+9nates
+9nation
+5stantial
+9tially
+4cken
+4fferable
+9bly
+6icience
+9ences
+9encies
+9ency
+9ent
+9ently
+6late
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+4la
+6e
+6nt
+8s
+6r
+7ism
+9ms
+8ties
+9y
+7ly
+7s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5in
+7ase
+9es
+7s
+5se
+6ities
+8y
+5t
+6able
+7nt
+6ed
+7r
+8s
+6ing
+9ly
+6ment
+9ts
+6s
+4perability
+9le
+9leness
+9ly
+5portable
+9ably
+6ressible
+9sibly
+4rabilities
+9ity
+7le
+6nce
+9r
+9rs
+9s
+7t
+8s
+5e
+6d
+7s
+6r
+7s
+6s
+5gence
+9es
+9ies
+9y
+8t
+9ly
+9s
+5ing
+5mountable
+9tably
+5rection
+9ional
+9ionary
+9ionism
+9ionist
+9ions
+4sceptible
+9ibly
+9ive
+9ively
+3wathe
+8d
+8s
+7ing
+4ept
+4ing
+7er
+9s
+7s
+2tact
+6ly
+6ness
+9ses
+4gli
+7ated
+7o
+8ed
+8ing
+8s
+4ke
+6s
+4ngibilities
+9lity
+8le
+9eness
+9es
+9y
+4rsia
+8s
+3eger
+7s
+5rabilities
+9lity
+8le
+7l
+8ities
+9ty
+8ly
+8s
+7nd
+9s
+8t
+9s
+7te
+9d
+9s
+8ing
+9on
+9onist
+9onists
+9ons
+9ve
+8or
+9rs
+6in
+8s
+7ties
+8y
+5ument
+9tal
+9tary
+9ts
+4l
+5lect
+9ed
+9ion
+9ions
+9ive
+9ively
+9s
+9ual
+9ualise
+9ualism
+9ualist
+9uality
+9ualize
+9ually
+9uals
+6igence
+9ncer
+9ncers
+9nces
+9nt
+9ntial
+9ntly
+9ntsia
+9ntsias
+9ntzia
+9ntzias
+8ibility
+9ble
+9bly
+5s
+4merate
+9ely
+9eness
+5perance
+9nces
+9nt
+9nts
+9te
+9tely
+9teness
+7stive
+9ively
+9ivity
+4nable
+5d
+6ance
+9es
+9ies
+9y
+8t
+9s
+6ed
+8ly
+8s
+7r
+8ed
+8ing
+8s
+6ing
+6ment
+9ts
+6s
+5erate
+9ed
+9es
+9ing
+9ion
+9ions
+5ible
+5sate
+9d
+9s
+8ing
+9ve
+9ves
+6e
+7ly
+7ness
+9sses
+7r
+7st
+6ification
+9ed
+9er
+9ers
+9es
+8y
+9ing
+7on
+9al
+9ality
+9ally
+9s
+7ties
+9ve
+9ves
+8y
+7ve
+9ly
+9ness
+9nesses
+9s
+5t
+6ion
+9al
+9ality
+9ally
+9ed
+9s
+7ve
+6ly
+6ness
+9ses
+6s
+4r
+5abang
+9gs
+6ct
+8ant
+9nts
+8ed
+8ing
+9on
+9onal
+9onism
+9onisms
+9onist
+9onists
+9ons
+9ve
+9vely
+9vities
+9vity
+8s
+6ge
+8ncy
+6llelic
+8ied
+6mbulacra
+9lacral
+9lacrum
+6nimation
+9ations
+7nual
+6rch
+9ed
+9es
+9ing
+6tomic
+5bank
+7sin
+6ed
+8ded
+9ing
+9ings
+8s
+7havior
+9vioral
+9viors
+6orough
+9ughs
+6rain
+9ns
+8nch
+7ed
+8ed
+9ding
+9dings
+9ds
+7oker
+5calar
+9rily
+9ry
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+7mpus
+7ste
+6ede
+9d
+9nt
+9r
+9rs
+9s
+8ing
+7ll
+9ular
+7nsal
+7pt
+9ed
+9er
+9ers
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+9s
+7ssion
+9ional
+9ions
+9or
+9orial
+9ors
+9ory
+6hain
+9ned
+9ning
+9ns
+8nge
+9geable
+9geably
+9ged
+9gement
+9ger
+9gers
+9ges
+9ging
+9nel
+8pter
+9ters
+7urch
+6ipient
+9ents
+7ty
+6lan
+8ss
+8vicle
+9icles
+9icular
+7ub
+8de
+9ed
+9es
+9ing
+8sion
+9ions
+9ter
+6oastal
+7llegiate
+9ine
+8onial
+9nially
+8umnar
+7m
+8munal
+9une
+9uned
+9unes
+9uning
+9union
+9unions
+9unity
+8pany
+9are
+9ared
+9ares
+9aring
+9arison
+8s
+7nnect
+9ected
+9ecting
+9ection
+9ector
+9ectors
+9ects
+9exion
+9exions
+8version
+9ert
+9erted
+9erting
+9erts
+7oled
+9er
+9ers
+7rporate
+8relate
+9elated
+9elates
+8tical
+7stal
+9ally
+9als
+7untry
+9ty
+8ple
+6rater
+7op
+9ped
+9ping
+9s
+8ss
+9sed
+9ses
+9sing
+7ural
+6ultural
+9urally
+9ure
+9ures
+7rrence
+9ences
+9ent
+9ently
+7t
+8s
+8ting
+5dash
+9ed
+9es
+9ing
+6eal
+9er
+9ers
+9ing
+9s
+9t
+7ntal
+9ally
+7pend
+9nded
+9ndence
+9ndency
+9ndent
+9nding
+9nds
+6ialectal
+7ct
+9ed
+9ing
+9ion
+9ions
+9ive
+9ively
+9or
+9ors
+9ory
+9s
+7ffuse
+9used
+9uses
+9using
+9usion
+9usions
+7gital
+9tate
+9tated
+9tates
+9tating
+9tation
+7ne
+9d
+9s
+8ing
+7strict
+7visional
+6ominion
+5electrode
+9trodes
+9tron
+9tronic
+6pidemic
+6ss
+8e
+9d
+9s
+8ing
+7t
+8ed
+9dly
+9dness
+8ing
+9ngly
+9ngness
+8s
+6thnic
+5face
+9d
+9s
+8ial
+9ally
+9ng
+9ngs
+8ulties
+9lty
+7ith
+7milial
+9ly
+7scicular
+6emoral
+7re
+9d
+9nce
+9nces
+9ntial
+9r
+9rs
+9s
+8ing
+9ngly
+8ogram
+9grams
+9meter
+9meters
+9metric
+9metry
+9n
+9ns
+8tile
+9ility
+6iber
+7le
+9d
+9s
+8ing
+7rm
+6low
+9ed
+9ing
+9s
+7uence
+9nces
+9nt
+8ous
+8ve
+9es
+9ial
+6old
+9ed
+9ing
+9s
+8iate
+9ated
+9ates
+9ating
+6raternity
+7etted
+7ontal
+6use
+9d
+9s
+8ing
+9on
+9ons
+5galactic
+7ng
+6eneration
+9ric
+6lacial
+9ials
+6radation
+9ations
+9e
+9ed
+9es
+9ient
+9ing
+8ft
+9ted
+9ting
+9ts
+8nular
+7ew
+7oup
+8w
+9ing
+9n
+9s
+9th
+9ths
+5im
+7s
+6ndividual
+8ustry
+7fluence
+9uenced
+9uences
+7volve
+9lved
+9lves
+9lving
+6onic
+7r
+8isation
+9se
+9sed
+9ses
+9sing
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+6sland
+5jacencies
+9ncy
+9nt
+8ulate
+9lated
+9lates
+9lating
+9latory
+6ect
+9ed
+9ing
+9ion
+9ional
+9ionary
+9ions
+9or
+9ors
+9ory
+9s
+9ural
+6oin
+9ed
+9ing
+9s
+5kineses
+9sis
+6nit
+9s
+9ted
+9ting
+7ot
+9s
+9ted
+9ting
+5lace
+9d
+9dly
+9ment
+9ments
+9s
+8ing
+8ustrine
+7id
+7minar
+9nate
+9nated
+9nates
+9nating
+9nation
+7p
+8ped
+9ing
+8s
+7rd
+9ed
+9ing
+9s
+7y
+8er
+9red
+9ring
+9rs
+8ing
+8s
+6eaf
+8ve
+9ed
+9es
+9ing
+7nd
+9ing
+9s
+8t
+7ukin
+9ins
+6ibrary
+7ne
+9al
+9ally
+9ar
+9arly
+9ars
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9d
+9r
+9rs
+9s
+8gua
+9ual
+9ually
+9uas
+8ing
+9ngs
+8k
+9ed
+9ing
+9s
+6oan
+9s
+7bular
+7cal
+9tion
+9tions
+8k
+9ed
+9er
+9ers
+9ing
+9s
+8ution
+9tions
+9tor
+9torily
+9tors
+9tory
+9tress
+9trice
+9trices
+9trix
+9trixes
+7op
+9ed
+9ing
+9s
+7pe
+9d
+9r
+9rs
+9s
+8ing
+6ude
+9d
+9s
+8ial
+9ng
+7nar
+9ry
+9tion
+9tions
+5male
+7rginal
+8riage
+9iages
+9ied
+9ies
+9y
+9ying
+7t
+8s
+8ted
+9ing
+7xilla
+9llae
+9llary
+6eddle
+9led
+9ler
+9lers
+9les
+9ling
+8ia
+9acies
+9acy
+9al
+9aries
+9ary
+9ate
+9ated
+9ately
+9ates
+9ating
+9ation
+9ations
+9ator
+9ators
+9atory
+9n
+9ns
+9um
+7mbrane
+7nstrual
+8t
+9s
+7sh
+9ed
+9es
+9ing
+7tallic
+9llics
+7zzi
+9o
+9os
+6igration
+9ations
+7nability
+9ble
+9bly
+8gle
+9led
+9les
+9ling
+7ssion
+9ions
+9ive
+7t
+8otic
+8s
+8ted
+9ence
+9ences
+9encies
+9ency
+9ent
+9ently
+9er
+9ers
+9ing
+9ingly
+9or
+9ors
+7x
+8ed
+9s
+8ing
+8ture
+9ures
+6odal
+8ulation
+7lecular
+7nt
+9ane
+7untain
+6undane
+7ral
+8e
+9d
+9s
+8ing
+5n
+6al
+8isation
+9se
+9sed
+9ses
+9sing
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8ness
+9esses
+8s
+7tional
+9onally
+9onals
+6e
+7cine
+9ve
+7d
+7e
+8s
+7s
+7t
+8s
+7ural
+9on
+9onal
+9ons
+6ing
+7st
+9s
+6ment
+9ts
+6odal
+8e
+9s
+8ial
+6s
+7hip
+9ps
+6uclear
+9eon
+9eonic
+9eotide
+7ncial
+9io
+9ios
+5observer
+9rvers
+6cean
+9nic
+8ptive
+9tor
+9tors
+7ular
+6ffice
+6perable
+9ative
+9atives
+6rbital
+7gan
+6sculant
+9late
+9lated
+9lates
+9lating
+9lation
+7seal
+9ous
+5page
+9d
+9s
+8ing
+7ndemic
+7rietal
+9sh
+8ochial
+9xysmal
+8ticle
+9y
+6ellant
+9ants
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ator
+9ators
+7netrable
+9trant
+9trate
+9trated
+9trates
+7rceptual
+8meate
+9eated
+9eates
+9eating
+8sonal
+9onally
+7tiolar
+6halangeal
+8se
+9es
+7one
+9es
+6ilaster
+9sters
+6lanetary
+9t
+9ted
+9ting
+9ts
+8y
+9ed
+9ing
+9s
+7ead
+9ded
+9der
+9ders
+9ding
+9ds
+8d
+8ural
+7uvial
+6oint
+9ts
+7lable
+9r
+9te
+9ted
+9ter
+9ters
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+7ne
+9d
+9s
+8ing
+7pulation
+7sable
+9l
+9ls
+8e
+9d
+9r
+9rs
+9s
+8ing
+9tion
+9tions
+6ret
+9able
+9ably
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+9ed
+9er
+9ers
+9ership
+9ess
+9esses
+9ing
+9ive
+9ively
+9ress
+9resses
+9s
+7ovincial
+8ximal
+6sychic
+6unction
+9tions
+9tuate
+9tuated
+9tuates
+7pillary
+5quartile
+5race
+8ial
+9ally
+7dial
+9ally
+9i
+9us
+9uses
+7il
+9ed
+9er
+9ers
+9ing
+9s
+7mal
+6ed
+7gal
+8es
+8ional
+8na
+9al
+9um
+9ums
+7late
+9ted
+9tedly
+9tes
+9ting
+9tion
+9tions
+8igious
+7nal
+7x
+6ing
+6obang
+9ngs
+7gable
+9nt
+9nts
+9te
+9ted
+9tee
+9tees
+9tes
+9ting
+9tingly
+9tion
+9tional
+9tions
+9tive
+9tively
+9tives
+9tor
+9tories
+9torily
+9tors
+9tory
+8ee
+9es
+7w
+6upt
+9ed
+9edly
+9er
+9ers
+9ible
+9ing
+9ion
+9ions
+9ive
+9ively
+9or
+9ors
+9s
+5s
+6capular
+7holastic
+9ol
+9ols
+7ribe
+9bed
+9bes
+9bing
+6ect
+9ed
+9ing
+9ion
+9ional
+9ions
+9s
+7gment
+9ental
+9ents
+7nsory
+7ptal
+7rt
+9al
+9ed
+9ing
+9s
+8vice
+7ssion
+9ions
+7x
+8es
+8ual
+9alism
+9alisms
+9ality
+9ally
+6idereal
+6ocietal
+9ety
+6pace
+9ed
+9es
+9ing
+8tial
+9ially
+7ecies
+9ific
+8rsal
+9sals
+9se
+9sed
+9sedly
+9ses
+9sing
+9sion
+9sions
+7inal
+9ous
+6tadial
+9ials
+8ge
+8te
+9es
+9ion
+7ellar
+9lary
+8rile
+9ility
+7ice
+9es
+8muli
+9ulus
+8tial
+9ially
+9ials
+7rain
+9ins
+9nd
+9nds
+9tified
+9tifies
+9tify
+6ubjective
+6ystem
+5tangle
+9led
+9lement
+9les
+9ling
+7rsal
+6entacular
+7rm
+9inal
+7xt
+9s
+9ual
+9uality
+9ually
+9ure
+9ures
+6idal
+9lly
+7e
+8s
+7ll
+9age
+9ages
+9ed
+9ing
+9s
+7ssued
+6raffic
+9fics
+7ial
+8bal
+8go
+9os
+7oop
+8pical
+6wine
+9ed
+9ement
+9ements
+9es
+9ing
+9ingly
+9ings
+8st
+9ted
+9ting
+9tingly
+9ts
+5union
+9ns
+8t
+8versity
+6rban
+9ns
+5val
+8e
+9s
+8ley
+9eys
+9ic
+9um
+9ums
+8ometer
+9meters
+8s
+7rsity
+6ein
+9ed
+9ing
+9s
+7ne
+9d
+9r
+9rs
+9s
+8ient
+9ng
+8or
+9rs
+8tion
+9ional
+9ionism
+9ionist
+9ions
+9or
+9ors
+7rtebral
+6iew
+9ed
+9ee
+9ees
+9er
+9ers
+9ing
+9s
+7llage
+7sibility
+9ble
+9tation
+7tal
+6ocalic
+7lve
+9ed
+9es
+9ing
+5war
+6eave
+9ed
+9ement
+9ements
+9er
+9ers
+9es
+9ing
+7b
+8s
+6ind
+9ing
+9s
+6ork
+9ed
+9ing
+9ings
+9s
+7und
+7ve
+9n
+6reathe
+9thed
+9thes
+9thing
+7ought
+5zonal
+8e
+9s
+4stacies
+8y
+7te
+9s
+6inal
+9lly
+8e
+9s
+3hral
+7l
+8ed
+8ing
+8s
+7s
+5one
+8d
+8s
+7ing
+3i
+4fada
+8h
+9s
+8s
+7eh
+9s
+4l
+4ma
+6cies
+7y
+6e
+6l
+6s
+6te
+8d
+8ly
+8ness
+9esses
+8r
+9s
+8s
+7ing
+8on
+9ns
+5e
+5idate
+9ed
+9es
+9ing
+9ingly
+9ion
+9ions
+9or
+9ors
+9ory
+6sm
+8s
+7t
+8e
+9s
+8s
+6ties
+7y
+4nction
+9ns
+5e
+6s
+4re
+4s
+4tle
+7d
+7s
+6ing
+5ule
+8d
+8s
+7ing
+3o
+4ed
+4lerability
+9le
+9leness
+9ly
+8nce
+9ces
+9t
+9tly
+9tness
+9ts
+8tion
+9ions
+4mb
+6ed
+6ing
+6s
+4naco
+8s
+6te
+8d
+8s
+7ing
+8on
+9nal
+9ns
+7or
+9s
+5e
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+4rsion
+9s
+5t
+6ed
+6ing
+7on
+9s
+6s
+4wn
+4xicable
+8nt
+9ts
+8te
+9ed
+9edly
+9es
+9ing
+9ingly
+9ion
+9ions
+9ive
+9or
+9ors
+6meter
+9ers
+3ra
+5capsular
+7rdiac
+9ial
+9ially
+7vitary
+6ellular
+9ularly
+7rebral
+9brally
+6ity
+6ompany
+6ranial
+9ially
+6tability
+9le
+9leness
+9ly
+6utaneous
+5da
+7s
+7y
+6ermal
+9ally
+9ic
+9ically
+6os
+8es
+5fallopian
+7scicular
+5galactic
+6enic
+5medullary
+7rcurial
+6olecular
+6undane
+7ral
+9lly
+7scular
+9ularly
+5nasal
+9lly
+7tional
+6et
+8s
+6sigeance
+9eances
+9eant
+9eantly
+9eants
+9ence
+9ences
+9encies
+9ency
+9ent
+9entism
+9entist
+9ently
+9ents
+8tive
+9ively
+9ivity
+7missible
+8utable
+6t
+7s
+6uclear
+5ocular
+9arly
+5parietal
+8tum
+6eritoneal
+8sonal
+7tiolar
+6late
+6opulation
+6reneur
+9eurial
+9eurs
+6sychic
+5sexual
+6pecies
+9ific
+6tate
+5telluric
+6hecal
+9ally
+7oracic
+5uterine
+5vasation
+9tions
+8cular
+9ularly
+6enous
+9uses
+9usly
+6ital
+9lly
+9m
+5zonal
+4eat
+7ed
+7full
+7ing
+9gly
+7ment
+9nts
+7s
+5nch
+8ant
+8ed
+9r
+9rs
+9s
+8ing
+8ment
+9ents
+5pid
+8ities
+9ty
+8ly
+8ness
+9esses
+4icacies
+8y
+7te
+9ly
+9ness
+9nesses
+5gant
+9e
+9es
+9s
+6uant
+9te
+9tes
+9ts
+7e
+8d
+8r
+9s
+8s
+7ing
+9gly
+5nce
+6sic
+9al
+9ality
+9ally
+9alness
+9ate
+4o
+5duce
+9d
+9r
+9rs
+9s
+8ible
+9ng
+8tion
+9ions
+9ive
+9orily
+9ory
+5fied
+8s
+6y
+7ing
+5gressant
+9sants
+9sion
+9sions
+9sive
+5it
+7al
+7s
+7us
+9es
+5ject
+9ed
+9ing
+9ion
+9ions
+9ive
+9s
+5ld
+5missible
+9ion
+9ions
+9ive
+7t
+8s
+8ted
+9ent
+9er
+9ers
+9ing
+5n
+6s
+5rse
+8ly
+5s
+6pect
+9ted
+9ting
+9tion
+9tional
+9tions
+9tive
+9tively
+9ts
+6usception
+5versible
+9ion
+9ions
+9ive
+9ively
+8t
+9ed
+9ing
+9ive
+9s
+4ude
+7d
+7r
+8s
+7s
+6ing
+9ly
+5sion
+9al
+9ist
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+9s
+6t
+7ed
+7ing
+7ment
+9nts
+7s
+3ubate
+8d
+8s
+7ing
+8on
+9ns
+4it
+6able
+6ed
+6ing
+7on
+9al
+9alism
+9alisms
+9alist
+9alists
+9ally
+9ism
+9isms
+9ist
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+8ism
+9sms
+6s
+4mesce
+9d
+9nce
+9nces
+9ncies
+9ncy
+9nt
+9s
+8ing
+4rbidate
+9ted
+9tes
+9ting
+5n
+6ed
+6s
+4se
+6s
+5suscept
+9epted
+9epting
+9eption
+9eptive
+9epts
+3wine
+7d
+7ment
+9nts
+7s
+6ing
+5st
+7ed
+7ing
+7s
+2ukshuit
+7k
+8s
+3la
+5s
+6e
+7s
+4in
+6s
+3mbrate
+9d
+9s
+8ing
+3nction
+9s
+4dant
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+9y
+3rbane
+8ly
+7ities
+9y
+4e
+5d
+6ness
+9ses
+5ment
+9s
+5s
+4ing
+4n
+5ed
+5ing
+5ment
+9s
+5s
+3sitate
+8ion
+9ons
+4t
+5ion
+8s
+3tile
+7ly
+6ities
+8y
+4terable
+2vadable
+5e
+6d
+6r
+7s
+6s
+5ing
+4ginable
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+4lid
+7ate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7ed
+7hood
+9ods
+7ing
+9gs
+8sm
+9ms
+8ties
+9y
+7ly
+7ness
+9sses
+7s
+5uable
+9eness
+9y
+4r
+5iabilities
+9lity
+8le
+9eness
+9es
+9y
+7nce
+9es
+9ies
+9y
+8t
+9s
+5s
+4sion
+8s
+6ve
+8ly
+8ness
+9esses
+3eagle
+8d
+8s
+7ing
+4cked
+5ted
+6ive
+9ly
+9ness
+9nesses
+9s
+4igh
+7ed
+8r
+9s
+7ing
+7s
+6le
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+4ndibilities
+9lity
+8le
+5it
+5t
+6able
+6ed
+7r
+8s
+6ible
+7ng
+7on
+9al
+9less
+9s
+7ve
+9ly
+9ness
+9nesses
+6or
+8iable
+9al
+9ally
+9ed
+9es
+8s
+8y
+9ing
+6ress
+9ses
+6s
+4racities
+9y
+5ities
+7y
+5ness
+9es
+5se
+7d
+7ly
+7s
+6ing
+7on
+9s
+7ve
+5t
+6ase
+9s
+6ebral
+9ate
+9ates
+7d
+8ly
+7r
+8s
+6ibilities
+9lity
+8le
+7n
+8g
+8s
+6or
+8s
+6s
+4st
+6able
+6ed
+6ible
+7gable
+9te
+9ted
+9tes
+9ting
+9tion
+9tional
+9tions
+9tive
+9tor
+9tors
+9tory
+7ng
+7tive
+8ure
+9res
+6ment
+9ts
+6or
+8s
+6s
+4teracies
+9y
+8te
+9ely
+9eness
+4xed
+3iabilities
+9ty
+6le
+8ness
+9esses
+7y
+4dious
+9ly
+9ness
+9nesses
+4gilate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+5orant
+9ts
+8te
+9ed
+9es
+9ing
+9ingly
+9ion
+9ions
+9ive
+9ively
+9or
+9ors
+4ncibilities
+9lity
+8le
+9eness
+9y
+4olabilities
+9lity
+8le
+9eness
+9y
+7cies
+8y
+7te
+9d
+9ly
+9ness
+9nesses
+5us
+4rile
+4scid
+5ibilities
+9ity
+7le
+9ness
+9nesses
+9s
+8y
+4tal
+6tion
+9nal
+9nals
+9ns
+7ories
+9y
+5e
+6d
+6e
+7s
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+8ness
+9esses
+8s
+3ocable
+6te
+8d
+8s
+7ing
+8on
+9nal
+9ns
+8ve
+7or
+9s
+9y
+4ice
+7d
+7s
+6ing
+4ke
+6d
+6r
+7s
+6s
+5ing
+4lucel
+9la
+9late
+9lated
+9lum
+9s
+7ra
+9l
+9te
+8e
+9s
+8um
+6ntarily
+9riness
+9ry
+6te
+8d
+9ly
+8ly
+8s
+7ing
+8on
+9nal
+9ns
+5ve
+7d
+8ly
+7ment
+9nts
+7r
+8s
+7s
+6ing
+3ulnerability
+9ble
+9bly
+5tuation
+9ions
+2wall
+6ed
+6ing
+6s
+4rd
+6ly
+6ness
+9ses
+6s
+3eave
+7d
+7s
+6ing
+3ick
+6ed
+6ing
+6s
+4nd
+6ing
+6s
+4t
+5h
+5s
+3ork
+6ed
+6ing
+9s
+6s
+5n
+4und
+4ve
+6n
+3rap
+6ped
+7ing
+6s
+4eathe
+9d
+9s
+8ing
+4ought
+2yala
+6s
+1o
+2date
+6d
+6s
+5ing
+6on
+8s
+3ic
+4d
+5e
+6s
+5s
+4n
+5ate
+8d
+8s
+7ing
+8on
+9ns
+5e
+6s
+5s
+4sation
+9ns
+5e
+6d
+6r
+7s
+6s
+5ing
+5m
+6s
+4zation
+9ns
+5e
+6d
+6r
+7s
+6s
+5ing
+3oform
+8s
+4metric
+9cal
+9cally
+9es
+8y
+4phile
+6or
+8s
+5sin
+8s
+4us
+3uret
+7s
+3yrite
+8s
+2lite
+6s
+2n
+3ic
+5ities
+7y
+5s
+4sable
+6tion
+9ns
+5e
+6d
+6r
+7s
+6s
+5ing
+4um
+6s
+4zable
+6tion
+9ns
+5e
+6d
+6r
+7s
+6s
+5ing
+3ogen
+7ic
+7s
+4mer
+7s
+4ne
+6s
+4pause
+9s
+5hore
+9s
+9ses
+9sis
+4sonde
+9s
+5phere
+9es
+9ic
+9ically
+4tropic
+9es
+8y
+3s
+3tophoreses
+9esis
+9etic
+2panoic
+2s
+2ta
+4cism
+8s
+4s
+1pecac
+6s
+6uanha
+9has
+2omoea
+7s
+2pon
+5s
+2ratropium
+9ums
+3indole
+9s
+3oniazid
+9ds
+2selateral
+3ilateral
+9ally
+1racund
+7ities
+9y
+7ulous
+3de
+5s
+3scibilities
+9ity
+7le
+9ness
+9nesses
+8y
+3te
+5ly
+5ness
+9es
+5r
+5st
+2e
+3d
+3ful
+6ly
+6ness
+9ses
+3less
+3nic
+6al
+8ly
+6ism
+9s
+6on
+8s
+6s
+4ologies
+8y
+3s
+2id
+4aceous
+5l
+4eal
+5ctomies
+9y
+5s
+6cence
+9ces
+9t
+9tly
+4ial
+6n
+5c
+5sation
+9ons
+6e
+7d
+7s
+6ing
+5um
+7s
+5zation
+9ons
+6e
+7d
+7s
+6ing
+4ocyte
+9s
+5logies
+9st
+9sts
+8y
+5smine
+9es
+8um
+9ms
+5tomies
+8y
+4s
+3ng
+3s
+4ate
+7d
+7s
+6ing
+7on
+9s
+4cope
+8s
+4ed
+5s
+4ing
+3tic
+5s
+6es
+2k
+3ed
+3ing
+3s
+4ome
+7ly
+7ness
+9sses
+2oko
+5s
+3n
+4bark
+8s
+5ound
+4clad
+8s
+4e
+5d
+5r
+6s
+5s
+4fisted
+4handed
+5earted
+4ic
+6al
+8ly
+8ness
+9esses
+5er
+6s
+7t
+5ng
+7s
+5se
+7d
+7s
+6ing
+6t
+7s
+5ze
+7d
+7s
+6ing
+4less
+5ike
+4man
+6ster
+9rs
+5en
+5onger
+9ries
+9rs
+9ry
+4ness
+8es
+4s
+5ide
+8s
+5mith
+9s
+5tone
+9s
+4ware
+8s
+5eed
+8s
+5oman
+7en
+6od
+8s
+6rk
+8er
+9rs
+8s
+4y
+2radiance
+9es
+9ies
+9y
+8t
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+6cable
+9ly
+8te
+9ed
+9es
+9ing
+4tional
+9lise
+9lised
+9lises
+9lising
+9lism
+9lisms
+9list
+9listic
+9lists
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9lness
+9ls
+3eal
+6isable
+7ties
+8y
+7zable
+4buttable
+4ceptive
+5iprocal
+9cities
+9city
+5laimable
+9ably
+5ognisable
+9tion
+9tions
+9zable
+6ncilable
+9lables
+9lably
+9led
+9lement
+6verable
+9ably
+5usable
+9ly
+4deemability
+9ble
+9bles
+9bly
+6nta
+9s
+8ism
+9sms
+9st
+9sts
+5ucibility
+9le
+9leness
+9ly
+7tibility
+9on
+9ons
+4flection
+9ions
+9ive
+7xion
+9ons
+9ve
+5ormability
+9ble
+9bly
+5ragability
+9ble
+9bly
+7ngible
+9ibly
+5utability
+9le
+9leness
+9ly
+4gardless
+5ular
+9ities
+9ity
+9ly
+9s
+4lated
+7ion
+9ns
+8ve
+9ely
+9eness
+5evance
+9ces
+9cies
+9cy
+9t
+9tly
+5ievable
+6gion
+9nist
+9nists
+9ns
+9us
+9usly
+9usness
+4meable
+9y
+6diable
+9bly
+5issibility
+9ble
+9bly
+9on
+9ons
+9ve
+5ovability
+9le
+9leness
+9ly
+4nowned
+4pairable
+6rability
+9le
+9leness
+9ly
+5ealability
+9ble
+9bly
+5laceable
+9ably
+6eviable
+9sable
+5rehensible
+9nsibly
+7ssible
+9ibly
+6oachable
+9hably
+7ducible
+7vable
+9bly
+4sistance
+9nces
+8ibility
+9ble
+9bly
+5olubility
+9le
+9ly
+8te
+9ely
+9eness
+9ion
+9ions
+7vability
+9ble
+9bly
+5pective
+9ively
+6irable
+6onsible
+9ibles
+9ibly
+9ive
+9ively
+5trainable
+5uscitable
+9tably
+4tention
+9ons
+9ve
+9veness
+5rievable
+9ably
+4verence
+9ces
+9t
+9tial
+9tly
+7sibility
+9ble
+9bly
+5ocability
+9le
+9leness
+9ly
+3identa
+9s
+4gable
+8y
+6te
+8d
+8s
+7ing
+8on
+9nal
+9ns
+8ve
+7or
+9s
+5uous
+4sion
+8s
+5ory
+4tabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6ncies
+8y
+7t
+8s
+6te
+8d
+9ly
+8s
+7ing
+9gly
+8on
+9ns
+8ve
+7or
+9s
+3otational
+3upt
+6ed
+6ing
+7on
+9s
+7ve
+9ly
+6s
+2ukandji
+9s
+1s
+2abel
+6la
+8s
+7ine
+9es
+6s
+3goge
+7s
+6ic
+8s
+3llobar
+9ic
+9s
+3postolic
+3rithm
+8s
+3tin
+6e
+7s
+6ic
+6s
+2ba
+4s
+2chaemia
+9s
+8c
+4emia
+8s
+7c
+4ia
+6dic
+6l
+6tic
+5um
+4uretic
+9cs
+6ia
+8s
+2eikonia
+9s
+8c
+3nergic
+4tropic
+9cally
+2h
+3es
+2inglass
+9es
+3t
+2land
+6ed
+7r
+8s
+6ing
+6s
+3e
+4d
+4less
+4man
+5en
+4s
+5man
+6en
+4t
+5ed
+5s
+3ing
+3omania
+9s
+2m
+3atic
+7al
+9ness
+9nesses
+3s
+2na
+4e
+2o
+3agglutinin
+9inins
+4lloxazine
+9zines
+4minile
+9es
+5yl
+7s
+4ntibodies
+9dy
+7gen
+9nic
+9ns
+3bar
+6e
+7s
+6ic
+7sm
+9s
+6ometric
+6s
+5se
+7s
+5th
+7ic
+7s
+4ilateral
+4ront
+8s
+4utane
+9s
+6ene
+9s
+6yl
+8ene
+9nes
+8s
+3caloric
+5rboxazid
+9azids
+4hasm
+8ic
+8s
+5eim
+8al
+9ls
+8enal
+9nals
+8ic
+8s
+5imal
+9s
+7e
+8s
+5or
+7e
+8s
+7ic
+7s
+5romatic
+8osome
+9somes
+7n
+8al
+9lly
+8e
+9s
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+8ous
+9usly
+8s
+7ous
+4linal
+9s
+7e
+8s
+7ic
+9s
+4racies
+7y
+6tic
+5ymal
+9s
+7e
+8s
+4yanate
+9es
+7ic
+8de
+9es
+5clic
+3diametric
+9rical
+6phere
+9res
+5ca
+6on
+5morphic
+9hism
+9hisms
+9hous
+4oma
+6on
+7us
+6um
+5nt
+7al
+9s
+7s
+5se
+7s
+4ynamic
+9cs
+3electric
+9onic
+4nzymatic
+8e
+9s
+8ic
+4tes
+3flavone
+9es
+4orm
+7s
+3gamete
+9s
+8ic
+6ic
+7es
+6ous
+6y
+4eneic
+7tic
+6ic
+7es
+6ous
+6y
+5otherm
+9rmal
+9rmals
+9rmic
+9rmics
+9rms
+4loss
+8al
+8es
+8ic
+6ttal
+8ic
+4on
+6al
+8s
+6e
+7s
+6ic
+8s
+7es
+6s
+6y
+4raft
+8ed
+8ing
+8s
+6m
+7s
+6ph
+8s
+5iv
+7s
+3hel
+6s
+4ydric
+5et
+7al
+9s
+7s
+3immunisation
+9zation
+3kinetic
+4ont
+7an
+9s
+7s
+3labilities
+9ty
+6le
+5table
+6e
+7d
+7s
+6ing
+7on
+9ism
+9isms
+9ist
+9ists
+9s
+7ve
+6or
+8s
+4ead
+7s
+5cithal
+5ucine
+9es
+5x
+6es
+4ine
+7s
+4og
+6ous
+6s
+6ue
+8s
+3magnetic
+9ics
+4er
+6ase
+9s
+6e
+7s
+6ic
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ous
+6s
+5tric
+9al
+9ally
+9s
+8es
+7opia
+9ias
+7y
+4orph
+8ic
+9cally
+9sm
+9sms
+8ous
+8s
+3niazid
+9e
+9es
+9s
+5trile
+9es
+4ome
+7s
+6ic
+7es
+6ous
+6y
+3octane
+9s
+3pach
+7s
+7yte
+9es
+4erimeter
+9ters
+9trical
+9tries
+9try
+4hone
+8s
+6tal
+7e
+8s
+4iestic
+9cally
+4leth
+8ic
+8s
+4od
+6an
+8s
+6ous
+6s
+5lities
+8y
+4renaline
+9ines
+7e
+8s
+7oid
+5opyl
+9s
+6terenol
+9enols
+4teran
+9s
+7ous
+4ycnal
+9s
+7ic
+9s
+3rhythmic
+3s
+4celes
+4eismal
+9ls
+8ic
+9cs
+4motic
+9ally
+4pin
+7s
+5ondylous
+6ries
+7ous
+7y
+4tacies
+7y
+6sies
+7y
+6tic
+9ally
+5emonous
+6ric
+5henuria
+9rias
+3tach
+7s
+6tic
+4eniscope
+9opes
+4heral
+9s
+7e
+8s
+7m
+8al
+9lly
+9ls
+8s
+4one
+7s
+6ic
+8ally
+8ities
+9ty
+5pe
+7s
+6ic
+8ally
+7es
+6y
+4retinoin
+9oins
+5on
+7s
+6pic
+9ally
+8es
+8sm
+9ms
+7ous
+7y
+4ype
+7s
+6ic
+3xsuprine
+9nes
+3zyme
+7s
+6ic
+2paghula
+9s
+2sei
+5s
+3uable
+7y
+5nce
+8s
+6t
+4e
+5d
+5less
+5r
+6s
+5s
+4ing
+2tana
+6s
+3hmi
+6an
+8s
+6c
+5oid
+5us
+7es
+3le
+5s
+1t
+2a
+3cism
+7s
+4olumite
+9tes
+5nic
+3lianate
+9ed
+9es
+9ing
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+5c
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+3s
+2ch
+4ed
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4weed
+8s
+4y
+2em
+4ed
+4ing
+5sation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+5zation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+4s
+3rance
+8s
+6t
+5te
+7d
+7s
+6ing
+7on
+9s
+7ve
+9ly
+9ness
+9nesses
+4oparities
+9ty
+8ous
+4um
+2her
+3yphalli
+9ic
+9ics
+9us
+9uses
+2ineracies
+8y
+7ncies
+9y
+8t
+9ly
+9s
+7ries
+8y
+7te
+9d
+9s
+8ing
+9on
+9ons
+2s
+3elf
+1ure
+1vermectin
+9ns
+2ied
+4s
+2oried
+6s
+5st
+7s
+4y
+5bill
+9s
+5like
+5wood
+9s
+2resse
+7s
+2y
+3like
+1wi
+3s
+1xia
+4s
+2odiases
+7is
+5d
+6s
+3ra
+5s
+2tle
+5s
+1zar
+4d
+5s
+4s
+2vestia
+8s
+7ya
+9s
+2zard
+6s
+4t
+5s
+0ja
+2ap
+4s
+2b
+3bed
+5r
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+6wock
+9kies
+9ks
+9ky
+4ing
+7ly
+4le
+6d
+6s
+5ing
+3ers
+3iru
+6s
+3orandi
+9s
+4t
+5icaba
+9as
+5s
+3s
+2cal
+5es
+5s
+4mar
+7s
+4na
+6s
+4randa
+9s
+5e
+6s
+3chus
+7es
+3ent
+3inth
+7e
+8s
+7s
+3k
+4al
+6led
+7ing
+6s
+5napes
+9ses
+5roo
+8ed
+8ing
+8s
+5ss
+7eries
+9y
+8s
+4boot
+8ed
+8ing
+8s
+4daw
+7s
+4ed
+5en
+7s
+5r
+6oo
+8ed
+8ing
+8s
+6s
+5t
+6ed
+6ing
+6less
+6s
+4fish
+8es
+5ruit
+9s
+4hammer
+9red
+9ring
+9rs
+4ies
+5ng
+7s
+4knife
+9d
+9s
+8ing
+7ves
+4leg
+7s
+5ight
+9ed
+9ing
+9s
+4man
+5en
+4plane
+9s
+5ot
+7s
+4rabbit
+9ts
+5oll
+8ed
+8ing
+8s
+4s
+5crew
+9s
+5haft
+9s
+5ie
+7s
+5melt
+9s
+6ith
+9s
+5nipe
+9s
+5tay
+8s
+6one
+9s
+6raw
+9s
+5y
+4y
+3obin
+7s
+5us
+7es
+4net
+7s
+3quard
+8s
+5erie
+9s
+3tation
+9s
+4itation
+9ons
+3ulate
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+9y
+4zzi
+7s
+2de
+4d
+5ly
+5ness
+9es
+4ite
+7s
+4like
+4ries
+5y
+4s
+3ing
+4sh
+6ly
+4tic
+2eger
+6s
+2fa
+4s
+3fa
+5s
+2g
+3a
+4ed
+4ing
+4s
+3er
+5s
+3g
+4aries
+6y
+4ed
+6er
+7st
+6ly
+6ness
+9ses
+5r
+6ies
+6s
+6y
+4heries
+7y
+4ier
+6s
+7t
+5ng
+4s
+4y
+3hir
+6dar
+9s
+6e
+7s
+6s
+3ir
+5s
+3less
+3ra
+5s
+3s
+3uar
+6ondi
+9is
+6s
+6undi
+9is
+2i
+3l
+4able
+4bird
+8s
+5reak
+9s
+4ed
+5r
+6ess
+9es
+6s
+4house
+9s
+4ing
+4less
+4or
+6ess
+9es
+6s
+4s
+2k
+3e
+4s
+5es
+4y
+5s
+3fruit
+8s
+3s
+2labib
+4p
+5eno
+8s
+5ic
+6n
+7s
+5s
+3frezi
+3op
+5ies
+5pies
+6y
+5s
+5y
+4use
+7d
+7s
+6ie
+8d
+8s
+7ng
+2m
+3aat
+6s
+4dar
+7s
+4hiriya
+9as
+3b
+4alaya
+9s
+5rt
+7s
+4e
+5au
+7x
+5d
+5e
+6s
+5r
+6s
+5s
+5ux
+4ier
+7s
+5ng
+5ya
+7h
+8s
+7s
+4o
+5k
+6ked
+7ing
+6s
+5lan
+8a
+9s
+8s
+5ne
+7s
+5ol
+7s
+5ree
+8s
+4s
+4u
+5l
+6s
+5s
+3dani
+7s
+3es
+5es
+3jar
+6s
+3like
+3mable
+4ed
+5r
+6s
+4ier
+6s
+7t
+5ng
+7s
+4y
+3on
+3packed
+5n
+6ee
+8s
+6i
+7s
+6s
+4ot
+6s
+3s
+2ne
+4s
+3gle
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5y
+3iform
+4saries
+7y
+5saries
+8y
+4tor
+7ial
+7s
+8hip
+9ips
+5ress
+9es
+6ix
+8es
+4zar
+7ian
+8es
+7s
+7y
+3ker
+6s
+3n
+4ies
+4ock
+7s
+4s
+4y
+3sky
+6s
+3tee
+4ier
+6s
+7t
+4y
+2pan
+5ise
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5ned
+7r
+8s
+6ing
+5s
+3e
+4d
+4r
+5ies
+5s
+5y
+4s
+3ing
+6ly
+6s
+3onaiserie
+9ries
+5ica
+8s
+3ped
+4ing
+3s
+2r
+3araca
+8s
+6ka
+8s
+3diniere
+9es
+3ful
+6s
+3gon
+6ed
+7er
+9s
+7l
+8le
+9es
+8s
+6ing
+7sation
+9tions
+8e
+9d
+9s
+8h
+8ing
+8t
+9ic
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+6y
+5on
+7s
+3head
+7s
+3ina
+6s
+3k
+4man
+5en
+4s
+3l
+4dom
+7s
+4s
+5berg
+9s
+3ool
+6s
+4site
+8s
+4vise
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+3p
+4ed
+4ing
+4s
+3rah
+6s
+4ed
+4ing
+7ly
+7s
+3s
+4ful
+3ta
+5s
+3ul
+5s
+3vey
+6s
+4ie
+6s
+2sey
+5s
+3ies
+3min
+6e
+7s
+6s
+4onate
+9s
+3p
+4e
+5r
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6ous
+6s
+6ware
+9es
+6y
+5s
+4idean
+7ous
+5lite
+9s
+5s
+6es
+4s
+3s
+4es
+4id
+6s
+3y
+2taka
+6s
+3o
+4s
+3ropha
+8s
+2uk
+4ed
+4ing
+4s
+3nce
+6d
+6s
+5ing
+4dice
+8d
+8s
+7ing
+4se
+6d
+6s
+5ing
+4t
+5ed
+6e
+5ie
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+8ly
+5s
+5y
+3p
+4ed
+4ing
+4s
+2va
+4s
+3el
+5in
+7a
+8s
+7ed
+7ing
+7s
+5s
+2w
+3an
+5s
+4ri
+6s
+3bation
+9s
+4one
+7d
+7r
+8s
+7s
+6ing
+9s
+5x
+6es
+4reaker
+9rs
+3crusher
+9rs
+3ed
+3fall
+7s
+3hole
+7s
+3ing
+6s
+3less
+4ike
+5ne
+7s
+3s
+2xie
+5s
+3y
+2y
+3bird
+7s
+3cee
+6s
+3gee
+6s
+3hawker
+9s
+3s
+3vee
+6s
+3walk
+7ed
+8r
+9s
+7ing
+9gs
+7s
+2zerant
+8s
+3ies
+3y
+3z
+4bo
+6s
+4ed
+5r
+6s
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4like
+4man
+5en
+4y
+1ealous
+7e
+8d
+8s
+7hood
+9ods
+7ies
+8ng
+7ly
+7ness
+9sses
+7y
+3n
+4ed
+5tte
+8s
+4s
+3t
+4s
+2bel
+5s
+2di
+4s
+2e
+3d
+3ing
+3l
+4ed
+4ie
+6d
+6ing
+6s
+5ng
+4s
+4y
+5ing
+3p
+4ed
+5rs
+4ing
+4ney
+7s
+4s
+3r
+4ed
+5r
+6s
+4ing
+7ly
+7s
+4s
+3s
+3z
+2fe
+4s
+3f
+4ed
+4ing
+4s
+2had
+5een
+5i
+6s
+7m
+8s
+7t
+8s
+5s
+3u
+4s
+2istiecor
+9rs
+2juna
+6l
+5e
+6ly
+6ness
+9ses
+5ities
+7y
+5ostomies
+9my
+5um
+2lab
+5s
+3l
+4aba
+7h
+8s
+7s
+4ed
+4ied
+6s
+5fication
+9tions
+7ed
+8s
+6y
+7ing
+5ng
+4o
+5s
+4s
+4y
+5bean
+9s
+5fish
+9es
+5graph
+9hed
+9hing
+9hs
+5ing
+5like
+5roll
+9s
+3utong
+8s
+2madar
+7s
+3be
+5s
+3idar
+7s
+4ma
+6s
+3mied
+6r
+6s
+7t
+5ness
+9es
+4y
+5ing
+2nnet
+6ing
+9s
+6s
+4ies
+4y
+2ofail
+7s
+3n
+3pard
+7ed
+8r
+9s
+7ied
+9s
+8ng
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7ous
+9sly
+7s
+7y
+8ing
+2querities
+8y
+4irities
+8y
+2rbil
+6s
+4oa
+6s
+3eed
+6s
+4miad
+8s
+4pigo
+8s
+3falcon
+9s
+3id
+5s
+3k
+4ed
+5r
+6s
+4ier
+6s
+7t
+5ly
+5n
+6ess
+9es
+6g
+7ly
+7s
+6head
+9ds
+6s
+4s
+4water
+9s
+4y
+3oboam
+8s
+3que
+6d
+6r
+7s
+6s
+5ing
+8s
+3reed
+7s
+4ican
+8s
+5d
+6s
+5es
+4y
+5can
+8s
+5mander
+9ered
+9ering
+9ers
+3sey
+6ed
+6s
+2ss
+4amies
+7ne
+9s
+6y
+5nt
+4e
+5d
+5rant
+9s
+5s
+4ie
+6s
+5ng
+3t
+4book
+8s
+4ed
+5e
+6s
+5r
+6s
+4ful
+4ing
+7ly
+7s
+4s
+3uit
+6ic
+8al
+9lly
+7sm
+9s
+6ries
+7y
+6s
+4s
+2t
+3bead
+7s
+3e
+4s
+3foil
+7s
+3lag
+6s
+4ike
+5ner
+8s
+3on
+5s
+3port
+7s
+3s
+4am
+6s
+4om
+6s
+5n
+6s
+4tream
+9s
+3tatura
+9s
+4ed
+4ied
+6r
+6s
+7t
+5ness
+9es
+6g
+5son
+8able
+8ed
+8ing
+8s
+4on
+6s
+4y
+5ing
+3way
+6s
+2u
+3ne
+3x
+2w
+3ed
+4l
+5ed
+6r
+7s
+5fish
+9es
+5ing
+5led
+7r
+8ies
+8s
+8y
+6ike
+7ng
+5ries
+6y
+5s
+5weed
+9s
+3fish
+7es
+3ie
+5s
+4ng
+3s
+2zail
+6s
+3ebel
+7s
+1hala
+5s
+3tka
+6s
+1iao
+4s
+2b
+3b
+4a
+5h
+6s
+5s
+4ed
+5r
+6ed
+6ing
+6s
+4ing
+7s
+4ons
+5om
+7s
+4s
+3e
+4d
+4r
+5s
+4s
+3ing
+6ly
+3s
+2cama
+6s
+3kajog
+8ged
+9ing
+8s
+2ff
+4ies
+4s
+4y
+2g
+3ajig
+7ged
+8ing
+7s
+5og
+7ged
+8ing
+7s
+4maree
+9s
+3ged
+5r
+6ed
+6ing
+6mast
+9ts
+6s
+4ier
+6st
+5ng
+7s
+5sh
+4le
+6d
+6s
+5ier
+7st
+6ng
+5y
+4umbob
+9s
+4y
+3jig
+6ged
+7ing
+6s
+3like
+3ot
+5s
+3s
+4aw
+6ed
+6ing
+6n
+6s
+2had
+5een
+5i
+6s
+7m
+8s
+7t
+8s
+5s
+2lbab
+6s
+3gie
+6s
+3l
+4aroo
+8s
+4et
+6s
+4flirt
+9s
+4ion
+7s
+7th
+4s
+3t
+4ed
+5r
+6s
+4ing
+4s
+2mcrack
+8s
+3iny
+3jam
+6s
+3mie
+6d
+6s
+5ny
+4y
+5ing
+3p
+4er
+5st
+4ier
+6st
+4ly
+4ness
+8es
+4son
+4y
+3son
+6weed
+9ds
+2n
+3gal
+6l
+7s
+6s
+4bang
+8s
+4ko
+6es
+4le
+6d
+6r
+7s
+6s
+6t
+7s
+5ier
+7st
+6ng
+5y
+4o
+5es
+5ish
+7m
+8s
+7t
+8ic
+9cally
+8s
+3jili
+7s
+3k
+4ed
+5r
+6ed
+6ing
+6s
+4ing
+4s
+3n
+4e
+5e
+4i
+5s
+4s
+3ricksha
+9as
+9aw
+9aws
+5kisha
+9as
+6sha
+9s
+3s
+3x
+4ed
+5s
+4ing
+2pijapa
+8s
+3yapa
+7s
+2rble
+6d
+6s
+5ing
+3d
+4s
+3ga
+5s
+3kinet
+8s
+3re
+2tney
+6s
+3ter
+6bug
+9ged
+9ging
+9s
+6ed
+6ier
+8st
+7ness
+9sses
+8g
+6s
+6y
+2ujitsu
+8s
+4utsu
+8s
+2ve
+4ass
+4d
+4r
+5s
+4s
+4y
+3ier
+5st
+4ng
+3y
+1nana
+5s
+1o
+2anna
+6s
+5es
+7es
+2b
+3ation
+8s
+3bed
+5r
+6ies
+6s
+6y
+4ie
+6s
+5ng
+7s
+3centre
+9s
+3e
+4d
+4rnowl
+9s
+4s
+3holder
+9s
+3ing
+3less
+7ness
+9sses
+3name
+7s
+3s
+4eeker
+9s
+4hare
+8s
+4worth
+9s
+2ck
+4ette
+8s
+5y
+6ed
+6ing
+7sh
+8m
+9s
+6s
+7hip
+9ps
+4ish
+4o
+5s
+4s
+5trap
+9s
+4teleg
+9s
+3o
+4se
+6ly
+6ness
+9ses
+6rious
+5ities
+7y
+3ular
+7ities
+9y
+7ly
+6tor
+9s
+4nd
+6ities
+8y
+6ly
+6ness
+9ses
+2del
+5led
+6ing
+5s
+3hpur
+7s
+2e
+3s
+3y
+4s
+2g
+3ged
+5r
+6s
+4ing
+7s
+4le
+6d
+6r
+7s
+6s
+5ing
+3pants
+3s
+3trot
+7s
+2hannes
+8es
+3n
+4boat
+8s
+4nie
+7s
+5y
+6cake
+9es
+4s
+5on
+7grass
+9asses
+7s
+2in
+4able
+4der
+7s
+4ed
+5r
+6ies
+6s
+6y
+4ing
+7s
+4s
+4t
+5ed
+7ly
+7ness
+9sses
+6r
+7s
+5ing
+8s
+5less
+6y
+5ness
+9es
+5ress
+9es
+5s
+5ure
+8d
+8s
+9s
+9ses
+7ing
+5weed
+9s
+6orm
+9s
+3st
+5ed
+5ing
+5s
+2joba
+6s
+2ke
+4d
+4r
+5s
+4s
+5mith
+9s
+5ome
+5ter
+8s
+4y
+3ier
+5st
+4ly
+4ness
+8es
+5g
+6ly
+3ol
+3y
+2l
+3e
+4d
+4s
+3ing
+4otium
+9s
+3l
+4ed
+5r
+6s
+5y
+6er
+8s
+6ing
+9s
+6s
+4ied
+6r
+7s
+6s
+7t
+5fication
+9tions
+7ed
+8s
+6y
+7ing
+5ly
+5ment
+9s
+5ness
+9es
+6g
+5ties
+6y
+4op
+6s
+4s
+4y
+5boat
+9s
+5er
+7s
+5head
+9s
+5ing
+8s
+3s
+3t
+4ed
+5r
+6head
+9ds
+6s
+4head
+8s
+4ier
+6st
+5ly
+5ng
+7ly
+4s
+4y
+2mo
+4n
+4s
+2ncanoe
+8s
+3es
+5ed
+6s
+5ing
+3g
+4leur
+8s
+4s
+3nock
+4ycake
+9s
+3quil
+7s
+3ties
+4y
+2ok
+4ed
+5ries
+6y
+4ing
+4s
+2r
+3am
+5s
+3dan
+6s
+4eloo
+8s
+3s
+3um
+5s
+2seph
+6inite
+9tes
+6s
+3h
+4ed
+5r
+6s
+5s
+4ing
+7ly
+3kin
+6s
+3s
+4er
+6s
+5s
+3tle
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8s
+2t
+3a
+4s
+3s
+3ted
+5r
+6s
+4ier
+6st
+5ng
+7s
+4y
+3un
+5n
+6s
+5s
+2ual
+5s
+3gs
+3isance
+9s
+3k
+4ed
+5ries
+6y
+4ing
+4s
+3le
+5d
+5s
+4ing
+3nce
+6d
+6s
+5ier
+7st
+6ng
+5y
+3r
+4nal
+7ed
+8se
+9es
+7ing
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7led
+8ing
+7s
+5ey
+7ed
+8r
+9s
+7ing
+7man
+8en
+7s
+7work
+9rks
+5o
+6s
+4s
+3st
+5ed
+6r
+7s
+5ing
+5s
+3ysaunce
+9es
+2vial
+6ities
+8y
+6ly
+6ness
+9ses
+6ties
+7y
+3ysaunce
+9es
+2w
+3ar
+5i
+6s
+5s
+3ed
+3ing
+3l
+4ed
+5r
+6s
+4ier
+6st
+5ness
+9es
+6g
+4s
+4y
+3s
+2y
+3ance
+7s
+3ed
+3ful
+6ler
+8st
+7y
+6ness
+9ses
+3ing
+3less
+7ly
+7ness
+9sses
+3ous
+6ly
+6ness
+9ses
+3pad
+6s
+4op
+6ped
+8r
+9s
+7ing
+6s
+3ridden
+6e
+7r
+8s
+7s
+6ing
+9s
+4ode
+3s
+4tick
+8s
+1uba
+4s
+4te
+3bah
+6s
+3e
+4s
+3hah
+6s
+3ilance
+9s
+8ies
+8y
+7t
+8ly
+6rian
+9ns
+6te
+8d
+8s
+7ing
+8on
+9ns
+5e
+6e
+7s
+6s
+2co
+4s
+2d
+3as
+5es
+3der
+6ed
+6ing
+6s
+6y
+3ge
+5able
+5d
+5less
+6ike
+5ment
+9al
+9ally
+9s
+5r
+6s
+5s
+6hip
+9s
+4ing
+7ly
+4matic
+9al
+9ally
+5ent
+8al
+9lly
+8s
+3icable
+6tion
+9ns
+8ve
+7or
+9ial
+9ies
+9s
+9y
+7ure
+9es
+5ial
+8ly
+7ries
+9ly
+8y
+6ous
+9ly
+9ness
+9nesses
+4es
+3o
+4gi
+6s
+4ist
+7s
+4ka
+6s
+4s
+3s
+3y
+2g
+3a
+4l
+5s
+4te
+3ful
+6s
+3ged
+5rnaut
+9ts
+4ing
+7s
+6s
+7es
+4le
+6d
+6r
+7ies
+7s
+7y
+6s
+5ing
+8ly
+8s
+3head
+7s
+3landaceous
+4et
+6s
+3s
+4ful
+3ula
+6r
+7s
+6te
+8d
+8s
+7ing
+8on
+9ns
+5um
+4m
+5s
+2ice
+5d
+5head
+9s
+5less
+5r
+6s
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4y
+2jitsu
+7s
+3u
+4be
+6s
+4ism
+7s
+6t
+7s
+4s
+4tsu
+7s
+2ke
+4box
+7es
+4d
+4s
+3ing
+3skei
+7s
+3u
+4s
+2lep
+5s
+3ienne
+8d
+8s
+7ing
+5t
+6s
+2mar
+5ed
+5ing
+5red
+6ing
+5s
+5t
+6s
+3bal
+6s
+4ie
+6s
+4le
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8ly
+5y
+4o
+5ise
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5s
+4uck
+7s
+4y
+3elle
+7s
+3houriya
+9as
+3p
+4able
+4ed
+5r
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7ly
+7s
+4off
+7s
+4s
+5uit
+8s
+4y
+2n
+3caceous
+5te
+7s
+4o
+5es
+5s
+4tion
+8al
+8s
+5ural
+7e
+8s
+4us
+6es
+3eating
+9s
+3gle
+6d
+6gym
+9s
+6like
+6s
+5i
+6er
+7st
+6s
+7t
+8s
+5y
+3ior
+6ate
+9s
+6ities
+8y
+6s
+4per
+7s
+3k
+4anoo
+8s
+4ed
+5r
+6s
+5t
+6ed
+7er
+9ed
+9ing
+9s
+7r
+8s
+6ing
+9s
+6s
+6ted
+8r
+9s
+7ing
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+4man
+5en
+4s
+4y
+5ard
+8s
+3ta
+5s
+4o
+5s
+2pati
+6s
+3e
+4s
+3on
+5s
+2ra
+4l
+5ly
+4nt
+6s
+4ssic
+4t
+5ory
+5s
+3e
+4l
+5s
+3idic
+7al
+9ly
+4ed
+5s
+4sconsult
+9ults
+5diction
+9ional
+9ions
+9ive
+5prudence
+9ences
+9ent
+9ential
+9ents
+5t
+6ic
+8al
+9lly
+6s
+3or
+5s
+3y
+4ing
+4less
+4man
+6st
+8s
+5en
+4woman
+7en
+2s
+3sive
+7s
+3t
+4ed
+5r
+6s
+5st
+4ice
+7r
+8s
+7s
+8hip
+9ips
+6iability
+9le
+8lism
+9isms
+8r
+9ies
+9s
+9ship
+9ships
+9y
+5fiability
+9le
+9leness
+9ly
+7cation
+9tions
+9tive
+9tor
+9tors
+9tory
+7ed
+8r
+9s
+8s
+6y
+7ing
+5ng
+4le
+6d
+6s
+5ing
+5y
+4ness
+8es
+4s
+2t
+3e
+4like
+4s
+3s
+3ted
+4ied
+6s
+5ng
+7ly
+4y
+5ing
+2ve
+4nal
+7s
+5escence
+9nces
+9nt
+5ile
+8ly
+8ness
+9esses
+8s
+7ia
+8ties
+9y
+4s
+3ie
+5s
+2xtapose
+9d
+9s
+8ing
+9tion
+9tional
+9tions
+1ymold
+2nx
+4es
+0ka
+2al
+3ma
+5s
+3s
+2b
+3ab
+5bed
+6ing
+5s
+4ddi
+7s
+4ka
+6s
+4la
+6s
+5ism
+8s
+7t
+8ic
+8s
+4r
+5agoya
+9as
+5s
+4ya
+6s
+3bala
+7h
+8s
+7s
+6ism
+9s
+8t
+9ic
+9s
+3ele
+6s
+5jou
+8s
+8w
+9s
+3iki
+6s
+3ob
+5bed
+6ing
+5s
+3s
+3uki
+6s
+2ccha
+6s
+3ha
+5hri
+8s
+4cha
+4eri
+7s
+4ina
+7s
+3k
+4s
+2daitcha
+9s
+3dish
+7es
+7im
+3e
+4s
+3i
+4s
+2e
+3d
+3ing
+3s
+2f
+3feeklatsch
+9tsches
+4ir
+6boom
+9ms
+6s
+5yah
+8s
+6eh
+8s
+3ila
+6s
+4r
+5s
+3s
+3tan
+6s
+2go
+4ol
+6s
+4s
+4ul
+6e
+7s
+6s
+3u
+4s
+2hal
+5s
+4wai
+7s
+3ikatea
+9s
+7oa
+9s
+3una
+6s
+2i
+3ak
+5ed
+5ing
+5s
+3d
+4s
+3e
+4s
+3f
+4s
+3k
+4a
+5i
+6s
+5s
+5waka
+9s
+4omako
+9s
+4s
+3l
+4s
+4yaird
+9s
+6rd
+8s
+3m
+4akam
+8s
+4s
+3n
+4g
+5a
+6s
+4it
+6e
+7s
+6s
+4ogeneses
+9sis
+9tic
+4s
+3romone
+9s
+3s
+4er
+6dom
+9s
+6in
+8s
+7sm
+9s
+6s
+7hip
+9ps
+3zen
+6s
+2jawah
+7s
+3eput
+7s
+2k
+3a
+4po
+6s
+4riki
+8s
+4s
+3emono
+8s
+3i
+4emon
+8s
+4s
+5tocracies
+9acy
+3odyl
+7s
+3s
+3uro
+6s
+2lam
+5ata
+8s
+5dan
+8s
+5kari
+9s
+5s
+4nchoe
+9s
+4shnikov
+9ovs
+3e
+4idophone
+9ones
+7scope
+9opes
+9opic
+4ndar
+8ed
+8ing
+8s
+6s
+4s
+4wife
+6ves
+4yard
+8s
+3i
+4an
+6s
+4f
+5ate
+8s
+5s
+4mba
+7s
+4nite
+8s
+4ph
+6ate
+9s
+6s
+4s
+4um
+6s
+3lidin
+8s
+5krein
+9ns
+5type
+9s
+3mia
+6s
+3ong
+6s
+4oki
+7e
+8s
+7s
+4type
+8s
+3pa
+5c
+6s
+5k
+6s
+5s
+4is
+6es
+3somine
+9d
+9s
+8ing
+3uki
+6s
+4mpit
+8s
+3yptra
+8s
+2m
+3a
+4aina
+8s
+4cite
+8s
+4hi
+6s
+4la
+6s
+4s
+3e
+4es
+6es
+5z
+6es
+4la
+6s
+6ukion
+9ons
+4rad
+7ed
+7ing
+7s
+4s
+3i
+4chi
+7s
+4k
+5aze
+8s
+5s
+4la
+6s
+4s
+5es
+3me
+3okamo
+8s
+3pong
+7s
+3seen
+7s
+4in
+6s
+2na
+4e
+5s
+4ka
+6s
+4mycin
+9s
+4s
+3ban
+6s
+3dies
+4y
+3e
+4h
+5s
+4s
+3g
+4a
+5roo
+8ed
+8ing
+8s
+5s
+4ha
+6s
+4s
+3ji
+5s
+3s
+4es
+3t
+4ar
+6s
+4ed
+5la
+7s
+6e
+7s
+5n
+6s
+4ha
+6s
+4ikoy
+8ed
+8ing
+8s
+5ng
+4s
+3uka
+6s
+3zu
+5s
+2oliang
+8s
+5n
+6e
+7s
+6ic
+7se
+9d
+9s
+8ing
+7te
+9s
+8ic
+7ze
+9d
+9s
+8ing
+6oses
+8is
+6s
+3n
+4ic
+4s
+2pa
+4s
+3ellmeister
+9sters
+3h
+4s
+3ok
+5s
+3pa
+5s
+3uka
+6s
+4t
+5t
+2ra
+4biner
+9s
+4ism
+7s
+5t
+6s
+4ka
+6s
+5ia
+7s
+5ul
+7s
+4mu
+6s
+4nga
+7ed
+7ing
+7s
+4oke
+7s
+4s
+4t
+5e
+6ist
+9s
+6ka
+8s
+6s
+5s
+3earea
+8s
+4ngo
+7s
+3ite
+6s
+3k
+4ed
+4ing
+4s
+3ma
+5s
+4ic
+6ally
+3n
+4s
+3o
+4o
+5s
+4ro
+6s
+4s
+5hi
+7s
+5s
+6es
+3ri
+5s
+4oo
+6s
+3sey
+6s
+4ies
+4t
+5ic
+6fication
+9ations
+8ed
+9s
+7y
+8ing
+5s
+4y
+3t
+4er
+6s
+4ing
+7s
+4s
+3uhiruhi
+9is
+3yogamic
+9es
+8y
+6ram
+9s
+5kineses
+9sis
+9tic
+5logic
+9cal
+9es
+9st
+9sts
+8y
+6ymph
+9hs
+7ses
+8is
+7tic
+5mapping
+9ings
+5n
+6s
+5plasm
+9mic
+9ms
+5some
+9s
+5tin
+8s
+6ype
+9d
+9s
+8ic
+9cal
+9cally
+9ng
+3zies
+4y
+2s
+3bah
+6s
+3ha
+5s
+4er
+6ed
+6ing
+6s
+4mir
+7s
+4rus
+7es
+6t
+7h
+8s
+7s
+3me
+2t
+3a
+4bases
+7is
+6tic
+5olic
+9ally
+8sm
+9ms
+6thron
+9ons
+4dromous
+4kana
+8s
+4l
+5s
+4na
+6s
+4s
+4thermometer
+4vothron
+9ons
+3china
+8s
+4ina
+7s
+3hak
+6ali
+9s
+6s
+5revousa
+9usas
+6ometer
+9ters
+6ses
+7is
+4odal
+6e
+7s
+6ic
+3i
+4on
+6s
+4po
+6s
+4s
+3orga
+7s
+3s
+4ura
+7s
+3ti
+5s
+3ydid
+7s
+3zenjammer
+9mers
+2ugh
+5s
+3matua
+8s
+3papa
+7s
+3ri
+5es
+5s
+4u
+5s
+4y
+2va
+4kava
+8s
+4l
+5s
+4s
+5s
+6es
+2w
+3a
+4kawa
+8s
+4natanga
+9gas
+4s
+4u
+5s
+3ed
+3ing
+3s
+2y
+3ak
+5ed
+6r
+7s
+5ing
+8s
+5s
+3le
+5s
+4ied
+3o
+4ed
+5s
+4ing
+7s
+4s
+3s
+2zachki
+6oc
+8s
+7k
+4tski
+8es
+7y
+5zka
+8s
+3i
+4llion
+9s
+4s
+3oo
+5s
+1bar
+4s
+1ea
+3s
+4ar
+6s
+3vie
+6s
+2b
+3ab
+5bed
+6ing
+5s
+4r
+5s
+3bed
+4ie
+6s
+5ng
+4ock
+7s
+4uck
+7s
+3ele
+6s
+3lah
+6s
+3ob
+5bed
+6ing
+5s
+3s
+2ck
+4ed
+4ing
+4le
+6d
+6s
+5ing
+8s
+4s
+5es
+5ies
+5y
+2d
+3dah
+6s
+3ge
+5d
+5r
+6ee
+8s
+6s
+5s
+4ier
+6st
+5ng
+4y
+3s
+2ech
+5es
+3f
+4s
+3k
+4ed
+5r
+6s
+4ing
+4s
+3l
+4age
+7s
+4boat
+8s
+4ed
+5r
+6s
+4hale
+8d
+8s
+7ing
+6ul
+8ed
+8ing
+9ngs
+8s
+4ie
+6s
+5ng
+7s
+5vine
+9s
+4less
+4man
+5en
+4s
+5on
+7s
+4yvine
+9s
+3ma
+5s
+3n
+4ed
+5r
+6s
+5st
+4ing
+7s
+4ly
+4ness
+8es
+4o
+5s
+4s
+3p
+4able
+4er
+6less
+6s
+7hip
+9ps
+4ing
+7s
+4net
+7s
+4s
+5ake
+8s
+7y
+3shond
+8en
+8s
+4ter
+7s
+3t
+4s
+3ve
+5s
+2f
+3fel
+6s
+4iyah
+8s
+6eh
+8s
+3ir
+5s
+3s
+3tedes
+3uffle
+8d
+8s
+7ing
+2g
+3eler
+7s
+3ged
+5r
+6s
+4ing
+3ler
+6s
+4ing
+7s
+3s
+2hua
+5s
+2ight
+3r
+4en
+6s
+5tsu
+8s
+4in
+6s
+4s
+3ster
+7s
+3tloa
+7s
+2keno
+6s
+4rengu
+9s
+3s
+4ye
+6s
+2lep
+5s
+3im
+5s
+3l
+4aut
+7s
+4ies
+4s
+4y
+3oid
+6al
+6s
+3p
+4ed
+5r
+6s
+4ie
+6s
+5ng
+4s
+4y
+3son
+6s
+3t
+4er
+6s
+4ie
+6s
+4s
+4y
+3vin
+6s
+3yphitic
+2mb
+4ed
+4ing
+4la
+6s
+4o
+5ed
+5ing
+5s
+4s
+3p
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7s
+4le
+6s
+4s
+4t
+4y
+2n
+3af
+5s
+3ch
+5es
+3do
+5s
+3ned
+5l
+6ed
+6ing
+6led
+7ing
+6man
+7en
+6s
+5r
+6s
+5t
+6s
+6t
+7ed
+7ing
+7s
+4ing
+7s
+3o
+4geneses
+9is
+8tic
+9ically
+4phobia
+9as
+4s
+5es
+5is
+7es
+4tic
+7ist
+9ts
+7s
+5ron
+8s
+3s
+4peck
+8le
+3t
+4e
+5d
+5s
+4ia
+6s
+5ng
+4ledge
+9s
+4s
+2p
+3halic
+8s
+7n
+8s
+4ir
+6s
+3i
+4s
+3ped
+5n
+4ing
+5t
+3s
+3t
+2ramic
+7s
+4tectomies
+9my
+5in
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ophilic
+8us
+7s
+6tides
+8s
+9es
+5ogenous
+6id
+6ma
+8s
+8ta
+7eter
+9ers
+6phyre
+9res
+7lastic
+9sties
+9sty
+6se
+8s
+7ic
+8s
+6tic
+7omies
+9y
+4unograph
+9aphs
+3b
+4aya
+7s
+4ed
+4ing
+7s
+4s
+5ide
+8s
+5tone
+9s
+3chief
+8ed
+8ing
+8s
+7ves
+5oo
+3el
+5s
+4ru
+6s
+3f
+4ed
+4ing
+4looey
+4s
+4uffle
+9d
+9s
+8ing
+3kier
+6st
+4y
+3ma
+5s
+4es
+6ite
+9s
+6s
+7e
+8s
+4is
+6es
+3n
+4e
+5d
+5l
+6ed
+6ing
+6led
+7ing
+7y
+6s
+5s
+4icterus
+9uses
+5ng
+7s
+5sh
+5te
+7s
+4mantel
+4s
+3o
+4gen
+7s
+4s
+5ene
+8s
+5ine
+8s
+3plunk
+8ed
+8ing
+8s
+3ria
+6s
+5es
+4y
+3santite
+9es
+4ey
+6mere
+9es
+6s
+3ve
+5d
+5s
+4ing
+3ygma
+7s
+7ta
+8ic
+2sar
+5s
+3h
+4es
+3t
+4ing
+4rel
+7s
+4s
+2t
+3a
+4mine
+8s
+4s
+3ch
+5es
+5ing
+5up
+7s
+3e
+4ne
+6s
+4s
+3mia
+6s
+3o
+4geneses
+9is
+7ic
+4l
+5s
+4naemia
+9as
+5e
+6mia
+9s
+6s
+5ic
+5uria
+9s
+4se
+6s
+5is
+5teroid
+9ids
+4tic
+4xime
+8s
+3s
+3tle
+6drum
+9mmer
+9mmers
+9ms
+6ful
+9s
+6s
+7titch
+9tches
+3ubah
+7s
+5ot
+7h
+2vel
+5s
+3il
+5s
+2wl
+4er
+5st
+3pie
+6s
+2x
+3es
+2y
+3board
+8ed
+9r
+9rs
+8ing
+9ngs
+9st
+9sts
+8s
+4ugle
+8s
+5tton
+9s
+3card
+7s
+3ed
+3hole
+7s
+3ing
+6s
+3less
+4ine
+7s
+4ogger
+9s
+7ing
+9gs
+3note
+7d
+7r
+8s
+7s
+6ing
+3pad
+6s
+5l
+6s
+4unch
+8ed
+9r
+9rs
+9s
+8ing
+3ring
+3s
+4et
+6s
+4ter
+7s
+5one
+8d
+8s
+7ing
+5roke
+9d
+9s
+8ing
+9ngs
+3way
+6s
+4ord
+7s
+6ker
+9s
+1gotla
+6s
+1haddar
+7s
+4i
+5s
+3f
+4s
+3ki
+5like
+5s
+3lat
+6s
+4if
+6a
+7h
+8s
+7s
+7t
+8e
+9s
+8s
+6s
+3mseen
+8s
+5in
+7s
+3n
+4ate
+7s
+4da
+6s
+4ga
+6s
+4jar
+7s
+4s
+5ama
+8h
+9s
+8s
+4um
+6s
+3ph
+5s
+3rif
+6s
+3t
+4s
+3ya
+5l
+6s
+5s
+3zen
+6im
+6s
+4i
+5s
+2eda
+5h
+6s
+5s
+4iva
+7l
+7s
+7te
+9s
+6e
+7s
+6ial
+8te
+9es
+3t
+4h
+5s
+4s
+2i
+3dmutgar
+9rs
+3lafat
+8s
+5t
+6s
+4im
+6s
+3mar
+6s
+3rkah
+7s
+3s
+3tmutgar
+9rs
+2odja
+6s
+3ja
+5s
+3r
+4s
+3tbah
+7s
+5eh
+7s
+3um
+5s
+2ud
+4s
+3rta
+6s
+3skhus
+8es
+3tbah
+7s
+1i
+2aat
+5s
+3ng
+5s
+3ugh
+6s
+2bbe
+5h
+6s
+5s
+4i
+5s
+5tz
+7ed
+8r
+9s
+8s
+7ing
+4le
+6d
+6s
+5ing
+4utz
+7im
+7nik
+9ks
+3e
+4i
+5s
+4s
+3itka
+7s
+5z
+6ed
+7r
+8s
+7s
+6ing
+3la
+5h
+6s
+5s
+3osh
+6ed
+7s
+6ing
+2ck
+4able
+6out
+9s
+5round
+9ds
+4back
+8s
+6ll
+8s
+5oard
+9s
+6x
+7ed
+8r
+9s
+8s
+7ing
+9gs
+4down
+8s
+4ed
+5r
+6s
+4flip
+8ped
+9ing
+8s
+4ier
+6st
+5ng
+4off
+7s
+5ut
+7s
+4s
+5haw
+8s
+9es
+5orter
+9rs
+5tand
+9s
+7rt
+9ed
+9ing
+9s
+4up
+6s
+4y
+2d
+3ded
+5r
+6s
+4ie
+6d
+6r
+7s
+6s
+6wink
+9kie
+9kies
+9ks
+5ng
+7ly
+5sh
+7ness
+9sses
+4le
+6s
+4o
+5es
+5s
+4ush
+7es
+4y
+5ing
+5wink
+9s
+3el
+5s
+3ge
+4ie
+6r
+6st
+4love
+3let
+6s
+4ike
+5ng
+7s
+3nap
+6ed
+7e
+8s
+7r
+8s
+6ing
+9s
+6ped
+8e
+9s
+8r
+9s
+7ing
+9gs
+6s
+4ey
+6like
+6s
+3ologies
+8st
+9ts
+7y
+3s
+4kin
+7s
+4takes
+3ult
+6s
+3vid
+6s
+2ef
+4s
+3kie
+6s
+3lbasa
+8s
+7i
+7y
+3r
+4ie
+6s
+4s
+3selguhr
+9rs
+8r
+9s
+5rite
+9s
+4ter
+7s
+3v
+4e
+5s
+4s
+2f
+3f
+3s
+2ght
+5s
+2koi
+5s
+3umon
+7s
+4yu
+6s
+2ld
+4erkin
+9s
+3erg
+6s
+4y
+5s
+3im
+5s
+3l
+4able
+5dar
+8s
+5s
+6es
+4cow
+7s
+5rop
+8s
+4dee
+7r
+8s
+7s
+4ed
+5r
+6s
+4ick
+7s
+5e
+6s
+5fish
+9es
+5kinick
+9cks
+5ng
+7ly
+7s
+4joy
+7s
+4ock
+7s
+5gie
+8s
+4s
+4ut
+6s
+3n
+4ed
+4ing
+4s
+3o
+4bar
+7s
+6se
+8s
+6ud
+8s
+5it
+7s
+5yte
+8s
+4calorie
+9ies
+5urie
+9s
+5ycle
+9s
+4gauss
+9es
+5ram
+8me
+9es
+8s
+7y
+8s
+4hertz
+9es
+4joule
+9s
+4liter
+9s
+7re
+9s
+4meter
+9s
+7re
+9s
+8ic
+9cal
+5ole
+8s
+4parsec
+9cs
+6scal
+9ls
+5ond
+8s
+4rad
+7s
+4s
+4ton
+7ne
+9s
+7s
+4volt
+8s
+4watt
+8s
+3p
+4s
+3t
+4ed
+5r
+6s
+4ie
+6s
+5ng
+7s
+4like
+4s
+4y
+2mberlite
+9es
+4o
+5ed
+5ing
+5s
+3chee
+7s
+5i
+6s
+3mer
+6s
+3ono
+6ed
+6s
+2n
+3a
+4estheses
+9sia
+9sias
+9sis
+9tic
+4kina
+8s
+4ra
+6s
+4s
+5e
+6s
+3chin
+7s
+4ob
+6s
+3d
+4a
+4ed
+5r
+6garten
+9tener
+9teners
+9tens
+9tner
+9tners
+6s
+7piel
+9els
+5st
+4hearted
+9edly
+9edness
+4ie
+6s
+5ng
+4le
+6d
+6r
+7s
+6s
+7s
+8ly
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5y
+4ness
+8es
+4red
+7ness
+9sses
+7s
+8hip
+9ips
+4s
+4y
+3e
+4ma
+6s
+6tic
+9al
+9ally
+9s
+7ograph
+9rapher
+9raphic
+9raphs
+9raphy
+4s
+5cope
+9d
+9s
+8ing
+5es
+5iatric
+9ics
+6c
+7s
+6ologies
+9gist
+9gists
+9gy
+6path
+9hic
+9hies
+9hist
+9hists
+9hs
+9hy
+6s
+6therapies
+9rapy
+5theses
+9ia
+9ias
+9is
+8tic
+9ically
+4theodolite
+9olites
+5ic
+7al
+9ly
+7ist
+9ts
+7s
+6n
+7s
+5ochore
+9res
+6graph
+9phs
+6nuclei
+9leus
+9leuses
+6plast
+9sts
+6scope
+9pes
+7ome
+9es
+3folk
+7s
+3g
+4bird
+8s
+5olt
+8s
+4craft
+9s
+5up
+7s
+4dom
+7ed
+7less
+7s
+4ed
+4fish
+8er
+9rs
+9s
+4hood
+8s
+4ing
+4klip
+8s
+4le
+6s
+7s
+6t
+7s
+5ier
+7st
+6hood
+9ds
+6ke
+6ness
+9ses
+7g
+8s
+5y
+4maker
+9s
+4pin
+7s
+5ost
+8s
+4s
+5hip
+8s
+5ide
+8s
+5nake
+9s
+4wood
+8s
+3in
+5s
+3k
+4ajou
+8s
+4ed
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4le
+6s
+4s
+3less
+3nikinic
+9ck
+9cks
+9cs
+8nick
+9icks
+3o
+4ne
+6s
+4s
+3red
+6s
+3s
+4folk
+8s
+4hip
+7s
+4man
+5en
+4woman
+7en
+3tledge
+9s
+2ore
+5s
+3sk
+5s
+2p
+3e
+4s
+3p
+4a
+5ge
+7s
+5s
+4ed
+5n
+5r
+6ed
+7r
+8s
+6ing
+6s
+4ing
+4s
+3s
+4kin
+7s
+3unji
+7s
+2r
+3ana
+6s
+3beh
+6s
+4igrip
+9s
+4y
+3igami
+8s
+4mon
+7s
+3k
+4ed
+4ing
+7s
+4man
+5en
+4s
+4ton
+7s
+4ward
+4yaird
+9s
+6rd
+8s
+3mess
+7es
+3n
+4ed
+4ing
+4s
+3pan
+6s
+3ri
+5s
+3s
+4ch
+6es
+6wasser
+9sers
+3tan
+6s
+4le
+6d
+6s
+2s
+3an
+5s
+3h
+4es
+4ka
+6s
+5e
+6s
+3mat
+6s
+4et
+6ic
+6s
+3s
+4able
+7y
+5gram
+9s
+4ed
+5l
+6s
+5r
+6s
+5s
+4ier
+6st
+5ng
+7s
+4ogram
+9s
+4peptin
+9ns
+4y
+3t
+4ed
+4ful
+7s
+4ing
+4s
+4vaen
+8s
+2t
+3bag
+6s
+3chen
+7alia
+9ias
+7dom
+9ms
+7ed
+8r
+9s
+8t
+9s
+9te
+9tes
+7ing
+7s
+7ware
+9res
+3e
+4board
+9s
+4d
+4like
+4nge
+7s
+4r
+5s
+4s
+5urfing
+9ngs
+3h
+4ara
+7s
+4e
+5d
+5s
+4ing
+4s
+3ing
+6s
+3ling
+7s
+3s
+4ch
+6es
+6ier
+8st
+7fied
+9es
+8y
+9ing
+7ly
+6ness
+9ses
+6y
+4et
+6s
+3ted
+5l
+6s
+5n
+6ed
+6ing
+7sh
+9ly
+9ness
+9nesses
+6s
+6y
+4ies
+5ng
+5wake
+9s
+4le
+6d
+6r
+6s
+7t
+5ier
+7st
+6ng
+5y
+4ul
+6s
+4y
+3ul
+5s
+2va
+4s
+2wi
+4fruit
+9s
+4s
+5ports
+1lang
+5farbe
+9es
+5s
+3p
+4ped
+5ing
+4s
+3tch
+6es
+4sch
+7es
+3vern
+7s
+4ier
+7s
+3xon
+6ed
+6ing
+6s
+2eagle
+7s
+3bsiella
+9as
+3enex
+7es
+3inhuisie
+9ies
+3ndusic
+8ties
+9y
+3pht
+6ic
+7sm
+9s
+6s
+4to
+6cracies
+9cy
+9tic
+6mania
+9iac
+9iacs
+9ias
+6s
+3tt
+5erschuh
+9huhe
+5s
+3zmer
+7s
+5orim
+2ick
+5s
+3eg
+3k
+4s
+3nker
+7s
+4ostat
+9s
+3pdas
+7es
+4springer
+9gers
+3ster
+7s
+2ondike
+8d
+8r
+9s
+8s
+7ing
+5yke
+8d
+8r
+9s
+8s
+7ing
+4g
+5s
+3och
+6es
+6man
+9s
+7en
+4f
+5s
+4tch
+7es
+7man
+9ns
+8en
+2udge
+6d
+6s
+6y
+5ier
+7st
+6ng
+5y
+3ge
+5d
+5s
+4ing
+3tz
+5es
+5ier
+7st
+6ness
+9ses
+5y
+2ystron
+8s
+1nack
+5ed
+6r
+7ed
+7ies
+8ng
+7s
+7y
+5ier
+7st
+6ness
+9ses
+7g
+6sh
+5s
+5wurst
+9ts
+5y
+3g
+4gier
+7st
+6ness
+9ses
+5y
+4s
+3idel
+5lach
+3p
+4ped
+6r
+7s
+5ing
+5le
+7d
+7s
+6ing
+4s
+5ack
+8ed
+8s
+4weed
+8s
+3r
+4l
+5ier
+7st
+5s
+5y
+4red
+5ier
+7st
+6ng
+5y
+4s
+3ur
+5s
+3ve
+5ries
+6y
+5s
+6hip
+9s
+4ish
+7ly
+7ness
+9sses
+3we
+5l
+6s
+5s
+2ead
+5able
+5ed
+6r
+7s
+5ing
+5s
+3e
+4cap
+7ped
+8ing
+9ngs
+7s
+4d
+4hole
+8s
+4ing
+4jerk
+4l
+5ed
+6r
+7s
+5ing
+5s
+4pad
+7s
+6n
+7s
+5iece
+9s
+4s
+5ies
+5ock
+8s
+3idel
+7s
+5lach
+3ll
+5ed
+5ing
+5s
+4t
+3sset
+7s
+3vell
+7ed
+7ing
+7s
+3w
+2icker
+7bocker
+9ckers
+7ed
+7s
+5knack
+9ks
+5point
+9ts
+5s
+3fe
+5d
+5less
+6ike
+5man
+6en
+5point
+9ts
+5r
+6est
+9s
+6s
+5s
+4ing
+7s
+3ght
+6age
+9s
+6ed
+6head
+9ds
+7ood
+9ds
+6ing
+6less
+7ier
+9st
+8ness
+9esses
+7y
+6s
+3phofia
+9s
+3sh
+5es
+3t
+4ch
+6es
+4s
+4table
+5ed
+6r
+7s
+5ing
+8s
+5le
+7s
+4wear
+8s
+3ve
+5d
+5s
+4ing
+2obbed
+6r
+7s
+5ier
+7st
+6ness
+9ses
+5le
+7d
+7s
+6ier
+8st
+7ng
+6y
+5y
+4heads
+4kerrie
+9es
+4like
+4s
+5tick
+9s
+3ck
+5about
+9ts
+5down
+9s
+5ed
+6r
+7s
+5ing
+8s
+5less
+5off
+8s
+6ut
+8s
+5s
+5wurst
+9ts
+3ll
+5ed
+6r
+7s
+5ier
+7st
+6ng
+5s
+5y
+3p
+4ped
+4s
+3sp
+5s
+3t
+4grass
+9es
+4hole
+8s
+4less
+5ike
+4s
+4ted
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5y
+4weed
+8s
+5ork
+8s
+3ut
+5ed
+5ing
+5s
+3w
+4able
+8ness
+9esses
+4e
+5r
+6s
+5s
+4how
+7s
+4ing
+7er
+8st
+7ly
+7ness
+9sses
+7s
+4ledgability
+9ble
+9bly
+8e
+9able
+9ably
+9d
+9s
+8ing
+4n
+5s
+4s
+2ub
+4bier
+7st
+5le
+7d
+7s
+6ier
+8st
+7ng
+6y
+5y
+4s
+3ckle
+7ball
+9ller
+9llers
+9lls
+8one
+9nes
+7d
+8uster
+9sters
+7head
+9aded
+9ads
+7r
+8s
+7s
+6ier
+8st
+7ng
+6y
+3r
+4l
+5ed
+5ier
+7st
+6ng
+8s
+5s
+5y
+4r
+5s
+4s
+3t
+4s
+1o
+2a
+3la
+5s
+3n
+4s
+3p
+4s
+3s
+2b
+3an
+5g
+6s
+5s
+3o
+4ld
+6s
+4s
+3s
+2chia
+6s
+2ekoea
+7s
+4sister
+9rs
+3l
+4s
+2ff
+4s
+3ta
+5s
+4gar
+7i
+8s
+7s
+4work
+8s
+2gal
+5s
+2ha
+4nim
+4s
+3ekohe
+8s
+4n
+3l
+4rabi
+8es
+8s
+4s
+3utuhutu
+9us
+2i
+3ne
+5s
+3s
+2ji
+4s
+2ka
+4ko
+6s
+4nee
+7s
+4s
+3er
+5s
+3iri
+6s
+3obeh
+4pu
+6s
+4wai
+7s
+3ra
+5s
+3um
+5s
+2la
+4cky
+4s
+3basi
+7s
+6si
+8s
+3hoz
+6es
+6y
+3inski
+8es
+7y
+3khos
+7es
+7y
+6z
+7es
+7nik
+9ki
+9ks
+7y
+4oz
+6es
+6y
+3o
+4s
+2matik
+7s
+3bu
+5s
+3issar
+8s
+4taji
+8s
+3ondor
+8ock
+9k
+8s
+2n
+3aki
+6s
+3bu
+5s
+3d
+4o
+5s
+3eke
+6s
+3fyt
+6s
+3goni
+3imeter
+9s
+4ni
+6s
+4ologies
+8y
+4scope
+9s
+3k
+4ed
+4ing
+4s
+3ning
+3s
+2odoo
+6s
+3k
+4aburra
+9as
+4ed
+4ie
+6r
+6st
+5ly
+5ness
+9es
+6g
+4s
+4y
+3lah
+6s
+3ri
+5es
+5s
+2p
+3asetic
+3eck
+6s
+4k
+5s
+3h
+4s
+3iyka
+7s
+5ok
+3je
+5s
+3pa
+5s
+4ie
+6s
+3s
+2r
+3a
+4i
+4ri
+6s
+4s
+4t
+5s
+3e
+4ro
+6ed
+6ing
+6s
+4s
+3fball
+8s
+3imako
+8s
+3kir
+6s
+3ma
+5s
+3o
+4miko
+8s
+4ra
+6s
+4s
+4wai
+7s
+3s
+3u
+4n
+5a
+6s
+5y
+4s
+2s
+3es
+3her
+6ed
+6ing
+6s
+3mos
+6es
+3s
+4es
+2tahitanga
+9gas
+4re
+6s
+3ch
+5ed
+6s
+5ing
+3o
+4s
+4w
+5ed
+6r
+7s
+5ing
+5s
+3tabos
+8es
+3uku
+6s
+6tuku
+9us
+3wal
+6s
+2ulan
+6s
+4ibiaca
+9as
+3mis
+6es
+6s
+7es
+4ys
+6es
+6s
+7es
+3prey
+7s
+3ra
+5s
+4bash
+8ed
+9s
+8ing
+4oi
+5s
+3skous
+8es
+4so
+6s
+2w
+3hai
+6s
+6whai
+9is
+3s
+3tow
+6ed
+7r
+8s
+6ing
+6s
+1raal
+5ed
+5ing
+5s
+3b
+4s
+3ft
+5s
+3it
+5s
+3ken
+6s
+4owiak
+9s
+3meria
+8s
+3ng
+5s
+4s
+5es
+4tz
+6es
+4z
+5es
+3ter
+6s
+3ut
+5s
+2easote
+8d
+8s
+7ing
+4tine
+8s
+3ep
+5s
+4se
+6d
+6s
+5ing
+3mlin
+7ologies
+9ogist
+9ogists
+9ogy
+7s
+3ng
+5s
+3osote
+8d
+8s
+7ing
+3plach
+5ech
+3utzer
+8s
+4zer
+7s
+3we
+5s
+2iegspiel
+9ls
+6spiel
+9els
+3ll
+5s
+3mmer
+7s
+3s
+4ed
+5s
+4ing
+2omeskies
+7y
+3na
+4e
+5n
+5r
+4or
+4ur
+3on
+5i
+5s
+2ubi
+5s
+4ut
+6s
+3gerrand
+9ds
+3ller
+7s
+3mhorn
+8s
+4kake
+8s
+4mholz
+7rn
+9s
+4per
+7s
+5ing
+8s
+3nk
+5ed
+5s
+2yolite
+8s
+7h
+8s
+4meter
+9s
+3pses
+5is
+4ton
+7ite
+7s
+3tron
+7s
+1sar
+4s
+1uccha
+6s
+3hcha
+4en
+6s
+2dlik
+6s
+3o
+4s
+5es
+3u
+4s
+3zu
+5s
+2e
+3h
+3s
+2fi
+4s
+4yah
+7s
+2gel
+5s
+2ia
+4s
+2kri
+5s
+3u
+4s
+2la
+4k
+5i
+5s
+4n
+5s
+4s
+3basa
+7s
+3fi
+5s
+3tur
+6s
+2mara
+6hou
+9s
+6s
+5i
+6s
+3baloi
+3era
+6s
+3ikumi
+8s
+4ss
+6es
+4te
+6s
+3mel
+6s
+5rbund
+9ds
+3quat
+7s
+3ys
+5es
+2na
+3dalini
+9s
+3e
+4kune
+8s
+3joos
+3kar
+6s
+4ur
+6s
+3zite
+7s
+2rbash
+7ed
+8s
+7ing
+3chatovium
+9iums
+3daitcha
+9as
+3fuffle
+9d
+9s
+8ing
+3gan
+6s
+3i
+4s
+3rajong
+9s
+4e
+5s
+3saal
+7s
+3ta
+5s
+4oses
+6is
+8es
+3u
+4s
+3vey
+6ed
+6ing
+6or
+8s
+6s
+2sso
+5s
+2ta
+4s
+3ch
+5a
+5es
+3i
+4s
+3u
+4s
+2vasz
+6ok
+2zu
+4s
+1vas
+4es
+4s
+5es
+2ell
+5ed
+5ing
+5s
+3tch
+6ed
+7r
+8s
+7s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6y
+1wacha
+6s
+3ito
+6s
+3nza
+6s
+3shiorkor
+9ors
+2ela
+5s
+1y
+2ack
+5s
+3k
+4s
+3ng
+5s
+4isation
+9ons
+6e
+7d
+7s
+6ing
+5te
+7s
+6ic
+5zation
+9ons
+6e
+7d
+7s
+6ing
+3r
+4s
+3t
+4s
+2bo
+4s
+5h
+6ed
+7s
+6ing
+2dst
+2e
+3s
+2le
+4s
+3ices
+4e
+5s
+4kes
+4n
+5s
+4x
+3loses
+6is
+3oe
+5s
+2mogram
+8s
+7ph
+9ic
+9ies
+9s
+9y
+2nd
+4e
+5d
+5s
+4ing
+4s
+3e
+2ogen
+6s
+2pe
+4s
+3hoses
+6is
+5tic
+2rie
+5lle
+8s
+5s
+2te
+4s
+3he
+5d
+5s
+4ing
+2u
+3s
+0la
+2ager
+6ed
+6ing
+6s
+3ri
+5s
+2b
+3anotation
+9ions
+4ra
+5um
+7s
+3da
+5cism
+9s
+5num
+8s
+5s
+3efactation
+9tions
+8ion
+9ons
+4l
+5able
+5ed
+6r
+7s
+5ing
+5la
+7te
+6ed
+7r
+8s
+6ing
+9s
+7st
+9s
+6oid
+6um
+5mate
+9s
+5s
+3ial
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+6s
+5te
+7d
+7s
+4le
+5ities
+7y
+4odental
+9als
+5nasal
+9ls
+5velar
+9rs
+4s
+5es
+4um
+3lab
+6s
+3or
+5atories
+9y
+5ed
+7ly
+7ness
+9sses
+6r
+7s
+5ing
+8ly
+6ous
+9ly
+9ness
+9nesses
+6sm
+8s
+7t
+8s
+6te
+8s
+5s
+6aving
+4ur
+6ed
+8ly
+8ness
+9esses
+7r
+8s
+6ing
+9ly
+7sm
+9s
+8t
+9s
+6s
+7ome
+3ra
+5doodle
+9les
+7r
+8escent
+8ite
+9tes
+8s
+5l
+4et
+6s
+4id
+6s
+4oid
+7s
+5se
+4um
+6s
+5sca
+4ys
+6es
+3s
+3urnum
+8s
+3yrinth
+9al
+9ian
+9ic
+9ical
+9ically
+9ine
+9itis
+9itises
+9odont
+9odonts
+9s
+2c
+3colite
+9s
+8h
+9ic
+9s
+8ic
+3e
+4bark
+8s
+4d
+4less
+5ike
+4r
+5abilities
+9ity
+7le
+6nt
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+5s
+5tian
+9s
+7d
+8s
+7lian
+9ans
+7ne
+4s
+4t
+5s
+4wing
+8s
+5ood
+8s
+6rk
+8s
+4y
+3hes
+6es
+4rymal
+9s
+8ries
+9y
+8tion
+9ions
+9or
+9ories
+9ors
+9ory
+7ose
+9ely
+9ities
+9ity
+3ier
+5st
+4ly
+4ness
+8es
+5g
+6s
+5ia
+7e
+7te
+9d
+8ion
+9ons
+3k
+4adaisical
+9ically
+9y
+7y
+4ed
+5r
+6ed
+6ing
+6s
+5y
+6ed
+6ing
+6s
+4ing
+4land
+8s
+5uster
+9rs
+8re
+9es
+4s
+3mus
+6es
+3onic
+7al
+9ly
+7ism
+9ms
+6sm
+8s
+3quer
+7ed
+8r
+9s
+7ing
+9gs
+7s
+7ware
+9res
+8ork
+9rks
+6y
+7ed
+7ing
+7s
+3rimal
+8s
+7ries
+8y
+7tion
+9ons
+8or
+9rs
+9ry
+6oso
+4osse
+8s
+4ymal
+8s
+7tor
+9rs
+9ry
+3s
+3talbumin
+9ins
+5m
+6s
+5rian
+9s
+6y
+5se
+7s
+5te
+7d
+7s
+6ing
+7on
+9al
+9ally
+9s
+4eal
+7ly
+7s
+6n
+5ous
+5scence
+9ces
+9t
+4ic
+5ferous
+9usness
+6ic
+6luous
+5vism
+9s
+8t
+9s
+4obacilli
+9llus
+5flavin
+9ins
+5genic
+6lobulin
+9ulins
+5meter
+9rs
+5ne
+7s
+6ic
+5protein
+9eins
+5scope
+9es
+6e
+7s
+6uria
+9as
+5vegetarian
+3una
+6e
+6l
+6r
+7ia
+7s
+7y
+6s
+6te
+5e
+6s
+5ose
+7ities
+9y
+4strine
+3y
+2d
+3anum
+7s
+3der
+6ed
+6ing
+6like
+6s
+6y
+4ie
+6s
+5sh
+7ness
+9sses
+6m
+7s
+3e
+4d
+4n
+5ed
+5ing
+5s
+4r
+5s
+4s
+4tte
+7s
+3hood
+7s
+3ies
+6wear
+9rs
+4fied
+7s
+5y
+6ing
+4ng
+6s
+5o
+6s
+3le
+5d
+5ful
+8s
+5r
+6s
+5s
+4ing
+3ron
+6e
+7s
+6s
+3s
+3y
+4bird
+8s
+5oy
+7s
+5ug
+7s
+4cow
+7s
+4fied
+7s
+6nger
+9rs
+6sh
+8es
+5lies
+6y
+5y
+6ing
+4hood
+8s
+4ish
+6m
+7s
+4kin
+7s
+4like
+8ness
+9esses
+5ove
+8s
+4palm
+8s
+4ship
+8s
+2eotropic
+3r
+4ed
+4ing
+4s
+3sie
+3tare
+7s
+4rile
+8s
+3vigate
+9d
+9s
+8ing
+4o
+5gyrate
+5rotary
+9tion
+9tions
+9tory
+4ulin
+8s
+6ose
+9s
+2g
+3an
+5s
+3ena
+6s
+5d
+6s
+5iform
+4r
+5ed
+5ing
+5phone
+9es
+5s
+3gard
+7ly
+7ness
+9sses
+7s
+4ed
+5n
+6s
+5r
+6s
+4in
+6g
+7ly
+7s
+6s
+3nappe
+8s
+4iappe
+9s
+3omorph
+9ic
+9ous
+9s
+4on
+6al
+6s
+3rimoso
+3s
+3una
+6s
+5e
+6s
+2h
+3ar
+5s
+3s
+2ic
+4al
+6ly
+4h
+5s
+4isation
+9ons
+6e
+7d
+7s
+6ing
+6m
+7s
+5ties
+6y
+5zation
+9ons
+6e
+7d
+7s
+6ing
+4s
+3d
+4ed
+4ing
+4ly
+4s
+3gh
+5er
+6st
+5s
+3k
+4a
+5s
+4ed
+5r
+6s
+4ing
+4s
+3n
+3pse
+6d
+6s
+5ing
+3r
+4age
+7s
+4d
+5ly
+5s
+6hip
+9s
+4ed
+4ier
+6st
+5ng
+5se
+7d
+7s
+6ing
+5ze
+7d
+7s
+6ing
+4s
+4y
+3sse
+6s
+3tance
+8s
+4h
+5ly
+4ies
+4y
+2ke
+4bed
+7s
+4d
+4front
+9s
+4land
+8s
+5et
+7s
+5ike
+4port
+8s
+4r
+5s
+4s
+5hore
+9s
+5ide
+8s
+3h
+4s
+3ier
+5st
+4n
+5g
+6s
+5s
+4sh
+3sa
+5s
+3y
+2lang
+6s
+4palooza
+9zas
+3die
+6s
+4y
+3ique
+7s
+3l
+4an
+6d
+7s
+6s
+5palooza
+9ozas
+5tion
+9s
+4ed
+4ing
+7s
+4s
+4ygag
+8ged
+9ing
+8s
+2m
+3a
+4istic
+4ntin
+8s
+4s
+5erai
+9s
+7ies
+7y
+3b
+4ada
+7s
+5st
+7e
+8d
+8s
+7ing
+7s
+4da
+6cism
+9ms
+6s
+5oid
+8al
+4ed
+5ncies
+7y
+6t
+7ly
+5r
+6s
+6t
+7s
+4ie
+6r
+6s
+7t
+5ng
+7s
+5tive
+9s
+4kill
+8s
+6n
+7s
+4like
+6ng
+8s
+4oys
+4requin
+9ns
+5usco
+9s
+4s
+5kin
+8s
+4y
+3e
+4brain
+9ed
+9s
+4d
+5h
+6s
+5s
+4lla
+7e
+7r
+8ly
+7s
+7te
+9d
+9ly
+8ion
+9ons
+6ibranch
+9anchs
+7corn
+9rns
+7form
+7rostral
+9strate
+6oid
+7se
+8ities
+9ty
+5y
+4ness
+8es
+5t
+6able
+9eness
+9y
+7tion
+9ons
+6ed
+8ly
+7r
+8s
+6ing
+9ly
+9s
+6s
+4r
+4s
+5t
+6ream
+9ms
+4ter
+7s
+3ia
+5e
+5s
+4ger
+7s
+4na
+6ble
+6e
+6l
+7s
+6r
+7ia
+9n
+9ns
+9s
+8n
+9s
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7y
+6s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5ectomies
+9my
+5g
+6ton
+9s
+5in
+7s
+6tis
+9es
+5ose
+6us
+4sh
+5ter
+8s
+4ter
+7s
+3med
+5r
+6geier
+9ers
+8yer
+9ers
+6s
+4ie
+6s
+5ger
+8s
+5ng
+7s
+4y
+3p
+4ad
+6aries
+8y
+6edromies
+9omy
+7phoria
+9orias
+6ist
+9s
+6omancies
+9ncy
+6s
+5s
+6es
+6se
+8s
+4black
+9s
+5rush
+4ed
+5r
+6n
+7s
+6s
+7es
+4holder
+9rs
+7e
+8s
+4ing
+7s
+5on
+7s
+4light
+9er
+9ers
+9s
+6t
+4oon
+7ed
+8r
+9ies
+9s
+9y
+7ing
+8st
+9ts
+7s
+4post
+8s
+4rey
+7s
+5ophyre
+9res
+9ric
+4s
+5hade
+9s
+6ell
+9s
+4uka
+7s
+6i
+7s
+4yrid
+8s
+3s
+4ter
+7s
+2na
+4i
+5s
+4s
+4te
+6d
+3ce
+5d
+5gay
+8s
+5jack
+9s
+5let
+8s
+5olar
+8te
+9ed
+9ely
+5r
+6s
+5s
+5t
+6ed
+6s
+5wood
+9s
+4h
+5ed
+6s
+5ing
+4iers
+5form
+5nate
+9d
+9s
+8ing
+9on
+9ons
+6g
+3d
+4amman
+9n
+9ns
+9s
+5u
+6let
+9s
+9te
+9tes
+6s
+4board
+9ing
+9ings
+9s
+4damne
+9d
+9s
+8ing
+5ros
+8es
+8t
+9s
+4e
+5d
+5r
+6s
+5s
+4fall
+8s
+5ill
+8ed
+8ing
+9ngs
+8s
+5orce
+9s
+7m
+8s
+4grab
+8s
+7vate
+9tes
+8e
+9s
+8iate
+9ates
+9ne
+9nes
+4holder
+9rs
+8ing
+9ngs
+4ing
+7s
+4ladies
+7y
+5er
+7s
+6ss
+8ness
+9esses
+5ine
+8s
+5ocked
+6per
+9s
+6rd
+8ism
+9sms
+8s
+5ubber
+9rly
+9rs
+8ing
+4man
+6rk
+8ed
+8ing
+8s
+6ss
+8es
+5en
+5ine
+8d
+8s
+7ing
+9gs
+4owner
+9s
+9ship
+9ships
+7ing
+9gs
+4race
+8s
+6il
+8s
+4s
+5cape
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+9st
+9sts
+5hark
+9s
+5ide
+8s
+5kip
+8ped
+9ing
+8s
+6necht
+9hts
+5leit
+6id
+8den
+8e
+9s
+8ing
+7p
+8s
+5man
+6en
+4waiter
+9rs
+6rd
+8s
+5ind
+8s
+3e
+4ly
+4s
+4way
+7s
+3g
+4aha
+7s
+5r
+6s
+4beinite
+9tes
+4er
+6ed
+6s
+5st
+4lauf
+8er
+9rs
+8s
+5ey
+7s
+4ostino
+9os
+5uste
+9s
+8ine
+9nes
+4rage
+8s
+5el
+7s
+5idge
+9s
+4shan
+8s
+5pel
+8s
+6iel
+9s
+5yne
+8s
+4uage
+8d
+8less
+8s
+7ing
+5e
+6d
+6s
+7cent
+6t
+7s
+7te
+9s
+5id
+7ly
+7ness
+9sses
+6sh
+8ed
+9r
+9rs
+9s
+8ing
+9ngly
+9ngs
+8ment
+9ents
+5or
+7ous
+9sly
+9sness
+7s
+5r
+6s
+3iard
+7s
+6ies
+6y
+4ferous
+4gerous
+4tal
+7s
+3k
+4ed
+5r
+5st
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4ly
+4ness
+8es
+4s
+4y
+3ner
+6et
+8s
+6s
+3olated
+5in
+7e
+8s
+7s
+4se
+5ities
+7y
+3squenet
+9ts
+3t
+4ana
+7s
+4erloo
+9s
+6n
+7ed
+7ing
+8st
+9ts
+7s
+4hanide
+9es
+7on
+9s
+7um
+9s
+5orn
+8s
+4s
+5kip
+8s
+3uginose
+8us
+9sness
+5o
+6s
+3x
+3yard
+7s
+3zknecht
+9ts
+2odicean
+9s
+3gai
+6s
+2p
+3aroscope
+9pes
+9pic
+9pies
+9pist
+9pists
+9py
+6tomies
+9y
+3board
+8s
+3dog
+6s
+3el
+5ed
+5led
+5s
+3ful
+6s
+3held
+3idarian
+8es
+8st
+9ts
+7y
+6te
+8d
+8s
+7ing
+8on
+9ns
+5eous
+6s
+7cence
+9nces
+9nt
+5icolous
+6fic
+9ation
+9ations
+8ed
+9s
+7y
+8ing
+6st
+8s
+4lli
+7form
+6us
+4n
+5s
+4s
+5es
+3je
+5s
+3ped
+5l
+6s
+5r
+6ed
+6ing
+6s
+5t
+6ed
+6s
+4ie
+6s
+5ng
+7s
+3s
+4able
+5ng
+7s
+4e
+5d
+5r
+6s
+5s
+4ible
+5ng
+4tone
+8s
+5rake
+9s
+6eak
+9s
+4us
+3top
+6s
+4ray
+7s
+3wing
+7s
+4ork
+7s
+2quearia
+2r
+3board
+8s
+3cener
+8s
+6ies
+7st
+9s
+6ous
+9ly
+6y
+4h
+5en
+6s
+3d
+4aceous
+5lite
+9s
+4ed
+5r
+6er
+8s
+6s
+4ier
+6st
+5ng
+4like
+4on
+6s
+5on
+7s
+4s
+4y
+3e
+4e
+5s
+4s
+3gando
+4e
+5hearted
+5ly
+5mouth
+9hs
+5n
+6ed
+7ss
+9es
+6ing
+6s
+5r
+5s
+6s
+7e
+8s
+6t
+4hetto
+9s
+4ish
+5tion
+9s
+4o
+5s
+3i
+4at
+6ed
+6ing
+6s
+4ne
+4s
+3k
+4ed
+5r
+6s
+4ier
+6st
+5ness
+9es
+6g
+5sh
+7ness
+9sses
+4s
+5ome
+5pur
+8s
+4y
+3mier
+7s
+3n
+4akes
+5x
+4ed
+5y
+6s
+4ier
+6st
+5ng
+4s
+3oid
+3rigan
+8s
+5kin
+8ism
+9sms
+8s
+4up
+6ed
+7r
+8s
+6ing
+6s
+3s
+3um
+5s
+3va
+5e
+5l
+5s
+5te
+7d
+4icidal
+8e
+9s
+5form
+5kite
+9s
+5parous
+3yngal
+8s
+6eal
+9ly
+9s
+7ctomee
+9omees
+9omies
+9omised
+9omized
+9omy
+7s
+6ismus
+9uses
+7tes
+8ic
+9des
+9s
+9ses
+6ologic
+9gical
+9gies
+9gist
+9gists
+9gy
+7phonies
+9ony
+7scope
+9opes
+9opic
+9opies
+9opist
+9opists
+9opy
+8pasm
+9asms
+7tomies
+9my
+5x
+6es
+2s
+3agna
+7s
+6e
+7s
+3car
+6s
+4ivious
+9sly
+9sness
+3e
+4d
+4r
+5disc
+9s
+8k
+9s
+5s
+5wort
+9s
+4s
+3h
+4ed
+5r
+6s
+5s
+4ing
+7ly
+7s
+6s
+4kar
+7s
+3ing
+6s
+3ket
+6s
+3que
+6s
+3s
+4es
+4i
+5e
+6s
+5s
+5tude
+9s
+4lorn
+4o
+5ck
+7s
+5ed
+6r
+7s
+6s
+5ing
+5s
+4u
+5s
+3t
+4age
+7s
+4born
+8s
+4ed
+5r
+6s
+4ing
+7ly
+7ness
+9sses
+7s
+4ly
+4s
+2t
+3ah
+5s
+4kia
+7s
+3ch
+5ed
+6s
+6t
+7s
+5ing
+5key
+8s
+5string
+9ngs
+3e
+4comer
+9s
+4d
+4en
+6er
+8s
+6rigged
+6s
+4ly
+4n
+5ce
+7s
+6ies
+6y
+5ed
+6ss
+8es
+5ing
+5s
+6ification
+5t
+6ly
+6s
+4r
+5ad
+6l
+7ed
+7ing
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7led
+8ing
+8y
+7s
+5born
+9s
+5igrade
+6sation
+9ions
+7e
+8d
+8s
+7ing
+6te
+8s
+7ic
+8ous
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5oversion
+9sions
+4scence
+9es
+8t
+5t
+6s
+4wake
+8s
+5ood
+8s
+4x
+5es
+3h
+4e
+5d
+5e
+6s
+5n
+5r
+6ed
+7r
+8s
+6ier
+8st
+7ng
+6s
+6y
+5s
+4i
+5er
+6st
+5ng
+7s
+5s
+4like
+4s
+4work
+8s
+4y
+5rism
+9s
+7tic
+6us
+8es
+3i
+4ces
+5ifer
+9ous
+9s
+5lave
+9s
+4fondi
+5undia
+9o
+9os
+9um
+4go
+6es
+6s
+4lla
+7s
+4meria
+9s
+4na
+6s
+5isation
+9ions
+7e
+8d
+8s
+7ing
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5o
+6s
+4rostral
+9ate
+4septate
+5h
+4tancies
+8y
+7t
+6t
+7ion
+9ns
+7s
+5ude
+8s
+7inal
+9ally
+9arian
+9arians
+9ous
+3ke
+5s
+3osol
+7ic
+7s
+3rant
+5tion
+9s
+4ia
+6s
+5ne
+7s
+4ocinia
+9es
+9um
+8y
+5n
+6s
+3s
+3te
+5n
+6s
+5r
+6ly
+6math
+9hs
+7ost
+5s
+4ice
+7d
+7s
+7work
+9rks
+6ing
+9s
+8i
+9o
+8o
+5n
+6s
+3u
+2uan
+5s
+3ch
+5ing
+5s
+3d
+4abilities
+9ty
+6le
+8ness
+9esses
+7y
+5num
+8s
+5tion
+9s
+7ve
+9s
+6or
+8ies
+8s
+8y
+4ed
+5r
+6s
+4ing
+4s
+3f
+4s
+3gh
+5able
+9ness
+9nesses
+8y
+5ed
+6r
+7s
+5ful
+5ier
+7st
+6ng
+8ly
+8s
+9tock
+9tocks
+5line
+9s
+5s
+6ome
+5ter
+8s
+5worthy
+5y
+3nce
+6d
+6gaye
+9es
+6s
+5h
+6ed
+7r
+8s
+7s
+6ing
+6pad
+9s
+5ing
+4d
+5er
+7ed
+8r
+9s
+8tte
+9tes
+7ing
+7s
+5ress
+9es
+7tte
+9es
+6ies
+6y
+7man
+8en
+7woman
+9men
+5s
+3ra
+5ceous
+5e
+5s
+4dalite
+9es
+4eate
+8d
+8s
+9hip
+9hips
+7ing
+8on
+9ns
+5l
+6ed
+6ing
+6led
+7ing
+6s
+4ic
+4ustine
+9es
+9us
+9uses
+4vikite
+9es
+4yl
+6s
+3wine
+7s
+2v
+3a
+4bo
+6es
+6s
+4form
+4ge
+6s
+4lava
+8s
+5ier
+8e
+9s
+8s
+6ke
+5liere
+9es
+4ndin
+8s
+4s
+5h
+6es
+4tera
+8s
+5ion
+8al
+8s
+5orial
+8es
+7y
+3e
+4d
+4er
+6ed
+6ing
+6s
+4ment
+8s
+4nder
+8ed
+8ing
+8s
+4r
+5bread
+9ds
+5ock
+8ed
+8ing
+8s
+5s
+4s
+3ing
+4sh
+6ed
+7r
+8s
+7s
+8t
+6ing
+6ly
+6ment
+9ts
+6ness
+9ses
+3olt
+6a
+7ed
+7ing
+7s
+6ed
+6ing
+6s
+3ra
+5s
+4ock
+7s
+3s
+3vies
+4y
+2w
+3book
+7s
+4reaker
+9rs
+8ing
+9ngs
+3court
+8s
+3ed
+4r
+4st
+3fare
+7s
+4ul
+6ly
+6ness
+9ses
+3giver
+8s
+6ing
+9s
+3in
+5e
+6s
+5g
+6s
+5s
+3k
+4s
+3land
+7s
+4ess
+7ly
+7ness
+9sses
+4ike
+3maker
+8s
+6ing
+9s
+5n
+4en
+4onger
+9s
+3n
+4ed
+4ier
+6st
+4mower
+9s
+4s
+4y
+3rencium
+9ms
+3s
+4uit
+7s
+3yer
+6ed
+6ing
+9s
+6like
+7y
+6s
+2x
+3ation
+8s
+6ve
+8ness
+9esses
+8s
+5or
+7s
+3er
+4s
+5t
+3ism
+6s
+5t
+6s
+4ties
+5y
+3ly
+3ness
+7es
+2y
+3about
+8s
+4way
+7s
+3back
+7ed
+7ing
+7s
+3deez
+3ed
+4r
+5age
+8s
+5ed
+5ing
+8s
+5s
+4tte
+7s
+3in
+5g
+6s
+5s
+3lock
+7s
+3man
+4en
+3off
+6s
+4ut
+6s
+4ver
+7s
+3people
+5rson
+9s
+3s
+4haft
+8s
+4tall
+8s
+3time
+7s
+3up
+5s
+3woman
+6en
+2zar
+5et
+7s
+7te
+9s
+8o
+9s
+5s
+3e
+4d
+4s
+3ied
+5r
+5s
+6t
+4ly
+4ness
+8es
+5g
+3o
+4ed
+5s
+4ing
+4s
+3uli
+6s
+6te
+8s
+4rite
+8s
+3y
+4bones
+4ing
+5sh
+3zarone
+8i
+4i
+4o
+1ea
+3ch
+5abilities
+9ity
+7le
+6te
+8s
+5ed
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5our
+8s
+5y
+3d
+4ed
+5n
+6ed
+6ing
+6ly
+6ness
+9ses
+6s
+5r
+6board
+9rds
+6ene
+9s
+7tte
+9es
+6less
+6s
+7hip
+9ps
+4ier
+6st
+5ng
+7ly
+7s
+4less
+4man
+5en
+4off
+7s
+4plant
+9s
+4s
+5crew
+9s
+5man
+6en
+4work
+8s
+7t
+8s
+4y
+3f
+4age
+7s
+4bud
+7s
+4cutter
+4ed
+5ries
+6y
+4hopper
+9rs
+4ier
+6st
+5ness
+9es
+6g
+4less
+8ness
+9esses
+6t
+7ed
+8er
+9rs
+8r
+9s
+7ing
+7s
+7ted
+8ing
+5ike
+4s
+5talk
+9s
+4worm
+8s
+4y
+3gue
+6d
+6r
+7ed
+7ing
+7s
+6s
+5ing
+3k
+4age
+7s
+4ed
+5r
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4less
+4proof
+4s
+4y
+3l
+4er
+5st
+4ly
+4ties
+5y
+3m
+4ed
+4ing
+4s
+3n
+4ed
+5r
+6s
+5st
+4ing
+7s
+4ly
+4ness
+8es
+4s
+4t
+4y
+3p
+4ed
+5r
+6ous
+6s
+4frog
+8ged
+9ing
+8s
+4ing
+4orous
+4rous
+4s
+4t
+3r
+4e
+5d
+5s
+4ier
+6st
+5ness
+9es
+6g
+4n
+5abilities
+9ity
+7le
+5ed
+7ly
+7ness
+9sses
+6r
+7s
+5ing
+8s
+5s
+5t
+4s
+4y
+3s
+4able
+4e
+5back
+9s
+5d
+5hold
+9er
+9ers
+9s
+5r
+6s
+5s
+4h
+5ed
+6s
+5ing
+4ing
+7s
+4ow
+6e
+7d
+7s
+6ing
+6s
+4t
+5aways
+5s
+5ways
+6ise
+4ure
+7s
+3t
+4her
+7back
+9cks
+7ed
+8tte
+9tes
+7goods
+7head
+9ads
+7ier
+9st
+8ness
+9esses
+9g
+9gs
+7jacket
+9ckets
+7leaf
+9aves
+8ike
+7n
+8eck
+9cks
+7s
+7wood
+9ods
+7y
+4s
+3ve
+5d
+5n
+6ed
+6ing
+9s
+6ous
+6s
+5r
+6s
+5s
+4ier
+6st
+5ng
+7s
+4y
+3ze
+5s
+2bbek
+6s
+3en
+5s
+6raum
+9ms
+3kuchen
+2canora
+8s
+3cies
+4y
+3h
+4aim
+7s
+5yim
+8s
+4ed
+5r
+6ed
+6ies
+7ng
+6ous
+9ly
+9ness
+9nesses
+6s
+6y
+5s
+4ing
+4we
+6s
+3ithin
+8ase
+9ses
+8s
+3tern
+7s
+4in
+6s
+5on
+7aries
+9y
+7s
+5sternia
+9nium
+4or
+6ate
+9s
+6s
+7hip
+9ps
+5type
+9s
+4ress
+8es
+4ure
+7d
+7r
+8s
+7s
+8hip
+9ips
+6ing
+6n
+7s
+3ythi
+7daceous
+7s
+6us
+2d
+3den
+6s
+3erhosen
+3ge
+5d
+5r
+6ed
+6ing
+6s
+5s
+4ier
+6st
+4y
+3um
+5s
+2e
+3ar
+5s
+3board
+8s
+3ch
+5craft
+9ts
+5dom
+8s
+5ed
+6e
+7s
+6s
+5ing
+5like
+3d
+3ing
+3k
+4s
+3p
+4ed
+4ing
+4s
+3r
+4ed
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7ly
+7s
+4s
+4y
+3s
+4e
+5s
+4ing
+3t
+4le
+4s
+5peak
+9s
+3ward
+7ly
+7s
+5y
+6s
+3ze
+2ft
+4e
+5r
+5st
+4ie
+6s
+5sh
+6m
+7s
+6t
+7s
+4most
+8s
+4over
+8s
+4s
+4ward
+8ly
+8s
+5ing
+4y
+2g
+3acies
+5y
+4l
+5ese
+8s
+5isation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+9cally
+8s
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5ly
+5s
+4taries
+7y
+5e
+6d
+6e
+7s
+6s
+7hip
+9ps
+5ine
+7g
+6on
+8ary
+8s
+6ssimo
+5o
+6r
+7ial
+7s
+6s
+3end
+6aries
+9ly
+8y
+6ise
+9d
+9s
+8ing
+8t
+9s
+7ze
+9d
+9s
+8ing
+6ries
+7y
+6s
+4r
+5demain
+9inist
+9inists
+9ins
+5ing
+8s
+6ties
+7y
+5s
+4s
+3ge
+5d
+5r
+6s
+5s
+4ie
+6r
+7o
+6s
+7t
+5n
+6ess
+9es
+6g
+7ed
+7s
+6s
+5sm
+7s
+4y
+3horn
+7s
+3ibilities
+9y
+5le
+7ness
+9sses
+6y
+4on
+6aries
+8y
+6ed
+7lla
+9ae
+9as
+6naire
+9res
+6s
+4slate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9vely
+9ves
+8or
+9rial
+9rs
+9rship
+9rships
+8ress
+9esses
+8ure
+9res
+5t
+6s
+4t
+5im
+7acies
+9y
+8te
+9ed
+9ely
+9eness
+9es
+9ing
+9ion
+9ions
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9or
+9ors
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7s
+5s
+3lan
+6s
+4en
+6s
+5ss
+7ness
+9sses
+5t
+6s
+4ike
+5n
+6s
+3man
+4en
+3ong
+6s
+3room
+7s
+3s
+4ide
+7s
+3uaan
+7s
+5n
+6s
+4me
+6s
+5in
+7ous
+7s
+3warmer
+9s
+4ear
+7s
+4ork
+7s
+2haim
+6s
+4yim
+7s
+3r
+4jahre
+4s
+3ua
+5s
+2i
+3dger
+7s
+3ger
+6s
+3omyoma
+9s
+9ta
+4trichies
+9ous
+9y
+3poa
+6s
+3r
+4ed
+4ing
+4s
+3s
+4h
+5er
+6st
+5mania
+9ae
+9al
+9as
+9ases
+9asis
+9oses
+9osis
+4ler
+7s
+4ter
+7ed
+7ing
+7s
+4urable
+9y
+6e
+7d
+7liness
+9nesses
+8y
+7s
+6ing
+3tmotif
+9s
+8v
+9s
+2k
+3e
+3gotla
+8s
+3ked
+5r
+4ing
+7s
+3s
+3u
+3var
+6s
+3ythi
+6oi
+7s
+6us
+2man
+5s
+3e
+4d
+4l
+5s
+4s
+3ing
+3ma
+5s
+5ta
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+4ing
+7like
+7s
+3niscal
+8te
+9es
+7i
+7us
+3on
+5ade
+8s
+5ed
+5fish
+9es
+5grass
+9ses
+5ier
+7st
+6ng
+6sh
+5like
+5s
+5wood
+9s
+5y
+3pira
+7s
+3ur
+5es
+5ian
+8s
+6ne
+8s
+5like
+5oid
+8s
+5s
+2nd
+4able
+4er
+6s
+4ing
+7s
+4s
+3es
+3g
+4ed
+5r
+5st
+4ing
+4s
+4th
+6en
+8ed
+9r
+9rs
+8ing
+8s
+6ful
+6ier
+8st
+7ly
+7ness
+9sses
+6man
+7en
+6s
+7man
+8en
+6ways
+7ise
+6y
+3ience
+8s
+7ies
+7y
+6t
+7ly
+7s
+4fied
+7s
+5y
+6ing
+4s
+4te
+6d
+6s
+5ies
+6ng
+6on
+8s
+6ve
+8ly
+8s
+5y
+3o
+4cinium
+9ms
+4s
+3s
+4e
+5d
+5s
+4ing
+4less
+4man
+5en
+3t
+4amente
+5ndo
+4en
+4i
+5c
+6el
+8late
+8s
+6le
+8s
+6ular
+9rly
+9rs
+8e
+9s
+5form
+5gines
+8ose
+9us
+6o
+5l
+6s
+5sc
+7s
+6k
+7s
+6simo
+5virus
+9ses
+4o
+5id
+7s
+5r
+6s
+5s
+5us
+3voy
+6s
+2one
+5s
+4ine
+4tiases
+8is
+5opodium
+9iums
+3pard
+7ess
+9ses
+7s
+3tard
+7ed
+7s
+2p
+3er
+5s
+3id
+5odendroid
+9droids
+6lite
+9es
+6melane
+9anes
+6ptera
+9ran
+9rans
+9rist
+9rists
+9rology
+9ron
+9rons
+9rous
+6siren
+9ens
+6te
+8s
+3orid
+7ae
+7s
+6ne
+3ped
+4ing
+3ra
+5s
+4echaun
+9nish
+9ns
+8wn
+9ns
+4omatous
+5saria
+9um
+9ums
+6e
+7rie
+9es
+8y
+6ies
+7ties
+8y
+6y
+5tic
+5us
+7ly
+7ness
+9sses
+3s
+3t
+4a
+4in
+6s
+4ocephali
+9alic
+9alous
+9alus
+7rcal
+5dactyl
+9ylous
+9yls
+5kurtic
+5me
+7s
+5n
+6ic
+6s
+5phos
+9es
+7yllous
+5rrhine
+5somatic
+8e
+9s
+8ic
+6piral
+9e
+9es
+9oses
+9osis
+5tene
+9s
+2quear
+7s
+2re
+4d
+4s
+3ing
+3p
+4s
+2s
+3bian
+7ism
+9ms
+7s
+5c
+4o
+5s
+3es
+3ion
+6ed
+6ing
+6s
+3pedeza
+9s
+3s
+4ee
+6s
+7hip
+9ps
+5n
+6ed
+6ing
+6s
+5r
+5s
+4on
+6ed
+6ing
+9s
+6s
+5r
+6s
+3t
+4ed
+4ing
+4s
+2t
+3ch
+5ed
+6s
+5ing
+8s
+3down
+7s
+3hal
+6ities
+8y
+6ly
+6s
+5rgic
+9al
+9ally
+8ed
+9s
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7y
+4e
+5an
+5e
+6s
+5s
+4ied
+5ferous
+3s
+3table
+4ed
+5r
+6box
+9ed
+9es
+9ing
+9ings
+6ed
+7r
+8s
+6form
+9ms
+6head
+9ds
+6ing
+9s
+6less
+6man
+7en
+6n
+7s
+6press
+9sses
+6s
+7et
+9s
+7pace
+9ces
+9cing
+9cings
+4ing
+7s
+4re
+6s
+4uce
+7s
+3up
+5s
+2u
+3caemia
+9s
+8c
+7ogen
+9enic
+9ens
+4emia
+8s
+7c
+4h
+5aemia
+9as
+5en
+4in
+6e
+7s
+6s
+5stic
+5te
+7s
+6ic
+6ohedra
+9dron
+9drons
+4o
+5blast
+9ts
+5cidin
+9ns
+6ratic
+6yte
+9s
+8haemia
+9aemias
+8ic
+8olyses
+9lysis
+9penia
+9penias
+9ses
+9sis
+9tic
+5depleted
+7rma
+9al
+9as
+9ia
+9ias
+9ic
+5ma
+7ine
+9es
+7s
+5penia
+9as
+9c
+6lakia
+9ias
+8st
+9tid
+9tids
+9ts
+6oieses
+9sis
+9tic
+5rrhoea
+9eal
+9eas
+5sin
+8s
+5tome
+9s
+8ies
+8y
+3d
+4es
+4s
+3gh
+5en
+3kaemia
+9s
+7ogeneses
+9enesis
+4emia
+8s
+7c
+8s
+6ogeneses
+9nesis
+9nic
+7id
+4oblast
+9ts
+5cyte
+9s
+8ic
+8oses
+9sis
+9sises
+9tic
+5derma
+9al
+9as
+9ic
+6ystrophy
+5ma
+7s
+5n
+6s
+5penia
+9as
+9c
+6lakia
+9ias
+9ic
+6oieses
+9sis
+9tic
+5rrhea
+9al
+9as
+5ses
+6is
+5tic
+6omies
+8y
+6riene
+9nes
+2v
+3a
+4nt
+6ed
+7r
+8s
+6ine
+9s
+8g
+6s
+4tor
+7es
+7s
+3e
+4e
+5d
+5ing
+5s
+4l
+5ed
+6r
+7s
+5headed
+9edness
+5ing
+5led
+7r
+8s
+7st
+6ing
+9s
+6y
+5ness
+9es
+5s
+4r
+5age
+8d
+8s
+7ing
+5ed
+6t
+7s
+5ing
+5s
+4s
+3iable
+5than
+9s
+4ed
+5r
+6s
+5s
+4gable
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+4n
+5s
+4rate
+8s
+7ic
+9al
+8on
+9ns
+4s
+4tate
+8d
+8s
+7ing
+8on
+9nal
+9ns
+7or
+9s
+5e
+6s
+5ic
+7al
+9ly
+6es
+5y
+3o
+4dopa
+8s
+4gyre
+4rotary
+8tory
+3ulin
+7s
+5ose
+8s
+3y
+4ing
+2w
+3d
+4er
+5st
+4ly
+4ness
+8es
+4sbies
+6y
+5ter
+8s
+3is
+5es
+5ia
+7s
+6te
+8s
+5son
+8s
+2x
+3eme
+6s
+5ic
+4s
+3ica
+6l
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+5ographer
+9phers
+9phic
+9phical
+9phies
+9phist
+9phists
+9phy
+6logical
+9ically
+9ies
+9ist
+9ists
+9y
+6n
+7s
+4gram
+8s
+7phic
+9ical
+9ies
+9y
+4s
+5es
+2y
+3landi
+8i
+9s
+8s
+3s
+2z
+3es
+3z
+4a
+5s
+4es
+4ie
+6s
+4y
+1herzolite
+9es
+1i
+2abilities
+8y
+4le
+6ness
+9ses
+3ise
+6d
+6s
+5ing
+5on
+7s
+3na
+5s
+4e
+5s
+4g
+5s
+4oid
+3r
+4d
+5s
+4s
+4t
+3s
+4es
+3tris
+7es
+2b
+3ant
+4te
+6d
+6s
+5ing
+6on
+8al
+9ry
+8s
+5ory
+3bard
+7s
+4ed
+5r
+6s
+4ing
+3ecchio
+9s
+6io
+8s
+4l
+5ant
+8s
+5ed
+6e
+7s
+6r
+7s
+5ing
+8s
+6st
+8s
+5lant
+9s
+6ed
+7e
+8s
+7r
+8s
+6ing
+9s
+6ous
+9ly
+5ous
+5s
+4r
+5al
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7ly
+7ness
+9sses
+7s
+6te
+8d
+8s
+7ing
+8on
+9nism
+9nisms
+9nist
+9nists
+9ns
+7or
+9s
+9y
+5o
+6s
+5s
+5tarian
+9anism
+9anisms
+9ans
+6icidal
+9de
+9des
+7es
+7nage
+9ges
+8e
+9s
+8ism
+9sms
+6y
+3idinal
+9ly
+7ist
+9ts
+7osities
+9ity
+8us
+9sly
+9sness
+5o
+6s
+3ken
+6s
+3lab
+6s
+3ra
+5e
+5ire
+8s
+7ie
+9s
+5rian
+9s
+9ship
+9ships
+7es
+6y
+5s
+5te
+7d
+7s
+6ing
+7on
+9al
+9s
+6ory
+4etti
+8st
+9ts
+7o
+8s
+4i
+5form
+3s
+2ce
+4nce
+7d
+7e
+8s
+7r
+8s
+7s
+6ing
+5sable
+6e
+7d
+7e
+8s
+7r
+8s
+7s
+6ing
+6or
+8s
+6ure
+9s
+5te
+6iate
+9es
+9eship
+9eships
+9ion
+9ions
+7ous
+9sly
+9sness
+3h
+4anos
+8es
+4ee
+6s
+5n
+6ed
+6in
+8g
+8s
+7sm
+9s
+8t
+9s
+6oid
+7logical
+9gies
+9gist
+9gists
+9gy
+7se
+7us
+6s
+5s
+4gate
+8s
+4i
+5s
+4t
+5ed
+6r
+6st
+5ing
+5lied
+8s
+6y
+7ing
+5s
+4wake
+8s
+6y
+7s
+3it
+5ly
+5ness
+9es
+3k
+4ed
+5r
+6ish
+9ly
+9ness
+9nesses
+6s
+4ing
+7s
+4pennies
+8y
+4s
+5pit
+8s
+8tle
+9les
+3orice
+8s
+3tor
+6ian
+6s
+2d
+3ar
+5s
+3ded
+4ing
+3ger
+6s
+3less
+3o
+4caine
+9s
+4s
+3s
+2e
+3bfraumilch
+9ilchs
+3d
+4er
+3f
+4er
+5st
+4ly
+4s
+3ge
+5dom
+8s
+5less
+5man
+6en
+5r
+6s
+5s
+3n
+4able
+5l
+4s
+4teric
+8es
+7y
+3r
+4ne
+6s
+4s
+3s
+3u
+4s
+4tenancies
+9cy
+9t
+9tries
+9try
+9ts
+9tship
+9tships
+3ve
+5r
+5s
+6t
+2fe
+4belt
+8s
+5lood
+9s
+5oat
+8s
+5uoy
+8s
+4care
+8s
+4ful
+4guard
+9ed
+9ing
+9s
+4hack
+8s
+5old
+4less
+8ly
+8ness
+9esses
+5ike
+8ness
+9esses
+6ne
+8s
+5ong
+4manship
+9ips
+4r
+5s
+4s
+5aver
+9s
+7ing
+9gs
+5ome
+5pan
+8s
+5tyle
+9r
+9rs
+9s
+4time
+8s
+4way
+7s
+5ork
+8s
+7ld
+9s
+3t
+4able
+4back
+8s
+5oy
+7s
+4ed
+5r
+6s
+4gate
+8s
+4ing
+4man
+5en
+4off
+7s
+4s
+3ull
+2g
+3ament
+8al
+9ry
+8ous
+8s
+4n
+5d
+6s
+5s
+4se
+6s
+4te
+6d
+6s
+5ing
+6on
+8s
+6ve
+5ure
+8d
+8s
+7ing
+3er
+5s
+3ge
+5d
+5r
+6s
+5s
+4ing
+7s
+3ht
+5bulb
+9s
+5ed
+6n
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6r
+7age
+9es
+7ed
+7ing
+7man
+8en
+7s
+6st
+5face
+9d
+9s
+7st
+9ness
+9nesses
+6ul
+5headed
+8rted
+9tedly
+6ouse
+9eman
+9emen
+9es
+5ing
+8s
+6sh
+5less
+6ied
+8s
+6y
+7ing
+5ness
+9es
+6ing
+9ed
+9s
+5plane
+9es
+6roof
+5s
+6hip
+9s
+6ome
+9ly
+9ness
+9nesses
+5tight
+5wave
+6eight
+9hts
+6ood
+9s
+3nage
+7s
+5loes
+5n
+6s
+4e
+5ous
+5s
+4icole
+8ous
+5fication
+9tions
+7ed
+8s
+6orm
+6y
+7ing
+5n
+6s
+5perdous
+5te
+7s
+6ic
+5vorous
+4ocaine
+9es
+6ellulose
+9uloses
+9ulosic
+5se
+7s
+6ulfonate
+9onates
+4um
+6s
+3roin
+7e
+8s
+7s
+3s
+3ula
+6e
+6r
+6s
+6te
+8d
+5e
+6s
+5ifloral
+5oid
+4re
+6s
+2kabilities
+9y
+5le
+7ness
+9sses
+6y
+3e
+4abilities
+9ty
+6le
+8ness
+9esses
+7y
+4d
+4lier
+7st
+6hood
+9ds
+6ness
+9ses
+5y
+4n
+5ed
+6ss
+8es
+5ing
+5s
+4r
+5s
+4s
+5t
+4wake
+8s
+6lk
+8s
+5ise
+3in
+5g
+6s
+5s
+3uta
+2lac
+5s
+4ngeni
+3iaceous
+4ed
+5s
+3l
+4ed
+4ing
+5put
+8ian
+9ans
+8s
+4s
+3o
+4s
+3t
+4ed
+4ing
+7ly
+7ness
+9sses
+4s
+3y
+4like
+2ma
+4cel
+7s
+6ous
+6s
+5iform
+6ne
+5ologies
+9ist
+9ists
+9y
+6n
+7s
+4il
+6s
+4n
+5s
+4s
+4tion
+8s
+4x
+3b
+4a
+5s
+5te
+4ec
+6k
+7s
+6s
+5d
+5r
+6ed
+7r
+7st
+6ing
+6ly
+6ness
+9ses
+6s
+4i
+5c
+5er
+6st
+5ng
+4less
+4meal
+4o
+5s
+5us
+4s
+4urgite
+9es
+5s
+6es
+4y
+3e
+4ade
+7s
+4d
+4kiln
+8s
+4less
+5ight
+9ed
+9er
+9ers
+9ing
+9s
+6t
+4n
+5s
+4pit
+7s
+4rick
+8s
+4s
+5cale
+9s
+5tone
+9s
+4wash
+8es
+6ter
+9s
+4y
+5s
+3icoline
+7ous
+4er
+5st
+4na
+6l
+5ess
+8es
+5g
+6s
+4t
+5able
+9ness
+9nesses
+6rian
+9ns
+7y
+6tion
+9nal
+9ns
+8ve
+5ed
+7ly
+7ness
+9sses
+7s
+6r
+7s
+6s
+5ing
+8ly
+8s
+5less
+9ly
+9ness
+9nesses
+5rophe
+5s
+4vorous
+3ma
+5s
+4er
+6s
+3n
+4aeid
+8s
+4ed
+5r
+6s
+5tic
+4ic
+5ng
+4ologic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+5philous
+4s
+3o
+4nene
+8s
+5ite
+8s
+7ic
+4s
+5es
+5is
+4us
+6ine
+9s
+3p
+4a
+5s
+4ed
+5r
+6s
+5st
+5t
+6s
+4id
+6ities
+8y
+6ly
+6ness
+9ses
+5ng
+7ly
+7s
+4kin
+7s
+4ly
+4ness
+8es
+4s
+5ey
+5ier
+7st
+5y
+3uli
+5oid
+8s
+5us
+7es
+3y
+2n
+3able
+4c
+5s
+4ge
+6s
+4lol
+7s
+6ol
+8s
+3ch
+5es
+6t
+7s
+5pin
+8s
+4omycin
+9ns
+4rusta
+9s
+4ture
+8s
+6s
+7es
+3d
+4ane
+7s
+4en
+6s
+4ies
+4s
+4worm
+8s
+4y
+3e
+4able
+5ge
+7s
+5l
+6ities
+8y
+6ly
+5ment
+9al
+9s
+5r
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+5te
+7d
+6ion
+9s
+4backer
+9rs
+8ing
+9ngs
+5red
+7eding
+9ings
+4caster
+9rs
+8ing
+9ngs
+5ut
+7s
+4d
+4less
+5ike
+4man
+5en
+4n
+5s
+5y
+4olate
+9d
+4r
+5board
+9ds
+5less
+5s
+4s
+5man
+6en
+4up
+6s
+4y
+3g
+4a
+5m
+6s
+5s
+4berries
+8y
+4cod
+7s
+4el
+6s
+5r
+6ed
+7r
+8s
+6ie
+8s
+7ng
+9ly
+9s
+6s
+4ier
+6st
+4le
+6s
+4o
+5es
+5nberries
+9ry
+5t
+6s
+4s
+5ter
+8s
+4ua
+6e
+6l
+7ly
+7s
+6s
+5ica
+8s
+6form
+6ne
+8s
+7i
+8s
+6sa
+8s
+7t
+8er
+9rs
+8ic
+9cal
+9cally
+9cian
+9cians
+9cs
+8ries
+9y
+8s
+5la
+7e
+7r
+7s
+7te
+9d
+4y
+3hay
+6s
+3ier
+5st
+4ment
+8s
+4n
+5g
+6s
+5s
+4sh
+6ed
+7r
+8s
+7s
+6ing
+9s
+3k
+4able
+5ge
+7s
+4boy
+7s
+4ed
+5r
+6s
+4ier
+6st
+5ng
+4man
+5en
+4rot
+7s
+4s
+5land
+9s
+5man
+6en
+5pan
+8s
+5ter
+8s
+4up
+6s
+4work
+8s
+4y
+3n
+4ed
+5t
+6s
+5y
+6s
+4ies
+5ng
+4s
+4y
+3o
+4cut
+7s
+4leate
+9s
+6ic
+6nic
+6um
+8s
+4s
+4type
+8d
+8r
+9s
+8s
+7ing
+3s
+4ang
+7s
+4eed
+7s
+5y
+6s
+4tock
+8s
+3t
+4ed
+5l
+6led
+6s
+5r
+6s
+4ie
+6r
+6s
+7t
+5ng
+4less
+4ol
+6s
+4s
+5eed
+8s
+5tock
+9s
+4white
+9s
+4y
+3um
+5s
+4ron
+7s
+4x
+5es
+3y
+2on
+4cel
+7le
+9s
+7s
+4el
+6s
+5ss
+7es
+5t
+6s
+4fish
+8es
+4head
+8s
+7rted
+9edness
+4isation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+6m
+7s
+5zation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+4like
+5y
+4s
+2p
+3a
+4emia
+8s
+4rite
+8s
+4s
+5e
+6s
+3e
+4ctomies
+8y
+4mia
+7s
+3id
+5e
+6s
+5ic
+5oplast
+9sts
+5s
+4n
+5s
+3less
+4ike
+3o
+4chrome
+9es
+5yte
+8s
+4dystrophies
+9ophy
+4geneses
+9is
+5ram
+8matic
+9atism
+9atisms
+9atist
+9atists
+8s
+7phies
+9y
+4ic
+5d
+6al
+6s
+4litic
+5yses
+7is
+6tic
+4ma
+6s
+6ta
+7oses
+9is
+8us
+4philic
+5last
+9s
+5rotein
+9ins
+4s
+5culpture
+9tures
+5omal
+7e
+8s
+5uck
+8ed
+8ing
+8s
+7tion
+9ons
+4tropic
+9es
+9n
+9ns
+8y
+3ped
+5n
+6ed
+6ing
+6s
+5r
+6ed
+6ing
+6s
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+7s
+5tude
+9s
+4y
+3read
+7er
+9s
+7ing
+9gs
+7s
+3s
+4alve
+8s
+4tick
+8ed
+8ing
+8s
+3uria
+7s
+2quable
+5te
+7d
+7s
+6ing
+7on
+9s
+4efacient
+9ents
+8tion
+9ions
+9ive
+6iable
+7ed
+8r
+9s
+8s
+6y
+7ing
+5sce
+8d
+8nce
+9ces
+9cies
+9cy
+9t
+8s
+7ing
+5ur
+7ed
+7ing
+7s
+4id
+6ambar
+9ars
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6ise
+9d
+9r
+9rs
+9s
+8ing
+7ties
+8y
+7ze
+9d
+9r
+9rs
+9s
+8ing
+6ly
+6ness
+9ses
+6s
+6us
+8es
+5fied
+8s
+6y
+7ing
+4or
+6ed
+6ice
+9s
+7ng
+7sh
+9ly
+9ness
+9nesses
+6s
+2ra
+4s
+3e
+3i
+4odendra
+9ron
+9rons
+5pe
+7s
+4pipe
+8s
+5oop
+8s
+3k
+4ed
+4ing
+4s
+3ot
+5h
+2s
+3ente
+3k
+4s
+3le
+5s
+3p
+4ed
+5r
+6s
+4ing
+7ly
+7s
+4ound
+8s
+4s
+4und
+7s
+3sencephalous
+5s
+4om
+6e
+7ly
+7ness
+9sses
+6ly
+6ness
+9ses
+5trichous
+3t
+4able
+4ed
+5e
+6s
+5l
+6s
+5n
+6abilities
+9lity
+8le
+6ed
+7r
+8s
+9hip
+9hips
+6ing
+9s
+6s
+5r
+6ia
+8l
+8s
+7oses
+9is
+6s
+5th
+4ful
+4ing
+7s
+4less
+8ly
+8ness
+9esses
+4s
+5erv
+8s
+2t
+3ai
+4nies
+5y
+4s
+3chi
+6s
+3e
+4d
+4ness
+8es
+4r
+5acies
+7y
+6l
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7ly
+7ness
+9sses
+7s
+6rily
+8ness
+9esses
+7y
+8ism
+9sms
+6te
+8ly
+8ness
+9esses
+8s
+7i
+8m
+8on
+9ns
+7o
+8r
+9s
+7ure
+9ed
+9es
+8s
+5ose
+7ities
+9y
+5s
+4s
+3h
+4arge
+8s
+5te
+7s
+4e
+5d
+5ly
+5mia
+8s
+7c
+5ness
+9es
+5r
+6ly
+5s
+6ome
+9ness
+9nesses
+6t
+4ia
+6s
+7es
+7is
+5c
+5fication
+9tions
+7ed
+8s
+6y
+7ing
+5ng
+5stid
+9s
+5te
+7s
+5um
+7s
+4o
+5chromatic
+9matics
+9mies
+9my
+6last
+9ts
+6yst
+9s
+5domous
+5ed
+5genous
+6lyph
+9hs
+6raph
+9hed
+9her
+9hers
+9hic
+9hical
+9hies
+9hing
+9hs
+9hy
+5id
+7al
+6ng
+5lapaxies
+9xy
+7tries
+9ous
+9y
+6ogic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+5mancies
+9y
+7rge
+9es
+6eteor
+9ors
+5nthryptic
+9yptics
+7riptic
+9ptics
+9ptist
+9ptists
+9ptor
+9ptors
+5phagous
+8ne
+9es
+7ilous
+7ysa
+9ae
+9e
+9es
+8te
+9es
+9ic
+6one
+9s
+6rint
+9ts
+6s
+5s
+6ol
+8s
+6permum
+9mums
+7here
+9res
+9ric
+6tatic
+5tome
+9s
+8ic
+9cal
+9es
+9st
+9sts
+8ous
+8y
+6ripsies
+9sy
+9ter
+9ters
+9tic
+9tics
+9tist
+9tists
+9tor
+9tors
+8te
+9es
+9ic
+9ics
+9ies
+9ise
+9ised
+9ises
+9ising
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+9or
+9ors
+9y
+4s
+3igable
+6nt
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5ious
+9ly
+9ness
+9nesses
+4ng
+3mus
+6es
+3oral
+4tes
+5ic
+3re
+5age
+8s
+5s
+3s
+3ten
+5r
+6ateur
+9urs
+6bag
+9s
+7ug
+9s
+6ed
+7r
+8s
+6ing
+6mate
+9es
+6s
+6y
+4le
+6neck
+9ks
+8ss
+9ses
+6r
+6s
+7t
+6worth
+5ie
+7s
+6n
+7g
+8s
+7s
+6sh
+4oral
+8s
+3u
+4rgic
+8al
+9lly
+8s
+7es
+7ologies
+9ogist
+9ogists
+9ogy
+7sm
+9s
+8t
+9ic
+9s
+6y
+4us
+6es
+2vabilities
+9y
+5le
+7ness
+9sses
+3e
+4abilities
+9ty
+6le
+8ness
+9esses
+4d
+5o
+6s
+4lier
+7st
+6head
+9ds
+7ood
+9ds
+6ly
+6ness
+9ses
+5od
+7s
+6ng
+8s
+6od
+8s
+5y
+4n
+5ed
+6r
+7s
+6ss
+8es
+5ing
+5s
+4r
+5ed
+5ied
+7s
+6ng
+6sh
+8ly
+8ness
+9esses
+5leaf
+8ves
+7ss
+5s
+5wort
+9s
+6urst
+9ts
+5y
+6man
+7en
+4s
+5t
+6ock
+9s
+4trap
+8ped
+9ing
+8s
+4ware
+8s
+4yer
+7e
+8s
+7s
+3id
+5er
+6st
+5ities
+7y
+5ly
+5ness
+9es
+4er
+6s
+4ng
+6ly
+6ness
+9ses
+6s
+3or
+5s
+3raison
+9s
+4e
+5s
+3yer
+6s
+2xivia
+7l
+7te
+9d
+9s
+8ing
+9on
+9ons
+6ous
+6um
+8s
+2zard
+6s
+3zie
+6s
+1lama
+5s
+3nero
+7s
+4o
+5s
+1o
+2ach
+5es
+3d
+4ed
+5n
+6ed
+6ing
+6s
+5r
+6s
+4ing
+7s
+4master
+9rs
+4s
+5amoney
+9eys
+9ies
+5pace
+9s
+5tar
+8s
+6one
+9s
+3f
+4ed
+5r
+6ish
+6s
+4ing
+7s
+4s
+3m
+4ed
+4ier
+6st
+5ness
+9es
+6g
+4less
+4s
+4y
+3n
+4able
+4back
+8s
+4ed
+5e
+6s
+5r
+6s
+4ing
+7s
+4s
+5hift
+9s
+4word
+8s
+3st
+3th
+5e
+6d
+7ness
+9sses
+6r
+7s
+6s
+7t
+5ful
+8ness
+9esses
+5ing
+8ly
+8s
+5liness
+9sses
+6y
+5ness
+9es
+5some
+9ly
+9ness
+9nesses
+5y
+3ve
+5d
+5s
+4ing
+2b
+3ar
+4te
+6d
+6ly
+5ion
+8s
+3bed
+5r
+6s
+4ied
+6s
+5ng
+4y
+5er
+7s
+5gow
+8s
+5ing
+8s
+6sm
+8s
+7t
+8s
+3e
+4ctomies
+8y
+4d
+4fin
+7s
+4less
+6t
+7s
+5ia
+7s
+6ne
+8s
+4s
+3i
+4ng
+6s
+4ped
+3lollies
+7y
+3o
+4la
+6s
+5o
+6s
+4s
+5e
+4tomies
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7y
+3s
+4couse
+9s
+4ter
+7ed
+8r
+9s
+7ing
+9gs
+7like
+7man
+8en
+7s
+5ick
+8s
+3ular
+7ly
+6te
+8d
+7ion
+9ns
+5e
+6s
+5i
+5ose
+5us
+4s
+3worm
+7s
+2ca
+4l
+5e
+6s
+5isability
+9le
+8tion
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+8s
+6te
+8s
+7ies
+7y
+6zability
+9le
+8tion
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5ly
+5ness
+9es
+5s
+4table
+5e
+6able
+6d
+6r
+7s
+6s
+5ing
+6on
+8al
+9lly
+8s
+6ve
+8s
+5or
+7s
+3ellate
+3h
+4an
+6s
+4ia
+6l
+4s
+3i
+3k
+4able
+5ge
+7s
+5way
+8s
+4box
+7es
+4down
+8s
+4ed
+5r
+6s
+5t
+6s
+4fast
+5ul
+7s
+4house
+9s
+4ing
+7s
+4jaw
+7s
+4keeper
+9rs
+4less
+4maker
+9s
+6n
+5en
+4nut
+7s
+4out
+7s
+4pick
+8s
+4ram
+7s
+4s
+5et
+7s
+5man
+6en
+6ith
+9eries
+9ery
+9ing
+9ings
+9s
+5tep
+8s
+6itch
+9hed
+9hes
+9hing
+4up
+6s
+3o
+4ed
+5s
+4foco
+8s
+4ing
+5sm
+7s
+4man
+5en
+5obile
+9es
+9ities
+9ity
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+9eness
+9es
+9ities
+9ity
+7or
+9s
+9y
+4plant
+9s
+4restive
+4s
+4weed
+8s
+3ulament
+9ts
+6r
+6te
+8d
+7ion
+9ns
+5e
+6d
+6s
+5i
+6cidal
+5us
+4m
+5s
+4plete
+4s
+5t
+6a
+7e
+7l
+6ed
+6ing
+6s
+4tion
+8ary
+8s
+5ories
+7y
+2d
+3e
+4n
+5s
+4s
+5man
+6en
+5tar
+8s
+6one
+9s
+3ge
+5able
+5d
+5ment
+9s
+5pole
+9s
+5r
+6s
+5s
+4ing
+7s
+4ment
+8s
+3icula
+8e
+7e
+8s
+3s
+2erie
+6s
+3ss
+5al
+5es
+5ial
+6c
+2ft
+4ed
+5r
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4less
+5ike
+4s
+5man
+6en
+4y
+2g
+3agraphia
+9ias
+4n
+5berries
+9y
+5ia
+7ceous
+7s
+5s
+4oedic
+9s
+4rithm
+9ic
+9ical
+9ically
+9s
+3board
+8s
+5ok
+7s
+3e
+4s
+3gat
+6s
+4ed
+5r
+6head
+9ded
+9ds
+6s
+5ts
+4ia
+6s
+5e
+6r
+6st
+5ng
+7s
+5sh
+4y
+3ia
+4c
+5al
+7ities
+9y
+7ly
+7ness
+9sses
+5ian
+8s
+6se
+8d
+8s
+7ing
+7m
+8s
+7t
+8s
+6ze
+8d
+8s
+7ing
+5less
+5s
+4e
+5r
+5s
+6t
+4ly
+4n
+5ess
+8es
+5s
+4on
+6s
+4stic
+8al
+9lly
+8ian
+9ans
+8s
+3jam
+6med
+7ing
+6s
+4uice
+8s
+3line
+7s
+4og
+6s
+3normal
+9ities
+9ity
+9ly
+3o
+4daedalic
+9lies
+9lus
+9luses
+9ly
+4ff
+6s
+4gram
+8matic
+8s
+7ph
+9er
+9ers
+9ic
+9ical
+9ically
+9ies
+9s
+9y
+6iph
+9ic
+9s
+4i
+4mach
+8ies
+9st
+9sts
+8s
+8y
+4n
+5s
+4paedic
+9cs
+5edic
+9s
+5hile
+9s
+4rrhea
+9s
+8ic
+7oea
+9as
+4s
+4thete
+9s
+5ype
+8s
+7ies
+7y
+4ut
+6s
+3roll
+7ed
+8r
+9s
+7ing
+9gs
+7s
+3s
+3way
+6s
+4ood
+7s
+3y
+2han
+5s
+2id
+4ed
+4ing
+4s
+3n
+4cloth
+9s
+4s
+3pe
+5n
+3r
+4s
+3ter
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+2ke
+4s
+3shen
+2ligo
+6s
+4um
+6s
+3l
+4apalooza
+9ozas
+4ed
+5r
+6s
+4ies
+5ng
+7ly
+5pop
+8s
+4op
+6ed
+6ing
+6s
+6y
+4s
+4y
+5gag
+8ged
+9ing
+8s
+5pop
+8s
+3og
+5s
+2ma
+4s
+4ta
+3e
+4d
+4in
+6s
+4nt
+6a
+7ceous
+6s
+6um
+8s
+4s
+3ing
+3pish
+2ne
+4lier
+7st
+6ly
+6ness
+9ses
+5y
+4ness
+8es
+4r
+5s
+4some
+8ly
+8ness
+9esses
+8s
+3g
+4a
+5eval
+7ous
+5n
+6imities
+9ty
+8ous
+6s
+5s
+4board
+9s
+7t
+8s
+6w
+7man
+8en
+7s
+4case
+5loth
+9s
+4e
+5d
+5ing
+5r
+6on
+8s
+6s
+5s
+6t
+5val
+6ities
+8y
+6ous
+4hair
+8ed
+8s
+6nd
+8s
+5ead
+8ed
+9dness
+8s
+5orn
+8s
+6use
+9s
+4icaudate
+6orn
+9s
+5es
+5ng
+7ly
+7s
+6quities
+9ty
+5pennate
+5rostral
+5sh
+5tude
+9s
+8inal
+9nally
+4jump
+8ed
+8ing
+8s
+4leaf
+7ves
+5ine
+8s
+6st
+8ed
+8ing
+8s
+5y
+4neck
+8s
+6ss
+8es
+4primer
+9rs
+4s
+5hip
+8s
+6ore
+9man
+9men
+8ing
+9ngs
+5ighted
+9edness
+5ome
+8ly
+8ness
+9esses
+5pur
+8s
+4time
+4ueur
+8s
+4wall
+8s
+6ys
+5earing
+5ise
+5orm
+8s
+3icera
+8s
+2o
+3bier
+6s
+7t
+5ly
+4y
+3ed
+4y
+5s
+3f
+4a
+5h
+6s
+5s
+4ful
+7s
+4s
+3ie
+5s
+4ng
+3k
+4alike
+9s
+4down
+8s
+4ed
+5r
+6s
+4ing
+5sm
+7s
+6t
+7s
+4out
+7s
+5ver
+8s
+4s
+5ism
+8s
+4up
+6s
+3m
+4ed
+4ing
+4s
+3n
+4ey
+6s
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+4s
+4y
+3p
+4ed
+5r
+6s
+4hole
+8d
+8s
+7ing
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4s
+4y
+3r
+4d
+5s
+3s
+4e
+5box
+8es
+5d
+5ly
+5n
+6ed
+7r
+8s
+7ss
+9es
+6ing
+6s
+5r
+5s
+6t
+7rife
+9fes
+4ie
+6s
+5ng
+7s
+3t
+4ed
+5n
+5r
+6s
+4ing
+7s
+4s
+3ves
+3yenwork
+9ks
+2p
+3e
+4d
+4r
+5s
+4s
+3grass
+8es
+3hobranch
+9chiate
+9chs
+5dont
+5phorate
+9e
+9es
+3ing
+3olith
+8s
+3ped
+5r
+6ed
+6ing
+6s
+4ier
+6s
+7t
+5ng
+7s
+4y
+3s
+4ided
+8ly
+8ness
+9esses
+4tick
+8s
+2quacious
+9sly
+9sness
+7ties
+8y
+5t
+6s
+4itur
+2r
+3al
+4n
+5s
+4te
+4zepam
+9s
+3cha
+6s
+3d
+4ed
+4ing
+7s
+4kin
+7s
+4less
+5ier
+7st
+6ke
+6ness
+9ses
+7g
+8s
+5y
+4olatries
+9y
+5ma
+7s
+5ses
+6is
+5tic
+4s
+5hip
+8s
+4y
+3e
+4al
+4l
+5s
+4s
+4tte
+7s
+3gnette
+9s
+5on
+7s
+3ic
+5a
+6e
+6te
+8d
+8s
+7ing
+8on
+9ns
+5s
+4es
+4keet
+8s
+4mer
+7s
+4ner
+7s
+5g
+6s
+4ot
+6s
+4s
+5es
+3n
+4ness
+8es
+3rell
+7s
+4ies
+4y
+3y
+2s
+3able
+7ness
+9sses
+3e
+4d
+4l
+5s
+4n
+4r
+5s
+4s
+3h
+3ing
+6ly
+6s
+3lyf
+6s
+3s
+4es
+4ier
+6st
+4less
+4maker
+9s
+7ing
+4y
+3t
+4ness
+8es
+2t
+3a
+4h
+5s
+4s
+3e
+4s
+3h
+4ario
+8s
+4efull
+5r
+5st
+4full
+4ness
+8es
+4some
+3i
+4c
+4on
+6s
+3o
+4s
+5es
+3s
+3te
+5d
+5r
+6ies
+6s
+6y
+5s
+4ing
+4o
+5s
+3us
+5es
+5land
+9s
+2u
+3che
+6ly
+6r
+6st
+3d
+4en
+6ed
+6ing
+6s
+5r
+5st
+4hailer
+9rs
+4ish
+4lier
+7st
+5y
+4mouth
+9ed
+9s
+4ness
+8es
+4speaker
+9ers
+3ed
+3gh
+5s
+3ie
+5s
+4ng
+4s
+3ma
+5s
+3n
+4d
+5ed
+6r
+7ed
+7ing
+9gs
+7s
+5ing
+5s
+4ed
+4ge
+6d
+6r
+7s
+6s
+6wear
+9rs
+6y
+5ier
+7st
+6ng
+8ly
+8s
+5y
+4ing
+4s
+3p
+4e
+5d
+5n
+5s
+4ing
+5t
+4s
+3r
+4e
+5d
+5s
+4ie
+6r
+6s
+7t
+5ng
+7ly
+7s
+4s
+4y
+3s
+4e
+5d
+5r
+6s
+5s
+5wort
+9s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4y
+3t
+4ed
+4ing
+5sh
+7ly
+7ness
+9sses
+4s
+3var
+6s
+4er
+6ed
+6s
+4re
+6d
+6s
+2vabilities
+9y
+5le
+7ness
+9sses
+6y
+4ge
+6s
+4statin
+9ns
+4t
+5s
+3e
+4abilities
+9ty
+6le
+8ness
+9esses
+7y
+4bird
+8s
+6te
+8s
+5ug
+7s
+4d
+4fest
+8s
+4less
+8ly
+8ness
+9esses
+5ier
+7s
+8t
+6ght
+9s
+6head
+9ds
+6ly
+6ness
+9ses
+5ock
+8s
+6rn
+8ness
+9esses
+5y
+4r
+5ed
+5less
+6y
+5s
+4s
+5eat
+8s
+5ick
+8ness
+9esses
+5ome
+5truck
+4vine
+8s
+4worthy
+4y
+5s
+3ing
+6ly
+6ness
+9ses
+6s
+2w
+3an
+5s
+3ball
+7ed
+7ing
+9gs
+7s
+4orn
+5y
+6s
+4red
+5ow
+7ed
+7ism
+9ms
+7s
+3down
+7s
+3e
+4d
+4r
+5able
+5case
+9d
+9s
+8ing
+6lassman
+9smen
+5ed
+5ier
+7st
+6ng
+8ly
+8s
+5most
+5s
+5y
+4s
+5t
+3ing
+6s
+4sh
+3land
+7er
+9s
+7s
+4ier
+6st
+5fe
+7r
+8s
+7s
+5ght
+8ed
+8ing
+8s
+5head
+9s
+5ly
+5ness
+9es
+5ves
+4y
+3n
+4d
+5ed
+5ing
+5s
+4e
+5d
+5s
+6s
+7es
+4ing
+4s
+3p
+4ed
+4ing
+4s
+3rider
+8s
+5e
+6s
+4y
+3s
+4e
+5d
+5ning
+9s
+5r
+5s
+6t
+4ing
+5t
+3t
+4ed
+4ing
+4s
+3veld
+7s
+2x
+3ed
+4s
+3ing
+3odrome
+9s
+8ic
+9cal
+9cally
+9cs
+9es
+8y
+3ygen
+7s
+2y
+3al
+5er
+6st
+5ism
+8s
+7t
+8s
+5ler
+7st
+6y
+5ness
+9es
+5ties
+6y
+3s
+2zell
+6s
+4n
+5ge
+7d
+7s
+6y
+5s
+1uach
+3u
+4s
+2bbard
+7s
+4er
+6liness
+9esses
+7y
+6s
+3e
+4d
+4s
+3fish
+7es
+3ing
+3ra
+5s
+4ic
+6al
+7nt
+9s
+7te
+9d
+9s
+8ing
+9on
+9onal
+9ons
+9ve
+8or
+9rs
+6ious
+9sly
+7ties
+8y
+6ous
+9ly
+5toria
+9um
+9ums
+2carne
+7s
+3e
+4nce
+7s
+6ies
+6y
+5t
+6ly
+4rn
+6e
+7s
+6s
+4s
+3hot
+6h
+3id
+5er
+6st
+5ities
+7y
+5ly
+5ness
+9es
+4fer
+7ase
+9es
+7in
+9s
+7ous
+7s
+5ugous
+4gen
+7s
+4te
+6s
+3k
+4ed
+5n
+6booth
+9ths
+6gowan
+9ans
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+4less
+8ly
+8ness
+9esses
+4pennies
+8y
+4s
+4y
+3rative
+9ly
+9ness
+9nesses
+4e
+5s
+3tation
+9s
+3ubrate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+4lent
+8ly
+4ma
+6s
+5o
+6nes
+6s
+2d
+3e
+4rick
+8s
+4s
+3ic
+5ally
+5rous
+9ly
+9ness
+9nesses
+3o
+4s
+3s
+4hip
+7s
+2es
+3tic
+6ally
+6s
+2ff
+4a
+5s
+4ed
+4ing
+4s
+3tmensch
+9hen
+2g
+3e
+4d
+4ing
+7s
+4r
+5s
+4s
+3gable
+8s
+5ge
+7s
+4ed
+5r
+6s
+4ie
+6s
+5ng
+3hole
+7s
+3ing
+6s
+3s
+4ail
+7s
+3ubrious
+9sly
+9sness
+3worm
+7s
+2it
+4en
+2ke
+4warm
+8ish
+8ly
+8ness
+9esses
+8th
+9hs
+2libub
+7s
+3l
+4abied
+8s
+6y
+7ing
+4ed
+5r
+6s
+4ing
+4s
+3u
+4s
+2m
+3a
+4s
+3baginous
+6o
+7s
+5ng
+7s
+5r
+6s
+4er
+6ed
+7r
+8s
+6ing
+9ly
+9ness
+9nesses
+9s
+6jack
+9ket
+9kets
+9ks
+6ly
+6man
+7en
+6s
+7ome
+9eness
+6yard
+9ds
+4osacral
+4rical
+9es
+9is
+9ises
+9s
+7i
+8form
+7oid
+7us
+9es
+3en
+5al
+5s
+3ina
+6ire
+9s
+6l
+6nce
+9s
+7t
+8s
+6ria
+9s
+8es
+8sm
+9ms
+9t
+9ts
+7y
+6tion
+9ns
+5e
+6d
+6s
+7ce
+9d
+9nce
+9nces
+9nt
+9s
+8ing
+5iferous
+6ng
+6sm
+8s
+7t
+8s
+5osities
+9y
+6us
+8ly
+8ness
+9esses
+4sterol
+9ls
+3me
+4ier
+6st
+4ox
+6es
+4y
+3p
+4ectomies
+9y
+5d
+5n
+6ly
+6s
+5r
+6s
+4fish
+8es
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7ly
+5sh
+7ly
+7ness
+9sses
+4kin
+7s
+4s
+5ucker
+9rs
+4y
+3s
+2na
+4cies
+5y
+4naut
+8s
+4r
+5ian
+8s
+6es
+6st
+8s
+5naut
+9s
+5s
+5y
+4s
+4te
+6d
+6ly
+6s
+5ic
+7al
+9ly
+7s
+6on
+8s
+3ch
+5box
+8es
+5ed
+6on
+8ed
+9tte
+9ttes
+8ing
+8s
+6r
+7s
+6s
+5ing
+5meat
+9s
+5room
+9s
+5time
+9s
+3e
+4s
+4t
+5s
+5te
+7s
+3g
+4an
+6s
+4e
+5d
+5e
+6s
+5ing
+5r
+6s
+5s
+4fish
+8es
+5ul
+7s
+4i
+5e
+6s
+5ng
+5s
+4less
+4s
+4worm
+8s
+7t
+8s
+4yi
+6s
+3ier
+5s
+6t
+4ness
+8es
+4solar
+4tidal
+3k
+4er
+6s
+4head
+8ed
+8s
+4s
+3t
+4ed
+4ing
+4s
+3ula
+6e
+6r
+6te
+8d
+5e
+6s
+3y
+4ie
+6s
+2panar
+7s
+3in
+5e
+6s
+5s
+3oid
+4us
+3pen
+3ulin
+7e
+7ic
+7s
+4s
+5es
+2r
+3ch
+5ed
+6r
+7s
+6s
+5ing
+3dan
+6e
+7s
+6s
+4en
+6s
+3e
+4d
+4r
+5s
+4s
+4x
+5es
+3gi
+5es
+5s
+4y
+3id
+5er
+6st
+5ly
+5ness
+9es
+4ng
+6ly
+6s
+3k
+4ed
+5r
+6s
+4ing
+7ly
+7s
+4s
+3ries
+4y
+3s
+3ve
+5s
+2scious
+8ly
+8ness
+9esses
+3er
+5s
+3h
+4ed
+5r
+6s
+5s
+6t
+4ier
+6st
+5ng
+4ly
+4ness
+8es
+4y
+3k
+4ed
+4ing
+5sh
+7ness
+9sses
+4s
+3ted
+5r
+6ed
+6ing
+6less
+6s
+6ware
+9es
+4ful
+7ly
+7ness
+9sses
+4ick
+5er
+6st
+5head
+9s
+6ood
+9s
+5ly
+5ness
+9es
+5que
+4less
+4ra
+6l
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+5e
+6d
+6less
+6s
+6ware
+9es
+5ine
+8s
+7g
+8s
+5ous
+8ly
+8ness
+9esses
+5um
+7s
+4s
+4y
+3us
+5es
+2tanist
+8s
+3e
+4a
+5l
+4cium
+8s
+4d
+4fisk
+8s
+4in
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+4nist
+8s
+4olin
+8s
+6ous
+5trophic
+9hin
+9hins
+9ic
+9in
+9ins
+5us
+4r
+5s
+4s
+5cent
+5tring
+9gs
+4tium
+8s
+4um
+3fisk
+7s
+3hern
+7s
+4ier
+7s
+3ing
+6s
+4st
+6s
+4te
+6s
+3ten
+3z
+4es
+2v
+3s
+3vie
+6dom
+9s
+6s
+4y
+2x
+3ate
+6d
+6s
+5ing
+6on
+8s
+3e
+4s
+3meter
+8s
+3ulianite
+9tes
+5lianite
+9ites
+5yanite
+9tes
+4riance
+9es
+9ies
+9y
+8t
+9ly
+7te
+9d
+9s
+8ing
+9on
+9ons
+6es
+6ous
+9ly
+9ness
+9nesses
+6st
+8s
+5y
+2z
+3ern
+6s
+3zes
+1wei
+4s
+1yam
+4s
+3rd
+4t
+3se
+5s
+2caenid
+8s
+4nthrope
+9pes
+9pic
+9pies
+9pist
+9pists
+9py
+3ea
+4e
+5s
+4um
+6s
+3h
+4ee
+6s
+5s
+4gate
+8s
+4nis
+7es
+5oscope
+9pes
+3opene
+8s
+5od
+7ium
+9ms
+7s
+3ra
+5s
+2ddite
+7s
+2e
+3s
+2full
+2ing
+5ly
+5s
+2kewake
+8s
+6lk
+8s
+2m
+3e
+4s
+3iter
+7s
+3ph
+5ad
+7enitis
+9itises
+9opathy
+7s
+6ngial
+9ogram
+9ograms
+9tic
+9tides
+9tis
+9tises
+6tic
+9ally
+9s
+5oadenoma
+9nomas
+9nomata
+6blast
+9stic
+9sts
+6cyte
+9es
+9ic
+9openia
+9oses
+9osis
+9osises
+9otic
+6gram
+9ms
+9nuloma
+9phic
+9phies
+9phy
+6id
+6kine
+9es
+6ma
+8s
+8ta
+9oid
+9oses
+9osis
+9ous
+6penia
+9ias
+7oieses
+9esis
+9etic
+6sarcoma
+9comas
+9comata
+6trophic
+5s
+3s
+2nage
+6s
+3cean
+4h
+5ed
+6r
+7s
+6s
+6t
+7s
+5ing
+8s
+5pin
+8s
+3e
+4s
+3x
+4es
+4like
+2olyses
+6is
+3merous
+3nnaise
+3phil
+7e
+8d
+7ic
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+5obe
+7ic
+3sorption
+9ons
+2ra
+4te
+6d
+6ly
+3e
+4bird
+8s
+4s
+3ic
+5al
+7ly
+7ness
+9sses
+5ise
+8d
+8s
+7ing
+7m
+8s
+7t
+8s
+6ze
+8d
+8s
+7ing
+5on
+7s
+5s
+4form
+4sm
+6s
+5t
+6s
+2sate
+6s
+3e
+4d
+4rgic
+7de
+9s
+4s
+3igenetic
+7ic
+7ous
+4meter
+9s
+7ric
+4n
+5e
+6s
+5g
+5s
+4s
+3ogen
+7ic
+9ities
+9ity
+8es
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7s
+7y
+4l
+5ecithin
+9hins
+5s
+4somal
+7e
+8s
+4zyme
+8s
+3sa
+5s
+2te
+4d
+4s
+3he
+5s
+4raceous
+3ic
+5ally
+4ng
+3ta
+5e
+5s
+0ma
+2a
+3ed
+3ing
+3r
+4e
+4s
+3s
+4es
+3tjes
+2be
+4la
+6s
+4s
+2c
+3aber
+7esque
+5re
+7ly
+4co
+6s
+4dam
+7ia
+9s
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7s
+4huba
+8s
+4llum
+8s
+4que
+7s
+4rise
+8d
+8s
+7ing
+7m
+8s
+6ze
+8d
+8s
+7ing
+5oni
+8c
+9ally
+9s
+8es
+8s
+6on
+8s
+4ssar
+8s
+4w
+5s
+3cabaw
+8s
+6oy
+8s
+5roni
+9es
+9s
+4heroncini
+9cinis
+5ia
+7to
+9s
+6e
+4oboy
+8s
+3e
+4bearer
+9rs
+4d
+5oine
+9s
+4r
+5al
+7s
+6nduba
+9bas
+6te
+8d
+8r
+9s
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+5s
+4s
+3h
+4air
+7odont
+9onts
+7s
+5n
+6s
+4e
+5r
+6s
+5s
+5te
+7s
+4i
+5avelian
+9ians
+9lian
+9lians
+5colate
+9ted
+9tes
+9ting
+9tion
+9tions
+5nabilities
+9lity
+8le
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6e
+7ability
+9le
+7d
+7gun
+9nned
+9nning
+9ns
+7less
+8ike
+7man
+8en
+7ries
+8y
+7s
+6ima
+9s
+7ng
+9s
+7st
+9s
+5smo
+8s
+4meter
+9s
+4o
+5ism
+8s
+5s
+4ree
+7s
+4s
+4tpolitik
+9tiks
+4zor
+7im
+7s
+3ing
+5tosh
+9es
+3k
+4erel
+8s
+4inaw
+8s
+6tosh
+9hes
+4le
+6d
+6s
+5ing
+4s
+3le
+5d
+5s
+3on
+5ochie
+9es
+5s
+4ya
+6s
+3rame
+7s
+6i
+7s
+4encephalia
+9halias
+9halies
+9haly
+4o
+5aggregate
+9egated
+9egates
+5bian
+7ota
+9e
+9es
+9ic
+9ics
+5carpa
+9as
+6ephalia
+9alias
+9alic
+9alies
+9alous
+9aly
+6limate
+9ates
+9atic
+6ode
+9s
+7pies
+8y
+7sm
+9ic
+9ically
+9s
+6ycle
+9es
+9ic
+7st
+9s
+7te
+9s
+8ic
+8oses
+9sis
+5dactyl
+9ylic
+9ylies
+9ylous
+9yly
+6iagonal
+9onals
+6ome
+9s
+7nt
+5economic
+9omics
+6volution
+9utions
+5fauna
+9ae
+9as
+6lora
+9ae
+9as
+6ossil
+9ils
+5gamete
+9tes
+6lia
+9s
+7obulin
+9ulins
+6raph
+9hic
+9hs
+5lide
+9s
+6ogies
+8y
+5mere
+9s
+6ole
+9cular
+9cule
+9cules
+9s
+5n
+6s
+6uclear
+9ei
+9eus
+9euses
+7trient
+9ients
+5phage
+9es
+9ic
+9ous
+7otograph
+7yla
+9um
+8sics
+8te
+9es
+9ic
+6inakoid
+9koids
+6od
+8s
+6rism
+9ms
+6sia
+9s
+6terous
+5s
+6cale
+9es
+7opic
+9ically
+6ociology
+6porangia
+9angium
+9e
+9es
+6tructural
+9cture
+9ctures
+5tous
+5zamia
+9as
+4ural
+7n
+8s
+6oid
+7us
+3s
+3tation
+9s
+3ula
+6e
+6r
+6s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7ure
+9es
+5e
+6d
+6s
+5ing
+5ose
+4mba
+7s
+2d
+3afu
+6s
+4m
+5e
+6d
+6s
+5ing
+5s
+4roses
+7is
+3brain
+8ed
+3cap
+6s
+3ded
+5n
+6ed
+6ing
+9ly
+9ness
+9nesses
+6s
+5r
+6s
+5st
+4ing
+7ly
+5sh
+4ock
+7s
+3e
+4faction
+9ons
+5ied
+7s
+5y
+6ing
+4ira
+7s
+4leine
+9s
+4moiselle
+9lles
+4risation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+3ge
+5s
+3house
+8s
+3id
+4son
+7s
+3ling
+7s
+4y
+3man
+4en
+3ness
+7es
+3onna
+7ish
+7s
+7wise
+4qua
+7s
+3ras
+6a
+7h
+8s
+7s
+6es
+6sa
+8h
+9s
+8s
+4e
+5poral
+8e
+9s
+8ian
+9ans
+9c
+9te
+9tes
+9tic
+5s
+4igal
+8esque
+8ian
+9st
+9sts
+8s
+5lene
+9s
+4ona
+7s
+6e
+7s
+6o
+7s
+3s
+3tom
+6s
+3uro
+6s
+3woman
+6en
+5rt
+7s
+3zoon
+7s
+2e
+3lid
+6s
+4strom
+9s
+3nad
+6es
+6ic
+8ally
+7sm
+9s
+6s
+3rl
+5s
+3s
+4toso
+8s
+5ri
+6o
+7s
+2ffia
+6s
+5ck
+7ed
+8r
+9s
+7ing
+9gs
+7s
+4led
+5in
+7g
+8s
+7s
+3ia
+5s
+4c
+5s
+4osi
+6o
+7s
+3ted
+4ir
+6s
+2g
+3ainin
+8s
+4log
+7s
+7ue
+9s
+4zine
+8s
+7ist
+9ts
+3dalen
+8e
+9s
+8s
+3e
+4nta
+7s
+4s
+5hip
+8s
+3g
+4ed
+4ie
+6s
+5ng
+4ot
+6ier
+8st
+6oria
+9um
+6s
+6y
+4s
+3i
+4an
+6ism
+9s
+6s
+4c
+5al
+7ly
+5ian
+8s
+5ked
+6ing
+5s
+4lp
+6s
+4sm
+6s
+5ter
+8ial
+9ally
+9alness
+9es
+9um
+9ums
+8s
+8y
+6racies
+9y
+8l
+9ities
+9ity
+9ly
+9s
+8nd
+9ds
+8te
+9es
+9eship
+9eships
+9ic
+9ical
+9ically
+9ure
+9ures
+3lev
+6s
+3ma
+5s
+5ta
+6ic
+7sm
+9s
+3nalium
+9s
+5nimities
+9ty
+8ous
+9usly
+9usness
+5te
+7s
+8hip
+9ips
+4es
+6es
+6ia
+8l
+8n
+8s
+7c
+7te
+9s
+7um
+9s
+6stone
+9nes
+5t
+6ar
+8s
+6ic
+8al
+9lly
+8ian
+9ans
+8s
+7sable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9s
+7te
+9s
+8ic
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6o
+7chemical
+7electric
+7graph
+9aphs
+7meter
+9ters
+9tric
+9tries
+9try
+8otive
+7n
+8s
+7pause
+9uses
+7s
+8phere
+9heres
+9heric
+8tatic
+9atics
+6ron
+9s
+6s
+4ifiable
+7c
+8al
+9lly
+9t
+9tion
+9tions
+9ts
+8ence
+9nces
+9nt
+9ntly
+9ntness
+8o
+9es
+9s
+7ed
+8r
+9s
+8s
+6y
+7ing
+5loquence
+9ences
+9ent
+9ently
+5tude
+9s
+8inous
+4olia
+8ceous
+8s
+5n
+6s
+5x
+6es
+4um
+6s
+5s
+3ot
+5s
+3pie
+6s
+3s
+4man
+5en
+3uey
+6s
+4s
+3yar
+2ha
+4raja
+8h
+9s
+8s
+6nee
+9s
+7i
+8s
+5ishi
+9s
+4tma
+7ism
+9ms
+7s
+3ewu
+6s
+3imahi
+8s
+3jong
+7g
+8s
+7s
+3lstick
+9s
+3mal
+6s
+3oe
+5s
+4ganies
+7y
+4nia
+7s
+4ut
+6s
+3seer
+7s
+4ir
+6s
+3ua
+5ng
+7s
+5s
+3wa
+5s
+3zor
+6im
+6s
+2iasaur
+8a
+9s
+8s
+3d
+4an
+6s
+4ed
+5n
+6hair
+9rs
+7ead
+9ds
+7ood
+9ds
+6ish
+6like
+8ness
+9esses
+7y
+6s
+6weed
+9ds
+4hood
+8s
+4ing
+5sh
+7ness
+9sses
+6m
+7s
+4less
+4s
+5ervant
+9nts
+3eutic
+8al
+8s
+3gre
+6s
+3hem
+6s
+3k
+4o
+5s
+4s
+3l
+4abilities
+9ty
+6le
+4bag
+7s
+5ox
+7es
+4car
+7s
+5oach
+9es
+4e
+5d
+5r
+6s
+5s
+4gram
+8med
+9ing
+8s
+4ing
+7s
+4l
+5ess
+5ot
+7s
+5s
+4man
+5en
+6rge
+9d
+9s
+8ing
+4pouch
+9es
+4room
+8s
+4s
+5ack
+8s
+5hot
+8s
+8ted
+9ing
+4van
+7s
+3m
+4ed
+6ness
+9ses
+5r
+6s
+4ing
+7s
+4s
+3n
+4boom
+8s
+5race
+9s
+4door
+8s
+4ed
+5r
+5st
+4frame
+9s
+4ing
+4land
+8er
+9rs
+8s
+5ine
+8d
+8r
+9s
+8s
+7ing
+9gs
+5y
+4mast
+8s
+4or
+6s
+5ur
+7s
+4pernor
+9rs
+5rise
+9s
+4s
+5ail
+8s
+5heet
+9s
+5pring
+9gs
+5tay
+8s
+6ream
+9med
+9ming
+9mings
+9ms
+8eting
+9tings
+4tain
+8ability
+9ble
+8ed
+9r
+9rs
+8ing
+8s
+5enance
+9ced
+9ces
+9cing
+5op
+7mast
+9sts
+7s
+8ail
+9ils
+4yard
+8s
+3olica
+8s
+3r
+4e
+5hau
+8s
+5s
+4s
+3se
+5s
+4onette
+9es
+6nette
+9tes
+4t
+5er
+7dome
+9mes
+7ed
+7ing
+7s
+5ries
+7ng
+9s
+6y
+5s
+3ze
+5s
+2jagua
+7s
+3estic
+8al
+9lly
+9lness
+8ness
+9esses
+7es
+6y
+3lis
+6es
+3olica
+8s
+8ware
+9ares
+4r
+5at
+7s
+5domo
+9s
+5ed
+6tte
+9s
+8ing
+9ngs
+5ing
+6taire
+9res
+8rian
+9ianism
+9ians
+7ies
+7y
+5ly
+5s
+6hip
+9s
+3uscular
+8e
+9s
+2k
+3able
+4r
+5s
+3e
+4able
+4bate
+8s
+4fast
+8s
+4less
+4over
+8s
+4r
+5eadies
+8y
+5s
+4s
+5hift
+9s
+4up
+6s
+4weight
+9ts
+3i
+4mono
+8s
+4ng
+6s
+4s
+3o
+4s
+3s
+3unouchi
+9is
+4ta
+5u
+6ed
+6ing
+6s
+2l
+3a
+4bsorption
+9tions
+4cca
+7s
+5hite
+9s
+5ia
+7s
+5ological
+9ies
+9ist
+9ists
+9y
+6philies
+9lous
+9ly
+8yllous
+7terygian
+6stracan
+9acans
+9acous
+4daptation
+9tions
+8ed
+8ive
+9vely
+5dress
+9ses
+5ies
+5justed
+9ive
+9ment
+9ments
+5minister
+9stered
+9sters
+5roit
+9ly
+9ness
+9nesses
+9s
+5y
+4guena
+9s
+7tta
+9as
+4ise
+7s
+4katoone
+9nes
+4m
+5s
+5ute
+8s
+4nder
+8s
+5ga
+7s
+4pert
+8ly
+8ness
+9esses
+8s
+5portioned
+6ropriate
+9riated
+9riates
+5rop
+8ian
+9sm
+9sms
+9st
+9sts
+8os
+8s
+4r
+5ia
+7l
+7n
+7s
+6ologies
+9gist
+9gists
+9gy
+7us
+5key
+8s
+6ies
+6y
+5oma
+8s
+5s
+4s
+5similation
+4te
+6s
+5hion
+9s
+4x
+5age
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5ed
+6s
+5ing
+3conformation
+6tent
+9ted
+9tedly
+9ts
+3deployment
+9ments
+4istribution
+3e
+4ate
+7s
+4dicent
+7t
+8ed
+8ing
+9on
+9ons
+9ve
+8ory
+8s
+4faction
+9ons
+8or
+9rs
+9ry
+8ress
+9esses
+5fect
+9s
+5ic
+7ally
+7e
+8nce
+9ces
+9t
+8s
+7ial
+4ic
+4miut
+8s
+5ute
+8s
+4ness
+8es
+5gine
+9s
+5tendu
+9us
+4s
+4volence
+9ces
+9t
+9tly
+3feasance
+9ces
+9t
+9ts
+5d
+4ormation
+9ions
+7ed
+4unction
+9oned
+9oning
+9onings
+9ons
+3grado
+5e
+6d
+6s
+5ing
+3i
+4bu
+4c
+5e
+6d
+6s
+5ho
+7s
+5ing
+6ous
+9ly
+9ness
+9nesses
+4gn
+6ance
+9es
+9ies
+9y
+8t
+9ly
+9s
+6ed
+7r
+8s
+6ing
+7ties
+8y
+6ly
+6ment
+9ts
+6s
+4hini
+8s
+4k
+5s
+4mprinted
+9ting
+9tings
+4ne
+6s
+5ger
+8ed
+9r
+9rs
+8ies
+9ng
+8s
+8y
+4s
+5m
+6s
+5on
+7s
+5t
+3kin
+6s
+3l
+4am
+6s
+5nder
+9s
+5rd
+7s
+4core
+8s
+4eabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6te
+8d
+8s
+7ing
+8on
+9ns
+5cho
+8s
+5d
+5e
+6s
+5i
+6form
+5maroking
+9kings
+6uck
+9s
+5nder
+9s
+5olar
+7i
+7us
+9es
+5t
+6s
+5us
+7es
+4ing
+7s
+4ophagous
+5w
+6puff
+9fs
+6s
+4s
+3m
+4ag
+6s
+4ier
+6st
+4s
+5ey
+7s
+5tone
+9s
+4y
+3nourished
+4utrition
+9ions
+3occluded
+8sion
+9ions
+4dor
+7ous
+9sly
+9sness
+7s
+6ur
+8s
+4lactic
+4nate
+8s
+5ic
+5ylurea
+9eas
+4ti
+3pighia
+9ceous
+4osed
+6ition
+9ons
+4ractice
+9ces
+9tioner
+5esentation
+3s
+4tick
+8s
+3t
+4alent
+9s
+5se
+7s
+4ed
+6s
+5se
+4ha
+6s
+4ier
+6st
+5ness
+9es
+6g
+7s
+4man
+5en
+4ol
+6s
+5se
+7s
+4reat
+8ed
+9r
+9rs
+8ing
+8ment
+9ents
+8s
+4s
+5ter
+8s
+4worm
+8s
+4y
+3va
+5ceous
+5s
+6ia
+8n
+8s
+4ersation
+9ions
+5sie
+8s
+4oisie
+9s
+3wa
+5re
+7s
+5s
+2m
+3a
+4guy
+7ed
+7ing
+7s
+4kau
+7s
+5o
+6s
+5u
+6s
+4liga
+8s
+4s
+3ba
+5s
+4o
+5ed
+6s
+5ing
+5s
+3ee
+5s
+4lon
+7s
+5uco
+8s
+6ke
+8s
+4y
+5es
+5s
+3ie
+5s
+4lla
+7e
+7r
+8y
+7te
+9d
+8ion
+9ons
+6iform
+3luk
+6s
+3ma
+5e
+5l
+6ian
+9s
+7ferous
+7ties
+8y
+6ogical
+9es
+9st
+9sts
+8y
+6s
+5plasties
+9ty
+5ries
+6y
+5s
+5te
+6i
+6us
+4ectomies
+9y
+5e
+6s
+5r
+6ed
+6ing
+6s
+5t
+6ries
+7y
+6s
+5y
+6s
+4ie
+6s
+5fer
+8ous
+8s
+6orm
+5lla
+8e
+8ria
+9ias
+9y
+8te
+9ed
+5tides
+7s
+4ock
+7ed
+7ing
+7s
+5genic
+6ram
+9s
+8ph
+9hic
+9hies
+9hs
+9hy
+5n
+6ish
+8m
+9s
+8t
+9ic
+9s
+7te
+9s
+6s
+5plasties
+9ty
+5th
+7s
+4y
+3para
+7s
+4oer
+7s
+3s
+4elle
+8s
+3zer
+6im
+6s
+2n
+3a
+4cle
+7d
+7s
+6ing
+4ge
+6abilities
+9lity
+8le
+9eness
+9y
+6d
+6ment
+9tal
+9ts
+6r
+7ess
+9ses
+7ial
+9lism
+9lisms
+9list
+9lists
+9lly
+7s
+8hip
+9ips
+6s
+5ing
+4ia
+6s
+4kin
+7s
+4na
+6s
+4s
+4t
+5ee
+7s
+5i
+6s
+5oid
+5s
+5u
+6s
+4wa
+6s
+3cala
+7s
+5ndo
+4he
+6s
+7ter
+9rs
+6t
+7s
+5ineel
+9ls
+4ipate
+9d
+9s
+8ing
+9on
+9ons
+8ory
+6le
+8s
+4us
+6es
+3d
+4ala
+7s
+6ic
+5mus
+8ed
+9s
+8ing
+5rin
+8ate
+9tes
+8e
+9s
+8ic
+9sm
+9sms
+8s
+5taries
+8y
+6e
+7d
+7s
+6ing
+6or
+8ies
+9ly
+8s
+8y
+4i
+5ble
+8s
+6ular
+9te
+9ted
+9tes
+5lion
+9s
+5oc
+7a
+8s
+7ca
+9s
+7s
+5r
+6a
+7s
+6s
+5s
+4ola
+7s
+6in
+8e
+9s
+8ist
+9sts
+8s
+5m
+6s
+5ra
+7s
+6la
+8s
+4ragora
+9as
+6ke
+8s
+5el
+7s
+5il
+7l
+8s
+7s
+4ucable
+7te
+9d
+9s
+8ing
+9on
+9ons
+8ory
+4ylion
+9s
+3e
+4d
+4ge
+6d
+6s
+5ing
+4h
+5s
+4less
+4nt
+4s
+4t
+4uver
+8ability
+9ble
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+3ful
+6ly
+6ness
+9ses
+3g
+4a
+5beira
+9as
+7y
+8s
+6ies
+6y
+5l
+6s
+7utra
+9ras
+5nate
+9s
+6ese
+9s
+8ian
+6ic
+7ferous
+7n
+8s
+7te
+9s
+6ous
+5s
+4e
+5ao
+7s
+5d
+5l
+6s
+6wurzel
+9zels
+5mange
+9es
+5r
+6s
+5s
+5tout
+9s
+5y
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4le
+6d
+6r
+7s
+6s
+5ing
+4o
+5es
+5ld
+7s
+7wurzel
+9rzels
+5nel
+8s
+5s
+6tan
+9s
+7een
+9ns
+5uste
+9s
+4rove
+8s
+4s
+4ulate
+9d
+9s
+8ing
+4y
+3handle
+9d
+9s
+8ing
+5ttan
+9s
+4ole
+7s
+5od
+7s
+4unt
+7er
+9s
+7s
+3i
+4a
+5c
+6al
+8ly
+6s
+5s
+4c
+5ally
+5otti
+9s
+5s
+5ure
+8d
+8s
+7ing
+8st
+9ts
+4es
+4fest
+8able
+9nt
+9nts
+9tion
+9tional
+9tions
+9tive
+8ed
+9r
+9rs
+8ible
+9ng
+8ly
+8ness
+9esses
+8o
+9ed
+9es
+9ing
+9s
+8s
+5old
+8ed
+9r
+9rs
+8ing
+8ly
+8ness
+9esses
+8s
+6rm
+4hoc
+7s
+6t
+7s
+4kin
+7s
+4la
+6s
+5la
+7s
+6e
+7s
+4oc
+6a
+7s
+6s
+4ple
+7s
+6ies
+5ulability
+9le
+8r
+9s
+8table
+9e
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9ively
+9or
+9ors
+9ory
+4s
+4to
+6s
+6u
+7s
+5u
+6s
+3jack
+7s
+3kier
+6st
+5nd
+7s
+6i
+7s
+4y
+3less
+4ier
+6st
+5hood
+5ke
+7ly
+5ly
+5ness
+9es
+4y
+3made
+3na
+5n
+6s
+5s
+4ed
+5quin
+9s
+5r
+6ed
+6ism
+9s
+8t
+9ic
+9ical
+9ically
+9s
+6less
+9sness
+7iness
+9esses
+7y
+6s
+4iferous
+5kin
+8s
+5ng
+5sh
+7ly
+7ness
+9sses
+5te
+7s
+6ic
+6ol
+8s
+4ose
+7s
+3o
+4ao
+6s
+4euvrability
+9ble
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+4meter
+9s
+7ric
+9cal
+9cally
+9es
+8y
+4r
+5ial
+8ism
+9sms
+5s
+4s
+5copies
+8y
+3pack
+7s
+4ower
+8s
+3que
+3red
+6s
+5nt
+7s
+4ider
+8s
+6ing
+5kigusari
+9saris
+4ope
+7s
+3s
+4ard
+7ed
+7s
+4e
+5rvant
+5s
+4hift
+8s
+4ion
+7aries
+9y
+7s
+4laughter
+9ters
+6yer
+9s
+4onries
+7y
+4uete
+7ude
+9es
+4worn
+3ta
+5s
+4eau
+7s
+7x
+5el
+7s
+5l
+6et
+8s
+6letta
+9tas
+6piece
+9ces
+6s
+7helf
+9lves
+6tree
+9es
+5s
+4ic
+6ally
+6ora
+9s
+8e
+9s
+5d
+6s
+5es
+5lla
+8s
+5s
+6es
+6sa
+8s
+4le
+6d
+6s
+6t
+7ree
+9es
+7s
+5ing
+8s
+4o
+5es
+5s
+4ra
+6m
+7s
+6p
+7s
+6s
+5ic
+4ua
+6s
+4y
+3ual
+6ly
+6s
+5ry
+4bria
+8l
+7um
+9s
+4factories
+9ry
+8urable
+9ral
+9re
+9red
+9rer
+9rers
+9res
+9ring
+9rings
+4hiri
+8s
+4ka
+6s
+4l
+5s
+4mea
+7s
+5ission
+9ons
+6t
+7s
+7ted
+9r
+9rs
+8ing
+4rance
+9s
+5e
+6d
+6r
+7s
+6s
+5ial
+6ng
+8s
+4s
+5cript
+9ts
+3ward
+7s
+4ise
+3y
+4ata
+7s
+6ta
+8s
+4fold
+4plies
+3zanilla
+9as
+7ta
+9s
+4ello
+8s
+2omao
+6s
+3rmor
+7s
+2p
+3au
+5s
+3le
+5like
+5s
+6s
+4ike
+3maker
+8s
+6ing
+9s
+3pable
+4ed
+5mond
+9s
+5r
+6ies
+6s
+6y
+4ing
+7s
+5st
+7s
+3s
+4tick
+8s
+3wise
+2quette
+8s
+4i
+5la
+7dora
+9ras
+7s
+6lage
+9es
+5s
+6ard
+9s
+2r
+3a
+4bi
+6s
+5ou
+7s
+7t
+8s
+5unta
+9s
+4ca
+6s
+4e
+5s
+4ging
+8s
+4h
+5s
+4natha
+9s
+5ta
+7s
+4ri
+6s
+4s
+5ca
+7s
+6hino
+9os
+5mic
+6oid
+6us
+8es
+4thon
+8er
+9rs
+8ing
+9ngs
+8s
+4ud
+6ed
+7r
+8s
+6ing
+9s
+6s
+4vedi
+8s
+3belise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+4le
+6d
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6r
+7s
+6s
+6wood
+9ds
+5ier
+7st
+6ng
+8s
+5y
+3c
+4antant
+9ts
+5site
+9s
+8ical
+5tissimo
+6o
+7s
+4el
+6la
+8s
+7ed
+8r
+9s
+7ing
+6s
+5scence
+9ces
+9t
+7ible
+4h
+5antia
+9as
+5ed
+6n
+6r
+7s
+6s
+7a
+8s
+7e
+7i
+5ing
+6oness
+9sses
+5land
+9s
+6ike
+5man
+6en
+5pane
+9s
+4oni
+7ed
+7gram
+9ams
+9aph
+9aphed
+9aphing
+9aphs
+7ing
+7s
+4s
+3d
+4ied
+6r
+6s
+7t
+4y
+5ing
+3e
+4mma
+7s
+6e
+4ngo
+4ro
+6s
+4s
+5chal
+9s
+3g
+4aric
+7n
+8e
+9s
+8s
+7ta
+9s
+8e
+9s
+8ic
+9ferous
+5y
+6s
+4e
+5nt
+7ed
+7ing
+7s
+5s
+4in
+6al
+8ia
+9sation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+7te
+9d
+9s
+8ing
+9on
+9ons
+6ed
+6ing
+6s
+4osa
+7s
+4ravate
+9es
+7e
+8s
+7ial
+9te
+9tes
+8ne
+9es
+4s
+4uerite
+9es
+3ia
+5chi
+8s
+5lite
+9s
+4culture
+9res
+9rist
+9rists
+4d
+5s
+4es
+4gold
+8s
+5ram
+8s
+7ph
+9s
+4huana
+9s
+4juana
+9s
+4mba
+7phone
+9ones
+7s
+6ist
+9s
+4na
+6de
+8d
+8s
+7ing
+6ra
+8s
+6s
+6te
+8d
+8s
+7ing
+8on
+9ns
+5e
+6r
+7a
+8s
+7s
+6s
+5iere
+4onberries
+9ry
+6ette
+9es
+4posa
+8s
+4schal
+9led
+9ling
+9s
+5h
+6es
+4tage
+8s
+6l
+7ly
+5ime
+4vaudage
+9ges
+3joram
+8s
+3k
+4a
+5s
+4down
+8s
+4ed
+6ly
+6ness
+9ses
+5r
+6s
+5t
+6abilities
+9lity
+8le
+9eness
+9y
+6ed
+7er
+9s
+7r
+8s
+6ing
+9s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6place
+9ces
+6s
+4hoor
+8s
+6r
+7s
+4ing
+7s
+4ka
+6a
+6s
+4man
+5en
+4s
+5man
+8ship
+9hips
+6en
+5woman
+8en
+4up
+6s
+3l
+4acious
+4e
+5d
+5s
+4ier
+6st
+5n
+6e
+7s
+8pike
+9ikes
+6g
+7s
+8pike
+9ikes
+6s
+7pike
+9kes
+5te
+7s
+6ic
+4s
+5tone
+9s
+4y
+3m
+4alade
+9s
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+5rise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6oses
+8is
+4elise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+5m
+4ite
+7s
+4oreal
+9ly
+8n
+5se
+7s
+7t
+8s
+5t
+6s
+4s
+3ocain
+8s
+4n
+5s
+4on
+6ed
+7r
+8s
+6ing
+9s
+6s
+4quin
+8s
+4r
+5s
+3plot
+7s
+4relate
+9ed
+9es
+9ing
+3que
+6e
+7s
+6s
+7s
+8ate
+9tes
+8es
+6terie
+9ies
+7ries
+8y
+5is
+7ate
+9es
+7e
+8s
+8tte
+9tes
+3ram
+6s
+5no
+7s
+4ed
+5ls
+5r
+6s
+4i
+5age
+8ability
+9ble
+8s
+5ed
+7s
+6r
+7s
+6s
+5ng
+5s
+4on
+6s
+5w
+6bone
+9es
+6ed
+6fat
+9s
+6ing
+7sh
+6less
+6s
+7kied
+9es
+8y
+9ing
+6y
+4um
+6s
+4y
+5ing
+8s
+3s
+4ala
+7s
+4e
+5ille
+9s
+5s
+4h
+5al
+7cies
+8y
+7ed
+8r
+9s
+7ing
+7l
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+7s
+8hip
+9ips
+5buck
+9s
+5es
+5ier
+7st
+6ness
+9ses
+5land
+9er
+9ers
+9s
+6ike
+6ocks
+9ses
+5mallow
+9ows
+9owy
+5wort
+9s
+5y
+4ipobranch
+9anchs
+4port
+8s
+4quake
+9s
+4upia
+8l
+9ian
+9ians
+9s
+8n
+9s
+7um
+9s
+3t
+4agon
+8s
+4ed
+5l
+6lando
+9dos
+8to
+7ed
+7ing
+7o
+8s
+6s
+5n
+6s
+7ite
+9es
+9ic
+9ically
+5xt
+7s
+4ial
+7ism
+9ms
+9t
+9ts
+7ly
+7ness
+9sses
+7s
+6n
+7s
+5n
+6et
+8ish
+9sm
+9sms
+8s
+6g
+7al
+9e
+9es
+9s
+6i
+7s
+6s
+4let
+7s
+4s
+4yr
+6dom
+9s
+6ed
+6ia
+7es
+7ng
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7um
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+6ologic
+9gical
+9gies
+9gist
+9gists
+9gy
+6s
+6y
+3vel
+6ed
+6ing
+6led
+7ing
+7ous
+9sly
+9sness
+6ous
+9ly
+9ness
+9nesses
+6s
+5r
+6ed
+6ing
+6s
+4ier
+6st
+4y
+3xisant
+3y
+4bud
+7s
+4jane
+8s
+3zipan
+8s
+2s
+3a
+4la
+6s
+4s
+3cara
+7ed
+7ing
+7s
+6on
+8s
+6pone
+9es
+4le
+6d
+6s
+4on
+6s
+5t
+6s
+4uline
+9ly
+9ness
+9nesses
+9s
+8isation
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+7st
+9s
+6y
+3e
+4d
+4r
+5s
+4s
+3h
+4allah
+4ed
+5r
+6s
+5s
+4giach
+7h
+6chim
+6him
+4iach
+8s
+5e
+6r
+6s
+7t
+5ng
+7s
+4lam
+7s
+5im
+7s
+6n
+7s
+5och
+8s
+5um
+7s
+4man
+5en
+4ua
+6s
+5p
+6s
+4y
+3ing
+3jid
+6s
+3k
+4able
+5llonge
+9ges
+6onge
+9es
+5nonge
+9es
+4ed
+5g
+6s
+5r
+6s
+4ing
+7s
+6onge
+9es
+5rovka
+9as
+4like
+4s
+3lin
+6s
+3on
+5ed
+5ic
+7ally
+6ng
+6te
+8s
+5ried
+8s
+6y
+5s
+4olah
+8s
+3que
+6r
+7ade
+9ed
+9er
+9ers
+9es
+9ing
+7s
+6s
+3s
+4a
+5cre
+8d
+8r
+9s
+8s
+7ing
+5ge
+7d
+7r
+8s
+7s
+6ing
+7st
+9s
+5randuba
+9ubas
+5s
+6auga
+9as
+4cult
+8s
+4e
+5d
+6ly
+5randuba
+9ubas
+5s
+5ter
+8ic
+8s
+5ur
+7s
+6se
+8s
+4icot
+8s
+5er
+6st
+5f
+6ication
+9tions
+6s
+5ness
+9es
+6g
+5ve
+7ly
+7ness
+9sses
+7s
+4less
+4oola
+8s
+5therapies
+9apist
+9apists
+9apy
+4priest
+9ts
+4tige
+8s
+4y
+5more
+9s
+3t
+4aba
+7h
+8s
+7s
+4ectomies
+9y
+5d
+5r
+6ate
+9s
+6class
+9sses
+6dom
+9s
+6ed
+6ful
+9ly
+9ness
+9nesses
+6hood
+9ds
+6ies
+7ng
+9s
+6less
+7iness
+9esses
+7y
+6mind
+9ded
+9ding
+9ds
+6piece
+9ces
+6s
+7hip
+9ps
+7inger
+9gers
+7troke
+9okes
+6work
+9ks
+9t
+9ts
+6y
+4ful
+4head
+8ed
+8ing
+8s
+5ouse
+9s
+4ic
+6able
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9ries
+9rs
+9ry
+6h
+7e
+8s
+7s
+6ot
+8s
+6s
+5er
+6st
+5ff
+7s
+5gophoran
+9orans
+9ore
+9ores
+9oric
+9orous
+5ng
+5tic
+7des
+7s
+8es
+5x
+6es
+4less
+5ike
+4odon
+8ic
+8s
+8t
+9ic
+9s
+6ynia
+9as
+5id
+7al
+7ectomies
+9tomy
+7ites
+9ides
+9is
+9ises
+7s
+5pexies
+8y
+4s
+4urbation
+9ions
+9or
+9ors
+9ory
+4y
+3u
+4la
+6s
+4rium
+8s
+4s
+2t
+3achin
+8a
+9s
+8i
+4dor
+7a
+8s
+7e
+8s
+7s
+4gouri
+9s
+4i
+5s
+4mata
+8s
+5bala
+4ta
+6s
+5u
+6s
+3ch
+5able
+5board
+9ding
+9dings
+9ds
+7ok
+9s
+7x
+8es
+5ed
+6r
+7s
+6s
+6t
+7s
+5ing
+5less
+9ly
+9ness
+9nesses
+6ock
+9s
+5made
+7ke
+9r
+9rs
+9s
+8ing
+9ngs
+7rk
+9ed
+9ing
+9s
+5play
+9s
+5stick
+9ks
+5up
+7s
+5wood
+9s
+3e
+4d
+4lasse
+9s
+5ess
+5lasse
+9es
+5ot
+7e
+8s
+7s
+7te
+9s
+4r
+5familias
+9liases
+5ial
+8isation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9sm
+9sms
+9st
+9stic
+9stical
+9sts
+9ties
+9ty
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8ly
+8ness
+9esses
+8s
+6el
+8s
+5nal
+8ism
+9sms
+9stic
+8ly
+6ities
+8y
+5s
+4s
+5hip
+8s
+4y
+5ness
+9es
+5s
+3fellon
+9s
+6on
+8s
+3grass
+8es
+3h
+4ematic
+9cal
+9cally
+9cian
+9cians
+9cise
+9cised
+9cises
+9cising
+9cism
+9cisms
+9cize
+9cized
+9cizes
+9cizing
+9cs
+9sation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+5ses
+6is
+4s
+3ico
+6s
+4er
+5s
+6t
+4lda
+7s
+5y
+4n
+5al
+5ee
+7s
+6ss
+8es
+5g
+6s
+5s
+4po
+6s
+3jes
+3less
+4o
+5s
+5w
+6s
+3oke
+6s
+4oke
+7s
+3rass
+7es
+4es
+6familias
+4iarch
+9al
+9alism
+9alisms
+9ate
+9ates
+9ic
+9ies
+9s
+9y
+5c
+6e
+7s
+6idal
+8e
+9s
+6linic
+9ous
+6s
+6ula
+9nt
+9nts
+9r
+9s
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+9tory
+5focal
+9lities
+9lity
+5lineal
+9ally
+9ar
+8ies
+8y
+6ocal
+9lities
+9lity
+9lly
+5monial
+9ally
+9es
+8y
+5oshka
+9i
+5x
+6es
+4oclinal
+9ic
+9ies
+9ous
+9y
+5n
+6age
+9s
+7l
+6hood
+9ds
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6liness
+9esses
+7y
+6s
+7hip
+9ps
+6ymic
+9cs
+5ss
+7es
+5yshka
+9as
+4yoshka
+9i
+3s
+4ah
+6s
+4uri
+7s
+5take
+9s
+3t
+4amore
+9s
+4e
+5d
+6ly
+5r
+6ed
+6ful
+6ing
+6less
+6s
+6y
+5s
+4ie
+6s
+5fied
+8s
+6y
+7ing
+5n
+6g
+7s
+6s
+4ock
+7s
+5id
+7s
+4rass
+8es
+5ess
+8es
+4s
+3urable
+6te
+8d
+8s
+7ing
+8on
+9nal
+9ns
+8ve
+5e
+6d
+6ly
+6ness
+9ses
+6r
+7s
+6s
+7t
+5ing
+6ties
+7y
+4tinal
+9ly
+7e
+3weed
+7s
+3y
+3za
+5h
+6s
+5s
+4o
+5h
+6s
+5on
+7s
+5s
+5t
+6h
+2ubies
+4y
+3d
+4lin
+7ism
+9ms
+7ly
+7ness
+9sses
+4s
+3ger
+4re
+6d
+6s
+5ing
+3l
+4ed
+5r
+6s
+4gre
+7d
+7s
+6ing
+4ing
+4s
+5tick
+9s
+4vi
+6s
+3met
+6ries
+7y
+6s
+3n
+4d
+5ed
+6r
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5ies
+6ng
+5s
+5y
+4gier
+7st
+5y
+4na
+3ri
+5s
+3solea
+8n
+7um
+9s
+3t
+4her
+7s
+4s
+3vais
+7e
+4e
+5in
+7e
+8s
+7s
+5r
+5s
+6t
+4in
+6e
+7s
+6s
+2ven
+5s
+4rick
+8ed
+8ing
+8s
+3ie
+5s
+4n
+5s
+4s
+5es
+3ourneen
+9ns
+7in
+9s
+2w
+3bound
+3ed
+3ger
+3ing
+3k
+4ier
+6st
+5n
+6s
+5sh
+7ly
+7ness
+9sses
+4s
+4y
+3met
+6ries
+7y
+6s
+3n
+3pus
+6es
+3r
+4s
+3s
+4eed
+7s
+3ther
+7s
+2x
+3ed
+4s
+3i
+4coat
+8s
+4lla
+7e
+7r
+8ies
+8y
+7s
+6iped
+9dary
+9de
+9des
+9ds
+6ofacial
+6ula
+9e
+4m
+5a
+6l
+7ist
+9ts
+7ly
+7s
+6philies
+9ly
+6tion
+9ns
+5in
+7s
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7t
+8s
+6te
+8s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5s
+5um
+7ly
+7s
+6s
+7es
+4ng
+4s
+4xe
+6s
+3well
+7s
+2y
+3a
+4n
+4pple
+8s
+4s
+3be
+5s
+4ird
+7s
+4ush
+7es
+3day
+6s
+3ed
+4st
+3flies
+5ower
+9s
+5y
+3hap
+6pen
+4em
+6s
+3ing
+6s
+3o
+4nnaise
+9es
+4r
+5al
+7ties
+8y
+5ess
+8es
+5s
+6hip
+9s
+4s
+3pole
+7s
+5p
+6s
+3s
+4t
+5er
+7dome
+9mes
+7s
+3vin
+6s
+3weed
+7s
+2zaedia
+7um
+4rd
+6s
+5inade
+9es
+7e
+8s
+3e
+4d
+5ly
+5ness
+9es
+4ful
+4like
+5tov
+4ment
+8s
+4r
+5s
+4s
+4y
+3hbi
+6s
+3ier
+5st
+4ly
+4ness
+8es
+5g
+3ourka
+8s
+5t
+6s
+3uma
+6s
+4rka
+7s
+4t
+5s
+3y
+3zard
+7s
+1baqanga
+8s
+2ira
+5s
+1e
+2acock
+7s
+3d
+4ow
+6land
+9ds
+8rk
+9ks
+6s
+7weet
+9ets
+6y
+4s
+3ger
+6ly
+6ness
+9ses
+4re
+6ly
+6ness
+9ses
+6r
+6s
+7t
+3l
+4ed
+5r
+6s
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+4less
+4s
+4time
+8s
+4worm
+8s
+4y
+5bug
+8s
+5mouthed
+3n
+4der
+7ed
+8r
+9s
+7ing
+9gly
+7s
+5rian
+6ous
+4e
+5d
+5r
+6s
+5s
+6t
+4ie
+6s
+5ng
+7ful
+9lly
+9lness
+7less
+9ssly
+9ssness
+8y
+7s
+4ly
+4ness
+8es
+4s
+4t
+5ime
+8s
+4while
+9s
+4y
+3re
+5s
+4ing
+3se
+5d
+5s
+4ing
+4le
+6d
+6s
+5ier
+7st
+6ness
+9ses
+7g
+5y
+4urabilities
+9lity
+8le
+9eness
+9y
+6e
+7d
+8ly
+8ness
+9esses
+7less
+9ssly
+9ssness
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9s
+3t
+4al
+5xe
+7s
+4ball
+8s
+4ed
+4h
+5e
+6ad
+8s
+6s
+5s
+4ier
+6st
+5ly
+5ness
+9es
+4less
+5oaf
+7ves
+4man
+5en
+4packing
+9ngs
+4s
+5creen
+9ns
+5pace
+9s
+4us
+6es
+4y
+3wes
+3zel
+6s
+2bos
+5es
+2camylamine
+9ines
+3ca
+5s
+3hanic
+8al
+9lism
+9lisms
+9lly
+9lness
+9ls
+8ian
+9ans
+8s
+7sable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ically
+9s
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ochemical
+7morphism
+7receptor
+7therapy
+5tronic
+9ics
+4itza
+8s
+7ot
+3k
+4s
+3lizine
+9s
+3onate
+8s
+5ic
+6n
+7s
+6um
+8s
+5opses
+8is
+2d
+3acca
+7s
+4illon
+9s
+4ka
+6s
+4l
+5ed
+6t
+7s
+5ing
+6st
+8s
+5led
+6ic
+7ng
+7on
+9ed
+9ing
+9s
+7st
+9s
+5play
+9s
+5s
+3cinal
+3dle
+6d
+6r
+7s
+6s
+7ome
+9ely
+9eness
+5ing
+8ly
+8s
+3evac
+7ed
+7ing
+7ked
+8ing
+7s
+3flies
+5y
+3ia
+5cies
+6y
+5d
+5e
+6val
+9ism
+9isms
+9ist
+9istic
+9ists
+9ly
+9s
+5genic
+5l
+6ly
+6s
+5n
+6ly
+6s
+6t
+7s
+5s
+6tina
+9al
+9um
+5te
+7d
+7ly
+7ness
+9sses
+7s
+6ing
+7on
+9al
+9s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7ve
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6or
+8ial
+9ally
+8s
+9hip
+9hips
+8y
+6ress
+9ses
+7ices
+8x
+9es
+4c
+5able
+8y
+6id
+8s
+6l
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7s
+6ment
+9tal
+9tally
+9tary
+9ted
+9ting
+9tous
+9ts
+6nt
+8s
+6re
+8s
+6ster
+9rs
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+5ide
+8s
+6nable
+8l
+9ly
+9s
+7e
+8d
+8r
+9s
+8s
+7ing
+5k
+6s
+5o
+6legal
+6s
+5s
+4eval
+8ism
+9sms
+9st
+9stic
+9sts
+8ly
+8s
+4gap
+7s
+4i
+4na
+6s
+4ocracies
+9y
+7e
+7ities
+9y
+4tate
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+9eness
+7or
+9s
+5erranean
+4um
+6istic
+6s
+7hip
+9ps
+5s
+6es
+4vac
+7ed
+7ing
+7ked
+8ing
+7s
+3lar
+6s
+4e
+5d
+5s
+5y
+6s
+4ing
+3resa
+7s
+6e
+7s
+6seh
+9s
+3s
+3ulla
+7e
+7r
+8y
+7s
+7te
+9d
+6oblastoma
+4sa
+6e
+6l
+6n
+7s
+6s
+5iform
+5oid
+8s
+2e
+3d
+4s
+3k
+4en
+6ed
+6ing
+6s
+5r
+5st
+4ly
+4ness
+8es
+3mie
+6s
+3r
+4cat
+7s
+4ed
+4ing
+4kat
+7s
+4s
+5chaum
+9ms
+3s
+3t
+4er
+6s
+5st
+4ing
+7house
+9uses
+7s
+4ly
+4ness
+8es
+4s
+2ff
+4s
+3loquine
+9es
+2g
+3a
+4bar
+7s
+5it
+7s
+5uck
+8s
+5yte
+8s
+4cephalic
+9lies
+9lous
+9ly
+5hurch
+9hes
+5ities
+7y
+5orporation
+5urie
+9s
+5ycle
+9s
+4deal
+8s
+7th
+9s
+5ose
+8s
+5yne
+8s
+4farad
+9s
+6una
+9e
+9l
+9s
+5lop
+8s
+7ra
+9e
+9s
+5og
+7s
+4gamete
+9es
+9ophyte
+6uss
+9es
+4herbivore
+9vores
+7tz
+9es
+5it
+7s
+4joule
+9s
+4karyocyte
+9cytes
+9cytic
+4lith
+8ic
+8s
+7re
+9s
+5oblast
+9stic
+9sts
+6cardia
+9dias
+7ephalic
+9halies
+9halous
+9haly
+6mania
+9iac
+9iacal
+9iacs
+9ias
+9ic
+6pic
+7olis
+9ises
+9itan
+9itans
+7s
+8es
+6saur
+9ri
+9rian
+9rians
+9rs
+9rus
+4newton
+9ns
+4parsec
+9cs
+5hone
+9d
+9s
+8ic
+9cally
+9ng
+6yll
+9s
+5ixel
+9s
+5lex
+8es
+5od
+7e
+8s
+7s
+5roject
+9cts
+4ra
+6d
+7s
+5on
+7s
+4scope
+9s
+8ic
+9cally
+5porangia
+9ngium
+8e
+9s
+8ic
+8ophyll
+9phylls
+5s
+6e
+7s
+5tar
+8s
+6ore
+9s
+6ructure
+9tures
+4technology
+5here
+9s
+8ian
+5on
+7ic
+7nage
+9ges
+7s
+4vertebrate
+9brates
+5itamin
+9ins
+5olt
+8s
+4watt
+8s
+3illa
+7h
+8s
+7s
+6oth
+5p
+6h
+7s
+6s
+3ohm
+6s
+3rim
+6s
+3s
+2h
+3ndi
+6s
+2ibomian
+3kle
+3n
+4ed
+5y
+6s
+4ie
+6s
+5ng
+4s
+4t
+4y
+3ocyte
+8s
+4fauna
+9e
+9l
+9s
+4nite
+8s
+4ses
+5is
+5pore
+9s
+4tic
+7ally
+3shi
+6s
+4ter
+7s
+3th
+5s
+4nerium
+9ms
+2jlis
+6es
+2kka
+5s
+3ometer
+9s
+2l
+3a
+4conite
+9es
+4leuca
+9s
+4mdim
+5ed
+5ine
+8s
+5pode
+9s
+4naemia
+9as
+5cholia
+9iac
+9iacs
+9iae
+9ias
+9ic
+9ically
+9ics
+9ies
+9ily
+9iness
+9ious
+9y
+5ge
+7s
+5ian
+6c
+7s
+6n
+7s
+6sation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8s
+7t
+8ic
+8s
+6te
+8s
+7ic
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5o
+6blast
+9sts
+6chroi
+9oic
+9oous
+7yte
+9es
+6geneses
+9esis
+6id
+8s
+6ma
+8s
+8ta
+6phore
+9res
+6s
+7es
+7is
+8ties
+9y
+7ome
+9es
+6tic
+7ropin
+9pins
+6us
+5terite
+9tes
+5uria
+9s
+8c
+4phyre
+9s
+4s
+5tomaceous
+8e
+4tonin
+9s
+3ba
+3d
+4ed
+5r
+6s
+4ing
+4s
+3ee
+5s
+4na
+6s
+3iaceous
+4c
+5k
+6s
+5otton
+9ns
+5s
+4k
+5s
+4lite
+8s
+5ot
+7s
+4nite
+8s
+4orable
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9ves
+8or
+9rs
+6ism
+9s
+8t
+9ic
+9s
+7ties
+8y
+4phagous
+4sma
+7s
+7ta
+8ic
+4ttin
+8s
+3l
+4ay
+6s
+4ed
+4iferous
+6ic
+8ation
+9tions
+6luence
+9nces
+9nt
+9ntly
+8ous
+9usly
+9usness
+5ng
+5phagous
+5te
+7s
+6ic
+5vorous
+4ophone
+9es
+5tron
+9s
+5w
+6ed
+7r
+7st
+6ing
+6ly
+6ness
+9ses
+6s
+7peak
+9aks
+6y
+4s
+3ocoton
+9s
+8on
+9ns
+4deon
+8s
+5ia
+7s
+6c
+7a
+8lly
+8s
+7s
+6es
+6on
+8s
+7us
+9ly
+9ness
+9nesses
+6se
+8d
+8r
+9s
+8s
+7ing
+7t
+8s
+6ze
+8d
+8r
+9s
+8s
+7ing
+5rama
+9s
+9tic
+9tics
+9tise
+9tised
+9tises
+9tising
+9tist
+9tists
+9tize
+9tized
+9tizes
+9tizing
+8e
+9s
+5y
+4id
+6s
+4mania
+9c
+9cs
+9s
+8c
+4n
+5gene
+9s
+5s
+4xicam
+9s
+3phalan
+9s
+3s
+3t
+4abilities
+9ty
+6le
+5ge
+7s
+4down
+8s
+4ed
+5mi
+7s
+5r
+6s
+4ier
+6st
+5ng
+7ly
+7ness
+9sses
+7s
+5th
+7s
+4on
+6s
+4s
+4water
+9s
+4y
+3ungeon
+9s
+2m
+3ber
+6ed
+6less
+6s
+7hip
+9ps
+4ral
+6naceous
+8l
+7e
+8d
+8ous
+8s
+7ous
+9sly
+3e
+4nto
+7es
+7s
+4s
+4tic
+7s
+3o
+4ir
+6ism
+9s
+8t
+9s
+6s
+4rabile
+9ia
+9ities
+9ity
+7le
+9ness
+9nesses
+8y
+6nda
+8um
+9ms
+6tive
+5ial
+8isation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9st
+9sts
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8ly
+8s
+6es
+6sable
+8tion
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+6ter
+6zable
+8tion
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5y
+4s
+3s
+4ahib
+8s
+2n
+3ace
+6d
+6r
+7s
+6s
+5ing
+8ly
+4d
+5ione
+9s
+5s
+4ge
+6d
+6rie
+9s
+6s
+5ing
+4quinone
+9nes
+4rche
+8al
+8s
+7ial
+4zon
+7s
+3d
+4able
+5cious
+9sly
+9sness
+7ties
+8y
+4ed
+5levium
+9ums
+5r
+6s
+4icancies
+9y
+8t
+9s
+6ities
+8y
+5go
+7s
+5ng
+7s
+4s
+3e
+4d
+4er
+6s
+4s
+3folk
+7s
+3g
+4e
+5d
+5s
+4ing
+4s
+3haden
+8s
+4ir
+6s
+3ial
+6ly
+6s
+4lite
+8s
+4ng
+6eal
+7s
+6ioma
+9as
+9ata
+7tic
+9des
+9s
+9ses
+6ocele
+9les
+8occal
+9cci
+9ccic
+9ccus
+5x
+4scal
+7te
+6ectomies
+9omy
+6i
+6oid
+6us
+8es
+5permaceous
+9um
+9ums
+3o
+4logies
+7y
+4minee
+9s
+7i
+8s
+4pausal
+8e
+9s
+8ic
+5olis
+9es
+6me
+8s
+4rah
+7s
+5rhagia
+9ias
+9ic
+7ea
+9s
+7oea
+9as
+3sa
+5e
+5l
+5s
+4ch
+6en
+7s
+6y
+4e
+5d
+5ful
+5less
+5rvants
+5s
+4h
+5ed
+6n
+6s
+5ing
+4ing
+4trua
+8l
+9ly
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+7ous
+7um
+9s
+4ual
+5rabilities
+9lity
+8le
+7l
+7tion
+9onal
+9ons
+9ve
+4wear
+8s
+3t
+4a
+5l
+6ese
+9s
+6ism
+9s
+8t
+9ic
+9ically
+9s
+7ties
+8y
+6ly
+5tion
+9s
+4ee
+6s
+4haceous
+5ene
+8s
+5ol
+7ated
+7s
+4icide
+9s
+5on
+7able
+7ed
+8r
+9s
+7ing
+7s
+4o
+5nniere
+9res
+5r
+6ed
+6ial
+7ng
+9s
+6s
+7hip
+9ps
+5s
+4um
+3u
+4do
+6s
+4isier
+9s
+4s
+3yie
+6s
+2ou
+4ed
+4ing
+4s
+3w
+4ed
+4ing
+4s
+2pacrine
+9s
+3eridine
+9es
+3hitic
+8al
+9lly
+7s
+8es
+8m
+9s
+3robamate
+9tes
+2ranti
+7s
+3bromin
+9s
+3c
+4antile
+9ism
+9isms
+9ist
+9istic
+9ists
+5ptan
+9s
+7ide
+9es
+7o
+8purine
+9urines
+5t
+6s
+4enaries
+9ly
+9ness
+9nesses
+9sm
+9sms
+8y
+5r
+6ies
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6s
+6y
+5s
+4h
+5andise
+9sed
+9ser
+9sers
+9ses
+9sing
+9sings
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+9zings
+7t
+8ability
+9ble
+8ed
+8ing
+9ngs
+8like
+8man
+9en
+8ries
+9y
+8s
+5es
+6t
+7s
+5ild
+8ren
+4iable
+5es
+5fide
+7ed
+8s
+6ul
+8ly
+8ness
+9esses
+6y
+7ing
+5less
+9ly
+9ness
+9nesses
+4s
+4urate
+9d
+9s
+8ing
+9on
+9ons
+6ial
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9ists
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+9ly
+9ness
+9nesses
+9s
+7c
+7es
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6ous
+6y
+4y
+3de
+5s
+4ivorous
+3e
+4d
+4l
+5l
+6s
+5s
+5y
+4ngue
+8s
+4ological
+9es
+8y
+4r
+4s
+5man
+6en
+5t
+6one
+9s
+4tricious
+9ously
+3folk
+7s
+3ganser
+9s
+4e
+5d
+5e
+6s
+5nce
+8s
+5r
+6s
+5s
+4ing
+7s
+3i
+4carp
+8s
+4dian
+8s
+6onal
+9lities
+9lity
+9lly
+9ls
+4l
+5s
+4make
+8s
+4ng
+6s
+6ue
+8s
+5o
+6s
+4s
+5es
+5is
+5m
+6s
+5tem
+8atic
+8s
+6ic
+8ally
+4t
+5ed
+5ing
+5less
+5ocracies
+9cy
+9t
+9tic
+9ts
+6rious
+9usly
+9usness
+5s
+3k
+4in
+6s
+4s
+3l
+4e
+5s
+4in
+6g
+7s
+6s
+4on
+6s
+5t
+6s
+4s
+3maid
+7en
+9s
+7s
+5n
+4en
+3oblastic
+9ically
+4crine
+4geneses
+9is
+8tic
+5onies
+7y
+4istic
+4me
+6s
+5orphic
+5yosin
+9ns
+4nym
+7ies
+7s
+7y
+4pia
+7s
+6c
+6dan
+9s
+5lankton
+9tons
+4some
+8s
+4zoite
+9s
+3people
+9s
+3rier
+6s
+7t
+5ly
+5ment
+9s
+5ness
+9es
+4y
+5maker
+9rs
+8ing
+9ngs
+7n
+6en
+5thought
+9ghts
+3salyl
+8s
+4e
+5s
+4ion
+7s
+3veilleuse
+9uses
+9ux
+9uxes
+3ycism
+8s
+2s
+3a
+4il
+6s
+4l
+5liance
+9ces
+6y
+4raic
+5ch
+4s
+4ticephalic
+9halies
+9halous
+9haly
+3cal
+6in
+8e
+9s
+8s
+7sm
+9s
+6s
+4lum
+7s
+6n
+7s
+3dames
+4emoiselles
+3e
+4emed
+7th
+6s
+4l
+5ed
+5s
+4ncephala
+9alic
+9alon
+9alons
+6hymal
+9atous
+9e
+9es
+5tera
+8ial
+9c
+9es
+9tis
+9tises
+8on
+9nic
+8y
+4s
+4ta
+6s
+3h
+4ed
+5s
+4ier
+6st
+5ng
+7s
+4uga
+7as
+9en
+7h
+7s
+8en
+6ga
+8h
+7e
+8nah
+9ahs
+9eh
+9ehs
+9er
+9ers
+4work
+8s
+4y
+3iad
+5l
+6ly
+5n
+4c
+5ally
+4tylene
+9es
+3meric
+8al
+9lly
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+3nalties
+7y
+4e
+5s
+3oamerican
+4benthos
+9oses
+5last
+9ic
+9s
+4carp
+8s
+5ephalic
+9lics
+9lies
+9lism
+9lisms
+9lous
+9ly
+5ranies
+8y
+7tic
+5yclone
+9nes
+4derm
+8al
+8ic
+8s
+4gastria
+9ic
+9ium
+5lea
+8l
+8s
+6oea
+9s
+5nathies
+9ism
+9isms
+9ous
+9y
+4hippus
+9ses
+4kurtic
+4lite
+8s
+4mere
+8s
+7ism
+9ms
+5orph
+9ic
+9ies
+9ism
+9isms
+9ous
+9s
+9y
+4n
+5ephric
+9oi
+9os
+9oses
+5ic
+5s
+4pause
+9s
+5elagic
+5hile
+9s
+8ic
+6yl
+8l
+9ic
+9ous
+9s
+8s
+7te
+9s
+8ic
+4scale
+7phe
+9es
+5ome
+8s
+5phere
+9es
+9ic
+4thelia
+9al
+9oma
+9omas
+9omata
+9um
+9ums
+7rapies
+9py
+6oraces
+9cic
+9x
+9xes
+8ium
+9ums
+5ron
+8s
+7phic
+4zoan
+8s
+6ic
+3prise
+8s
+6ze
+8s
+3quin
+7e
+8rie
+9ies
+6t
+7e
+8s
+7s
+3s
+4age
+7d
+7s
+6ing
+9s
+5line
+9s
+5n
+6s
+4ed
+5igneurs
+5nger
+9ed
+9ing
+9s
+5s
+4iah
+7s
+8hip
+9ips
+6nic
+9ally
+8sm
+9ms
+6s
+7es
+5er
+6st
+6urs
+5ly
+5ness
+9es
+6g
+4man
+6te
+8s
+5en
+4uage
+8s
+4y
+3tee
+6s
+5r
+6s
+5so
+7es
+7s
+4ino
+7es
+7s
+5za
+7s
+6o
+7es
+7s
+4o
+5m
+6e
+7s
+6s
+4ranol
+9s
+2t
+3a
+4bases
+7is
+6tic
+5olic
+9ally
+8es
+8sable
+9e
+9ed
+9es
+9ing
+9m
+9ms
+8te
+9es
+8zable
+9e
+9ed
+9es
+9ing
+7ome
+9es
+9ics
+7y
+6tropic
+4carpal
+9ls
+8i
+8us
+5enter
+9rs
+8re
+9es
+9ic
+9ics
+6rcaria
+9riae
+9rial
+5hromatic
+9atism
+9atisms
+8nism
+9isms
+8ses
+9is
+5innabarite
+5ognition
+9tions
+6mputer
+9ters
+9ting
+9tings
+4data
+4ethical
+9s
+4female
+9es
+5iction
+9onal
+9onist
+9onists
+9ons
+6le
+8s
+4galactic
+8xies
+9y
+5e
+6neses
+9is
+8tic
+9ically
+7ic
+6s
+5nathism
+9isms
+9ous
+5rabolise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+6obolise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+4irie
+8s
+4l
+5anguage
+9ages
+5dehyde
+9des
+5ed
+6pses
+8is
+7tic
+9cal
+5head
+9s
+5ing
+8uistic
+9istics
+6se
+8d
+8s
+7ing
+7t
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5led
+6ic
+8ally
+8s
+7ding
+9ngs
+7ferous
+7ke
+7ne
+8g
+9s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8t
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ocene
+9nes
+7genetic
+9nic
+9nies
+9ny
+8rapher
+9aphers
+9aphic
+9aphies
+9aphist
+9aphy
+7id
+9al
+9s
+7phone
+9ones
+6urgic
+9ical
+9ically
+9ies
+9ist
+9ists
+9y
+6y
+5mark
+9s
+5s
+6mith
+9hs
+5ware
+9s
+6ork
+9er
+9ers
+9ing
+9ings
+9s
+4male
+8s
+6thematics
+5er
+7al
+7e
+8s
+7ic
+9ally
+8sm
+9ms
+7s
+5ict
+8isation
+9zation
+5orphic
+9ically
+9ism
+9isms
+9ist
+9ists
+9ose
+9osed
+9oses
+9osing
+9osis
+9ous
+4nalyses
+9is
+6rrative
+9tives
+5ephric
+9oi
+9os
+5oia
+8s
+4pelet
+6riodic
+5hase
+9s
+6or
+8ic
+9cal
+9cally
+9st
+9sts
+8s
+7sphate
+9hates
+9horic
+6rase
+9ed
+9es
+9ing
+9is
+9t
+9tic
+9tical
+9ts
+6ysic
+9cal
+9cally
+9cian
+9cians
+9cise
+9cised
+9cises
+9cising
+9cist
+9cists
+9cize
+9cized
+9cizes
+9cizing
+9cs
+5lases
+8ia
+9as
+9s
+8m
+9ic
+9s
+8tic
+6ot
+5olitical
+9ics
+5sychic
+9ical
+9ics
+9ology
+4rchon
+9s
+4sequoia
+9ias
+5ilicate
+9ates
+9ic
+5oma
+8s
+8ta
+9ic
+9ism
+9isms
+9oses
+9osis
+5tabilities
+9lity
+8le
+9es
+9y
+7ses
+8is
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+7tic
+9cally
+4tag
+7s
+6rsal
+9ls
+8i
+8us
+5e
+6s
+5heoretical
+9ies
+9y
+7rian
+9ans
+7ses
+8is
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+7tic
+9cal
+9cally
+6oraces
+9cic
+9x
+9xes
+5ungstic
+4vanadic
+5erse
+9s
+4xylem
+9s
+4yage
+8s
+5er
+7s
+4zoa
+7l
+7n
+8s
+6ic
+6on
+3cast
+7s
+3e
+4cdyses
+8is
+4d
+4mpiric
+9cal
+9cally
+9cism
+9cisms
+9cist
+9cists
+9cs
+6sychoses
+9hosis
+9hosist
+4ncephala
+9alic
+9alon
+9alons
+4or
+6ic
+8ally
+7sm
+9s
+8t
+9s
+7tal
+8e
+9s
+8ic
+9cal
+9cist
+9cists
+9cs
+6ogram
+9ams
+9aph
+9aphic
+9aphs
+7id
+9al
+9s
+7lite
+9tes
+8ogic
+9gical
+9gies
+9gist
+9gists
+9gy
+7us
+6s
+4pa
+6s
+4r
+5age
+8s
+5ed
+5ing
+5s
+6tick
+9ks
+4s
+5tick
+9s
+6rous
+7us
+9es
+4wand
+8s
+4yard
+8s
+3formin
+9s
+3h
+4acrylate
+9ates
+9ic
+5don
+8e
+9s
+8s
+5emoglobin
+9lobins
+5mphetamine
+5nal
+8s
+7tion
+9ons
+6e
+7s
+6oic
+7l
+8s
+7meter
+9ters
+5qualone
+9ones
+4edrine
+9es
+5glin
+9s
+5moglobin
+9obins
+5namine
+9nes
+4icillin
+9ins
+5nk
+7eth
+7s
+5onine
+9es
+4o
+5d
+6ic
+8al
+9lly
+9lness
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ological
+9gies
+9gist
+9gists
+9gy
+6s
+5mania
+9as
+5s
+5trexate
+9ates
+5ught
+5xide
+9s
+6y
+7benzene
+9nzenes
+7chlor
+9lors
+7flurane
+9uranes
+7l
+4s
+4yl
+6al
+8s
+7mine
+9nes
+7se
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6cellulose
+6dopa
+9as
+6ene
+9s
+6ic
+6mercuries
+9cury
+6phenidate
+9nol
+9nols
+6s
+6thionine
+9onines
+6xanthine
+9thines
+5sergide
+9ides
+7s
+6is
+6tic
+3ic
+5ais
+6l
+7s
+5s
+5ulosities
+9ity
+8us
+9sly
+9sness
+4er
+6s
+4f
+5s
+4ng
+4s
+5se
+7s
+3oestrous
+8us
+9ses
+4l
+5s
+4nym
+7ic
+9al
+9ally
+8es
+7s
+7y
+4pae
+5e
+6s
+5ic
+6sm
+8s
+5on
+7s
+6scopic
+9pical
+9pies
+9pist
+9pists
+9py
+5ryl
+8s
+3ralgia
+9s
+5zol
+8s
+4e
+5d
+5s
+4ic
+6al
+8ly
+7te
+9d
+9s
+8ing
+9on
+9ons
+6ian
+9s
+7se
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7ze
+9d
+9s
+8ing
+6s
+5fication
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5ng
+5st
+7s
+5tis
+8es
+4o
+5logic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+5mania
+9as
+5nidazole
+9zoles
+6ome
+9s
+8ic
+9cal
+9cally
+6ymic
+9cs
+5plex
+9es
+6olis
+9ses
+9tan
+9tanate
+9tanise
+9tanism
+9tanize
+9tans
+9tical
+5rrhagia
+9gias
+5s
+6exual
+9als
+6tyle
+9es
+3s
+3tle
+6d
+6s
+7ome
+9eness
+3ump
+6s
+2u
+3niere
+3s
+4e
+5d
+5s
+4ing
+2ve
+4d
+4s
+3ing
+3rou
+6s
+2w
+3ed
+3ing
+3l
+4ed
+5r
+6s
+4ing
+4s
+3s
+4ed
+5s
+4ing
+2ynt
+2zail
+6s
+3cal
+6ine
+9s
+6s
+3e
+4reon
+8s
+6um
+8s
+4s
+3quit
+7e
+8s
+7s
+3uza
+6h
+7s
+6s
+5ot
+7h
+3z
+4aluna
+9s
+5nine
+9s
+4e
+5s
+4o
+5s
+5tint
+9ed
+9er
+9ers
+9ing
+9o
+9os
+9s
+1ganga
+6s
+1ho
+3rr
+5s
+3s
+1i
+2aou
+5ed
+5ing
+5s
+4w
+5ed
+5ing
+5s
+3rolitic
+3sm
+5a
+6l
+6s
+6ta
+7ic
+9al
+7ous
+5ic
+7ally
+5ous
+5s
+3ul
+5ed
+5ing
+5s
+2b
+3s
+3una
+6s
+2c
+3a
+4ceous
+4s
+4te
+6d
+6s
+5ing
+4wber
+8s
+3e
+4ll
+6a
+7e
+7r
+7s
+6e
+7s
+6s
+3h
+4ael
+7s
+4e
+5d
+5r
+6s
+5s
+4igan
+8s
+5ng
+7s
+4t
+5s
+3k
+4eries
+6y
+5y
+6ed
+6ing
+6s
+4ies
+4le
+6r
+6s
+7t
+4s
+4y
+3o
+4s
+3ra
+4ified
+8s
+6y
+7ing
+4o
+5aerophile
+9philes
+9philic
+6mpere
+9res
+6nalyses
+9ysis
+9yst
+9ysts
+9ytic
+9ytical
+8tomical
+9omies
+9omy
+6rray
+9ys
+5balance
+9nces
+7r
+8ograph
+9graphs
+8s
+6e
+7am
+9s
+7s
+6ial
+8n
+7c
+7ologic
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+8ta
+6log
+9ger
+9gers
+9ging
+9gings
+9s
+6rew
+9er
+9eries
+9ers
+9ery
+9ing
+9ings
+9s
+6ubbles
+7rst
+9ts
+7s
+8es
+8ses
+5cap
+8sule
+9ules
+7r
+8d
+9s
+8s
+7ssette
+9ettes
+6elebrity
+7phal
+9alic
+9alics
+9alies
+9alous
+9als
+9aly
+6hemical
+9istry
+7ip
+9ped
+9ping
+9s
+6ircuit
+9uitry
+9uits
+6limate
+9ates
+9atic
+8ne
+9es
+6occal
+9i
+9us
+7de
+9s
+7mponent
+9onents
+9uter
+9uters
+9uting
+9utings
+7pied
+9es
+8y
+9ing
+9ings
+7sm
+9ic
+9ical
+9ically
+9os
+9oses
+9s
+6rack
+9ked
+9king
+9kings
+9ks
+7ystal
+9tals
+6ultural
+9ure
+9ures
+7rie
+9es
+6yte
+9s
+8ic
+5detection
+9ctions
+9ctor
+9ctors
+6issection
+6ont
+9ous
+7t
+8s
+6rive
+9es
+5earthquake
+6conomic
+9omics
+6lectrode
+9trodes
+9tronic
+8ment
+9ents
+6volution
+9utions
+5farad
+9ds
+7una
+9ae
+9al
+9as
+6elsitic
+6iber
+9rs
+8re
+9es
+9il
+9illar
+9ils
+7che
+9es
+7lament
+9ments
+9ria
+9riae
+9rial
+8ing
+9ngs
+8m
+9able
+9ed
+9er
+9ers
+9ing
+9s
+8ter
+9ers
+6loppies
+9py
+8ra
+9ae
+9al
+9as
+6orm
+9s
+7ssil
+9ils
+6ungi
+9us
+9uses
+5gamete
+9tes
+9tocyte
+6eneration
+6lia
+9s
+6ram
+9s
+8nite
+9ites
+9itic
+8ph
+9hed
+9her
+9hers
+9hic
+9hics
+9hies
+9hing
+9hs
+9hy
+8vities
+9ity
+7eens
+7oove
+9ves
+5habitat
+9tats
+6m
+7s
+5image
+9es
+6nch
+9es
+7ject
+9cted
+9cting
+9ction
+9ctions
+9cts
+5jet
+8s
+5light
+9ting
+9tings
+9ts
+7te
+9r
+9rs
+9s
+8h
+9ic
+9s
+8ic
+6oan
+9s
+7gic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+6uces
+7x
+8es
+5manage
+9ged
+9gement
+9ger
+9gers
+9ges
+9ging
+7rketing
+9etings
+6ere
+9s
+7sh
+9es
+7teorite
+9orites
+9oritic
+9oroid
+9oroids
+9r
+9rs
+8hod
+9ods
+8re
+9es
+9ic
+9ical
+9ies
+9y
+6ho
+8s
+6icrocurie
+9ofarad
+7llimetre
+7ni
+9ature
+9s
+6olar
+8e
+9s
+7rphology
+5n
+6ation
+9ons
+6eedle
+9les
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+6uclei
+9eus
+9euses
+7trient
+9ients
+5organism
+9nisms
+5parasite
+9sites
+9sitic
+8ticle
+9icles
+7yment
+9ents
+6egmatite
+9atites
+9atitic
+6hage
+9es
+9ous
+7one
+9es
+9ic
+9ics
+8tograph
+9ometer
+9ometry
+7yll
+9lous
+9ls
+8sical
+9ically
+9ics
+8te
+9es
+9ic
+6ipet
+9ts
+9tte
+9ttes
+6lankton
+9ktons
+6olis
+9ses
+7re
+9s
+8osities
+9sity
+9us
+7wer
+9rs
+6rint
+9ted
+9ting
+9tings
+9ts
+8sm
+9ms
+7obe
+9es
+8cessing
+9essor
+9essors
+8gram
+9rams
+8jection
+9ector
+9ectors
+6sia
+9s
+6terous
+6ublisher
+9ishers
+9ishing
+7lsation
+9ations
+7mp
+9s
+7ncture
+9tures
+6ylar
+8e
+9s
+7rometer
+9meters
+5quake
+9es
+5radiograph
+6eader
+9ers
+5s
+6atellite
+9llites
+6cale
+9es
+7ope
+9es
+9ic
+9ical
+9ically
+9ies
+9ist
+9ists
+9y
+6econd
+9nds
+7ism
+9mic
+9mical
+9micity
+9ms
+6ite
+9s
+6kirt
+9ts
+6leep
+9ps
+6matic
+6omal
+8e
+9s
+6pecies
+7here
+9res
+9rical
+7orangia
+9angium
+9e
+9es
+9ic
+9ocyte
+9ocytes
+9ophyll
+9ous
+6tate
+9es
+7omatous
+9ous
+7ructural
+9cture
+9ctures
+6urgeon
+9eons
+9eries
+9ery
+9ical
+6witch
+9ches
+5technic
+9nics
+9nique
+9niques
+9nology
+6ome
+9s
+8ic
+9cal
+9es
+9st
+9sts
+8y
+7nal
+9lities
+9lity
+9lly
+8e
+9s
+6ubular
+9le
+9les
+7nnelling
+5vascular
+6illar
+9i
+9ous
+9us
+6olt
+9s
+5watt
+9s
+7vable
+8e
+9able
+9d
+9s
+8ing
+6ire
+9s
+6orld
+9ds
+6riter
+9ers
+4urgies
+7y
+3s
+3tion
+7s
+4urate
+9d
+9s
+8ing
+6ition
+9ons
+2d
+3air
+6s
+3band
+4rain
+8s
+3cap
+4ourse
+4ult
+7s
+3day
+6s
+4elmannetjie
+6skot
+9ts
+5n
+6s
+7tead
+9ads
+5st
+4ie
+6s
+4le
+6breaker
+9akers
+8ow
+9wed
+9wism
+9wisms
+9ws
+7uster
+9ters
+6d
+6man
+7en
+7ost
+6r
+7s
+6s
+6ware
+9es
+7eight
+9ghts
+5ing
+8ly
+8s
+4orsal
+4y
+3field
+8er
+9rs
+8s
+3ge
+5s
+5t
+6s
+4ie
+6r
+6s
+7t
+4ut
+6s
+4y
+3i
+4nette
+9s
+4ron
+7s
+4s
+5kirt
+9s
+3land
+7er
+9s
+7s
+5titude
+9des
+4eg
+6s
+4ife
+7r
+8s
+5ne
+7s
+5st
+7s
+5ttoral
+9als
+5ves
+3month
+8s
+5st
+7s
+3night
+8ly
+8s
+4oon
+7s
+3point
+8s
+3range
+8s
+5sh
+7ic
+8m
+7ot
+9h
+4ib
+6s
+5ff
+7s
+3s
+4agittal
+4ection
+9ns
+4hip
+7man
+9te
+9tes
+8en
+7s
+4ize
+7d
+4ole
+7s
+4pace
+8s
+4t
+5ories
+7y
+5ream
+9s
+5s
+4ummer
+9s
+3term
+7s
+4own
+7s
+3watch
+8es
+5y
+6s
+4eek
+7ly
+7s
+5stern
+4ife
+7d
+7ries
+8y
+7s
+6ing
+5nter
+9s
+5ve
+7d
+7s
+6ing
+3year
+7s
+2elie
+6s
+3n
+4s
+3ve
+5d
+5s
+4ing
+2fepristone
+9ones
+3f
+4ed
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4s
+4y
+3ty
+2g
+3g
+4le
+6s
+4s
+3ht
+5est
+5ful
+5ier
+7st
+6ly
+6ness
+9ses
+5s
+6t
+5y
+3matite
+9s
+3non
+6ette
+9es
+6ne
+8s
+6s
+3raine
+8s
+8ur
+9rs
+7ous
+5nt
+7s
+5te
+7d
+7s
+6ing
+7on
+9al
+9ist
+9ists
+9s
+6or
+8s
+8y
+3s
+2ha
+4s
+3i
+4ed
+4ing
+4s
+3rab
+6s
+2jnheer
+8s
+2kado
+6s
+3e
+4d
+4s
+3ing
+3ra
+4on
+6s
+3vah
+6s
+4eh
+6s
+4os
+5t
+6h
+2l
+3adi
+6es
+6s
+5y
+4ge
+6s
+3ch
+5ig
+6k
+3d
+4ed
+5n
+6ed
+6ing
+6s
+5r
+5st
+5w
+6ed
+6ing
+6s
+6y
+4ing
+4ly
+4ness
+8es
+4s
+3e
+4age
+7s
+4ometer
+9rs
+4post
+8s
+4r
+5s
+4s
+5ian
+6mo
+8s
+5tone
+9s
+3foil
+7s
+3ia
+5ria
+8l
+8s
+6y
+4eu
+6s
+6x
+4tance
+9s
+8ies
+8y
+7t
+8ly
+8ness
+9esses
+8s
+6r
+7ia
+8es
+8ly
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7y
+6te
+8d
+8s
+7ing
+8on
+9ns
+5ia
+7man
+8en
+7s
+4um
+3k
+4ed
+5n
+5r
+6s
+4fish
+8es
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4less
+5ike
+4maid
+8s
+6n
+5en
+4o
+5s
+4s
+5hake
+9s
+6ed
+8s
+5op
+7ism
+9ms
+7ping
+8y
+7s
+4toast
+9s
+4weed
+8s
+5ood
+8s
+6rt
+8s
+4y
+3l
+4able
+5ge
+7s
+4board
+9s
+4cake
+8s
+4dam
+7s
+4e
+5d
+5feuille
+9lles
+6iori
+9is
+6leur
+9rs
+5narian
+9anism
+9anisms
+9ans
+9es
+9sm
+9sms
+8y
+6nia
+9l
+9lism
+9lisms
+9list
+9lists
+9lly
+9nism
+9nisms
+9rism
+9risms
+8um
+9ms
+5ped
+8e
+9s
+8s
+6ore
+9s
+5r
+6ite
+9s
+6s
+5s
+6imal
+9lly
+9ls
+5t
+6s
+4hand
+8s
+5ouse
+9s
+4iampere
+9res
+6rd
+8s
+7e
+8s
+7ies
+7y
+5bar
+8s
+5curie
+9es
+5degree
+9ees
+5e
+6me
+8s
+6r
+7s
+6s
+5gal
+8s
+6ram
+9me
+9mes
+9s
+5henries
+9y
+9ys
+5lambert
+9erts
+6iter
+9rs
+8re
+9es
+6uces
+7x
+8es
+5me
+7s
+7ter
+9rs
+8re
+9es
+6ho
+8s
+6icron
+9ons
+6olar
+8e
+9s
+5ne
+7r
+8ies
+8s
+8y
+7s
+6g
+7s
+5ohm
+8s
+6n
+7aire
+9res
+9ress
+9resses
+8ry
+7fold
+7naire
+9ires
+9iress
+7s
+7th
+9s
+6smol
+9ls
+5ped
+8e
+9s
+8s
+6robe
+9es
+5radian
+9ans
+6em
+8s
+6oentgen
+9tgens
+5second
+9nds
+6ievert
+9erts
+5volt
+9s
+5watt
+9s
+4ocracies
+9y
+8t
+9s
+4pond
+8s
+4race
+8s
+5ind
+8s
+5un
+7s
+4s
+5cale
+9s
+5tone
+9s
+6ream
+9ms
+4tail
+8s
+4wheel
+9s
+5ork
+8s
+5right
+9ts
+3neb
+6s
+3o
+4meter
+9s
+4r
+5d
+6s
+5s
+4s
+3pa
+5s
+3quetoast
+9sts
+3reis
+3s
+4ey
+6s
+3t
+4ed
+5r
+6s
+4ier
+6st
+5ng
+4onia
+8s
+4s
+4y
+4z
+5es
+3vine
+2m
+3bar
+6s
+3e
+4d
+4o
+5ed
+5graph
+9hed
+9hing
+9hs
+5ing
+5s
+4r
+5s
+4s
+5es
+5is
+7es
+5ter
+8s
+4tic
+7al
+9ly
+6te
+8s
+3ic
+5al
+5ked
+7r
+8s
+6ing
+5ries
+6y
+5s
+4ng
+4virus
+9es
+3mer
+5st
+4ick
+7ed
+7ing
+7s
+3ographer
+9ers
+9ies
+9y
+4sa
+6ceous
+6e
+6s
+3sey
+4ier
+6st
+4y
+3ulus
+7es
+2na
+4ble
+4cious
+9ly
+6ties
+7y
+4e
+4r
+5et
+7ed
+7s
+5s
+4s
+4torial
+9lly
+8ly
+7y
+4uderie
+9es
+6iere
+9es
+3bar
+6s
+3ce
+5d
+5meat
+9s
+5r
+6s
+5s
+5ur
+4ier
+6st
+5ng
+7ly
+4y
+3d
+4blower
+9rs
+4ed
+6ness
+9ses
+5r
+6s
+4ful
+7ly
+7ness
+9sses
+4ing
+7s
+4less
+8ly
+8ness
+9esses
+4s
+5et
+7s
+5hare
+9s
+3e
+4able
+4d
+4field
+9s
+4hunter
+9rs
+4layer
+9s
+4ola
+7s
+4r
+5al
+7isable
+9ation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9t
+9ts
+8zable
+9ation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7ogic
+9ical
+9ically
+9ies
+9ise
+9ised
+9ises
+9ising
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+9y
+7s
+5s
+4s
+5haft
+9s
+5tone
+9s
+6rone
+9es
+5weeper
+9ers
+9ing
+9ings
+4tte
+7s
+4ver
+7s
+3g
+4e
+5d
+5r
+6s
+5s
+4ier
+6st
+5mingi
+9is
+5ness
+9es
+6g
+4le
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+8s
+4s
+4y
+3i
+4ate
+7d
+7s
+6ing
+7on
+9s
+6ure
+9d
+9s
+8ing
+9sation
+9se
+9sed
+9ses
+9sing
+9st
+9stic
+9sts
+9zation
+9ze
+9zed
+9zes
+9zing
+4bar
+7s
+5ike
+8r
+9s
+8s
+5reak
+9s
+5udget
+9ts
+6s
+7es
+7ses
+4cab
+7bing
+9ngs
+7s
+6m
+7p
+8s
+7s
+6r
+7s
+5om
+7puter
+9ters
+7s
+6urse
+9es
+4disc
+8s
+7h
+8es
+7k
+8s
+5ress
+9es
+4er
+5st
+4fication
+9ions
+6ed
+7s
+5loppies
+9y
+5y
+6ing
+4kin
+7s
+4lab
+7s
+4m
+5a
+6l
+7ism
+9ms
+9t
+9ts
+7ly
+7s
+6rt
+8s
+6x
+7ed
+8s
+7ing
+5ent
+8s
+5ill
+8s
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5oto
+8s
+5s
+5um
+7s
+6s
+7es
+4ng
+6s
+4on
+6s
+4park
+8s
+5ill
+8s
+4rugbies
+8y
+4s
+5chool
+9ls
+6ule
+9s
+5eries
+5h
+6ed
+7s
+6ing
+5ki
+7rt
+9ed
+9s
+7s
+5tate
+9s
+6er
+8ed
+8ia
+9al
+9alist
+9alists
+9ally
+9ng
+9um
+8s
+9hip
+9hips
+6rant
+9ts
+8tion
+9ions
+9ive
+7ess
+9ses
+7ies
+7oke
+9es
+7y
+4tower
+9s
+5rack
+9s
+4um
+6s
+4van
+7s
+5er
+7s
+6t
+7s
+5olley
+9ys
+3k
+4e
+5s
+4s
+3neola
+8s
+5singer
+9ers
+4ick
+7ed
+7ing
+7s
+5e
+6s
+4ock
+7ed
+7ing
+7s
+5w
+6s
+4y
+3o
+4r
+5ca
+7s
+5ed
+5ing
+6taire
+9res
+7ies
+7y
+5s
+6hip
+9s
+4s
+4taur
+4xidil
+9s
+3shuku
+8s
+4ter
+7s
+5rel
+8s
+9ies
+9y
+3t
+4age
+7s
+4ed
+5r
+6s
+4ier
+6st
+5ng
+4s
+4y
+3uend
+7s
+5t
+6s
+4s
+5cular
+8e
+9s
+5es
+4te
+6d
+6ly
+6man
+7en
+6ness
+9ses
+6r
+6s
+7t
+5ia
+7e
+7l
+6ng
+6ose
+3x
+4es
+4ish
+3y
+4an
+6im
+6s
+2ocene
+3mbo
+6s
+3ses
+4is
+3tic
+6s
+2ps
+2quelet
+8s
+2r
+3abelle
+9s
+5ilia
+8s
+9es
+5le
+4cidia
+9l
+8um
+5le
+7s
+5ulous
+9sly
+9sness
+4dor
+7s
+4ge
+6s
+4ndise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+3bane
+7s
+3chi
+3e
+4d
+4poix
+4s
+4x
+5es
+3i
+4er
+5st
+4fic
+7al
+9ly
+4n
+5ess
+8es
+5g
+5s
+4ti
+6s
+3k
+4er
+5st
+4ier
+6st
+5ly
+5ness
+9es
+4s
+4y
+3lier
+6st
+5goes
+5ton
+8s
+4y
+3o
+4miro
+8s
+4s
+3ror
+6ed
+6ing
+6like
+6s
+6wise
+3s
+3th
+5ful
+8ly
+8ness
+9esses
+5less
+9ly
+9ness
+9nesses
+5s
+3v
+4ed
+4ing
+4s
+3y
+3za
+5s
+2s
+3acceptation
+9ations
+5t
+6ed
+6ing
+6s
+4dapt
+8ed
+8ing
+8s
+5d
+6ed
+6ing
+6ress
+9sed
+9ses
+9sing
+6s
+5just
+9ed
+9ing
+9s
+5venture
+9ured
+9urer
+9urers
+9ures
+9urous
+7rtence
+9ences
+6ice
+9s
+7se
+9d
+9dly
+9dness
+9s
+8ing
+4gent
+8s
+4im
+6ed
+6ing
+6s
+4lign
+8ed
+8ing
+8ment
+9ents
+8s
+5lege
+9d
+9s
+8ing
+6iance
+9ces
+7ed
+8s
+6ocate
+9ted
+9tes
+9ting
+9tion
+9tions
+7t
+8ment
+9ents
+8s
+8ted
+9ing
+6y
+7ing
+5ter
+8ed
+8ing
+8s
+4nalyses
+9is
+5dries
+8st
+9ts
+7ous
+7y
+5thrope
+9pes
+9pic
+9pical
+9pies
+9pist
+9pists
+9pos
+9poses
+9py
+4pplication
+9ations
+8ed
+9s
+7y
+8ing
+6raisal
+9sals
+7eciate
+9iated
+9iates
+9iating
+9iation
+9iative
+8hend
+9ended
+9ending
+9ends
+9ension
+9ensive
+7opriate
+9riated
+9riates
+4rrange
+9ed
+9ement
+9ements
+9es
+9ing
+7y
+8s
+5ticulate
+9lated
+9lates
+9lating
+4ssay
+8ed
+8ing
+8s
+6emble
+9led
+9les
+9ling
+6ign
+9ed
+9ing
+9s
+6umption
+9tions
+4te
+5one
+8d
+8s
+7ing
+5tribute
+9uted
+9utes
+9uting
+9ution
+9utions
+4unter
+9s
+4ver
+7red
+8ing
+7s
+5ised
+4ward
+8ed
+8ing
+8s
+3balance
+9ed
+9es
+9ing
+4ecame
+6ome
+9s
+8ing
+9ngness
+5gan
+6in
+8ning
+8s
+6ot
+8ten
+6un
+5have
+9d
+9r
+9rs
+9s
+8ing
+9or
+9ors
+9our
+9ours
+5lief
+9s
+8ve
+9ed
+9er
+9ers
+9es
+9ing
+5seem
+9ed
+9ing
+9s
+6tow
+9al
+9als
+9ed
+9ing
+9s
+4ias
+7ed
+8s
+7ing
+7sed
+9s
+8ing
+5ll
+7ed
+7ing
+7s
+5nd
+7ing
+7s
+5rth
+8s
+4orn
+5und
+4rand
+8ed
+8ing
+8s
+4uild
+8ing
+8s
+7t
+5tton
+9ed
+9ing
+9s
+3calculate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ator
+9ators
+6l
+7ed
+8r
+9s
+7ing
+7s
+5nthus
+9ses
+5ption
+9ned
+9ning
+9ns
+5rriage
+9ges
+8ed
+9s
+7y
+8ing
+5st
+7ing
+7s
+5talog
+9ged
+9ging
+9gs
+4egen
+8ate
+9ted
+9tes
+9ting
+9tion
+9tional
+9tions
+9tor
+9tors
+8e
+9s
+9tic
+8ist
+9sts
+8s
+6ine
+9s
+5llanarian
+9arians
+9ea
+9eous
+9eously
+9ies
+9ist
+9ists
+9y
+4h
+5allenge
+9nges
+6nce
+9d
+9ful
+9s
+8ing
+8y
+7nel
+9led
+9ling
+9lled
+9lling
+9ls
+7ter
+9rs
+6racterise
+9terize
+7ge
+9d
+9s
+8ing
+5ief
+8ed
+8ing
+8s
+7vous
+9usly
+9usness
+5metal
+9ls
+5oice
+9s
+6ose
+9s
+8ing
+6se
+8n
+4ibilities
+9ty
+6le
+5tation
+9ons
+6e
+7d
+7s
+6ing
+4laim
+8ed
+8ing
+8s
+6ss
+8ed
+9s
+8ified
+9fies
+9fy
+9fying
+9ng
+4ode
+7d
+7s
+6ing
+5in
+7ed
+7ing
+7s
+5lor
+8ed
+8ing
+8s
+7ur
+9ed
+9ing
+9s
+5mprehend
+9hended
+9hends
+7utation
+9ations
+9e
+9ed
+9es
+9ing
+5nceit
+9ted
+9ting
+9ts
+9ve
+9ved
+9ver
+9vers
+9ves
+9ving
+8ption
+9tions
+6duct
+9ted
+9ting
+9ts
+6jecture
+9tured
+9tures
+9turing
+6nect
+9ted
+9ting
+9tion
+9tions
+9ts
+6ster
+9red
+9ring
+9rs
+8ruct
+9ucted
+9ucting
+9uction
+9ucts
+9ue
+9ued
+9ues
+9uing
+6tent
+9ted
+9ting
+9tment
+9tments
+9ts
+5ok
+7ed
+7ing
+7s
+5pied
+8s
+6y
+7ing
+5rrect
+9ted
+9ting
+9tion
+9tions
+9ts
+8lation
+9ations
+5unsel
+9lled
+9lling
+9ls
+7t
+8ed
+8ing
+8s
+4reance
+9es
+9ies
+9y
+8t
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+7unce
+9ces
+6dit
+9ed
+9ing
+9s
+6ed
+8s
+4ue
+6d
+6ing
+6s
+5ing
+5t
+6s
+6ting
+3date
+7d
+7s
+6ing
+4eal
+7er
+9s
+7ing
+7s
+7t
+5ed
+7s
+6m
+7ed
+7ful
+7ing
+9gs
+7s
+5fine
+9d
+9s
+8ing
+5mean
+9ant
+9ants
+9ed
+9ing
+9or
+9ors
+9our
+9ours
+9s
+6pt
+5scribe
+9bed
+9bes
+9bing
+9ption
+9ptions
+6ert
+9s
+5velop
+9ped
+9ping
+9ps
+6otion
+9ons
+4iagnose
+9sed
+9ses
+9sing
+9sis
+6l
+7ed
+7ing
+7led
+8ing
+7s
+5d
+5et
+7s
+5ght
+5rect
+9ed
+9ing
+9ion
+9ions
+9s
+5stribution
+5vide
+9d
+9s
+8ing
+7sion
+9ons
+4o
+5er
+7s
+6s
+5ing
+8s
+5ne
+6ne
+5ubt
+8ed
+8ful
+8ing
+8s
+4raw
+7ing
+9gs
+7n
+7s
+5ead
+8s
+6w
+5ive
+8n
+8s
+7ing
+5ove
+3e
+4ase
+7s
+5t
+6en
+6ing
+6s
+4dit
+7ed
+7ing
+7s
+5ucate
+9ed
+9es
+9ing
+9ion
+9ions
+4mphases
+9is
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+6loy
+9ed
+9ing
+9ment
+9ments
+9s
+4nrol
+8l
+9ed
+9ing
+9s
+8s
+5ter
+8ed
+8ing
+8s
+6reat
+9ted
+9ting
+9ts
+7ies
+7y
+4r
+5abilism
+9isms
+9ist
+9ists
+7le
+9ness
+9nesses
+9s
+8ism
+9sms
+9st
+9sts
+8y
+5e
+6re
+8s
+6s
+5icord
+9de
+9des
+9ds
+6es
+5lier
+8st
+7ness
+9sses
+6y
+5s
+5y
+4s
+5teem
+9ed
+9ing
+9s
+6imate
+9ted
+9tes
+9ting
+9tion
+9tions
+4valuate
+9ted
+9tes
+9ting
+9tion
+9tions
+5ent
+8s
+3faith
+8s
+5ll
+7en
+7ing
+7s
+6ne
+5re
+7d
+7s
+6ing
+9s
+4easance
+9ces
+7or
+9s
+6ture
+9ed
+9es
+9ing
+5d
+5ed
+7ing
+7s
+5ign
+8ed
+8ing
+8s
+5ll
+4ield
+8ed
+8ing
+8s
+5le
+7d
+7s
+6ing
+5re
+7d
+7s
+6ing
+5t
+6s
+6ted
+7ing
+4ocus
+8ed
+9s
+8ing
+8sed
+9es
+9ing
+5rm
+7ation
+9ions
+7ed
+7ing
+7s
+6tune
+9ed
+9es
+4rame
+8d
+8s
+7ing
+4unction
+9oned
+9oning
+9ons
+3gauge
+8d
+8s
+7ing
+5ve
+4ive
+7n
+7s
+6ing
+9s
+4o
+5es
+5ing
+5ne
+5tten
+5vern
+9aunce
+9aunces
+9ed
+9ing
+9ment
+9ments
+9or
+9ors
+9s
+4rade
+8d
+8s
+7ing
+6ff
+7t
+8ed
+8ing
+8s
+5ew
+5ow
+7ing
+7n
+7s
+7th
+9s
+4uess
+8ed
+9s
+8ing
+5ggle
+9d
+9s
+8ing
+5idance
+9ces
+7e
+8d
+9ly
+9ness
+9nesses
+8r
+9s
+8s
+7ing
+3hallowed
+5ndle
+9d
+9s
+8ing
+6ter
+9s
+5p
+6ped
+8n
+9ed
+9ing
+9s
+7ing
+6s
+6t
+4ear
+7d
+7ing
+7s
+5gaas
+9en
+6oss
+4guggle
+9ed
+9es
+9ing
+4it
+6s
+6ting
+4mash
+8es
+5ee
+7s
+5i
+6s
+5osh
+8es
+3identified
+9fies
+9fy
+9fying
+4mpression
+9sions
+7ove
+9ed
+9ement
+9ements
+9es
+9ing
+4nfer
+8red
+9ing
+8s
+6orm
+9ant
+9ants
+9ation
+9ations
+9ed
+9er
+9ers
+9ing
+9s
+5struct
+9cted
+9cting
+9ction
+9ctions
+9cts
+5telligence
+7nd
+9ed
+9ing
+9s
+7r
+8pret
+9reted
+9reter
+9reters
+9reting
+9rets
+8red
+9ing
+8s
+3join
+7der
+9rs
+7ed
+7ing
+7s
+4udge
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+7ment
+9nts
+3kal
+6s
+4eep
+7ing
+7s
+5n
+6ned
+7ing
+6s
+6t
+5pt
+5y
+6ed
+6ing
+6s
+4ick
+7ed
+7ing
+7s
+4new
+5ow
+7ing
+7ledge
+9dges
+7n
+7s
+3label
+8ed
+8ing
+8led
+9ing
+8s
+6or
+8ed
+8ing
+8s
+5id
+6n
+5y
+6er
+8s
+6ing
+6s
+4ead
+7er
+9s
+7ing
+9gly
+7s
+6red
+7n
+8ed
+8ing
+8s
+8t
+5d
+5eke
+8d
+8s
+7ing
+5toe
+8s
+4ie
+6s
+5ght
+8ed
+8ing
+8s
+5ke
+7d
+7r
+8s
+7s
+6ing
+9s
+5ppen
+9ed
+9ing
+9s
+5t
+5ve
+7d
+7s
+6ing
+4ocate
+9d
+9s
+8ing
+9on
+9ons
+5dge
+8d
+8s
+7ing
+4uck
+7ed
+7ing
+7s
+4ying
+3made
+5ke
+7s
+6ing
+5nage
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+6ners
+5rk
+7ed
+7ing
+7s
+6riage
+9ges
+8ed
+9s
+7y
+8ing
+5tch
+8ed
+9s
+8ing
+8ment
+9ents
+6e
+7d
+7s
+6ing
+4easure
+9ed
+9ement
+9ements
+9es
+9ing
+5et
+7ing
+7s
+5t
+6re
+8d
+8s
+7ing
+4ove
+7d
+7s
+6ing
+3name
+7d
+7s
+6ing
+4omer
+8ed
+8ing
+8s
+4umber
+9ed
+9ing
+9s
+3o
+4bservance
+9ances
+9e
+9ed
+9es
+9ing
+4capnic
+5lere
+4gamic
+8es
+8st
+9ts
+7y
+5ynic
+8es
+8st
+9tic
+9tical
+9ts
+7ous
+7y
+4logies
+8st
+9ts
+7y
+4neism
+9s
+8t
+9ic
+9s
+4rder
+8ed
+8ing
+8s
+5ient
+9ation
+9ations
+9ed
+9ing
+9s
+4s
+3package
+9ed
+9es
+9ing
+5ge
+7d
+7s
+6ing
+5int
+8ed
+8ing
+8s
+5rse
+8d
+8s
+7ing
+6t
+7ed
+7ing
+7s
+5tch
+8ed
+9s
+8ing
+4en
+6ned
+7ing
+6s
+5rceive
+9ved
+9ves
+9ving
+8ption
+9tions
+6suade
+9ded
+9des
+9ding
+9sion
+9sions
+4hrase
+9d
+9s
+8ing
+4ickel
+9s
+4lace
+8d
+8ment
+9ents
+8s
+7ing
+6n
+7ned
+8ing
+7s
+7t
+8ed
+8ing
+8s
+6y
+7ed
+7ing
+7s
+5ead
+8ed
+8ing
+9ngs
+8s
+7se
+9d
+9s
+8ing
+6d
+4oint
+8ed
+8ing
+8s
+6se
+8d
+8s
+7ing
+5sition
+9oned
+9oning
+9ons
+4raise
+9d
+9s
+8ing
+5ice
+8d
+8s
+7ing
+6nt
+8ed
+8ing
+8s
+6se
+8d
+8s
+7ing
+8on
+9ns
+6ze
+8d
+8r
+9s
+8s
+7ing
+5ogram
+9med
+9ming
+9mmed
+9mming
+9ms
+6nounce
+9nced
+9nces
+9ncing
+6portion
+9tioned
+9tions
+6ud
+4unctuate
+9ated
+9ates
+9ating
+9ation
+9ations
+3quotation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+3raise
+8d
+8s
+7ing
+5te
+7d
+7s
+6ing
+4ead
+7ing
+9gs
+7s
+5ckon
+9ed
+9ing
+9ings
+9s
+6ollection
+7rd
+9ed
+9ing
+9s
+5fer
+8ence
+9nces
+8red
+9ing
+8s
+5gard
+9s
+6ister
+9ered
+9ering
+9ers
+9ration
+5late
+9d
+9s
+8ing
+9on
+9ons
+6ied
+8s
+6y
+7ing
+5member
+9ered
+9ering
+9ers
+5nder
+9ed
+9ing
+9s
+5port
+9ed
+9er
+9ers
+9ing
+9s
+6resent
+9ented
+9enter
+9enters
+9enting
+9ents
+4hymed
+4oute
+8d
+8ing
+8s
+7ing
+4ule
+7d
+7s
+6ing
+3s
+4a
+5ble
+5e
+5id
+5l
+6s
+5w
+5y
+6ing
+9s
+6s
+4eat
+7ed
+7ing
+7s
+5d
+5e
+6ing
+6m
+7ed
+7ing
+9gs
+7s
+6n
+6s
+5l
+6l
+7ing
+9gs
+7s
+6s
+5nd
+7ing
+7s
+6se
+8s
+6t
+5s
+5t
+6s
+6ting
+4hape
+8d
+8n
+9ly
+9ness
+9nesses
+8r
+9s
+8s
+7ing
+5eathed
+5od
+6od
+8s
+4ier
+6s
+7t
+5le
+7er
+9s
+7man
+8en
+7ries
+8y
+7s
+6ries
+7y
+5ng
+7ly
+5ologies
+9y
+6n
+7al
+8ries
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9y
+7ed
+8r
+9s
+7ing
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7s
+5s
+6es
+6h
+7ness
+9sses
+5ve
+7s
+4old
+5rt
+7ed
+7ing
+7s
+5und
+8ed
+8ing
+8s
+6t
+7s
+4pace
+8d
+8s
+7ing
+5eak
+8ing
+8s
+6ll
+8ed
+8ing
+9ngs
+8s
+7t
+6nd
+8er
+9rs
+8ing
+8s
+7t
+5oke
+8n
+4tamp
+8ed
+8ing
+8s
+6rt
+8ed
+8ing
+8s
+6te
+8d
+8ment
+9ents
+8s
+7ing
+5eer
+8ed
+8ing
+8s
+6p
+7ped
+8ing
+7s
+5op
+7ped
+8ing
+7s
+5ricken
+7ke
+9s
+8ing
+6uck
+5yle
+8d
+8s
+7ing
+4uit
+7ed
+7ing
+7s
+5mmation
+9ions
+5s
+6es
+4y
+3t
+4akable
+9y
+6e
+7able
+9ly
+7n
+8ly
+8ness
+9esses
+7r
+8s
+7s
+6ing
+9s
+5l
+6s
+5ught
+4bow
+7s
+4each
+8es
+8ing
+5d
+5ll
+7ing
+7s
+5mper
+9ed
+9ing
+9s
+5nd
+7ed
+7ing
+7s
+5r
+6ed
+6ies
+7ng
+6m
+7ed
+7ing
+7s
+6s
+6y
+5uk
+4ful
+4hink
+8ing
+8s
+5ought
+9ts
+5rew
+6ow
+8ing
+8n
+8s
+4ico
+7s
+5er
+6st
+5gris
+9es
+5ly
+5me
+7d
+7s
+6ing
+5ness
+9es
+6g
+7s
+5tle
+8d
+8s
+7ing
+4le
+6d
+6s
+6toe
+9s
+5ing
+4old
+5ok
+5uch
+8ed
+9s
+8ing
+4race
+8d
+8s
+7ing
+6in
+8ed
+8ing
+8s
+6l
+7s
+6nscribe
+9ribed
+9ribes
+9ribing
+8late
+9ated
+9ates
+9ating
+9ation
+9ations
+6yned
+5eading
+9ngs
+7t
+8ed
+8ing
+8ment
+9ents
+8s
+6ss
+8ed
+9s
+8ing
+8less
+9y
+5ial
+8s
+5ust
+8ed
+9r
+9rs
+8ful
+9ully
+9ulness
+8ing
+9ngly
+8less
+8s
+6th
+8s
+5yst
+8ed
+8ing
+8s
+4s
+4une
+7d
+7s
+6ing
+5tor
+8ed
+8ing
+8s
+4y
+5pe
+7d
+7s
+6ing
+3understand
+9tands
+9tood
+5ion
+8s
+4sage
+8s
+5e
+6d
+6r
+7s
+6s
+5ing
+5t
+4tilisation
+9ations
+8zation
+9ations
+3value
+8d
+8s
+7ing
+4enture
+9es
+9ous
+4ocalisation
+9zation
+3wandred
+4een
+7ed
+7ing
+7s
+5nd
+7ing
+7s
+6t
+4ord
+7ed
+7ing
+9gs
+7s
+6ship
+9pped
+9pping
+9ps
+4rit
+7e
+8s
+7ing
+7ten
+5ote
+3yoke
+7d
+7s
+6ing
+2tch
+5ed
+6s
+5ing
+3e
+4r
+5ed
+6r
+7s
+5ing
+5s
+5wort
+9s
+4s
+3her
+6ed
+6ing
+6s
+4radatic
+5idate
+9es
+9ic
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ize
+9ized
+9izes
+9izing
+3icidal
+7e
+8s
+4er
+5st
+4gable
+6nt
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9es
+7or
+9s
+9y
+4s
+5es
+3ochondria
+9rial
+9rion
+4gen
+7etic
+7ic
+9ities
+9ity
+7s
+4mycin
+9s
+4ses
+5is
+4tic
+7ally
+3raille
+9s
+9ur
+9urs
+9use
+9uses
+5l
+4e
+5d
+5s
+5wort
+9s
+4iform
+5ng
+3svah
+7s
+5oth
+3t
+4en
+6ed
+6s
+4imus
+8es
+4s
+3umba
+7s
+3y
+3zvah
+7s
+5oth
+2urus
+6es
+2x
+3abilities
+9y
+5le
+3down
+7s
+3ed
+5ly
+5ness
+9es
+4n
+5s
+4r
+5s
+4s
+3ible
+4er
+5st
+4ng
+3master
+9s
+3obarbaric
+4logies
+8st
+9ts
+7y
+5ydian
+4trophic
+3t
+4e
+4ion
+7s
+4ure
+7s
+3up
+5s
+3y
+2z
+3en
+5mast
+9s
+5s
+3maze
+7s
+3una
+6s
+3z
+4en
+6mast
+9ts
+6s
+5s
+4le
+6d
+6s
+5ier
+7st
+6ng
+8s
+5y
+4onite
+9s
+4y
+1m
+1na
+3s
+2eme
+5s
+4ic
+4on
+6ic
+8al
+9lly
+8s
+7st
+9s
+6s
+5technic
+9nics
+9nist
+9nists
+1o
+2a
+3i
+3n
+4ed
+5r
+6s
+4ful
+7ly
+4ing
+7ly
+7s
+4s
+3s
+3t
+4ed
+4ing
+4like
+4s
+2b
+3bed
+5r
+6s
+4ie
+6s
+5ng
+7s
+5sh
+7ly
+6m
+7s
+4le
+6d
+6s
+5ing
+4y
+3cap
+6s
+5st
+7ed
+7ing
+9gs
+7s
+3e
+4s
+4y
+5s
+3ie
+5s
+4le
+6s
+5isable
+8tion
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+6ties
+7y
+6zable
+8tion
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+3le
+5d
+5s
+4ing
+4og
+6ger
+9s
+6s
+3ocracies
+8y
+7t
+8ic
+9cal
+8s
+3s
+4man
+5en
+4ter
+7s
+3y
+2c
+3assin
+8s
+3casin
+8s
+4ies
+3h
+4a
+5s
+4ell
+7s
+4ie
+6r
+6st
+5la
+7s
+5ness
+9es
+4s
+4y
+3k
+4able
+5do
+7es
+5ge
+7s
+4ed
+5r
+6ed
+6ies
+7ng
+6nut
+9s
+6s
+6y
+4ing
+7bird
+9rds
+7ly
+7s
+4ney
+7s
+4s
+4tail
+8s
+4umentaries
+9ary
+5p
+6s
+3ock
+6s
+3s
+3uck
+6s
+4ddum
+8s
+2d
+3afinil
+9s
+4l
+5ism
+8s
+7t
+8ic
+8s
+6ties
+7y
+5ly
+5s
+3ded
+5r
+6s
+4ing
+7s
+3e
+4l
+5ed
+6r
+7s
+5ing
+8s
+6st
+8s
+5led
+7r
+8s
+6i
+7ng
+9s
+6o
+7s
+5s
+4m
+5ed
+5ing
+5s
+4na
+6s
+4r
+5ate
+8d
+8ly
+8ness
+9esses
+8s
+7ing
+8on
+9ns
+8sm
+9ms
+7o
+8r
+9s
+9ship
+9ships
+8s
+7rices
+9x
+9xes
+5n
+6e
+7r
+7s
+8t
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ically
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ly
+6ness
+9ses
+6s
+5s
+4s
+5t
+6er
+7st
+6ies
+6ly
+6y
+3ge
+5d
+5s
+4ing
+3i
+4ca
+5um
+7s
+4fiabilities
+9lity
+8le
+9eness
+6cation
+9ions
+9ive
+9ory
+6ed
+7r
+8s
+7s
+5y
+6ing
+4i
+4llion
+9s
+4olar
+6i
+6us
+4sh
+6ly
+6ness
+9ses
+5t
+6e
+7s
+6s
+4us
+4wort
+8s
+3s
+3ulabilities
+9ity
+6r
+7ised
+8ties
+9y
+8zed
+7ly
+7s
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+9y
+5e
+6s
+5i
+5o
+5us
+4s
+2e
+3llon
+7s
+3r
+4ed
+4ing
+4s
+3s
+2fette
+7s
+3fette
+8s
+4ie
+6s
+3ussil
+8s
+2g
+3gan
+6s
+4ed
+4ie
+6s
+5ng
+4y
+3hul
+6s
+3s
+3ul
+5ed
+5s
+2hair
+6s
+4lim
+4wk
+6s
+3el
+5im
+5s
+3ican
+7s
+3r
+4s
+3ua
+5s
+4r
+5s
+2i
+3der
+6ed
+6ing
+6s
+4ore
+7s
+3eties
+5y
+3l
+4ed
+5r
+6s
+4ing
+7ly
+4s
+3neau
+7s
+3ra
+5i
+4e
+5s
+3ser
+6s
+4t
+5ed
+6n
+7ed
+8r
+9s
+7ing
+7s
+6r
+6st
+5ful
+5ified
+9s
+7y
+8ing
+6ng
+5ly
+5ness
+9es
+5s
+5ure
+8less
+8s
+7ise
+9ed
+9er
+9ers
+9es
+9ing
+8ze
+9ed
+9er
+9ers
+9es
+9ing
+3t
+4her
+7ed
+7ing
+7s
+4s
+2jarra
+7s
+3ito
+6s
+3o
+4es
+4s
+2kaddam
+8s
+3e
+4s
+3i
+4hi
+6s
+4s
+3o
+4moko
+8s
+4puna
+8s
+4ro
+6s
+4s
+3sha
+6s
+2l
+3a
+4l
+5ities
+7y
+4r
+5ities
+7y
+5s
+4s
+5se
+7s
+8es
+3d
+4abilities
+9ty
+6le
+5vite
+9s
+4board
+9s
+4ed
+5r
+6ed
+6ing
+6s
+4ier
+6st
+5ness
+9es
+6g
+7s
+4s
+4warp
+8s
+4y
+3e
+4cast
+8s
+6tcher
+9ers
+5ular
+9ities
+9ity
+9ly
+7e
+8s
+4hill
+8s
+4ndinar
+9ries
+9rs
+9ry
+4s
+5kin
+8s
+5t
+6ation
+9ons
+6ed
+7r
+8s
+6ful
+6ing
+6s
+3ies
+4men
+7s
+5inous
+4ne
+6s
+6t
+7s
+3l
+4a
+5h
+6s
+5s
+4ie
+6s
+5fiable
+7cation
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5ties
+7ous
+4s
+4usc
+7a
+8n
+9s
+7icidal
+9ide
+9ides
+7oid
+9dal
+9ds
+8us
+7s
+7um
+6k
+7an
+9s
+7s
+4y
+5coddle
+9led
+9ler
+9lers
+9les
+9ling
+5hawk
+9s
+5mawk
+9s
+3och
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6s
+4ssi
+6us
+3s
+3t
+4ed
+5n
+6ly
+5r
+6s
+4ing
+4o
+4s
+3y
+4bdate
+9s
+6enite
+9tes
+8oses
+9sis
+9us
+8um
+9ms
+6ic
+6oses
+8is
+7us
+2m
+3e
+4nt
+6a
+7neous
+8y
+7rily
+9ness
+9nesses
+8y
+6ly
+6o
+7es
+7s
+7us
+9ly
+9ness
+9nesses
+6s
+6um
+8s
+4s
+3i
+4sm
+6s
+3ma
+5s
+4et
+6s
+4ies
+4y
+3s
+4er
+6s
+3us
+5es
+3zer
+6im
+6s
+2n
+3a
+4chal
+6ism
+9s
+8t
+9s
+5id
+7ic
+7s
+5t
+6inal
+8e
+4d
+5al
+5elphous
+6s
+5ic
+7al
+9ly
+6form
+6sm
+8s
+7tic
+5nock
+9s
+5ologies
+9y
+5s
+4l
+5s
+4ndries
+7ous
+7y
+5thous
+4rch
+7al
+9ly
+7ial
+8c
+9al
+9ally
+8es
+8se
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ze
+9ed
+9es
+9ing
+7s
+7y
+5da
+7s
+4s
+5es
+5terial
+9es
+8y
+6ic
+8al
+9lly
+8ism
+9sms
+8s
+4tomic
+4ul
+6s
+5ral
+8ly
+4xial
+5on
+7ic
+7s
+4zite
+8s
+3chiquite
+9tes
+3dain
+7e
+8s
+7s
+4e
+5green
+9ns
+5s
+4ial
+4o
+5s
+3ecian
+6ous
+9ly
+4llin
+8s
+4me
+6s
+4r
+5a
+6n
+7s
+5gism
+9s
+5on
+4strous
+4tarily
+8sm
+9ms
+9t
+9ts
+7y
+5h
+6s
+5isation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+4y
+5bag
+8s
+5changer
+9gers
+5ed
+6r
+7s
+5grubbing
+9bings
+5lender
+9ers
+9ing
+9ings
+7ss
+5maker
+9rs
+8ing
+9ngs
+7n
+6en
+5s
+6pinning
+5wort
+9s
+3g
+4corn
+8s
+4ed
+5ese
+5r
+6ed
+6ies
+7ng
+9s
+6s
+6y
+4o
+5e
+6s
+5l
+6ian
+7sm
+9s
+6oid
+9s
+6s
+5ose
+8s
+5s
+4rel
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7ly
+7s
+4s
+5t
+3ial
+6s
+4cker
+8s
+4e
+5d
+5s
+4ker
+7s
+4lia
+7l
+7s
+8es
+8is
+6form
+4ment
+8s
+4plies
+4sh
+6ed
+7s
+6ing
+5m
+6s
+5t
+6ic
+8al
+9lly
+6s
+4tion
+8s
+6ve
+5or
+7ed
+7ial
+9lly
+8es
+8ng
+9gs
+7s
+8hip
+9ips
+7y
+5ress
+9es
+3k
+4eries
+6y
+5y
+6ed
+6gland
+6ing
+7sh
+8m
+9s
+6pod
+9s
+8t
+9s
+6s
+7hine
+9nes
+4fish
+8es
+4hood
+8s
+4ish
+7ly
+7ness
+9sses
+4s
+5hood
+9s
+3o
+4acid
+8ic
+8s
+5mine
+9rgic
+9s
+5o
+6s
+5tomic
+4basic
+5lepses
+9is
+5row
+8s
+4carboxylic
+7dian
+7p
+8ellary
+8ic
+8ous
+8s
+5eros
+9es
+8us
+5hasia
+9al
+9um
+6lamydeous
+7oride
+9ides
+6ord
+9s
+6roic
+9cs
+8masies
+9asy
+9at
+9ate
+9ates
+9atic
+9atics
+9atism
+9atisms
+9ator
+9ators
+9ats
+9e
+9es
+9ic
+9ical
+9ies
+9ist
+9ists
+9y
+5le
+7d
+7s
+6inal
+9lly
+9ls
+8e
+9s
+8ic
+9sm
+9sms
+8ous
+6onal
+9ls
+5oque
+9s
+6t
+7s
+7yl
+9edon
+9edons
+9s
+5racies
+8y
+7t
+8ic
+8s
+6ystal
+9alline
+9als
+5ular
+9ly
+9s
+7ous
+7tural
+9re
+9res
+5ycle
+9s
+8ic
+6te
+8s
+7ic
+7oid
+4dactylous
+5elphian
+9ic
+9ous
+5ic
+7al
+9ly
+6es
+6sperse
+7t
+8s
+5ont
+5rama
+9s
+9tic
+5y
+4ecies
+7ous
+9sly
+7sm
+9s
+6y
+5ster
+9s
+4fil
+7ament
+9ents
+7s
+5uel
+8s
+4gamic
+8es
+8st
+9tic
+9ts
+7ous
+9sly
+9sness
+7y
+6stric
+5enean
+9ns
+8ses
+9is
+8tic
+7ic
+9ally
+8es
+8sm
+9ms
+9t
+9tic
+9ts
+7ous
+7y
+6rm
+5lot
+8s
+6yceride
+9rides
+5onies
+7y
+5ram
+8ed
+8ing
+8matic
+9ed
+9er
+9ers
+9ing
+8s
+7ph
+9ed
+9er
+9ers
+9ic
+9ical
+9ically
+9ies
+9ing
+9ist
+9ists
+9s
+9y
+5ynian
+8es
+8st
+9ts
+7ous
+7y
+4hull
+8s
+5ybrid
+9ds
+6drate
+9ted
+9tes
+8ic
+8ogen
+9xy
+4icous
+9ly
+4kine
+8s
+7i
+8s
+4later
+9s
+7ries
+9st
+9sts
+8ous
+8y
+6yer
+9s
+5ine
+7gual
+9alism
+9alisms
+9als
+9ist
+9ists
+6th
+8ic
+9cally
+8s
+5og
+7ged
+8ing
+7ic
+9al
+8es
+8se
+9ed
+9es
+9ing
+9t
+9ts
+8ze
+9ed
+9es
+9ing
+7s
+7ue
+9d
+9s
+8ing
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+7y
+4machia
+9as
+9es
+8y
+6nia
+9c
+9cal
+9cally
+9cs
+9s
+6rk
+8s
+5er
+7ic
+7ous
+7s
+6tallic
+9lism
+9lisms
+9list
+9lists
+7er
+9s
+7ric
+9cal
+5ial
+8s
+5ode
+6lecular
+9ularly
+6rphemic
+9ic
+9ism
+9isms
+9ous
+5yarian
+4nuclear
+9ars
+9ate
+9ated
+9oses
+9osis
+9osises
+9otide
+9otides
+5ym
+7s
+4petalous
+5hagies
+8ous
+8y
+7se
+8ic
+6obia
+9as
+9c
+9cs
+7nic
+9cally
+9es
+8y
+7sphate
+9hates
+6thong
+9ngal
+9ngise
+9ngised
+9ngises
+9ngize
+9ngized
+9ngizes
+9ngs
+6yletic
+8ies
+8lous
+8y
+7odont
+9onts
+7site
+9tes
+9tic
+9tism
+9tisms
+5itch
+5lane
+9s
+6egia
+9as
+9c
+9cs
+6oid
+9s
+5od
+7e
+8s
+7ia
+9l
+9lly
+8es
+8um
+7s
+7y
+6le
+8s
+7ies
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7y
+5rionidian
+6opellant
+9llants
+5sonies
+9st
+9stic
+9sts
+8y
+5tera
+9l
+8oi
+9n
+9s
+9ses
+6ote
+9s
+5ulse
+9s
+4rail
+8s
+5chid
+9ism
+9isms
+9s
+8sm
+9ms
+5hinal
+8e
+6yme
+9d
+9s
+4s
+5accharide
+9arides
+6turated
+5emies
+7y
+6palous
+6s
+5ies
+6s
+5ki
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5odium
+6me
+8s
+7ic
+9s
+8es
+7y
+5paced
+6ecific
+9ficity
+7rmal
+9ous
+5table
+6ele
+9s
+8ic
+9es
+8y
+6ich
+9ic
+9ous
+9s
+6ome
+8ous
+6rophe
+9hes
+9hic
+9hics
+6ylar
+8e
+8ous
+5y
+6llabic
+9bicity
+9bism
+9bisms
+9ble
+9bles
+6mmetric
+9trical
+9tries
+9try
+6naptic
+4task
+8ed
+8ing
+9ngs
+8s
+5elephone
+9hones
+6rpene
+9nes
+5halamic
+9mous
+6ecal
+8ous
+7ism
+9ms
+9t
+9tic
+9tical
+9ts
+7lete
+9tes
+9tic
+9tical
+9tism
+9tisms
+8ism
+9sms
+9te
+9tes
+9tism
+9tisms
+7rapies
+9py
+5int
+8s
+5ocous
+6ne
+8d
+8s
+7ic
+9ally
+9ities
+9ity
+8es
+8ng
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7ous
+9sly
+9sness
+7y
+5rematous
+8e
+9s
+6ichic
+9ous
+6och
+9s
+5ype
+8s
+7ic
+4unsaturate
+9urated
+9urates
+4valence
+9ces
+9cies
+9cy
+9t
+5ular
+4xide
+8s
+5ylon
+9s
+8us
+4zygotic
+8us
+3s
+4eigneur
+4ieur
+5gnor
+9i
+9ial
+9s
+4oon
+7al
+7s
+4ter
+7a
+8s
+7ed
+7ing
+9gs
+7s
+5rance
+9es
+6osities
+9ty
+7us
+9ly
+9ness
+9nesses
+6uosities
+9ity
+8us
+3tadale
+9s
+5ge
+7d
+7s
+6ing
+6nard
+9ds
+5n
+6e
+7s
+6t
+7o
+8s
+7s
+5ria
+8s
+4bretia
+9as
+4e
+5ith
+8s
+5limar
+9rs
+5m
+6s
+5ro
+7s
+5s
+4golfier
+9ers
+4h
+5lies
+7ng
+9s
+6ong
+6y
+5s
+4icellite
+9ites
+6le
+8s
+6olous
+6ulate
+8e
+9s
+8ous
+8us
+9ses
+5es
+4morillonite
+4re
+6s
+4ure
+7s
+4y
+3ument
+8al
+9lise
+9lised
+9lises
+9lising
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lly
+8ed
+8ing
+8s
+4ron
+7s
+3y
+4plies
+3zonite
+9s
+8ic
+2o
+3bs
+3ch
+5ed
+6r
+7s
+6s
+5ing
+3d
+4ied
+6r
+6s
+7t
+5ly
+5ness
+9es
+4s
+4y
+5ing
+3ed
+3i
+4ng
+3k
+4s
+4tar
+7s
+3l
+4a
+5h
+6s
+5s
+4ed
+5y
+6s
+4i
+5es
+5ng
+5s
+4oo
+6s
+4s
+4vi
+6e
+7s
+6s
+4y
+3n
+4beam
+8s
+5lind
+5ow
+7s
+4cake
+8s
+6lf
+7ves
+5hild
+9ren
+4dust
+8s
+4ed
+5r
+6s
+5ye
+7s
+4face
+8d
+8s
+5ish
+8es
+5lower
+9rs
+4g
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+5sh
+7ly
+4less
+6t
+7s
+5ight
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+6ke
+6t
+4phase
+9s
+5ort
+8s
+4quake
+9s
+4raker
+9s
+7ing
+9gs
+5ise
+8s
+5ock
+8s
+6of
+8s
+4s
+5ail
+8s
+5cape
+9s
+5eed
+8s
+6t
+7s
+5hee
+8s
+6ine
+9d
+9r
+9rs
+9s
+8ing
+8y
+6ot
+8s
+5tone
+9s
+6ricken
+8ke
+9es
+7uck
+4walk
+8ed
+9r
+9rs
+8ing
+8s
+6rd
+8s
+5ort
+8s
+4y
+3p
+4ed
+4ing
+4s
+3r
+4age
+7s
+4burn
+8s
+6zzard
+9rds
+4cock
+8s
+4ed
+4fowl
+8s
+4hen
+7s
+4ier
+6st
+5ll
+7s
+5ng
+7s
+5sh
+4land
+8s
+5og
+7s
+4man
+5en
+4s
+4va
+6s
+4wort
+8s
+4y
+3s
+4e
+5bird
+9s
+5wood
+9s
+5yard
+9s
+3t
+4able
+4ed
+5r
+6s
+5st
+4ing
+7s
+4man
+5en
+4ness
+8es
+4s
+3ve
+5d
+5s
+4ing
+2p
+3ane
+6s
+5i
+6s
+3board
+8s
+3e
+4d
+5s
+4hawk
+8s
+4r
+5ies
+5s
+5y
+4s
+4y
+3head
+7s
+3ier
+5st
+4ly
+4ness
+8es
+5g
+6ly
+4sh
+6ly
+6ness
+9ses
+3oke
+6s
+3ped
+5r
+6s
+5t
+6s
+4ier
+6st
+5ng
+4y
+3s
+4ies
+4tick
+8s
+4y
+3us
+5es
+3y
+2quette
+8s
+2r
+3a
+4ceous
+4e
+4inal
+6e
+7s
+6ic
+4l
+5e
+6s
+5isation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+9cally
+8s
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5l
+6ed
+7r
+8s
+6ing
+6s
+6y
+5s
+4s
+5s
+6es
+6y
+4t
+5oria
+8um
+9ms
+7y
+5s
+4y
+5s
+3bid
+6er
+7st
+7zza
+9as
+6ities
+8y
+6ly
+6ness
+9ses
+5ferous
+6ic
+8ally
+5lli
+8form
+8virus
+9iruses
+7ous
+4us
+6es
+3ceau
+7x
+4ha
+6s
+3dacious
+9sly
+9sness
+7ties
+8y
+5ncies
+7y
+6t
+7ed
+7ing
+7ly
+7s
+4ent
+7s
+3e
+4en
+6s
+4ish
+4l
+5le
+7s
+6o
+7s
+5s
+4ndo
+5ess
+8es
+4over
+4pork
+8s
+4s
+5que
+8s
+3gan
+6atic
+9cally
+6ite
+9s
+6s
+5y
+6s
+4en
+6s
+7tern
+9rns
+4ue
+6s
+3ia
+5s
+4bund
+8ities
+9ty
+8ly
+4che
+7s
+4gerate
+9ion
+9ions
+7ous
+4on
+6s
+4sco
+7es
+7s
+5h
+3kin
+6s
+3ling
+7s
+3maor
+7s
+3n
+4ay
+6s
+4e
+5d
+5s
+4ing
+7s
+4s
+3occo
+7s
+4n
+5ic
+7ally
+6sm
+8s
+6ties
+7y
+5s
+4se
+6ly
+6ness
+9ses
+6r
+6st
+5ities
+7y
+3ph
+5actin
+9ns
+6llaxes
+9xis
+5ean
+6d
+6me
+8s
+7ic
+9ally
+9s
+6tic
+6w
+7s
+5ia
+7s
+6c
+6n
+7e
+8s
+7g
+8s
+7ic
+8sm
+9ms
+7omania
+9aniac
+9aniacs
+9anias
+7s
+5o
+6gen
+9eses
+9esis
+9etic
+9ic
+9ies
+9s
+9y
+7rapher
+9phers
+9phies
+9phy
+6lino
+9os
+7ogic
+9ical
+9ically
+9ies
+9ist
+9ists
+9y
+6metric
+9rics
+9ries
+9ry
+6phoneme
+9nemes
+9nemic
+9nemics
+6s
+7es
+7is
+6tic
+7ropic
+9pies
+9py
+5s
+3ra
+5s
+4ell
+7s
+4hua
+7s
+4ice
+7s
+5on
+7s
+5s
+6ed
+7s
+6ing
+4o
+5s
+5w
+6s
+3s
+4al
+4e
+5l
+6ed
+6ing
+6led
+7ing
+6s
+5s
+4ure
+7s
+3t
+4adella
+9as
+9e
+5l
+6ise
+9d
+9s
+8ing
+7ties
+8y
+7ze
+9d
+9s
+8ing
+6ly
+6s
+5r
+6board
+9rds
+6ed
+6ing
+6less
+6man
+7en
+6s
+6y
+4bell
+8s
+4cloth
+9s
+4gage
+8able
+8d
+8e
+9s
+8r
+9s
+8s
+7ing
+7or
+9s
+4ice
+7d
+7r
+8s
+7s
+6ian
+9s
+7ng
+5ferous
+9usness
+6ic
+8ation
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+9gly
+9gs
+5se
+7d
+7r
+8s
+7s
+6ing
+4ling
+8s
+4main
+8s
+4s
+5afe
+8s
+4uaries
+7y
+3ula
+6e
+6r
+6s
+6tion
+9ns
+3wong
+7s
+3yah
+2s
+3aic
+6ally
+6ism
+9s
+8t
+9s
+6ked
+7ing
+6like
+6s
+4saur
+8i
+8s
+8us
+3bolletjie
+9jies
+3chate
+8l
+9s
+5iferous
+3e
+4d
+4lle
+7s
+4s
+4y
+5ed
+5ing
+5s
+3h
+4av
+6im
+4ed
+5r
+6s
+5s
+4ing
+7s
+3ing
+3k
+4onfyt
+9s
+4s
+3lings
+3que
+6s
+5ito
+8es
+9y
+8s
+3s
+4back
+8ed
+8s
+5luiter
+9ers
+5unker
+9rs
+4ed
+5r
+6s
+5s
+4grown
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+4land
+8s
+5ike
+4o
+4plant
+9s
+4trooper
+9ers
+4y
+3t
+4e
+5st
+7s
+4ly
+4s
+4what
+2t
+3e
+4d
+4l
+5ier
+8s
+5s
+4n
+4s
+4t
+5s
+5t
+6ist
+9s
+6s
+4y
+3h
+4ball
+8ed
+8ing
+8s
+4ed
+5r
+6board
+9rds
+6craft
+9fts
+6ed
+7se
+9s
+6hood
+9ds
+8use
+9ses
+6ing
+9s
+6land
+9ds
+7ess
+9sness
+7iness
+9esses
+7y
+6s
+6wort
+9ts
+6y
+4ier
+6st
+4like
+4proof
+9ed
+9er
+9ers
+9ing
+9s
+4s
+4y
+3i
+4er
+5st
+4f
+5ic
+5s
+4le
+6s
+5ities
+7y
+4on
+6al
+6ed
+7r
+8s
+6ing
+7st
+9s
+6less
+9sly
+9sness
+6s
+4s
+4vate
+8d
+8s
+7ing
+8on
+9nal
+9nally
+9ns
+8ve
+7or
+9s
+5e
+6d
+6less
+9sly
+9sness
+6s
+5ic
+6ng
+6ties
+7y
+3ley
+6er
+7st
+6s
+4ier
+6st
+3mot
+6s
+3ocross
+9es
+4neuron
+9nal
+9ns
+4r
+5able
+6il
+8s
+5bicycle
+9cles
+7ke
+9d
+9s
+8ing
+6oat
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+6us
+8es
+8ses
+5cade
+9d
+9s
+8ing
+7r
+8s
+6oach
+9hes
+6ycle
+9ed
+9es
+9ing
+9ings
+9ist
+9ists
+5dom
+8s
+5ed
+5home
+9s
+5ial
+6c
+7ally
+6ng
+8s
+6sation
+9ions
+7e
+8d
+8s
+7ing
+7t
+8s
+6um
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5less
+5man
+6en
+6outh
+9hs
+5s
+6hip
+9s
+5truck
+9ks
+5way
+8s
+5y
+4scafi
+8o
+3s
+4er
+6s
+3t
+4e
+5s
+4ier
+6s
+7t
+4le
+6d
+6r
+7s
+6s
+5ing
+8s
+4o
+5ed
+6s
+5s
+4s
+4y
+3u
+4ca
+6s
+4s
+3za
+5s
+2u
+3ch
+5arabies
+9y
+7d
+8s
+5ed
+6r
+7s
+6s
+5ing
+5oir
+8s
+3diewart
+9ts
+7ort
+9ts
+5wart
+9s
+6ort
+9s
+3e
+4s
+3fflon
+8s
+4lon
+7s
+3ght
+3ille
+3jik
+6s
+3lage
+7s
+4d
+5abilities
+9ity
+7le
+5board
+9ds
+5ed
+6r
+7ed
+7ing
+7s
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5s
+5warp
+9s
+5y
+6warp
+9ps
+4in
+6et
+8s
+6s
+4s
+4t
+5ed
+6n
+6r
+7s
+5ing
+8s
+5s
+3nd
+5bird
+9s
+5ed
+5ing
+5s
+4seer
+8s
+4t
+5able
+6in
+8board
+9oarder
+9oards
+8ed
+9er
+9ered
+9ering
+9erings
+9ers
+8ous
+9usly
+9usness
+8s
+9ide
+9ides
+8top
+9ops
+8y
+6nt
+8s
+5ebank
+9ked
+9keries
+9kery
+9king
+9kings
+9kism
+9kisms
+9ks
+6d
+6nance
+9ces
+8unce
+9nces
+6r
+7s
+5ing
+8s
+5s
+3p
+4ed
+4ing
+4s
+3rn
+5ed
+6r
+7s
+5ful
+8ler
+9est
+9y
+8ness
+9esses
+5ing
+8ly
+8s
+6val
+9s
+5s
+3s
+4aka
+7s
+4e
+5bird
+9s
+5d
+5kin
+8s
+5like
+5mat
+8s
+5over
+9s
+5pad
+8s
+6iece
+9es
+5r
+6ies
+6s
+6y
+5s
+5tail
+9s
+6rap
+9ped
+9ping
+9s
+5y
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+4le
+6d
+6s
+5ing
+4me
+6e
+7s
+6s
+4quetaire
+9ires
+4saka
+8s
+5e
+6d
+6line
+9es
+6s
+5ing
+4t
+5ache
+9d
+9s
+8ial
+9o
+9os
+5ed
+5ing
+5s
+4y
+3tan
+6s
+4er
+6ed
+7r
+8s
+6ing
+6s
+4h
+5able
+5breather
+9thers
+8eder
+9ders
+7ooder
+9ders
+5ed
+6r
+7s
+5feel
+9s
+6ul
+8s
+5ier
+7st
+6ly
+6ng
+5less
+6ike
+5part
+9s
+6iece
+9es
+5s
+5wash
+9es
+7tering
+9ringly
+5y
+4on
+6nee
+6s
+3vemente
+2vabilities
+9y
+5le
+7ness
+9sses
+7s
+6y
+3e
+4abilities
+9ty
+6le
+8ness
+9esses
+8s
+7y
+4d
+4less
+8ly
+8ness
+9esses
+4ment
+8s
+4r
+5s
+4s
+3ie
+5dom
+8s
+5goer
+9s
+7ing
+9gs
+5land
+9s
+5maker
+9rs
+8ing
+9ngs
+5oke
+8s
+6la
+8s
+5s
+4ng
+6ly
+4ola
+7s
+2w
+3a
+4s
+3burn
+7ed
+7ing
+7s
+7t
+3die
+6s
+6wart
+9ts
+7ort
+9ts
+3ed
+4r
+5s
+3ing
+6s
+3n
+3ra
+5s
+3s
+2xa
+4s
+3ibustion
+9ons
+4e
+5s
+2y
+3a
+4s
+3ities
+5y
+3l
+4e
+5d
+5s
+4ing
+4s
+3s
+2z
+3e
+4d
+4s
+4tta
+7s
+6e
+3ing
+3o
+4s
+3z
+4arella
+9as
+4es
+5tta
+8s
+7e
+4ie
+6s
+4le
+6s
+1pret
+5s
+1ridamgam
+9s
+5ng
+7a
+8m
+9s
+8s
+7s
+1u
+2cate
+6s
+3edinous
+3h
+4acha
+8s
+7o
+8s
+4el
+6l
+7s
+6s
+5s
+4ly
+4ness
+8es
+4o
+3ic
+4d
+5ities
+7y
+5ness
+9es
+4ferous
+4gen
+7s
+4lage
+8s
+7inous
+9ously
+4n
+5ogen
+9s
+6id
+6us
+5s
+3k
+4amuck
+9ed
+9ing
+9s
+4ed
+5nder
+9s
+5r
+6ed
+6ing
+7sh
+6s
+4heap
+8s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4le
+6s
+5uck
+8s
+4rake
+8d
+8r
+9s
+8s
+7ing
+9gs
+4s
+5pread
+9der
+9ders
+9ding
+9ds
+5weat
+9s
+4worm
+8s
+4y
+5muck
+9s
+3luc
+6s
+3ocutaneous
+4id
+6al
+6s
+4lytic
+4membranous
+4peptide
+9des
+5rotein
+9ins
+5urulent
+4r
+5s
+4sa
+6e
+6l
+6nguineous
+6s
+5e
+5ities
+7y
+4us
+4viscidoses
+9dosis
+3ro
+5nate
+9d
+8ion
+9ons
+6es
+5s
+3ulent
+4s
+5es
+2d
+3bath
+7s
+4ug
+6s
+3cap
+6ped
+7ing
+6s
+5t
+6s
+3ded
+5r
+6s
+4ied
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+4le
+6d
+7ness
+9sses
+6headed
+9dedly
+6ment
+9ts
+6r
+7s
+6s
+5ier
+7st
+6ng
+8ly
+8s
+5y
+4y
+5ing
+3ejar
+7es
+4ye
+6s
+3fish
+7es
+4lap
+7s
+6t
+7s
+5ow
+7s
+3ge
+5d
+5r
+6s
+5s
+4ing
+4uard
+8s
+3hen
+6s
+4ole
+7s
+5ok
+7s
+5pper
+9s
+3ir
+5ia
+7s
+6eh
+8s
+5s
+3lark
+7ed
+7ing
+7s
+4ogger
+9s
+7ing
+9gs
+3pack
+7s
+4uppies
+7y
+3ra
+5s
+4ock
+7s
+5om
+7s
+3s
+4cow
+7s
+4ill
+7s
+4kipper
+9rs
+4lide
+8s
+6nger
+9rs
+8ing
+9ngs
+4tone
+8s
+3wort
+7s
+2eddin
+7s
+3nster
+8s
+3sli
+6s
+3zzin
+7s
+2ffed
+5ttee
+9s
+4in
+6eer
+9s
+6g
+6s
+5sh
+4le
+6d
+6r
+7ed
+7s
+6s
+5ing
+4s
+3lon
+6s
+3ti
+5s
+2g
+3earite
+9s
+3ful
+6s
+3g
+4a
+5r
+6s
+5s
+4ed
+5e
+6s
+5r
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+6s
+7es
+5sh
+4s
+4ur
+6s
+4y
+3hal
+6s
+3s
+4hot
+7s
+3wort
+7s
+4ump
+7eries
+9y
+7ish
+9m
+9ms
+7s
+2hlies
+4y
+2id
+4s
+3l
+4s
+3r
+4burn
+8s
+4s
+3st
+5ed
+5ing
+5s
+2jahedeen
+7in
+5ideen
+7in
+3ik
+5s
+2khtar
+7s
+3luk
+6s
+3tuk
+6s
+2latta
+7s
+6o
+7es
+7s
+6ress
+9ses
+3berries
+7y
+3ch
+5ed
+6s
+5ing
+4t
+5ed
+5ing
+5s
+3e
+4d
+4s
+5ed
+6s
+5ing
+8s
+4ta
+6s
+5eer
+8s
+4y
+5s
+3ga
+5s
+3iebrities
+9y
+4ng
+4sh
+6ly
+6ness
+9ses
+3l
+4a
+5h
+6ed
+6ing
+7sm
+9s
+6s
+5rkies
+7y
+5s
+4ed
+5in
+7s
+5n
+6s
+5r
+6ed
+6ing
+6s
+5t
+6s
+5y
+6s
+4igan
+8s
+7tawnies
+9wny
+6rubs
+5ng
+5on
+7ed
+7ing
+7s
+5te
+7s
+4ock
+7s
+7y
+5way
+8s
+4s
+3mul
+6l
+7s
+6s
+3se
+5s
+4h
+5ed
+6s
+5ing
+3tangular
+6imous
+5rticulate
+4eities
+7y
+4iaccess
+9sses
+6ge
+8ncy
+6ngular
+6rmed
+7ticulate
+6tom
+6uthor
+6xial
+5band
+8k
+7rrel
+9eled
+6illion
+9ions
+6laded
+6ranched
+6uilding
+5camerate
+8pus
+7pitate
+7r
+8bon
+7st
+9s
+7uline
+8sal
+6ell
+9ed
+9ular
+7nter
+9ral
+9ric
+6hain
+8mbered
+8nnel
+9nels
+8racter
+6ide
+9s
+7pital
+7ty
+6lient
+6oated
+7lor
+9red
+9rs
+9ur
+9ured
+9urs
+8umn
+7mponent
+7nductor
+7py
+7state
+7unty
+8rse
+9ses
+6ulti
+9is
+9ural
+9urally
+7rie
+8rencies
+9ency
+7spid
+9idate
+9ids
+6ycle
+9es
+5day
+6entate
+6ialectal
+7gitate
+7sc
+9ipline
+7visional
+6omain
+6rug
+5electrode
+8ment
+6mployer
+9oyers
+6ngine
+9nes
+7zyme
+6thnic
+9ics
+5faced
+9ted
+8tor
+9orial
+7mily
+7rious
+9ously
+6id
+8ly
+8ous
+7l
+8ament
+9ments
+8s
+6lash
+7ora
+9as
+9ous
+6ocal
+7il
+9s
+7ld
+8iate
+9olate
+7rm
+9ities
+9ity
+9s
+6requency
+6unction
+9tional
+5genic
+7rm
+6rade
+8in
+9ns
+8vida
+9idae
+9idas
+7id
+7oup
+6ym
+8s
+5headed
+6ospital
+6ued
+7ll
+9s
+5jet
+6ugate
+8ous
+5lane
+9s
+7teral
+9ralism
+9ralist
+9rally
+7yer
+9red
+6evel
+9led
+6ine
+9al
+9ar
+8gual
+9ualism
+9ually
+9uist
+9uists
+6obate
+8e
+9d
+9s
+8ular
+9late
+7cational
+8ular
+9late
+7quence
+9ences
+9ent
+9ies
+9ous
+9y
+5manned
+6edia
+9as
+7gaton
+9tons
+9watt
+9watts
+7mber
+7tallic
+8er
+9rs
+6illennial
+9ion
+9ions
+6odal
+8e
+7lecular
+5nation
+9onal
+9onals
+6omial
+9als
+9nal
+6uclear
+9eate
+9eated
+9eolate
+5pack
+9s
+7ge
+7ned
+7ra
+9e
+9meter
+9s
+8ities
+9ty
+8ous
+8t
+9icle
+9ite
+9y
+9yism
+9yisms
+7th
+6ed
+8e
+9s
+8s
+6hase
+9ic
+7oton
+6icture
+7ece
+7on
+7ston
+6lane
+9es
+9t
+8yer
+9ers
+7e
+8s
+8t
+9s
+8x
+9ed
+9er
+9ers
+9es
+9ing
+9or
+9ors
+7iable
+8cable
+9and
+9ands
+9ate
+9ates
+9ation
+9ations
+9ative
+9ator
+9ators
+9ities
+9ity
+8ed
+9r
+9rs
+9s
+7y
+8ing
+6olar
+9rities
+9rity
+8e
+9s
+7rt
+7tent
+9ntial
+7wer
+6resence
+9ences
+9ent
+7oblem
+8cessing
+9essor
+9essors
+8duct
+8nged
+6urpose
+5racial
+9alism
+9alisms
+9ally
+7mified
+7nge
+6egional
+7ligious
+6ole
+7om
+5science
+9nces
+7reen
+6ense
+9ory
+7ptate
+7rial
+9ate
+8vice
+6ided
+7te
+7ze
+6kill
+9led
+9ling
+9lings
+9ls
+6onant
+7urce
+6pecies
+9tral
+8ed
+7iral
+7ort
+6tage
+8te
+7emmed
+8p
+7orey
+9eys
+9ied
+9ies
+9y
+7randed
+8ike
+9kes
+6ulcate
+6yllabic
+7stem
+5talented
+7sk
+9ed
+9ing
+9ings
+9s
+6erminal
+6hreading
+9adings
+6iered
+6on
+8e
+9s
+7ol
+9s
+7wered
+6rack
+9ked
+9king
+9ks
+7illion
+9lions
+6ude
+9s
+8inary
+9nous
+9nously
+5union
+8t
+6se
+8r
+5valence
+9nces
+9ncies
+9ncy
+9nt
+9nts
+7riable
+9ate
+9ous
+6erse
+9es
+9ities
+9ity
+6ibrator
+9ators
+7ous
+7tamin
+9mins
+6ocal
+9ls
+7ltine
+8ume
+5wall
+7rhead
+7velength
+6indow
+9ows
+5year
+4ocular
+4um
+6s
+5ngulate
+9ates
+5re
+7d
+7r
+8s
+7s
+6ing
+2m
+3ble
+6d
+6ment
+9ts
+6r
+7s
+6s
+6typeg
+9egs
+5ier
+7st
+6ng
+8ly
+8s
+5y
+3chance
+9s
+3m
+4ed
+5r
+6ies
+6s
+6y
+4ia
+6s
+5chog
+9s
+5ed
+6s
+5fication
+9tions
+7ed
+8s
+6orm
+6y
+7ing
+5ng
+7s
+4ock
+7s
+4s
+4y
+5ing
+3p
+4ed
+5r
+6s
+4ing
+5sh
+7ly
+7ness
+9sses
+4s
+5imus
+9es
+3s
+4ier
+6st
+4y
+3u
+4s
+2n
+3ch
+5able
+9s
+5ed
+6r
+7s
+6s
+5ies
+6ng
+5kin
+8s
+3dane
+7ly
+7ness
+9sses
+7r
+7st
+6ities
+8y
+4ic
+6s
+5fication
+9tions
+9tive
+7ed
+8s
+6y
+7ing
+4ungo
+8s
+7us
+9es
+3g
+4a
+5s
+4corn
+8s
+4e
+5d
+5s
+4ing
+4o
+5es
+5ose
+8s
+5s
+4s
+3i
+4cipal
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9ists
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+9ly
+9s
+4ficence
+9ces
+9t
+9tly
+9tness
+6ed
+7nce
+9es
+7s
+5y
+6ing
+4ment
+8s
+4s
+4te
+6d
+6s
+5ing
+6on
+8ed
+9er
+9ers
+9r
+9rs
+9tte
+9ttes
+8ing
+8s
+3nion
+7s
+3s
+4hi
+6s
+4ter
+7s
+3t
+4er
+6s
+4in
+6g
+7s
+6s
+4jac
+7s
+6k
+7s
+4rie
+7s
+4s
+4u
+5s
+2on
+4ic
+5um
+7s
+4s
+2ppet
+6s
+2qaddam
+8s
+2ra
+4ena
+7s
+6id
+8s
+4ge
+6s
+4l
+5ed
+5ist
+8s
+5led
+5s
+4s
+3dabad
+4er
+6ball
+9ls
+6ed
+7e
+8s
+7r
+8s
+7ss
+9es
+6ing
+6ous
+9ly
+9ness
+9nesses
+6s
+3e
+4d
+4in
+6s
+4na
+6s
+4s
+4x
+5es
+3geon
+7ed
+7ing
+7s
+3iate
+7d
+7s
+6ic
+4cate
+8d
+5es
+4d
+5s
+4form
+4ne
+6s
+5g
+3k
+4er
+5st
+4ier
+6st
+5ly
+5ness
+9es
+5sh
+4ly
+4s
+5ome
+4y
+3l
+4ain
+7s
+5n
+6s
+4ed
+4ier
+6st
+5n
+6g
+6s
+4s
+4y
+3mur
+6ation
+9ons
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6ous
+9ly
+6s
+3phies
+5y
+3r
+4a
+5gh
+7s
+5in
+7ed
+7s
+5m
+6s
+5s
+5y
+6s
+4e
+5e
+6s
+5let
+8s
+5n
+6s
+5s
+5y
+6s
+4ha
+6s
+5ine
+8s
+4i
+5es
+5n
+6e
+7s
+6s
+5on
+7s
+5s
+4s
+4y
+3ther
+7ed
+8r
+9s
+7ing
+7s
+4i
+5s
+3va
+5s
+2s
+3aceous
+4ng
+6s
+4r
+5s
+3ca
+5del
+8le
+9es
+8s
+7t
+8s
+6in
+8e
+9s
+8s
+5e
+5rdine
+9es
+6ine
+9s
+8ic
+5t
+6el
+8s
+6oria
+9um
+6s
+5vado
+9s
+4id
+6s
+4le
+6bound
+6d
+6man
+7en
+6s
+5ier
+7st
+6ng
+8s
+5y
+4oid
+5logies
+8y
+5ne
+7s
+5se
+5vado
+9s
+6ite
+9s
+6y
+4ular
+8ities
+9ty
+8ly
+7tion
+9ons
+8ure
+9res
+6oskeletal
+7us
+3e
+4d
+4ful
+7ly
+4ological
+9es
+9st
+9sts
+8y
+4r
+5s
+4s
+4t
+5s
+5te
+7s
+4um
+6s
+3h
+4a
+4ed
+5r
+6s
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4mouth
+9s
+4room
+8ed
+9r
+9rs
+8ing
+8s
+4y
+3ic
+5al
+7e
+8s
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7ness
+9sses
+7s
+5ian
+8er
+9rs
+8ly
+8s
+9hip
+9hips
+5k
+6ed
+7r
+8s
+6ing
+6s
+5less
+5ological
+9ically
+9ies
+9ist
+9ists
+9y
+6therapies
+9rapy
+5s
+4mon
+7s
+4ng
+6ly
+6s
+4t
+5s
+4ve
+3jid
+6s
+3k
+4ed
+5g
+6s
+5llunge
+9ges
+5t
+6eer
+9s
+6oon
+9s
+6ries
+7y
+6s
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+5t
+6s
+4le
+6s
+4melon
+9s
+4one
+7s
+5x
+6en
+4rat
+7s
+5oot
+8s
+4s
+4y
+3lin
+6ed
+7t
+8s
+6s
+3mon
+6s
+3o
+4s
+3pike
+7s
+3quash
+8es
+5etoon
+9ns
+3rol
+6s
+3s
+4e
+5d
+5l
+6cracker
+9ckers
+6led
+6s
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+5tate
+9d
+9s
+8ing
+9on
+9ons
+4y
+3t
+4ache
+8d
+8s
+7io
+9ed
+9s
+5ng
+7s
+5rd
+7s
+7y
+4ed
+5e
+6s
+5lid
+8s
+7ne
+9s
+5r
+6ed
+7r
+8s
+6ing
+6s
+4h
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4s
+4y
+2t
+3abilities
+9y
+5le
+7ness
+9sses
+6y
+4gen
+7eses
+9is
+7ic
+9ally
+9ities
+9ity
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7s
+4nda
+6um
+5t
+6s
+4se
+6s
+4te
+6d
+6s
+5ing
+6on
+8al
+9lly
+8ist
+9sts
+8s
+6ve
+5ory
+3ch
+5ed
+6s
+5ing
+5kin
+8s
+3e
+4d
+5ly
+4ly
+4ness
+8es
+4r
+4s
+5sarif
+9fat
+9fats
+9fs
+5t
+3has
+3i
+4cate
+5ous
+4late
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+4ne
+6d
+6er
+8ed
+8ing
+8s
+6s
+5g
+5ied
+7s
+6ng
+5ous
+8ly
+8ness
+9esses
+5y
+6ing
+4s
+5m
+6s
+3on
+5s
+4scope
+9s
+3s
+3t
+4er
+6ation
+9ons
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+4on
+6bird
+9der
+9ders
+9ds
+6chops
+6fish
+9hes
+6head
+9ded
+9ds
+6s
+6y
+4s
+3ual
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+6ness
+9ses
+6s
+4ca
+6s
+4el
+6s
+4lar
+5e
+6s
+4um
+6s
+2umuu
+6s
+2x
+3ed
+4s
+3ing
+2zaky
+3hik
+6s
+3jik
+6s
+3z
+4ed
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4le
+6d
+6r
+7s
+6s
+5ing
+4y
+1vule
+5s
+1wah
+3limu
+7s
+1y
+2al
+4gia
+7s
+6c
+4ism
+7s
+6t
+7s
+4l
+5s
+3ses
+4is
+4thenia
+9as
+9c
+9cs
+2c
+3ele
+6s
+5ia
+7l
+7n
+6um
+5la
+7s
+5oid
+4tes
+5ologies
+9y
+6ma
+8s
+8ta
+9ous
+6phagous
+6zoan
+9ns
+3obacteria
+9rial
+9rium
+5iont
+9s
+4domatia
+9ium
+4flora
+9e
+9s
+4logic
+9al
+9ally
+8es
+8st
+9ts
+7y
+4phagies
+9st
+9sts
+8ous
+8y
+6ile
+9s
+5lasma
+9al
+9as
+9ata
+9oses
+9osis
+4rhiza
+9e
+9l
+9s
+5rhiza
+9ae
+9al
+9as
+4ses
+5is
+4tic
+5oxicoses
+9osis
+8n
+9s
+7ologies
+9ogy
+5rophic
+4virus
+9es
+3s
+2driases
+7is
+6tic
+9s
+2elencephala
+9halic
+9halon
+9halons
+4in
+6ated
+6e
+7s
+6ic
+6s
+5tides
+7s
+8es
+4oblast
+9tic
+9ts
+5cyte
+9s
+8ic
+5fibroses
+9osis
+9otic
+5genous
+6ram
+9s
+8phies
+9hy
+5id
+5ma
+7s
+7ta
+8oid
+9us
+5n
+6s
+5pathic
+9ies
+9y
+2gale
+6s
+2iases
+5is
+3ophilies
+8ous
+8y
+2lar
+5s
+3odon
+7s
+7t
+8s
+4hyoid
+9s
+4nite
+8s
+7ic
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+2na
+4h
+5s
+4s
+3heer
+7s
+2oblast
+8ic
+8s
+3cardia
+9l
+8ograph
+9graphs
+9pathy
+8tis
+9ises
+8um
+4lonic
+7us
+9es
+3electric
+9ical
+3fibril
+9lar
+9s
+5lament
+9nts
+3gen
+6ic
+6s
+4lobin
+9s
+4ram
+7s
+6ph
+8ic
+9cal
+9cally
+9es
+9st
+9sts
+8s
+8y
+3id
+4nositol
+9ols
+3logic
+8al
+7es
+7st
+9s
+6y
+3ma
+5ncies
+7y
+6tic
+5s
+5ta
+6ous
+4ectomies
+9y
+3neural
+3pathic
+8es
+7y
+4e
+5s
+4hilies
+7ous
+7y
+4ia
+6s
+5c
+6ally
+6s
+5es
+4s
+5es
+4y
+3scope
+8s
+4es
+4in
+6s
+5s
+5tis
+8es
+4ote
+7s
+6is
+8es
+4tatin
+9s
+3tic
+6s
+4ome
+7s
+5nia
+8s
+7c
+4ube
+7s
+2rbane
+7s
+3iad
+6fold
+9ds
+6s
+6th
+8s
+5pod
+8an
+8ous
+8s
+4ca
+6s
+4nga
+7s
+6itis
+9ses
+6oscope
+9opes
+7tomies
+9my
+4opod
+8s
+5rama
+9s
+5scope
+9es
+4stic
+8ivorous
+3mecochories
+9ory
+7id
+7logic
+9gical
+9gies
+9gist
+9gists
+9gy
+7phagous
+9ile
+9iles
+9ilies
+9ilous
+9ily
+4idon
+8es
+8ian
+8s
+3obalan
+9s
+3rh
+5ic
+6ne
+5ol
+7s
+5s
+3taceous
+4le
+6s
+2self
+3id
+5s
+3ophobia
+9as
+4st
+6s
+3pace
+7d
+7s
+6ing
+3tagog
+8ic
+9cal
+9cally
+9es
+8s
+8ue
+9es
+9s
+9ses
+8y
+4eries
+7ous
+9sly
+9sness
+6y
+4ic
+6al
+8ly
+8ness
+9esses
+6ete
+9s
+6ism
+9s
+6ly
+6s
+5fication
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+9gly
+5que
+8s
+2th
+4i
+5c
+6al
+8ly
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+5er
+6st
+5se
+7d
+7s
+6ing
+6m
+7s
+6t
+7s
+5ze
+7d
+7s
+6ing
+4maker
+9s
+7ing
+9gs
+4ogeneses
+9sis
+6rapher
+9hers
+9hies
+9hy
+5i
+5loger
+9rs
+8ian
+9ans
+9c
+9cal
+9cally
+9es
+9sation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9st
+9sts
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8y
+5mane
+9s
+8ia
+9ac
+9acs
+9as
+5peic
+6oeia
+9as
+9c
+9sm
+9sms
+9st
+9sts
+8ses
+9is
+8t
+9ic
+9ical
+9s
+5s
+4s
+4us
+4y
+3iliform
+5oid
+2xameba
+8e
+8s
+5oeba
+9e
+9s
+3edema
+8s
+8tous
+7ic
+3o
+4cyte
+8s
+4edema
+9s
+9tous
+8ic
+4id
+4ma
+6s
+6ta
+7oses
+9is
+9ises
+8us
+5ycete
+9es
+9ous
+4s
+4viral
+7us
+9es
+1zee
+4s
+2ungu
+6s
+0na
+2am
+4s
+3n
+4s
+3rtje
+7s
+6ie
+8s
+2b
+3bed
+5r
+6s
+4ing
+3e
+4s
+3is
+3k
+4s
+3la
+5s
+3ob
+5eries
+7y
+6ss
+8es
+5ish
+7m
+8s
+5s
+3s
+2carat
+7s
+3elle
+7s
+3h
+4as
+4e
+5s
+4o
+5s
+4tmaal
+9s
+3ket
+6s
+3re
+5d
+5ous
+5s
+4ite
+7s
+4ous
+2da
+4s
+3ir
+5al
+5s
+3ors
+3s
+2e
+3bodies
+6y
+3thing
+8s
+3ve
+5s
+4i
+4oid
+4us
+2ff
+4ed
+5r
+5st
+4ing
+4ly
+4ness
+8es
+4s
+2g
+3a
+4na
+6s
+4pie
+7s
+4ri
+6s
+4s
+3ged
+5r
+6s
+4ier
+6st
+5ng
+7ly
+7s
+4y
+3maal
+7s
+3or
+5s
+3s
+2h
+3al
+5s
+2iad
+5es
+5s
+4nt
+3f
+4er
+5st
+4ly
+4ness
+8es
+4s
+3k
+4s
+3l
+4biter
+9s
+5rush
+9es
+4ed
+5r
+6ies
+6s
+6y
+4file
+8s
+5old
+8s
+4head
+8s
+4ing
+7s
+4less
+4s
+5et
+7s
+3n
+4sell
+8s
+5ook
+8s
+3ra
+5s
+4u
+5s
+3ssance
+9s
+7t
+3ve
+5ly
+5ness
+9es
+5r
+5s
+6t
+5te
+7s
+6ies
+6y
+4ist
+2ked
+5er
+6st
+5ly
+5ness
+9es
+4r
+5s
+3fa
+5s
+2la
+4s
+3buphine
+9es
+3ed
+5s
+3idixic
+3la
+5h
+6s
+5s
+3orphine
+9es
+4xone
+8s
+3trexone
+9es
+2m
+3able
+4skar
+8s
+5te
+7s
+4ycush
+9es
+3e
+4able
+4check
+9ed
+9ing
+9s
+4d
+4less
+8ly
+8ness
+9esses
+5y
+4plate
+9s
+4r
+5s
+4s
+5ake
+8s
+4tag
+7s
+6pe
+8s
+4worthy
+3ing
+6s
+3ma
+3s
+3u
+4s
+2n
+3a
+4s
+3ce
+5s
+4ies
+5fied
+4y
+3din
+6a
+7s
+6e
+7s
+6s
+4oo
+6s
+4rolone
+9es
+4u
+5s
+3e
+3g
+3isation
+9ns
+5m
+6s
+4te
+6s
+4zation
+9ns
+3keen
+7s
+4in
+6s
+3na
+5s
+4ie
+6d
+6s
+4oplankton
+9ktons
+4y
+5gai
+8s
+5ing
+6sh
+3obe
+6s
+5ot
+7s
+4dot
+7s
+4gram
+8me
+9es
+8s
+4material
+9ials
+5eter
+9s
+7re
+9s
+4ok
+6s
+4particle
+9cles
+5hysics
+5lankton
+9tons
+5ore
+8s
+5ublishing
+9shings
+4scale
+5econd
+9ds
+4tech
+8nology
+8s
+6sla
+9s
+5ube
+8s
+4watt
+8s
+5ire
+8s
+5orld
+9s
+3s
+3ua
+5s
+2oi
+3s
+4es
+2p
+3a
+4lm
+6ed
+6ing
+6s
+4s
+3e
+4d
+4ries
+5y
+4s
+3htha
+7lene
+9nes
+8ic
+9n
+9ne
+9nes
+9ns
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+7s
+6ene
+9s
+8ic
+6ol
+8s
+7us
+6yl
+8amine
+9mines
+8s
+5ol
+7s
+3iform
+4ng
+3kin
+6s
+3less
+3oleon
+8ite
+9tes
+8s
+4o
+5ed
+5ing
+5s
+3pa
+5s
+4e
+5d
+5r
+6s
+5s
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+4y
+3rapathies
+9y
+4on
+6s
+5xen
+8s
+3s
+2ras
+5es
+3c
+4een
+7s
+5in
+7e
+8s
+7s
+4ism
+7s
+6si
+8sm
+9ms
+9t
+9tic
+9ts
+7us
+9es
+6t
+7ic
+7s
+4o
+5analyses
+9ysis
+5catharses
+9arsis
+5hypnoses
+9osis
+5lepsies
+9y
+8tic
+9ics
+5ma
+7s
+7ta
+5s
+6e
+7s
+6is
+6yntheses
+9hesis
+5terrorism
+9orisms
+9orist
+9orists
+6ic
+8ally
+8s
+7ne
+9s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+4s
+3d
+4ed
+4ine
+6g
+4oo
+6s
+4s
+3e
+4s
+3ghile
+8s
+7ies
+7lies
+8y
+7y
+4ile
+7h
+8s
+7s
+6ies
+6y
+4uileh
+9s
+3ial
+4c
+5orn
+8s
+4ne
+4s
+3k
+4ed
+4ier
+6st
+5ng
+4s
+4y
+3quois
+3ras
+6es
+5table
+6e
+7d
+7r
+8s
+7s
+6ing
+7on
+9al
+9s
+7ve
+9ly
+9s
+6ological
+9gies
+9gist
+9gists
+9gy
+7r
+8s
+8y
+4e
+4ow
+6band
+9ds
+6cast
+9ted
+9ting
+9tings
+9ts
+6ed
+7r
+7st
+6ing
+9s
+7sh
+6ly
+6ness
+9ses
+6s
+3thex
+7es
+4jie
+7s
+3wal
+6s
+4hal
+7e
+8s
+7s
+3y
+2s
+3al
+5isation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8s
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ly
+5s
+4rd
+6s
+3cence
+8s
+7ies
+7y
+6t
+3eberries
+8y
+3hgab
+7s
+4i
+5s
+3ial
+4on
+6s
+3ofrontal
+4gastric
+4lacrymal
+4pharyngeal
+9nges
+9nx
+9nxes
+3sella
+3talik
+8s
+4ic
+5er
+6s
+7t
+5ly
+5ness
+9es
+4urtium
+9ms
+4y
+3ute
+6s
+2t
+3al
+5itial
+8es
+7y
+4nt
+6ly
+4tion
+8al
+8s
+5oria
+9l
+8um
+9ms
+7y
+3ch
+5es
+3es
+3heless
+9e
+5mo
+7re
+4less
+3iform
+4on
+6al
+8isation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9sm
+9sms
+9st
+9stic
+9sts
+9ties
+9ty
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8ly
+8s
+6hood
+9ds
+6less
+6s
+6wide
+4s
+4ve
+6ly
+6ness
+9ses
+6s
+5ism
+8s
+7t
+8ic
+8s
+6ties
+7y
+3rium
+7s
+6reses
+9is
+8tic
+9ics
+4olite
+9s
+5n
+6s
+3s
+3ter
+6ed
+7r
+8s
+6ing
+6jack
+9ks
+6s
+6y
+4ier
+6st
+5ly
+5ness
+9es
+4y
+3ura
+6e
+6l
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7ness
+9sses
+7s
+5e
+6d
+6s
+5ing
+6sm
+8s
+7t
+8ic
+8s
+5opath
+9hic
+9hies
+9hs
+9hy
+2uch
+5es
+3gahyde
+9s
+4ht
+6ier
+8s
+9t
+7ly
+7ness
+9sses
+6s
+6y
+3machia
+9e
+9s
+8es
+7y
+3nt
+5s
+3plial
+6i
+7form
+6oid
+6us
+3sea
+6nt
+8s
+6s
+6te
+8d
+8s
+7ing
+9gly
+8on
+9ns
+8ve
+5ous
+8ly
+8ness
+9esses
+3tch
+6es
+4ic
+6al
+8ly
+6s
+5li
+6oid
+9s
+6us
+8es
+2vaid
+6s
+4l
+5ism
+8s
+5ly
+4r
+5ch
+7ies
+7s
+7y
+5ho
+7s
+5in
+7s
+5s
+3e
+4l
+5s
+5wort
+9s
+4s
+4tte
+7s
+4w
+5s
+3icert
+8s
+5ula
+8r
+9e
+9es
+9s
+8s
+4es
+4gabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6te
+8d
+8s
+7ing
+8on
+9nal
+9nally
+9ns
+7or
+9s
+3vied
+6s
+4y
+5ing
+3y
+2w
+3ab
+5s
+2y
+3s
+4aid
+5y
+6er
+8s
+6ing
+9s
+6s
+3thles
+3ward
+7s
+4ord
+7s
+2ze
+4s
+3ir
+5s
+4s
+1e
+2afe
+5s
+4fe
+6s
+3l
+4ed
+4ing
+4s
+3ndertal
+9ler
+9lers
+9ls
+8hal
+9aler
+9alers
+9aloid
+9als
+4ic
+3p
+4ed
+4ing
+4olitan
+9ns
+4s
+3r
+4by
+4ed
+5r
+5st
+4ing
+4lier
+7st
+5y
+4ness
+8es
+4s
+5hore
+5ide
+8s
+6ghted
+9edly
+9edness
+4throses
+9is
+3t
+4en
+6ed
+6ing
+6s
+5r
+5st
+4h
+5erd
+8s
+4ly
+4ness
+8es
+5ik
+7s
+4s
+2b
+3bed
+4ich
+7s
+5ng
+5sh
+7e
+8r
+9s
+8s
+7y
+4uk
+6s
+3eck
+6s
+4k
+5s
+4l
+5s
+4nkern
+9s
+3ish
+6es
+3ris
+6es
+3s
+3uchadnezzar
+9ezzars
+4la
+6e
+6r
+6s
+5e
+6s
+5isation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+6um
+8s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5ose
+7ities
+9y
+6us
+8ly
+8ness
+9esses
+5y
+2cessaire
+9es
+7rian
+9anism
+9anisms
+9ans
+9es
+9ly
+9ness
+9nesses
+8y
+6itarian
+9rians
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+8ied
+9es
+8ous
+9usly
+9usness
+8y
+3k
+4atee
+8s
+4band
+8s
+5eef
+8s
+4cloth
+9s
+4ed
+5r
+6chief
+9efs
+9eves
+6s
+4gear
+8s
+4ing
+7s
+4lace
+8d
+8s
+7ing
+9gs
+5ess
+6t
+7s
+5ike
+6ne
+8s
+4piece
+9s
+4s
+4tie
+7s
+4verse
+9s
+4wear
+8s
+6ed
+8s
+3robioses
+9is
+8tic
+5grapher
+9hers
+5later
+9rs
+8ries
+9y
+6ogic
+9cal
+9es
+9st
+9sts
+8y
+5mancer
+9ers
+9ies
+9y
+8ia
+9ac
+9acs
+9as
+8tic
+9ical
+9ically
+5phagous
+7il
+9e
+9es
+9ia
+9iac
+9iacs
+9ias
+9ic
+9ies
+9ism
+9isms
+9ous
+9s
+9y
+7obe
+9es
+9ia
+9ias
+9ic
+8rous
+6oleis
+9s
+8i
+9s
+9ses
+6sied
+9s
+7y
+8ing
+5scopic
+9ical
+9ies
+9y
+6e
+7d
+7s
+6ing
+7s
+5tic
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6omies
+8y
+6roph
+9hic
+9hs
+3tar
+6eal
+8n
+7d
+7ous
+9sness
+6ial
+7ed
+8s
+7ferous
+7ne
+9s
+7vorous
+6ous
+6s
+6y
+4ocalyces
+9x
+2d
+3dier
+6s
+7t
+5sh
+4y
+3ette
+7s
+3s
+2e
+3d
+4cessities
+9ty
+4ed
+5r
+6s
+4fire
+8s
+5ul
+7ly
+7ness
+9sses
+7s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4le
+6cord
+9ds
+7raft
+9fts
+6d
+6fish
+9hes
+7ul
+9s
+6like
+6point
+9nts
+6r
+7s
+6s
+7s
+8ly
+8ness
+9esses
+7tick
+6woman
+9en
+8rk
+9ker
+9kers
+9ks
+5ier
+7st
+6ng
+8s
+5y
+4ment
+8s
+4s
+4y
+3ld
+5s
+4e
+5s
+3m
+4b
+5s
+4s
+3p
+4s
+3sberries
+8y
+4e
+5d
+5s
+4ing
+3ze
+5d
+5s
+4ing
+2f
+3andous
+4rious
+9ly
+9ness
+9nesses
+4st
+3s
+2g
+3ate
+6d
+6r
+7s
+6s
+5ing
+6on
+8al
+8ist
+9sts
+8s
+6ve
+8d
+8ly
+8ness
+9esses
+8s
+7ing
+8sm
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+5on
+7s
+6r
+7s
+7y
+5ron
+8s
+3lect
+7able
+7ed
+9ness
+9nesses
+8r
+9s
+7ful
+9lly
+9lness
+7ing
+9gly
+8on
+9ns
+8ve
+7or
+9s
+7s
+4ige
+7able
+7e
+8s
+7nce
+9es
+8t
+9ly
+7s
+6ibilities
+9lity
+8le
+9eness
+9y
+3ociant
+9s
+4tiabilities
+9lity
+8le
+7nt
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+9ry
+8ress
+9esses
+9ices
+9ix
+9ixes
+3ress
+7es
+4itude
+9s
+4oism
+8s
+5ni
+7s
+3s
+3us
+5es
+2if
+4s
+3gh
+5bor
+8ed
+8hood
+9oods
+8ing
+8less
+9iness
+9y
+8s
+7ur
+9ed
+9hood
+9hoods
+9ing
+9less
+9liness
+9ly
+9s
+5ed
+5ing
+5s
+3nei
+6s
+3st
+3ther
+3ve
+5s
+2k
+3s
+3ton
+6ic
+6s
+2lies
+4s
+3lie
+6s
+4y
+3son
+6s
+3umbium
+9s
+6o
+7s
+2ma
+4s
+4thelminth
+9inthic
+9inths
+5ic
+7idal
+9e
+9es
+5oblast
+9sts
+6cidal
+9e
+9es
+7yst
+9tic
+9ts
+6de
+8s
+7iriases
+9iasis
+9us
+9uses
+6id
+6logical
+9ies
+9ist
+9ists
+9y
+6phore
+9res
+3ertean
+9s
+6ian
+9s
+7ne
+9s
+4ses
+5ia
+7s
+6s
+3n
+4ed
+4ing
+4s
+3ophila
+9s
+4ral
+5ous
+3pt
+2ne
+4s
+3nigai
+8s
+3uphar
+8s
+2oanthropic
+4rsphenamine
+3blast
+8s
+3classic
+9cal
+9cism
+9cisms
+9cist
+9cists
+4olonial
+9alism
+9alisms
+9alist
+9alists
+5n
+6s
+7ervatism
+9vative
+5rtex
+9es
+7ical
+9es
+3dymium
+9s
+3gene
+7ses
+8is
+7tic
+4othic
+9s
+4rammarian
+9rians
+3liberal
+9lism
+9lisms
+9ls
+5th
+7ic
+7s
+4ogian
+9s
+7c
+8al
+9lly
+7es
+7se
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ical
+9ically
+9s
+7ze
+9d
+9s
+8ing
+6y
+3morph
+8s
+4ycin
+8s
+3n
+4atal
+8ly
+6e
+7s
+6icide
+9des
+6ologies
+9gist
+9gists
+9gy
+4ed
+4omian
+9ism
+9isms
+9s
+4s
+3orthodox
+9oxies
+9oxy
+3pagan
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+8s
+4hile
+8s
+7ia
+9c
+9cs
+9s
+5obe
+8s
+7ia
+9s
+8c
+5yte
+8s
+7ic
+4ilina
+9s
+4lasia
+9s
+7m
+8s
+7tic
+9cism
+9cisms
+9cist
+9cists
+9es
+8y
+4rene
+8s
+3realism
+9ms
+9t
+9tic
+9ts
+3soul
+7s
+4tigmine
+9nes
+3teinia
+9s
+5nic
+7es
+6ous
+6y
+5ric
+8al
+9lly
+9ls
+8s
+7se
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7ze
+9d
+9s
+8ing
+4oxin
+8s
+4ropic
+9s
+4ype
+7s
+3vitalism
+9sms
+9st
+9sts
+2p
+3enthe
+8an
+8s
+4r
+5s
+4ta
+6s
+3halism
+9s
+8t
+9s
+4eline
+9s
+8ic
+9te
+9tes
+9tic
+7te
+9s
+6ometer
+9ters
+9tric
+9tries
+9try
+5w
+6s
+4ogram
+9s
+8ph
+9hs
+5logic
+9cal
+9es
+9st
+9sts
+8y
+5scope
+9es
+4ralgia
+9as
+9c
+9es
+8y
+5ectomies
+9mise
+9mised
+9mises
+9mising
+9mize
+9mized
+9mizes
+9mizing
+9my
+5ic
+6dia
+9l
+8um
+6sm
+8s
+6te
+8s
+7ic
+9al
+9s
+8des
+8s
+9es
+5oblastoma
+9stomas
+6id
+6lepis
+9ises
+7ogical
+9ies
+9ist
+9ists
+9y
+6n
+7s
+6pathic
+9hies
+9hy
+7exies
+9y
+7toses
+9sis
+6scope
+9pes
+9pies
+9py
+7es
+7is
+7tome
+9mes
+6tic
+9s
+7omies
+9y
+8xic
+9icity
+3ionic
+4t
+5s
+3otic
+6sm
+8s
+7t
+8ic
+8s
+3s
+3tunium
+9s
+2ral
+5s
+3d
+4ic
+6s
+5er
+6st
+5ness
+9es
+5sh
+4s
+4y
+3eid
+6es
+6s
+5s
+3ine
+6s
+4te
+6s
+5ic
+3k
+4a
+5s
+4s
+3ol
+5i
+6s
+5s
+3ts
+4z
+3val
+5te
+6ion
+9s
+6ure
+9s
+4e
+5d
+5less
+9ly
+9ness
+9nesses
+7t
+8s
+5r
+6s
+5s
+4ier
+6st
+5ly
+5ne
+7s
+8s
+9es
+6g
+7s
+4osities
+8y
+5us
+7ly
+7ness
+9sses
+4ular
+6e
+7s
+5ration
+9ons
+6e
+7s
+4y
+2science
+9s
+7t
+8s
+3h
+4er
+5st
+4ness
+8es
+3s
+4elrode
+9es
+5s
+3t
+4able
+4ed
+5r
+6s
+4ful
+7s
+4ing
+7s
+4le
+6d
+6r
+7s
+6s
+5ike
+6ng
+8s
+4or
+6s
+4s
+2t
+3ball
+7er
+9s
+7s
+3e
+4s
+3ful
+6s
+3head
+7s
+5less
+5r
+6lings
+6more
+8st
+6stock
+9cks
+6ward
+9ds
+7orld
+9lds
+3iquette
+9es
+4zen
+7s
+3less
+4ike
+3minder
+9s
+3op
+5s
+3root
+7s
+3s
+4peak
+8s
+4uke
+7s
+3t
+4able
+4ed
+5r
+6s
+4ie
+6r
+6s
+7t
+5ng
+7s
+4le
+6d
+6like
+6r
+7s
+6s
+7ome
+5ier
+7st
+6ng
+5y
+4s
+4y
+3work
+7ed
+8r
+9s
+7ing
+9gs
+7s
+2uk
+4s
+3m
+4atic
+4e
+5s
+4ic
+4s
+3ral
+6gia
+9s
+8c
+6ly
+5minidase
+9dases
+5sthenia
+9niac
+9niacs
+9nias
+9nic
+9nics
+5tion
+9s
+5xon
+8s
+4ectomies
+9y
+4ilemma
+9al
+9as
+6ities
+8y
+5ne
+7s
+5sm
+7s
+5te
+7s
+6ic
+8s
+7des
+7s
+8es
+4oactive
+6natomic
+9omical
+9omies
+9omist
+9omists
+9omy
+5biological
+9ogies
+9ogist
+9ogists
+9ogy
+6last
+9toma
+9tomas
+9tomata
+9ts
+5chemical
+9icals
+9ist
+9istry
+9ists
+7ip
+9s
+6oel
+9e
+9es
+9s
+7gnitive
+7mputer
+9uters
+9uting
+9utings
+5ectodermal
+6ndocrine
+6thologies
+9logy
+5feedback
+9backs
+6ibril
+9ilar
+9illar
+9illary
+9ils
+9oma
+9omas
+9omata
+5geneses
+9sis
+8ic
+9cally
+6lia
+9l
+9s
+6ram
+9s
+5hormonal
+9one
+9ones
+6umor
+9ral
+9rs
+6ypnology
+8ophyses
+9physis
+5id
+5lemma
+9as
+7ptic
+9ics
+6inguist
+9uistic
+9uists
+6ogic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+6yses
+8is
+5ma
+7rketing
+9etings
+7s
+8t
+9s
+7ta
+8ous
+6uscular
+5n
+6al
+6e
+7s
+6ic
+6s
+5path
+9ic
+9ical
+9ically
+9ies
+9ist
+9ists
+9ologic
+9ology
+9s
+9y
+6eptide
+9ides
+6hysiology
+6il
+8s
+6lasm
+9ms
+6sychiatry
+9hology
+6tera
+9an
+9ans
+9ist
+9ists
+9on
+9ous
+5radiology
+5sal
+6cience
+9nces
+9ntific
+9ntist
+9ntists
+6ecretion
+9etions
+9etory
+7nsory
+7s
+6is
+6pora
+9as
+6urgeon
+9eons
+9eries
+9ery
+9ical
+9ically
+6yphilis
+9ilises
+5tic
+8ally
+8ism
+9sms
+8s
+6omies
+9st
+9sts
+8y
+7xic
+9cities
+9city
+9n
+9ns
+6rophic
+9hies
+9hy
+9ic
+5vascular
+4ula
+7e
+7r
+7s
+7tion
+9ons
+4ypnologies
+9ogy
+3stic
+5on
+7ic
+7s
+3ter
+6ed
+6ing
+6s
+4ral
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7ly
+7ness
+9sses
+7s
+5etto
+9s
+5ino
+8less
+8s
+5on
+7ic
+7s
+6penia
+9ias
+7hil
+9le
+9les
+9lic
+9ls
+2ve
+4l
+5led
+6ing
+5s
+4r
+5mind
+9s
+6ore
+5theless
+8more
+4s
+3i
+3oid
+3us
+2w
+3bie
+6s
+4orn
+7s
+3come
+7r
+8s
+3ed
+4l
+5l
+6ed
+6s
+5s
+4r
+4st
+3fangle
+9d
+9dly
+9dness
+9ness
+9nesses
+4ound
+3ie
+5s
+4ng
+4sh
+6ly
+6ness
+9ses
+3ly
+5wed
+8s
+3market
+9s
+4own
+3ness
+7es
+3s
+4agencies
+9y
+8t
+9s
+4beat
+8s
+5oy
+7s
+5reak
+9s
+4cast
+8er
+9rs
+8ing
+9ngs
+8s
+4dealer
+9rs
+6sk
+8s
+4ed
+5s
+4flash
+9es
+4girl
+8s
+5roup
+9s
+4hawk
+8s
+5ound
+9s
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+4less
+6tter
+9rs
+4magazine
+9ines
+6ker
+9s
+6n
+5en
+5onger
+9rs
+4paper
+9dom
+9doms
+9ed
+9ing
+9ism
+9isms
+9man
+9men
+9s
+9woman
+9women
+5eak
+8s
+6ople
+6rson
+9ns
+5rint
+9s
+4reader
+9rs
+6el
+8s
+5oom
+8s
+4stand
+9s
+4trade
+9s
+4weeklies
+9y
+5ire
+8s
+5oman
+7en
+6rthiness
+9y
+5riting
+9ngs
+4y
+3t
+4on
+6s
+4s
+3waver
+8s
+2xt
+4door
+4ly
+4ness
+8es
+4s
+3us
+5es
+1gai
+4o
+5s
+3na
+5s
+3rara
+7s
+3ti
+5s
+2oma
+5s
+2ultrum
+8s
+2wee
+1handu
+6s
+1iacin
+6amide
+9des
+6s
+3iserie
+9s
+3lamide
+9s
+2b
+3bed
+4ing
+4le
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+3lick
+7s
+5ke
+3s
+2cad
+5s
+3colite
+9s
+3e
+4ish
+4ly
+4ness
+8es
+4r
+4st
+4ties
+5y
+3he
+5d
+5r
+6ed
+6ing
+6s
+5s
+4ing
+4t
+5s
+3ish
+3k
+4ar
+6s
+4ed
+5l
+6ed
+6ic
+7ferous
+7ne
+9s
+8g
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6led
+7ing
+6odeon
+9ons
+7us
+6s
+5r
+6ed
+6ing
+6s
+4ing
+4le
+6d
+6s
+5ing
+4nack
+8s
+6me
+8d
+8r
+9s
+8s
+7ing
+4point
+9s
+4s
+5tick
+9s
+4um
+6poop
+9ps
+6s
+3oise
+4l
+5s
+4mpoop
+9s
+4tian
+8a
+9s
+8s
+6n
+7amide
+9ides
+7e
+8d
+8s
+7ic
+8sm
+9ms
+7s
+3rosilal
+9ls
+3tate
+7d
+7s
+6ing
+7on
+9s
+4itant
+7te
+9d
+9s
+8ing
+9on
+9ons
+2d
+3al
+4menta
+9l
+8um
+4te
+6d
+6s
+5ing
+6on
+8s
+3dering
+9s
+6ling
+9gs
+4ick
+7s
+3e
+4d
+4ring
+8s
+5ling
+9s
+4s
+3get
+6s
+3i
+4colous
+4ficate
+9ed
+9es
+9ing
+9ion
+9ions
+6ed
+7s
+5ugous
+5y
+6ing
+4ng
+6s
+3or
+5ous
+5s
+3s
+3ulation
+9ns
+4s
+5es
+2e
+3ce
+5s
+3d
+3f
+4s
+3llated
+5i
+6st
+8s
+5o
+6ed
+6ing
+6s
+3s
+3ve
+5ful
+8s
+5s
+2fe
+4dipine
+9es
+4s
+3f
+4ed
+5r
+6ed
+6ing
+6s
+4ier
+6st
+5ng
+4naff
+8ed
+8ing
+8s
+4s
+4y
+3tier
+6s
+7t
+5ly
+5ness
+9es
+4y
+2gella
+7s
+4r
+5s
+3gle
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8ly
+8s
+5y
+3h
+4ed
+5r
+5st
+4ing
+4ly
+4ness
+8es
+4s
+4t
+5bird
+9s
+6lind
+5cap
+8s
+6lass
+9ses
+7othes
+7ub
+9bed
+9ber
+9bers
+9bing
+9bings
+9s
+5dress
+9ses
+5ed
+5fall
+9s
+7ring
+6ire
+9s
+5gear
+9s
+6low
+9s
+6own
+9s
+5hawk
+9s
+5ie
+7s
+6ngale
+9les
+5jar
+8s
+5less
+6ife
+9s
+7ke
+7ves
+6ong
+6y
+5mare
+9s
+8ish
+9shly
+9shness
+8y
+5piece
+9es
+5rider
+9rs
+8ing
+9ngs
+5s
+6cope
+9es
+6hade
+9es
+7irt
+9ts
+6ide
+9s
+6pot
+9s
+6tand
+9ds
+7ick
+9ks
+5tide
+9s
+7me
+9s
+5walker
+9ers
+7rd
+6ear
+9s
+5y
+3iri
+6s
+3rescence
+9ces
+9t
+4icant
+5fied
+8s
+6y
+7ing
+5tude
+9s
+4omancies
+9y
+5sin
+8e
+9s
+8s
+2hil
+5ism
+8s
+7t
+8ic
+8s
+6ties
+7y
+5s
+3onga
+7s
+2kab
+5s
+4h
+5s
+4u
+5s
+3ethamide
+9des
+2l
+3gai
+6s
+5u
+6s
+4hai
+7s
+6u
+7s
+3l
+4ed
+4ing
+4s
+3potent
+9s
+3s
+2m
+3b
+4ed
+4i
+4le
+6ness
+9ses
+6r
+6sse
+9s
+7t
+6wit
+9s
+9ted
+5y
+4ostrati
+9tus
+4s
+4us
+6ed
+7s
+4yism
+8s
+5ness
+9es
+3ieties
+6y
+4ous
+3med
+5r
+6s
+4ing
+3onic
+3ps
+3rod
+6s
+3s
+2ncom
+6poop
+9peries
+9pery
+9ps
+6s
+4um
+6s
+3e
+4bark
+8s
+4fold
+4holes
+4pence
+9s
+7nies
+8y
+5in
+7s
+4s
+5core
+9s
+4teen
+8s
+8th
+9hly
+9hs
+5ies
+7th
+9s
+5y
+3hydrin
+9s
+3ja
+5s
+4itsu
+8s
+4utsu
+8s
+3nies
+4y
+5hammer
+9ers
+5ish
+3on
+5s
+3th
+5ly
+5s
+2obate
+7s
+4ic
+5te
+7s
+5um
+7s
+4ous
+2p
+3a
+4s
+3cheese
+9s
+3ped
+5r
+6ed
+6ing
+6kin
+9s
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7ly
+4lewort
+9ts
+5ing
+4y
+3s
+3ter
+6s
+2qab
+5s
+2ramiai
+8s
+3l
+4ed
+4ie
+6r
+6st
+5ng
+5t
+4s
+4y
+3vana
+7s
+6ic
+2s
+3berries
+7y
+3ei
+5s
+3gul
+6s
+3h
+4es
+3i
+3se
+5s
+3us
+2t
+3chie
+7s
+3e
+4r
+5ie
+7s
+5s
+5y
+4s
+3her
+6ed
+6ing
+6s
+4ing
+7s
+3id
+4nol
+7s
+3on
+5s
+3pick
+7ed
+8r
+9s
+7ier
+9st
+8ng
+7s
+7y
+3ramine
+9s
+5niline
+9nes
+5te
+7d
+7s
+6ine
+9s
+8g
+7on
+9s
+6or
+8s
+5zepam
+9ms
+4e
+5s
+4ic
+5d
+6e
+7d
+7s
+6ing
+9s
+6s
+5fiable
+7cation
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5l
+6e
+7s
+6s
+5te
+7s
+4o
+5bacteria
+9erium
+6enzene
+9enes
+5cellulose
+9uloses
+6hloroform
+6otton
+9ons
+5furan
+9ns
+5gen
+8ase
+9ses
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8ous
+8s
+6lycerin
+9erine
+9erines
+9erins
+5lic
+5meter
+9rs
+8hane
+9anes
+8ric
+5paraffin
+9ffins
+6hilous
+5s
+6amine
+9nes
+7tion
+9ons
+6o
+6yl
+8s
+5toluene
+9enes
+5us
+5x
+6es
+6yl
+8s
+4y
+5l
+6s
+3s
+3tier
+6st
+4y
+3wit
+6s
+6ted
+9ness
+9nesses
+8ries
+9y
+2val
+4tion
+8s
+3eous
+2x
+3e
+4d
+4r
+5s
+4s
+3ie
+5s
+4ng
+3y
+2zam
+5ate
+8s
+5s
+1kosi
+5s
+1o
+2ah
+4s
+2bbier
+6st
+5ly
+5ness
+9es
+4le
+6d
+6r
+7s
+6s
+5ing
+4ut
+4y
+3elium
+8s
+3ilesse
+9s
+5iary
+6tate
+9ed
+9es
+9ing
+9ion
+9ions
+7ies
+7y
+3le
+5man
+6en
+5ness
+9es
+5r
+5s
+6se
+8s
+6t
+5woman
+8en
+4y
+3odies
+5y
+3s
+2cake
+6s
+3ent
+6ly
+6s
+3hel
+6ed
+6ing
+6led
+7ing
+6s
+3iceptive
+8or
+9rs
+4receptor
+9tors
+3k
+4ed
+5t
+6s
+4ing
+4s
+3tambulation
+9ations
+9ism
+9isms
+9ist
+9ists
+4ilio
+8s
+6uca
+9e
+9s
+8ence
+9nces
+9nt
+8ous
+5vagant
+9tion
+9tions
+8ous
+4ua
+6ries
+7y
+6s
+5id
+7s
+5le
+7s
+5oid
+5ria
+8s
+6n
+7al
+9ities
+9ity
+9ly
+9s
+7e
+8s
+7s
+3uous
+7ly
+7ness
+9sses
+2d
+3al
+5ise
+8d
+8s
+7ing
+6ties
+7y
+6ze
+8d
+8s
+7ing
+5ly
+4ted
+5ion
+8s
+3ded
+5r
+6s
+4ier
+6s
+7t
+5ng
+7ly
+7s
+4le
+6d
+6s
+5ing
+4y
+3e
+4s
+3i
+4cal
+3ose
+5ities
+7y
+4us
+3s
+3ular
+6ted
+7ion
+9ns
+5e
+6d
+6s
+5ose
+6us
+4s
+2el
+4s
+3matical
+9lly
+3s
+4es
+4is
+6es
+3tic
+2g
+3aku
+3g
+4ed
+4in
+6g
+7s
+6s
+4s
+3s
+2h
+3ow
+5ish
+2il
+4ier
+6st
+4s
+4y
+3nt
+5ed
+6r
+7s
+5ing
+5s
+3r
+4ish
+4s
+3se
+5d
+5ful
+5less
+9ly
+9ness
+9nesses
+5maker
+9rs
+8ing
+9ngs
+5nik
+8s
+5s
+5tte
+8s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4ome
+7ly
+7ness
+9sses
+4y
+2le
+4s
+3ition
+8s
+3l
+4s
+3o
+4s
+2m
+3a
+4d
+5e
+6s
+5ic
+7ally
+6es
+6sation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5s
+5y
+4rch
+7ies
+7s
+7y
+4s
+3bles
+4ril
+7s
+3e
+4n
+5clative
+9or
+9orial
+9ors
+9ural
+9ure
+9ures
+5klatura
+9uras
+4s
+3ic
+4na
+6ble
+6l
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7s
+6te
+8d
+8ly
+8s
+7ing
+8on
+9ns
+8val
+9ally
+9e
+9ely
+9es
+7or
+9s
+5ee
+7s
+4sm
+6s
+5tic
+3ocracies
+8y
+4genies
+7y
+5ram
+8s
+7ph
+9er
+9ers
+9ic
+9ical
+9ically
+9ies
+9s
+9y
+4i
+4logic
+9al
+9ally
+8es
+8st
+9ts
+7y
+4s
+4thete
+9s
+8ic
+9cal
+3s
+2n
+3a
+4brasive
+5sorbable
+9ent
+9ents
+8ptive
+6tract
+4cademic
+9ics
+5ceptance
+9ances
+6idental
+6ountable
+6redited
+7ual
+5hievement
+9ements
+5id
+7ic
+7s
+5quisitive
+5ting
+7on
+9s
+7vated
+8e
+6or
+8s
+4daptive
+5dict
+9ive
+9s
+7tive
+9vities
+9vity
+5hesive
+5iabatic
+5jacent
+5mirer
+9rs
+7ssion
+9ions
+5ult
+8s
+4esthetic
+4ffiliated
+6luent
+4ge
+6d
+6narian
+9ians
+6s
+7imal
+9als
+5gression
+9sions
+9sive
+5on
+7al
+7s
+5ricultural
+4lcoholic
+9lics
+5igned
+8ment
+9ents
+5lelic
+7rgenic
+9ic
+5phabetic
+5uminum
+4mbiguous
+4nalytic
+6tomic
+5e
+6s
+5imal
+5oic
+5swer
+9s
+5tagonistic
+6ibiotic
+9otics
+7genic
+4ppearance
+9ances
+4quatic
+6eous
+4rable
+5bitrary
+5chitect
+9ects
+9ecture
+5gument
+9nts
+5istocratic
+5omatic
+9ics
+5t
+6ist
+9ic
+9s
+6s
+5y
+4s
+5cetic
+9cs
+5pirin
+9ns
+5sertive
+6ociated
+5tronomical
+4thlete
+9es
+9ic
+5omic
+5tached
+9ment
+9ments
+6endance
+9ances
+9er
+9ers
+4uditory
+5thor
+9s
+6omated
+9tic
+8otive
+7nomous
+4vailability
+3bacterial
+5nk
+7ing
+7s
+5rbiturate
+9urates
+5sic
+4earing
+5havioral
+5ing
+8s
+5lief
+9s
+8ver
+9ers
+6ligerency
+9erent
+9erents
+5tting
+4inary
+6ding
+5ographical
+6logical
+9ically
+9ist
+9ists
+5ting
+4lack
+8s
+4odies
+6y
+5nded
+7ing
+5ok
+7s
+5tanist
+9sts
+4rand
+5eakable
+7thing
+6eder
+9rs
+8ing
+9ngs
+5oadcast
+9asts
+4uilding
+9ngs
+5rnable
+5siness
+5ying
+3cabinet
+9ts
+5king
+5llable
+6oric
+5mpus
+5ncelable
+8rous
+6didacies
+9acy
+9ate
+9ates
+5pital
+9list
+9lists
+9ls
+5rcinogen
+9ogenic
+9ogens
+6diac
+6eer
+6rier
+9rs
+5sh
+6ual
+5usal
+4e
+5lebration
+9ations
+9ities
+9ity
+6lular
+9osic
+5ntral
+5real
+6tificated
+9ied
+5s
+4halance
+9ces
+9t
+9tly
+6racter
+9ters
+7ismatic
+9matics
+6uvinist
+9nists
+5emical
+9als
+5romosomal
+5urch
+9goer
+9goers
+4ircular
+9ating
+5tizen
+9ns
+4landestine
+6ss
+8es
+8ical
+9fied
+8room
+9ooms
+5erical
+9als
+5ing
+7ical
+5ogging
+4oding
+5ercive
+5gnitive
+9ivism
+9ivisms
+5herent
+5incidence
+9dences
+6tal
+5king
+5la
+7s
+6lector
+9tors
+8ge
+9es
+9iate
+7inear
+6or
+8ed
+8fast
+8s
+5m
+6bat
+9ant
+9ants
+9ive
+7ustible
+9tibles
+6mercial
+9cials
+7issioned
+8tment
+9ments
+9tal
+9tally
+9ted
+7unist
+9ists
+9ities
+9ity
+8tative
+6parable
+8tible
+7etition
+9itive
+9itor
+9itors
+7lex
+8iance
+9ances
+9ant
+9cated
+8ying
+9ings
+7oser
+9ers
+8und
+9nds
+7ressible
+7uter
+9erised
+9erized
+6s
+5nceptual
+8rn
+9ns
+7lusion
+9sions
+7ur
+9red
+9rence
+9rences
+9rent
+9ring
+9s
+6densable
+7itioned
+7ucting
+9tion
+9tions
+9tive
+9tor
+9tors
+6ference
+9ences
+7idence
+9ences
+9ential
+7licting
+7orm
+9mance
+9mances
+9med
+9mer
+9mers
+9ming
+9mism
+9misms
+9mist
+9mists
+9mities
+9mity
+9ms
+6gruent
+6jugated
+6nection
+9tions
+6scious
+7ecutive
+8nsual
+8rvation
+9vative
+7olidated
+7tant
+9nts
+8ruction
+9uctive
+7umer
+9ers
+9ing
+9ption
+9ptions
+9ptive
+6tact
+9ts
+8gious
+7emporary
+7iguous
+8ngent
+9uous
+7ract
+9ctual
+8ibutory
+8ollable
+9lled
+9lling
+6ventional
+8rtible
+5operation
+9ations
+9ative
+9ator
+9ators
+5planar
+5re
+6porate
+6relation
+9ations
+7odible
+9ing
+9ings
+8sive
+5untries
+9y
+8y
+5verage
+9ges
+4reative
+9vities
+9vity
+6dentialed
+7it
+5ime
+8s
+7inal
+9als
+6ses
+7is
+6tical
+5ossover
+5ushable
+5ystalline
+4ulinary
+6tivated
+9ation
+9ations
+7ural
+5mulative
+5rrent
+5stodial
+8mer
+9ers
+4yclic
+9al
+3dairy
+5nce
+8r
+9s
+8s
+4eceptive
+6ision
+9ons
+6reasing
+5ductible
+9ive
+5fense
+7rrable
+6orming
+5generate
+9rates
+6radable
+9ables
+7ee
+5legate
+9tes
+6iberate
+7nquent
+9uents
+7veries
+9ry
+5mand
+9ing
+9s
+6ocratic
+5partmental
+6endent
+9ents
+6letable
+9ing
+6osition
+9tions
+6ressed
+5rivative
+9tives
+5script
+9ptive
+9ptly
+9ptness
+9pts
+6ert
+6tructive
+5tachable
+5velopment
+9pments
+6iant
+9ts
+4iabetic
+9ics
+6lysable
+8zable
+6pausing
+5dactic
+5ffusible
+5mensional
+5plomatic
+5rected
+9ional
+9ive
+5sabled
+9eds
+6closure
+9sures
+7ount
+7ursive
+6junction
+9ctions
+6persive
+6ruptive
+6tinctive
+5versified
+6iding
+4octor
+9s
+7rinaire
+6umentary
+5gmatic
+5llar
+5mestic
+9ics
+6iciled
+7nant
+9nts
+5rmant
+4ramatic
+5inker
+9rs
+8ing
+6p
+6ver
+9s
+5ug
+5ying
+4urable
+9es
+3e
+4arning
+9gs
+4conomic
+9ist
+9ists
+4dible
+9s
+6torial
+5ucation
+9ional
+9ions
+4ffective
+9ives
+4go
+6s
+4lastic
+5ect
+8ed
+8ion
+9ons
+9ve
+9ves
+8ric
+9ical
+9ics
+9olyte
+9olytes
+9onic
+9onics
+6mentary
+5ite
+4mergencies
+9ncy
+5otional
+5phatic
+6irical
+6loyee
+9ees
+9ment
+9ments
+6ty
+4ncapsulated
+5ding
+5ergy
+5forcement
+9ements
+5gagement
+9ments
+6ineering
+9erings
+5tities
+8y
+6ries
+7y
+5zymatic
+8ic
+4qual
+8s
+6ilibria
+9brium
+9briums
+7valence
+9lences
+9lent
+9lents
+4s
+5sential
+9ials
+5tablished
+6erified
+5uch
+8es
+4t
+5heless
+6ical
+6nic
+9s
+5s
+5te
+7s
+6i
+6o
+7s
+4valuative
+5ent
+8s
+5idence
+9ces
+4xclusive
+5ecutive
+9ives
+6mpt
+9s
+5istence
+9nces
+9nt
+9ntial
+5otic
+5pendable
+7rimental
+8t
+9s
+6lanatory
+7oitation
+9tative
+9tive
+8sive
+9ives
+6osed
+5tant
+3fact
+7or
+9s
+7s
+7ual
+6ulty
+5ding
+5milial
+9es
+8y
+5n
+6s
+5rm
+7er
+9s
+5t
+6al
+6tening
+7y
+4easance
+9ces
+5deral
+9ted
+5minist
+9sts
+5rrous
+5udal
+4iction
+9nal
+9nally
+9ns
+5gurative
+5lamentous
+6ial
+6terable
+5nal
+7ncial
+6ite
+5scal
+6sionable
+4lammability
+9ble
+5owering
+5uencies
+9y
+6id
+8s
+6orescent
+5ying
+4ocal
+5od
+5rfeitable
+9ture
+9tures
+6mal
+5ssil
+4reezing
+5ivolous
+5ozen
+4uel
+5lfillment
+9lments
+5nctional
+9oning
+6ded
+3g
+4ame
+5seous
+5y
+6s
+4enetic
+6ital
+5ometrical
+4hetto
+4lamorous
+6re
+8s
+6zed
+5ossy
+4olfer
+9s
+5nococcal
+5vernment
+9mental
+9ments
+4raded
+7uate
+9tes
+6mmatical
+6nular
+5easy
+6en
+6garious
+5owing
+7th
+4s
+4uest
+8s
+5ilt
+8s
+3halogenated
+5ndicapped
+5ppening
+9ings
+5rdy
+6monic
+5zardous
+4eme
+6olytic
+5reditary
+6o
+7es
+7ic
+4ierarchical
+5stone
+8rical
+4ome
+6ogeneous
+7logous
+7sexual
+9xuals
+5rmonal
+5spital
+9alised
+9alized
+9als
+6tile
+5using
+9gs
+4uman
+8s
+5nter
+9s
+7ing
+4ygroscopic
+5sterical
+3i
+4deal
+6ntical
+9ties
+9ty
+6ological
+4llion
+9s
+9th
+9ths
+4mage
+8s
+5itative
+5migrant
+9ants
+6une
+5pact
+6lication
+9ations
+6ortation
+9ations
+4nclusion
+9ions
+6reasing
+6umbent
+9ents
+5dependence
+6igenous
+7vidual
+6uctive
+7strial
+9ry
+5ert
+5fected
+9ious
+9ive
+7sted
+6lammable
+9matory
+8tionary
+7ectional
+7uence
+9nces
+6ormation
+9ations
+6ringement
+5itial
+9te
+9tes
+5jury
+5sect
+9icidal
+9s
+6tallment
+9lments
+7rumental
+6urance
+9nces
+8ed
+5tegral
+9ated
+7llectual
+7racting
+9ctive
+8course
+9ourses
+8est
+9sts
+8ference
+8secting
+8vention
+6imidating
+6oxicant
+9cants
+9cating
+6rusive
+6uitive
+5vasive
+6olved
+9ement
+9ements
+4onic
+7zing
+4ron
+5radiated
+6igated
+7tant
+9nts
+9ting
+4s
+5sue
+8s
+3joinder
+9rs
+7er
+9s
+4udgemental
+7mental
+6icial
+5ries
+7ng
+6or
+8s
+6y
+5sticiable
+3kosher
+9s
+3labor
+5ndowner
+9ners
+6guage
+9ges
+5wyer
+9s
+4eaded
+6fy
+6gue
+5gal
+6ume
+9s
+8inous
+5thal
+5vel
+5xical
+4iable
+5brarian
+9ians
+9ies
+9y
+5fe
+5neal
+8r
+9ities
+9ity
+6guistic
+5quid
+9s
+5teral
+9ry
+9te
+9tes
+5ves
+6ing
+9s
+4ocal
+8s
+5gical
+5ving
+5yal
+4uminous
+4yric
+3magnetic
+5instream
+5jor
+8s
+5lignant
+6leable
+5n
+6agement
+9ments
+9rial
+6ual
+5rital
+6ket
+9s
+5terial
+6hematical
+6riculated
+6ure
+4eaningful
+6surable
+6t
+5chanical
+9istic
+5dical
+5eting
+9gs
+5mber
+9s
+9ship
+9ships
+5n
+6tal
+5rcurial
+5tal
+8lic
+8s
+7meric
+7phorical
+6ric
+9al
+7o
+8politan
+4icrobial
+5grant
+9ts
+8tory
+5litant
+9nts
+9ry
+5metic
+5norities
+9ty
+4obile
+5dal
+6ern
+9s
+5lecular
+5netarist
+9rists
+9ry
+7y
+6ogamous
+5ral
+6tal
+9s
+5tile
+8ities
+9ty
+6orised
+9zed
+5ving
+4unicipal
+5sic
+8al
+9ls
+8ian
+9ans
+8s
+5tant
+9s
+6ual
+4yelinated
+5stical
+3narrative
+9ives
+5sal
+5tional
+9als
+7ve
+9s
+6ural
+5val
+4ecessities
+9ity
+5gative
+6ligent
+6otiable
+9ables
+5twork
+5ural
+5ws
+4ies
+5trogenous
+4oble
+5rmal
+8tive
+5vel
+8s
+4uclear
+9ted
+5merical
+9cals
+5tritious
+9ive
+4y
+3obese
+5jective
+9ivism
+9ivisms
+9ivist
+9ivists
+9ivity
+5scene
+6ervance
+9ances
+9ant
+5vious
+4ccupational
+7rrence
+9ences
+4fficial
+9als
+4hmic
+4ily
+4peratic
+9ing
+9ional
+9ive
+5timal
+4ral
+7ly
+5ganic
+5thodox
+4verlapping
+9ppings
+4wner
+8s
+4xidising
+8zing
+3pagan
+8s
+5id
+5pal
+6ist
+9s
+5r
+6allel
+9els
+7metric
+7sitic
+6eil
+9s
+7nt
+9s
+6ities
+8y
+6ous
+6ticipant
+9ipants
+8es
+8san
+9ans
+9anship
+8zan
+9anship
+7y
+5sserine
+7ive
+6t
+7s
+5thogenic
+5ying
+6ment
+9ts
+4eak
+5rformance
+9mances
+9mer
+9mers
+9ming
+6ishable
+9ables
+6manent
+7issive
+6sistent
+7on
+9al
+9s
+5troleum
+9eums
+4hilosopher
+9ophers
+5onemic
+8tic
+6sphate
+9ates
+6tographic
+5ysical
+9ian
+9ians
+4lanar
+6stic
+9cs
+6y
+7er
+9s
+7ing
+7s
+5iant
+5us
+7ed
+8s
+7ing
+7sed
+9s
+8ing
+4oetic
+5int
+6sonous
+5lar
+8isable
+9zable
+6ice
+7tical
+9cally
+9cian
+9cians
+6luting
+5or
+5rous
+5ssession
+9sions
+6tal
+4ractical
+9cing
+9sing
+5egnant
+6scription
+5int
+5oblem
+9ms
+6ducing
+9tive
+9tivity
+6fessional
+9sorial
+7it
+9s
+6gram
+9mmer
+9mmers
+9ms
+8essive
+9ssives
+6prietary
+6s
+7sed
+9s
+8ing
+6tein
+6ven
+4sychiatric
+9atrist
+8otic
+4ublic
+5nitive
+5rposive
+3quantifiable
+9tative
+5ota
+3racial
+9ly
+5dioactive
+5ilroad
+5ndom
+9ness
+9nesses
+5ted
+6ional
+4eactive
+8or
+9rs
+6der
+9s
+7ing
+6listic
+5ceipt
+9ts
+6iprocal
+9ocals
+6ognition
+9itions
+7mbinant
+9inants
+7urse
+6urrent
+9ing
+6yclable
+9ables
+5ducing
+7ndant
+5fillable
+6lecting
+8xive
+6undable
+5gulated
+9tion
+9tions
+5lative
+9ves
+9vistic
+6evant
+6igious
+5newable
+9l
+9ls
+5payable
+6roducible
+9uctive
+5sidence
+9nces
+9ncies
+9ncy
+9nt
+9ntial
+9nts
+7stance
+9ances
+9ant
+9ants
+6onant
+6pondent
+9dents
+9der
+9ders
+9se
+9ses
+9sive
+6tricted
+9ctive
+5tractile
+7oactive
+6urn
+9able
+9ables
+5usable
+9les
+5versible
+4hotic
+9ities
+9ity
+4igid
+5oter
+9s
+7ing
+5val
+8s
+4otating
+5utine
+9es
+5yal
+4ubber
+5ling
+5minant
+9nts
+5ral
+3sacred
+5lable
+6ine
+5ponifiable
+4cheduled
+6ool
+5ience
+9es
+8tific
+9ist
+9ists
+4easonal
+5cret
+9or
+9ories
+9ors
+9ory
+9s
+6tarian
+6ure
+5dimentable
+5gregated
+9ation
+9ations
+5lected
+9ive
+6f
+6ves
+5nsational
+7e
+8s
+7ical
+9ality
+9ally
+9alness
+8tive
+7uous
+6tence
+9ces
+5ptate
+5quential
+5rial
+9s
+7ous
+5xist
+6ual
+4hrink
+9able
+4igner
+9s
+7ificant
+5multaneous
+5nkable
+4kater
+9s
+5ed
+7s
+6letal
+5id
+6er
+8s
+4lip
+4moker
+9s
+7ing
+4ocial
+9ist
+9ists
+5lar
+6id
+8s
+6ution
+9ons
+4patial
+5eaker
+9rs
+8ing
+6cialist
+9lists
+8fic
+9ically
+7tacular
+7ular
+9ative
+6ech
+5herical
+5orting
+4tandard
+6ple
+9s
+6rter
+9rs
+6tic
+8onaries
+9nary
+8stical
+8ve
+9es
+5eady
+6roid
+9dal
+9ds
+5ick
+8y
+5op
+7s
+6ries
+7y
+5rategic
+6iated
+6uctural
+9ured
+5udent
+9ts
+5yle
+8s
+4ubject
+9tive
+9ts
+6sidised
+9ized
+5ccess
+9ses
+6h
+7es
+5gar
+8s
+5it
+7ed
+7ing
+7s
+5pervisory
+6port
+9ts
+5rgical
+4wimmer
+9rs
+4yllabic
+5mbolic
+6metric
+9rical
+5nchronous
+5stem
+9atic
+9ic
+9s
+3talker
+9s
+5rget
+6iff
+5x
+6able
+9es
+6es
+4eaching
+5chnical
+5mporal
+9als
+5nured
+5rminal
+9als
+9ating
+4heatrical
+6ist
+9ic
+9s
+6ological
+7retical
+6rapeutic
+7mal
+5inking
+9ngs
+5reatening
+4idal
+5tle
+4obacco
+9os
+5nal
+6ic
+5talitarian
+5xic
+4raditional
+6gic
+6nsferable
+8itive
+5eatment
+9ents
+5ibal
+6vial
+5opical
+5ump
+6th
+8s
+4urbulent
+4ypical
+3unanimous
+5iform
+9mities
+9mity
+6on
+8ised
+9sm
+9sms
+9st
+9sts
+9zed
+8s
+6que
+9ness
+9nesses
+6versal
+9sals
+9sities
+9sity
+4ple
+7s
+7t
+8s
+4rban
+5gent
+4sable
+5e
+6r
+7s
+6s
+5ing
+4tilitarian
+9arians
+9ies
+9y
+5opian
+3vacant
+5lid
+8ities
+9ty
+5nishing
+5scular
+4ector
+9s
+5getarian
+9rians
+5nomous
+7us
+5rbal
+9ly
+5sted
+5teran
+9ns
+4iable
+5ewer
+9s
+5ntage
+5olence
+9ces
+9t
+9tly
+5ral
+6gin
+9s
+6ile
+5scous
+6ual
+5tal
+4ocal
+8s
+7tional
+5latile
+6canic
+6untary
+5ter
+8s
+6ing
+3wage
+5r
+6s
+4hite
+8s
+4inged
+6ning
+4oody
+6l
+5rd
+7s
+6k
+7er
+9s
+7ing
+5ven
+8s
+4riter
+9s
+3yellowing
+4l
+5s
+3zero
+2o
+3b
+4s
+3dge
+6d
+6s
+5ing
+4le
+6d
+7om
+9s
+6s
+5ing
+8s
+3geneses
+8is
+4ie
+6s
+3it
+3k
+4ie
+6r
+6s
+7t
+4like
+4s
+4y
+3logies
+6y
+3metries
+7y
+3n
+4day
+7s
+4ed
+5r
+6s
+4ing
+7s
+4s
+4tide
+8s
+6me
+8s
+3p
+4s
+3se
+5d
+5r
+6s
+5s
+4ing
+4phere
+9s
+3tropic
+9s
+2pal
+5es
+5ito
+8s
+5s
+3e
+3lace
+2r
+3adrenalin
+9line
+9lines
+9lins
+8ergic
+3dic
+3epinephrine
+9hrines
+4thindrone
+9rones
+7sterone
+9erones
+3i
+4a
+5s
+4mon
+7s
+4s
+4te
+6s
+5ic
+3k
+4s
+3land
+7s
+3m
+4a
+5l
+6cies
+7y
+6isable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7ties
+8y
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ly
+6s
+5n
+6de
+6s
+5s
+5tive
+9ly
+9ness
+9nesses
+4ed
+4less
+4otensive
+9ives
+6hermia
+9mias
+9mic
+4s
+3ovirus
+9es
+3sel
+6led
+8r
+9s
+7ing
+6s
+3tena
+7s
+6o
+7s
+4h
+5bound
+5countryman
+9trymen
+5east
+9er
+9erlies
+9erly
+9ern
+9ers
+9s
+9ward
+9wardly
+9wards
+6d
+6r
+7ed
+7ing
+7lies
+9ness
+9nesses
+8y
+7most
+7n
+8er
+9rs
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+8most
+8s
+7s
+5ing
+8s
+5land
+9s
+5most
+5s
+5ward
+9ly
+9s
+6est
+9er
+9erlies
+9erly
+9ern
+9ers
+9s
+9ward
+9wardly
+9wards
+4riptyline
+9lines
+3ward
+7s
+2s
+3e
+4an
+6s
+4bag
+7s
+6nd
+8ed
+8s
+5leed
+9ing
+9ings
+9s
+4d
+5ive
+8d
+8s
+7ing
+5ove
+4gay
+7s
+5uard
+9s
+4less
+5ike
+6te
+8s
+4piece
+9s
+4r
+5s
+4s
+4wheel
+9s
+4y
+5s
+3h
+4ed
+5r
+6ie
+8s
+6s
+6y
+5s
+4ing
+3ier
+5s
+6t
+4ly
+4ness
+8es
+5g
+6s
+3ocomial
+4de
+6s
+4grapher
+9ers
+9ic
+9ies
+9y
+4logic
+9al
+9ally
+8es
+8st
+9ts
+7y
+4phobia
+9as
+3talgia
+9s
+8c
+9ally
+9s
+8st
+9ts
+4oc
+6s
+5i
+5logic
+9cal
+9es
+8y
+5mania
+9as
+5pathies
+9y
+5s
+4radamic
+5il
+7s
+5o
+5um
+7s
+3y
+2t
+3a
+4bilia
+8ties
+9y
+5le
+7ness
+9sses
+7s
+6y
+4eum
+7s
+4ire
+7s
+4l
+4nda
+6um
+4philic
+9es
+9sm
+9sms
+9st
+9sts
+8y
+4rial
+8ly
+6es
+6sation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5y
+6ship
+9ps
+4te
+6d
+6s
+5ing
+6on
+8al
+8s
+3ch
+5back
+9s
+5ed
+6l
+7ed
+7ing
+7led
+8ing
+7s
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5y
+3e
+4book
+8s
+4card
+8s
+6se
+8s
+4d
+5ly
+5ness
+9es
+4less
+6t
+7s
+4pad
+7s
+6per
+9s
+4r
+5s
+4s
+4worthily
+9iness
+9y
+3her
+4ing
+7arian
+9ianism
+9ians
+7ism
+9ms
+7ness
+9sses
+7s
+3ice
+6abilities
+9lity
+8le
+9y
+6d
+6r
+7s
+6s
+5ing
+4fiable
+6cation
+9ions
+6ed
+7r
+8s
+7s
+5y
+6ing
+4ng
+4on
+6al
+8ist
+9sts
+9ties
+9ty
+8ly
+6ist
+9s
+6s
+4tia
+7e
+7s
+3ochord
+9al
+9s
+4dontid
+9ds
+4nectal
+4rieties
+8y
+6ous
+9ly
+9ness
+9nesses
+5nis
+8es
+4therium
+9ums
+4ungulate
+9ates
+5r
+3t
+4urni
+7o
+3um
+4ngulate
+9tes
+3withstanding
+2ugat
+6ine
+9s
+6s
+4ht
+6ies
+6s
+3l
+4d
+5e
+4e
+5s
+4s
+3mena
+7l
+8ism
+9sms
+9st
+9sts
+9ties
+9ty
+8ly
+6on
+3n
+4al
+6ly
+4ier
+6st
+4less
+4s
+4y
+3p
+4s
+3rice
+7s
+5sh
+7able
+7ed
+8r
+9s
+8s
+7ing
+9gly
+7ment
+9nts
+5ture
+9s
+4riture
+9es
+4sle
+7d
+7s
+6ing
+3s
+4ell
+7ed
+7ing
+7s
+5s
+4le
+6d
+6s
+5ing
+3t
+3veau
+7x
+5lle
+8s
+2va
+4culite
+9es
+4e
+4lia
+6ke
+4s
+4te
+6d
+6s
+5ing
+6on
+8s
+3el
+5dom
+8s
+5ese
+8s
+6tte
+9s
+8ish
+9st
+9sts
+5isation
+9ions
+7e
+8d
+8r
+9s
+8s
+7h
+7ing
+7m
+8s
+7t
+8ic
+9cally
+8s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5la
+7e
+7s
+6e
+6y
+5s
+5ties
+6y
+4mber
+5decillion
+9llions
+4na
+6e
+6ries
+7y
+6s
+5nial
+4rcal
+5int
+8s
+3ice
+6hood
+9ds
+6s
+7hip
+9ps
+5iate
+9s
+4tiate
+9s
+6es
+5y
+3obiocin
+9ns
+4caine
+9s
+5entenaries
+9nary
+4damus
+9es
+3um
+5s
+2w
+3adays
+4y
+5s
+3casting
+9gs
+3ed
+3hence
+5re
+7s
+4ither
+3ise
+3l
+4s
+3n
+4ess
+7es
+3s
+3t
+4ier
+6st
+4s
+4y
+3y
+2x
+3al
+3es
+3ious
+7ly
+7ness
+9sses
+2y
+3ade
+6s
+4nce
+7s
+4u
+5s
+3ed
+4s
+5es
+3ing
+3ous
+3s
+4ome
+2zzer
+6s
+4le
+6s
+1th
+1u
+2ance
+6d
+6s
+5ing
+2b
+3bed
+4ier
+6st
+5n
+6ess
+9es
+6g
+6s
+4le
+6d
+6s
+5ier
+7st
+6ng
+5y
+4y
+3ecula
+8e
+3ia
+5s
+4ferous
+5orm
+4genous
+4le
+5ities
+7y
+5ose
+6us
+3s
+3uck
+6s
+2cellar
+6i
+6us
+3ha
+5e
+5l
+6s
+3iferous
+4vorous
+3leal
+6r
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+6se
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5i
+6c
+6de
+8s
+6n
+7ic
+7s
+5ocapsid
+9sids
+6id
+8s
+6lar
+8te
+9ed
+7e
+8s
+7i
+7us
+6n
+7ic
+9ally
+9s
+7s
+6phile
+9les
+9lic
+9licity
+7lasm
+9smatic
+9smic
+9sms
+7rotein
+9teins
+6side
+9es
+7omal
+9e
+9es
+7yntheses
+9thesis
+9thetic
+6tidase
+9ases
+9e
+9es
+5us
+7es
+4ide
+7s
+6ic
+3ule
+6s
+2dation
+8s
+3dies
+4y
+3ely
+4r
+4st
+3ge
+5d
+5r
+6s
+5s
+4ing
+3ibranch
+9hiate
+9hiates
+9hs
+4caudate
+7l
+8ous
+3nick
+7s
+5k
+6s
+3zh
+5ed
+6s
+5ing
+2ff
+4in
+6s
+4s
+2gae
+4toriness
+9esses
+7y
+3gar
+6s
+4et
+6ed
+6ing
+6s
+6ted
+7ing
+6y
+2isance
+8r
+9s
+8s
+2ke
+4d
+4s
+3ing
+2ll
+4a
+5h
+6s
+5s
+4ed
+4ification
+9tions
+7dian
+9ans
+7ed
+8r
+9s
+8s
+6y
+7ing
+5ng
+7s
+5para
+9e
+9s
+8ities
+9ty
+8ous
+6ore
+9s
+5ties
+6y
+4ness
+8es
+4s
+2mb
+4at
+6s
+4ed
+5r
+6able
+6ed
+7r
+8s
+6ing
+9s
+6less
+9sly
+9sness
+6plate
+9tes
+6s
+5st
+4fish
+8es
+4ing
+7ly
+4les
+5y
+4ness
+8es
+4s
+5kull
+9s
+3chuck
+8s
+3dah
+6s
+3en
+4rabilities
+9ity
+7le
+8y
+6cies
+7y
+6ire
+9s
+6l
+7ly
+7s
+6ry
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+5ic
+7al
+9ly
+7s
+5ological
+9ies
+9ist
+9ists
+9y
+6sities
+9y
+6us
+8ly
+8ness
+9esses
+3ina
+5ous
+8es
+8ness
+9esses
+4smatic
+9cally
+9cs
+9st
+9sts
+8ologies
+9logist
+9logy
+3mary
+4ular
+8y
+7ted
+8ion
+9ons
+6ine
+7te
+9s
+8ic
+3nah
+6s
+3pties
+5y
+3skull
+8ed
+8s
+2n
+3atak
+7er
+7s
+3chaku
+8s
+5eon
+8s
+5ucks
+4iature
+9es
+5o
+6s
+4le
+6s
+4upate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8ory
+3dinal
+6e
+7s
+3hood
+7s
+3like
+3nation
+9s
+4eries
+6y
+4ish
+7ness
+9sses
+4y
+3s
+4hip
+7s
+2ptial
+7ities
+9y
+7ly
+7s
+2r
+3aghe
+6i
+7c
+3d
+4ier
+6st
+5sh
+4le
+6d
+6s
+5ing
+4s
+4y
+3hag
+6s
+3l
+4ed
+4ing
+4s
+3r
+4s
+3s
+4e
+5d
+5hound
+9ds
+5like
+7ng
+9s
+5maid
+9ed
+9ing
+9s
+5r
+6ies
+6s
+6y
+7maid
+9ids
+9n
+8en
+5s
+4ing
+7s
+4le
+6d
+6s
+5ing
+8s
+3turable
+7l
+7nce
+9es
+8t
+6e
+7d
+7r
+8s
+7s
+6ing
+2s
+2t
+3ant
+4rian
+8s
+4te
+6d
+6s
+5ing
+6on
+8al
+8s
+3brown
+4utter
+9s
+3case
+7s
+4racker
+9rs
+3gall
+7s
+4rass
+8es
+3hatch
+8es
+4ouse
+8s
+3job
+6ber
+9s
+6s
+3let
+6s
+4ike
+3meal
+7s
+6t
+7s
+5g
+6ged
+7ing
+7y
+6s
+3pecker
+9s
+4ick
+7s
+3raceutical
+9icals
+4ia
+6s
+5ent
+8s
+5genetics
+5ment
+9al
+9s
+5tion
+9al
+9ally
+9ary
+9ist
+9ists
+9s
+8us
+9sly
+9sness
+7ve
+9ly
+9s
+3s
+4edge
+8s
+4hell
+8s
+4ier
+6st
+4o
+4y
+3ted
+5r
+6ies
+6s
+6y
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4y
+3wood
+7s
+2zzer
+6s
+4le
+6d
+6r
+7s
+6s
+5ing
+1y
+2aff
+5ed
+5ing
+5s
+3la
+5s
+3nza
+6s
+3s
+4es
+2bble
+6s
+2chthemeral
+9ron
+9rons
+3taginaceous
+5lopes
+8ia
+9as
+9c
+8s
+5nthous
+4inastic
+9ies
+9y
+5tropic
+9ism
+9isms
+4ophobia
+9ias
+9ic
+2e
+3d
+3s
+2ing
+2lghai
+7s
+6u
+7s
+3on
+5s
+2mph
+5a
+6e
+7a
+8ceous
+7um
+9s
+6l
+7id
+9s
+5ean
+6t
+7ic
+7s
+7te
+9s
+5ic
+7al
+6sh
+5like
+6y
+5olepsies
+9sy
+9t
+9tic
+9ts
+6maniac
+9iacal
+9iacs
+9ias
+6s
+5s
+2s
+3sa
+5s
+3tagmic
+7oid
+7us
+9es
+5tin
+8s
+0oaf
+3ish
+6ly
+6ness
+9ses
+3s
+2k
+3ed
+4n
+5shaw
+9s
+4r
+5s
+3ier
+5s
+6t
+3like
+5ng
+7s
+3moss
+7es
+3s
+3um
+5s
+3y
+2nshagh
+8s
+2r
+3age
+6s
+3ed
+3fish
+7es
+3ier
+5st
+4ng
+3less
+4ike
+4ock
+7s
+3s
+4man
+7ship
+9ips
+5en
+4woman
+7en
+3weed
+7s
+3y
+2ses
+3is
+3t
+4house
+9s
+4s
+2t
+3cake
+7s
+3en
+4r
+5s
+3h
+4able
+4s
+3ier
+5st
+3like
+3meal
+7s
+3s
+3y
+2ves
+1b
+2a
+3ng
+5s
+3s
+2bligati
+8o
+9s
+2compressed
+4nic
+7al
+4rdate
+2duracies
+7y
+6te
+8d
+8ly
+8ness
+9esses
+8s
+7ing
+8on
+9ns
+5e
+6d
+6s
+5ing
+2e
+3ah
+5ed
+5ing
+6sm
+8s
+5s
+3che
+6s
+3dience
+9s
+7t
+8ial
+9aries
+9ary
+8ly
+3isance
+9s
+7t
+8ly
+5m
+6s
+3li
+5a
+6s
+5on
+5scal
+7oid
+6e
+7d
+7s
+6ing
+6k
+7oid
+7s
+6m
+7s
+5ze
+7d
+7s
+6ing
+4us
+3nto
+6s
+3s
+4e
+5ly
+5ness
+9es
+5r
+5st
+4ities
+6y
+4ogenic
+3y
+4able
+4ed
+5r
+6s
+4ing
+4s
+2fuscate
+9d
+9s
+8ing
+9on
+9ons
+8ory
+2i
+3a
+4s
+3ed
+3ing
+4sm
+6s
+4t
+3s
+3t
+4al
+4er
+4s
+4ual
+6ries
+8st
+9ts
+7y
+2ject
+6ed
+6ification
+9ed
+9es
+8y
+9ing
+7ng
+7on
+9able
+9ably
+9s
+7val
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+8e
+9ly
+9ness
+9nesses
+9s
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9stic
+9sts
+9ties
+9ty
+9ze
+9zed
+9zes
+9zing
+6less
+9sness
+6or
+8s
+6s
+4t
+5s
+3uration
+9ns
+5e
+6d
+6s
+5gate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+5ing
+2lanceolate
+4st
+6i
+6s
+4te
+6ly
+6ness
+9ses
+6s
+5ion
+8al
+8s
+5ory
+3igable
+6nt
+8s
+6te
+8d
+8ly
+8s
+7i
+8ng
+8on
+9nal
+9ns
+8ve
+7o
+8r
+9ily
+9iness
+9s
+9y
+8s
+5e
+6d
+6e
+7s
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+8ness
+9esses
+5or
+7s
+4quation
+9ons
+6e
+7d
+7ly
+7ness
+9sses
+7r
+7s
+8t
+6id
+7ng
+7ties
+8ous
+8y
+4terate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+4vion
+8s
+7us
+9ly
+9ness
+9nesses
+6scence
+9nces
+3ong
+6ly
+6s
+4quial
+7es
+6y
+2mutescence
+9nces
+9nt
+2noxious
+9ly
+9ness
+9nesses
+3ubilate
+9ed
+9es
+9ing
+9ion
+9ions
+2o
+3e
+4s
+3ist
+6s
+3l
+4ary
+4e
+5s
+4i
+4s
+4us
+3s
+3vate
+7ly
+4oid
+2reption
+9s
+7tious
+2s
+3cene
+7ly
+7ness
+9sses
+7r
+7st
+6ities
+8y
+4urant
+9ic
+9ism
+9isms
+9ist
+9ists
+9s
+7tion
+9ons
+6e
+7d
+7ly
+7ment
+9nts
+7ness
+9sses
+7r
+8s
+7s
+8t
+6ing
+7ties
+8y
+3ecrate
+9d
+9s
+8ing
+9on
+9ons
+4quent
+6ial
+7e
+8s
+7ous
+9sly
+9sness
+6y
+4rvabilities
+9lity
+8le
+9eness
+9es
+9y
+7nce
+9es
+9ies
+9y
+8t
+9ly
+9s
+7tion
+9onal
+9onally
+9ons
+9ve
+8or
+9ries
+9rs
+9ry
+6e
+7d
+7r
+8s
+7s
+6ing
+9ly
+4ss
+6ed
+7s
+6ing
+7on
+9al
+9ally
+9ist
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+9s
+6or
+8s
+3idian
+8s
+6onal
+9ry
+4gn
+6ate
+9d
+9s
+8ing
+9on
+9ons
+8ory
+6ed
+6ing
+6s
+3olesce
+9d
+9nce
+9nces
+9nt
+9ntly
+9s
+8ing
+6te
+8d
+8ly
+8ness
+9esses
+8s
+7ing
+8on
+9ns
+8sm
+9ms
+3tacle
+8s
+4etric
+9al
+9ally
+9ian
+9ians
+9s
+4inacies
+8y
+7te
+9ly
+9ness
+9nesses
+5pation
+9ons
+4reperate
+9ated
+9ates
+9ating
+9ous
+9ously
+5iction
+9ons
+5opalous
+7ulous
+5uct
+8ed
+9r
+9rs
+8ing
+9on
+9onal
+9onally
+9onism
+9onisms
+9onist
+9onists
+9ons
+9ve
+9vely
+9veness
+9ves
+8or
+9rs
+8s
+6ent
+9s
+2tain
+6abilities
+9lity
+8le
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+3ect
+6ed
+4mper
+8ate
+9ted
+9tes
+9ting
+8ed
+8ing
+8s
+4nd
+6ed
+6ing
+6s
+5tion
+9s
+4st
+6ation
+9ons
+6ed
+6ing
+6s
+3rude
+7d
+7r
+8s
+7s
+6ing
+9s
+5ncate
+9ed
+9es
+9ing
+5sion
+9s
+7ve
+9ly
+9ness
+9nesses
+3und
+6ed
+7nt
+9s
+6ing
+7ties
+8y
+6s
+4rate
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+4se
+6ly
+6ness
+9ses
+6r
+6st
+5ities
+7y
+2umbrate
+9d
+9s
+8ing
+9on
+9ons
+2vention
+9s
+4rse
+7ly
+7s
+6ion
+9s
+5t
+6ed
+6ing
+6s
+3iable
+5te
+7d
+7s
+6ing
+7on
+9s
+6or
+8s
+4ous
+7ly
+7ness
+9sses
+3olute
+8d
+7ion
+9ns
+8ve
+5vent
+1ca
+3rina
+7s
+3s
+2cam
+5ies
+5s
+5y
+4sion
+8al
+9lism
+9lisms
+9list
+9lists
+9lities
+9lity
+9lly
+8ed
+9r
+9rs
+8ing
+8s
+3ident
+8al
+9lise
+9lised
+9lises
+9lising
+9lism
+9lisms
+9list
+9lists
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9ls
+8s
+4es
+4pita
+8l
+9ly
+9s
+5ut
+7s
+3lude
+7d
+7nt
+9s
+7r
+8s
+7s
+6ing
+5sal
+6ion
+9s
+7ve
+9ness
+9nesses
+9s
+6or
+8s
+3ult
+6ation
+9ons
+6ed
+7r
+8s
+6ing
+7sm
+9s
+8t
+9s
+6ly
+6ness
+9ses
+6s
+4pance
+9s
+8ies
+8y
+7t
+8s
+6te
+8d
+8s
+7ing
+8on
+9nal
+9nally
+9ns
+8ve
+5ied
+7r
+8s
+7s
+5y
+6ing
+4r
+5red
+7nce
+9es
+8t
+9s
+6ing
+5s
+3y
+2ean
+5aria
+8um
+9ms
+6ut
+8s
+5front
+9ts
+5going
+5ic
+6d
+7es
+7s
+5ographer
+9phers
+9phic
+9phical
+9phies
+9phy
+6logical
+9ies
+9ist
+9ists
+9y
+5s
+3llar
+6te
+8d
+7ion
+9ns
+5i
+5us
+4oid
+5t
+6s
+2h
+3e
+4r
+5ed
+5ing
+5ous
+5s
+5y
+4s
+3idore
+8s
+3locracies
+9y
+8t
+9ic
+9ical
+9ically
+9s
+5phobia
+9iac
+9iacs
+9ias
+9ic
+3one
+3raceous
+4e
+5a
+6e
+6te
+5d
+5ous
+5s
+5y
+4ing
+4oid
+5leucous
+5us
+4y
+2icat
+6s
+2ker
+5ism
+8s
+5s
+3odols
+2otillo
+8s
+2rea
+5e
+5te
+2ta
+4chord
+9al
+9s
+4d
+5ic
+5s
+4gon
+7al
+9ly
+7s
+4hedra
+9l
+9lly
+8ite
+9tes
+8on
+9ns
+4l
+5s
+4merous
+6ter
+9s
+4n
+5drian
+7ous
+5e
+6dioic
+6s
+5gle
+8s
+6ular
+5ol
+7s
+5s
+5t
+6al
+6s
+4peptide
+9des
+5la
+7s
+6oid
+9ies
+9s
+9y
+5odic
+8es
+7y
+4rchies
+7y
+5oon
+8s
+4s
+5tich
+9on
+9ons
+9ous
+9s
+6rophic
+6yle
+9s
+4val
+7ent
+5e
+6s
+5o
+6s
+3ennial
+9ly
+4t
+5s
+5t
+6e
+7s
+6s
+3illion
+9s
+9th
+9ths
+4ngenaries
+9ry
+8tenary
+3ocentenaries
+9nary
+4decillion
+9lions
+8mo
+9os
+4fid
+4genarian
+9ians
+9ies
+9y
+5ynous
+4hedra
+8on
+9ns
+4narian
+9ns
+8es
+8i
+8us
+7y
+5ocular
+4petalous
+5i
+5loid
+9s
+5od
+7an
+9s
+7es
+7ous
+7s
+6id
+5us
+7es
+7h
+8er
+9rs
+9s
+4roon
+8s
+4sepalous
+5tichous
+6yle
+9s
+5yllabic
+9bics
+9ble
+9bles
+4thorp
+9s
+3roi
+6s
+3uor
+6s
+4ple
+7d
+7s
+7t
+8s
+7x
+6icate
+9tes
+7ng
+6y
+3yl
+5s
+2ular
+6ist
+9s
+6ly
+6s
+5te
+7d
+4i
+5st
+7s
+4omotor
+4us
+1d
+2a
+3h
+4s
+3l
+4ique
+8s
+5sk
+7s
+6que
+9s
+4ler
+7s
+4s
+3s
+2d
+3ball
+7s
+3er
+4st
+3ish
+4ties
+5y
+3ly
+3ment
+7s
+3ness
+7es
+3s
+4maker
+9s
+6n
+5en
+2e
+3a
+3on
+5s
+3s
+3um
+5s
+2ic
+3ferous
+3ous
+6ly
+6ness
+9ses
+3sm
+5s
+4t
+5s
+3um
+5s
+2ograph
+8s
+3meter
+8s
+6ries
+7y
+3nate
+7s
+6ist
+9s
+6ologies
+9gist
+9gists
+9gy
+4talgia
+9as
+9c
+9es
+8y
+5ic
+6st
+8s
+5oblast
+9stic
+9sts
+6cete
+9es
+6genic
+9ies
+9y
+7lossum
+9ssums
+7raph
+9phies
+9phs
+9phy
+6id
+8s
+6lite
+9es
+7ogic
+9ical
+9ies
+9ist
+9ists
+9y
+6ma
+8s
+8ta
+9ous
+6phobia
+9bias
+9ral
+9ran
+9re
+9res
+9rous
+6rhynchous
+7nithes
+6stomatous
+3r
+4ant
+7s
+5te
+4ed
+4ful
+4iferous
+9usly
+9usness
+5metries
+9y
+5phore
+9es
+5se
+7d
+7s
+6ing
+5ze
+7d
+7s
+6ing
+4less
+4ous
+7ly
+7ness
+9sses
+4s
+3ur
+5ed
+5ful
+5less
+5s
+2s
+3o
+2yl
+4e
+5s
+4ism
+7s
+4s
+3ssey
+7s
+2zooks
+1e
+2cist
+6s
+3ologic
+9al
+9ally
+8es
+8st
+9ts
+7y
+3umenic
+9al
+9ally
+2dema
+6s
+6ta
+7ose
+8us
+3ipal
+7ly
+5ean
+3ometer
+9s
+2illade
+8s
+2nanthic
+3ological
+8es
+8st
+9ts
+7y
+4mancies
+8y
+7ia
+9s
+5el
+7s
+6ter
+9s
+4phil
+8e
+9s
+8ies
+9st
+9sts
+8s
+8y
+4thera
+9s
+2rlikon
+8s
+3sted
+7s
+2s
+3ophageal
+8i
+9tis
+9tises
+8oscope
+9scopes
+9scopy
+8us
+3tradiol
+9ls
+6l
+5in
+7s
+6ol
+8s
+5ogen
+9ic
+9ically
+9s
+6ne
+8s
+6us
+5um
+7s
+6s
+7es
+2uvre
+6s
+1f
+2ay
+4s
+2f
+3al
+5s
+3beat
+7s
+3cast
+7s
+4ut
+6s
+3ed
+4nce
+7ful
+7less
+7s
+5d
+6ed
+8ly
+7r
+8s
+6ing
+6ress
+9ses
+6s
+5se
+7less
+7s
+6ive
+9ly
+9ness
+9nesses
+9s
+4r
+5able
+5ed
+6e
+7s
+6r
+7s
+5ing
+8s
+5or
+7s
+5s
+5tories
+8y
+3hand
+7ed
+9ly
+9ness
+9nesses
+3ice
+6holder
+9ders
+6r
+7ed
+7ing
+7s
+6s
+5ial
+8dom
+9oms
+8ese
+9ses
+8ism
+9sms
+9ties
+9ty
+8ly
+8s
+8ties
+9y
+7nt
+9s
+7ries
+8y
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6nal
+9ly
+9s
+6ous
+9ly
+9ness
+9nesses
+4e
+5s
+4ng
+6s
+4sh
+6ly
+6ness
+9ses
+3key
+3line
+4oad
+7ed
+7ing
+7s
+3peak
+4rint
+8ed
+8ing
+8s
+4ut
+6s
+3ramp
+7s
+3s
+4addle
+9d
+9s
+8ing
+4couring
+9ngs
+5reen
+5um
+7s
+4eason
+9s
+5t
+6able
+6s
+6ting
+4hoot
+8s
+6re
+8d
+8s
+7ing
+9gs
+4ide
+7r
+8s
+7s
+4pring
+9s
+4tage
+8s
+3take
+7s
+4rack
+3y
+2lag
+5s
+2t
+3en
+5er
+6st
+5ness
+9es
+5times
+4r
+4st
+3times
+1gam
+4ic
+4s
+2doad
+6s
+2ee
+4d
+4s
+2gin
+5s
+2ham
+5ic
+6st
+8s
+5s
+2ival
+4e
+5s
+2le
+4d
+4r
+5s
+4s
+3ing
+6s
+2mic
+2re
+4ish
+7ly
+6m
+7s
+4s
+5s
+6es
+3ish
+6ly
+5m
+6s
+1h
+2ed
+2ia
+4s
+3ng
+2m
+3age
+6s
+3ic
+5ally
+3meter
+8s
+3s
+2o
+3ne
+2s
+1i
+2dia
+4oid
+4um
+2k
+3ist
+6s
+3s
+2l
+3bird
+7s
+3camp
+7s
+5n
+6s
+4loth
+8s
+4up
+6s
+3ed
+4r
+5ies
+5s
+5y
+3field
+8s
+5red
+3gas
+6es
+3hole
+7s
+3ier
+5st
+4ly
+4ness
+8es
+5g
+3let
+6s
+3man
+4en
+3nut
+6s
+3paper
+8s
+4roof
+3s
+4eed
+7s
+4kin
+7s
+4tone
+8s
+3tight
+3way
+6s
+3y
+2nk
+4ed
+4ing
+4s
+3ologies
+7y
+4mel
+7s
+3t
+4ed
+4ing
+4ment
+8s
+4s
+2s
+2ticica
+8s
+1jime
+5s
+1ka
+3pi
+5s
+3s
+3y
+4ed
+4ing
+4s
+2e
+3h
+4s
+3s
+3ydoke
+8y
+2imono
+7s
+2ra
+4s
+2ta
+4s
+1ld
+3e
+4n
+5ed
+5ing
+5s
+4r
+4st
+3fangled
+3ie
+5s
+4sh
+3ness
+7es
+3s
+4quaw
+8s
+4ter
+7s
+5yle
+8s
+3wife
+5ves
+3y
+2e
+3a
+4ceous
+4ginous
+9sly
+9sness
+4nder
+8s
+6omycin
+9cins
+4ria
+7s
+4ster
+8s
+4te
+6s
+3cranal
+7on
+9s
+3fiant
+5n
+6e
+7s
+6ic
+6s
+3ic
+4ferous
+4n
+5e
+6s
+5s
+3nt
+3o
+4graph
+9ic
+9ies
+9s
+9y
+4margarin
+9rine
+9rines
+9rins
+4philic
+4resin
+9ous
+9s
+4s
+3raceous
+3s
+4tra
+7s
+3um
+5s
+2fact
+6ed
+6ible
+7ng
+7on
+9s
+7ve
+6ologies
+9gist
+9gists
+9gy
+7meter
+9ters
+9tries
+9try
+7ries
+8y
+6ronics
+6s
+2ibanum
+8s
+3cook
+7s
+3d
+3gaemia
+9s
+8c
+5rch
+8al
+8ic
+9cal
+9cally
+9es
+8s
+8y
+4emia
+8s
+7c
+4ist
+7s
+4ocene
+6haete
+9tes
+7rome
+9mes
+6lase
+9es
+6ythaemia
+9aemias
+5dendrocyte
+9roglia
+5gene
+9s
+5mer
+8ic
+9sation
+9zation
+8ous
+8s
+5nucleotide
+5peptide
+9ides
+6hagies
+9ous
+9y
+6olies
+9stic
+8y
+6sonies
+9istic
+9y
+5saccharide
+6permia
+9mias
+5trophic
+9hies
+9hy
+4ureses
+8is
+7tic
+6ia
+8s
+7c
+3ngo
+6s
+3o
+4s
+3phant
+8s
+3tories
+6y
+3vaceous
+5ry
+4e
+5nite
+9s
+5r
+6s
+5s
+5t
+6s
+4ine
+7s
+6ic
+7tic
+2la
+4mh
+6s
+4s
+4v
+5s
+3er
+5s
+3ie
+5s
+2m
+3s
+2ogies
+5st
+7s
+4oan
+7ed
+7ing
+7s
+4y
+3liuqui
+9s
+3roso
+7s
+2pae
+3e
+4s
+2ycook
+7s
+3koek
+7s
+3mpiad
+8s
+6cs
+1m
+2adhaun
+8s
+3sa
+5l
+4um
+2ber
+5s
+3re
+5lla
+8s
+5s
+4ogenous
+5meter
+9rs
+5phil
+9e
+9es
+9ous
+9s
+7obe
+9es
+9ous
+3u
+4dsman
+9ship
+9ships
+7en
+4s
+2ega
+5s
+3let
+6s
+6te
+8s
+3n
+4ed
+4ing
+4s
+4ta
+6l
+5um
+7s
+3r
+4s
+4ta
+6s
+2icron
+7s
+3god
+3kron
+7s
+3nous
+7ly
+7ness
+9sses
+3ssible
+6on
+8s
+6ve
+8ness
+9esses
+3t
+4s
+4tance
+9s
+5ed
+6r
+7s
+5ing
+2lah
+5s
+2matea
+6um
+5idia
+9l
+8um
+5ophore
+9res
+9rous
+2neities
+6y
+3iana
+5rch
+8s
+4benevolence
+9olent
+5us
+7es
+7ses
+4competence
+9tences
+9tent
+4directional
+4eties
+6y
+4farious
+9usly
+9usness
+5erous
+5ic
+7ence
+9ces
+9t
+6ed
+7s
+5orm
+8ities
+9ty
+5y
+6ing
+4genous
+4mode
+4parities
+9y
+7ous
+6tient
+5otence
+9ces
+9cies
+9cy
+9t
+9tly
+9ts
+5resence
+9nces
+9nt
+4range
+9s
+4science
+9ces
+9t
+9tly
+4um
+6s
+4vora
+7e
+8s
+7ies
+7ous
+9sly
+9sness
+7y
+2ohyoid
+8s
+3phagia
+9s
+8c
+8es
+7ous
+7y
+5oria
+8on
+4late
+8s
+7oscopies
+9copy
+3v
+4s
+2phacite
+9s
+5li
+7c
+6oid
+7mancies
+9ncy
+7s
+8kepses
+9epsis
+2rah
+5s
+2s
+1n
+2ager
+6s
+4raceous
+5i
+3nism
+7s
+6t
+7ic
+7s
+2beat
+6s
+3oard
+2ce
+4r
+5s
+4s
+4t
+3hocerciases
+9iasis
+3idium
+8s
+3ogen
+7e
+8s
+9es
+9is
+8ticist
+9icists
+7ic
+9ities
+9ity
+7ous
+7s
+4logic
+9al
+8es
+8st
+9ts
+7y
+5yses
+7is
+6tic
+9s
+4me
+6s
+6ter
+9s
+5ing
+8s
+4rnavirus
+9ruses
+4st
+6man
+7en
+6s
+4tomies
+7y
+4virus
+9es
+3us
+2datra
+7s
+3ine
+6s
+5g
+6s
+3ogram
+8s
+7ph
+9s
+2e
+3fold
+3iric
+7ally
+5ocritic
+9tical
+9ticism
+9tics
+6dynia
+9ias
+6logies
+9y
+6mancer
+9cers
+9cies
+9cy
+6scopies
+9pist
+9pists
+9py
+3ly
+3ness
+7es
+3r
+4ier
+6st
+4ous
+7ly
+7ness
+9sses
+4s
+4y
+3s
+4elf
+3time
+3yer
+6s
+4re
+6s
+2fall
+6s
+3low
+6s
+2gaonga
+8s
+3oing
+7ness
+9sses
+7s
+2ie
+3on
+5ed
+5ier
+7st
+6ng
+5s
+6kin
+9s
+5y
+3ric
+3scoid
+3um
+5s
+2kus
+2lay
+5s
+3iest
+4ne
+6r
+7s
+3oad
+6ed
+6ing
+6s
+4oker
+8s
+6ing
+3y
+2ned
+3ing
+2o
+3centaur
+9rs
+3masiologies
+9ogy
+6tic
+9ally
+9ian
+9ians
+9on
+9ons
+9s
+5tologies
+9gist
+9gists
+9gy
+7poeia
+9eias
+9eic
+9eses
+9esis
+9etic
+9ieses
+9iesis
+3s
+2rush
+6es
+6ing
+2s
+3creen
+3et
+5s
+5ter
+8s
+6ing
+9s
+3hore
+6ing
+9s
+3ide
+6s
+3laught
+9s
+3t
+4age
+4ead
+7s
+4ream
+2tic
+5ally
+3o
+4geneses
+9is
+8tic
+9ically
+7ic
+9ally
+8es
+7y
+4logic
+9al
+9ally
+8es
+8st
+9ts
+7y
+2us
+4es
+2ward
+6ly
+6s
+2y
+3cha
+6s
+5ia
+7s
+6te
+8s
+7is
+9es
+6um
+8s
+5ocryptoses
+9ptosis
+6mancies
+9cy
+6phagies
+9gist
+9gists
+9gy
+8oran
+9rans
+3mous
+3x
+4es
+1o
+2bit
+5s
+2cyst
+6s
+4te
+6s
+2dles
+4ins
+2f
+3ier
+5st
+3s
+3tish
+7es
+3y
+2gamete
+8s
+5ies
+5ous
+8ly
+5y
+3eneses
+7is
+6tic
+5ies
+5y
+3onia
+7l
+6um
+8s
+2h
+3ed
+3ing
+3s
+2idal
+2lachan
+8s
+4kan
+7s
+3ite
+6s
+5h
+6s
+5ic
+3ogic
+7al
+6es
+6st
+8s
+5y
+4ng
+6s
+2m
+3iac
+6k
+7s
+6s
+5k
+6s
+3pah
+6ed
+6ing
+6s
+4h
+5s
+3s
+3ycete
+8s
+2n
+3s
+3t
+4s
+2p
+3ed
+3horectomies
+9omise
+9omised
+9omises
+9omize
+9omized
+9omizes
+9omy
+6itic
+9s
+9ses
+6on
+8s
+4yte
+7s
+6ic
+3ing
+3s
+2r
+3ali
+6s
+3ial
+6s
+4e
+5r
+5st
+2s
+3e
+4s
+3ier
+5st
+3perm
+7s
+4here
+8s
+4ore
+7s
+6ic
+6ous
+3y
+2t
+3heca
+7e
+7l
+3id
+5s
+3s
+2ze
+4d
+4s
+3ier
+5st
+4ly
+4ness
+8es
+5g
+3y
+1p
+2acified
+8r
+9s
+8s
+6y
+7ing
+5ties
+6y
+4ous
+3h
+4s
+3l
+4ed
+5sce
+8d
+8nce
+9ces
+9t
+9tly
+8s
+7ing
+4ine
+7s
+5sed
+5zed
+4s
+3que
+6d
+6ly
+6ness
+9ses
+6r
+6s
+7t
+5ing
+2code
+6s
+2e
+3d
+3idoscope
+9pes
+3n
+4abilities
+9ty
+6le
+4cast
+4ed
+5r
+6s
+5st
+4handed
+9dly
+9dness
+5earted
+9edly
+9edness
+4ing
+7s
+4ly
+4mouthed
+9edly
+9edness
+4ness
+8es
+4s
+5ide
+8s
+4work
+8s
+3pe
+5s
+3ra
+5bilities
+9ty
+6le
+7y
+5goer
+9s
+7ing
+9gs
+5nd
+7s
+6t
+7ly
+7s
+5s
+5te
+7d
+7s
+6ic
+8ally
+8s
+7ng
+7on
+9al
+9alism
+9alisms
+9alist
+9alists
+9ally
+9ism
+9isms
+9ist
+9ists
+9s
+7se
+9d
+9s
+8ing
+7ve
+9ly
+9ness
+9nesses
+9s
+8ities
+9ty
+7ze
+9d
+9s
+8ing
+6or
+8less
+8s
+4cele
+8s
+5ula
+8r
+9s
+8te
+9ed
+7e
+8s
+7um
+9s
+4etta
+8s
+7ist
+9ts
+4on
+6s
+5se
+7ly
+7ness
+9sses
+6ities
+8y
+3s
+2gefok
+2hicalcite
+9tes
+5leide
+9es
+4dian
+8s
+7ria
+9um
+9ums
+4olater
+9rs
+8ries
+9ous
+9y
+6ite
+9s
+8ic
+6ogic
+9cal
+9es
+9st
+9sts
+8y
+5morph
+9hic
+9hous
+9hs
+5phagous
+7ilist
+9ists
+4te
+6s
+5ic
+4ura
+7n
+8s
+7s
+6id
+8s
+6oid
+9s
+3thalmia
+9as
+9c
+9st
+9sts
+9tis
+9tises
+8ologic
+9logies
+9logist
+9logy
+9meter
+9meters
+9metry
+9phobia
+9plegia
+9scope
+9scopes
+9scopic
+9scopy
+2iate
+6d
+6s
+5ing
+3ficer
+8s
+3nable
+4e
+5d
+5s
+4g
+4icus
+8es
+5ng
+5on
+7ated
+9edly
+9edness
+9ely
+9ive
+9ively
+9or
+9ors
+7ed
+7ist
+9ts
+7s
+3oid
+6s
+3someter
+9rs
+4thobranch
+9anchs
+7coelian
+9elous
+7domoi
+9mos
+7glossal
+8nathism
+9athous
+8raph
+9aphic
+9aphies
+9aphs
+9aphy
+7soma
+9mata
+7tonic
+9nos
+9noses
+3um
+5ism
+8s
+5s
+2obalsam
+9s
+3deldoc
+9s
+3panax
+8es
+3rice
+7s
+3ssum
+7s
+3therapies
+9y
+2pidan
+7s
+4gnerate
+9ted
+9tes
+9ting
+6orate
+9ted
+9tes
+9ting
+9tion
+9tions
+4lant
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+3o
+4nencies
+8y
+7t
+8s
+4rtune
+9ly
+9ness
+9nesses
+8ism
+9sms
+9st
+9stic
+9sts
+9ties
+9ty
+4s
+5abilities
+9ity
+7le
+8y
+6l
+7s
+5e
+6d
+6less
+6r
+7s
+6s
+5ing
+8ly
+6te
+8ly
+8ness
+9esses
+8s
+7ion
+9nal
+9nist
+9nists
+9nless
+9ns
+8ve
+3ress
+7ed
+8s
+7ing
+9gly
+8on
+9ns
+8ve
+9ely
+9eness
+7or
+9s
+4obrious
+9usly
+9usness
+8um
+9ms
+3ugn
+6ancies
+9y
+8t
+9ly
+9s
+6ed
+7r
+8s
+6ing
+6s
+2s
+3imath
+8ies
+8s
+8y
+4n
+5s
+4ometer
+9rs
+3omania
+9c
+9cs
+9s
+4nic
+6fication
+9ations
+8ed
+9s
+7y
+8ing
+6n
+7s
+6sation
+9ions
+7e
+8d
+8s
+7ing
+6um
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+2t
+3ant
+6s
+4tive
+8ly
+8s
+3ed
+4r
+5s
+3ic
+5al
+7ly
+5ian
+8s
+6st
+8s
+5s
+4ma
+6l
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+6te
+8s
+5e
+6s
+5isation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+9cal
+9cally
+8s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5um
+7s
+4ng
+4on
+6al
+8ities
+9ty
+8ly
+8s
+6ed
+7e
+8s
+6ing
+6s
+3oacoustic
+4electronic
+9ronics
+4kinetic
+4logies
+8st
+9ts
+7y
+4meter
+9s
+7ric
+9cal
+9es
+9st
+9sts
+8y
+4phone
+9s
+3ronics
+3s
+2ulence
+8s
+7ies
+7y
+6t
+7ly
+4us
+6es
+3ntia
+7s
+3s
+4cle
+7s
+5ula
+8r
+7e
+8s
+7um
+4es
+1quassa
+7s
+1r
+2a
+3ch
+5e
+6s
+4ies
+4le
+6d
+6s
+5ing
+4ular
+8ities
+9ty
+8ly
+8ness
+9esses
+6ous
+9ly
+9ness
+9nesses
+4y
+3d
+3gious
+3l
+4ism
+7s
+6t
+7s
+5ties
+6y
+4ly
+4s
+3ng
+5e
+6ade
+9s
+6r
+7ie
+9s
+7y
+6s
+7t
+6wood
+9ds
+6y
+5ier
+7st
+6sh
+5s
+5utan
+9s
+5y
+4t
+5s
+3ria
+6n
+7s
+5on
+7s
+5um
+7s
+3te
+5d
+5s
+4ing
+5on
+7s
+4or
+6ial
+8n
+9s
+7cal
+9lly
+7es
+7o
+8s
+6s
+6y
+4ress
+8es
+5ices
+6x
+7es
+2b
+3ed
+3icular
+9es
+9is
+9ities
+9ity
+9ly
+8te
+9ed
+4er
+5st
+4ng
+4t
+5a
+6l
+7ly
+7s
+6s
+5ed
+6r
+7s
+5ies
+6ng
+5s
+5y
+3less
+3s
+3y
+2c
+3a
+4s
+3ein
+6s
+3hard
+7ing
+9gs
+8st
+9ts
+7man
+8en
+7s
+5t
+6s
+4el
+6la
+8s
+6s
+5ses
+6is
+6ographies
+9aphy
+6tic
+9s
+7ra
+9l
+9list
+9lists
+9lly
+9s
+9te
+9ted
+9ter
+9ters
+9tes
+9ting
+9tion
+9tional
+9tions
+9tor
+9tors
+8ic
+9na
+9nas
+9on
+9ons
+4id
+6aceous
+6ectomies
+9omy
+7ous
+6ist
+9s
+6like
+6ologies
+9gist
+9gists
+9gy
+7mania
+9niac
+9niacs
+9nias
+6s
+5ectomies
+9my
+5l
+6la
+8s
+6s
+5s
+6es
+5tic
+7s
+8es
+3in
+5e
+6s
+5ol
+7s
+5s
+3s
+2d
+3ain
+6able
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4lian
+6um
+8s
+3eal
+6s
+4r
+5able
+5ed
+6r
+7s
+5ing
+8s
+5less
+6ies
+7ness
+9sses
+6y
+5s
+3inaire
+9s
+6l
+7ly
+7s
+6nce
+9s
+7d
+8s
+7t
+8s
+6r
+7ier
+9s
+9st
+8ly
+8ness
+9esses
+7s
+7y
+6te
+8d
+8ly
+8s
+7ing
+8on
+9ns
+5ee
+7s
+6s
+3nance
+8s
+3o
+4nnance
+9es
+4s
+3s
+3ure
+6s
+5ous
+2e
+3ad
+5es
+5s
+3cchiette
+9tes
+9ti
+4tic
+6ve
+3gano
+7s
+3ide
+6s
+3odont
+8s
+4graphic
+9ical
+9ically
+9ies
+9y
+4logical
+8es
+8st
+9ts
+7y
+3pearch
+9ed
+9es
+9ing
+3s
+4tunck
+3weed
+7s
+3xin
+6s
+5s
+6es
+2f
+3e
+4s
+3ray
+6s
+3s
+2gan
+5a
+5die
+8s
+6y
+5elle
+9s
+5ic
+7al
+9ly
+7ism
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+7s
+6sability
+9le
+8tion
+9ional
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8al
+9lly
+8ic
+9cally
+8s
+7t
+8rum
+9ums
+8s
+6ties
+7y
+6zability
+9le
+8tion
+9ional
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5ochlorine
+9orines
+6geneses
+9esis
+9etic
+9ies
+9y
+7ram
+9ms
+9phic
+9phical
+9phies
+9phist
+9phists
+9phy
+6leptic
+7ogical
+9ies
+9ist
+9ists
+9y
+6mercurial
+8tallic
+9allics
+6n
+7s
+6phosphate
+6sol
+9s
+6therapies
+9rapy
+7in
+5s
+5um
+7s
+5za
+7s
+6ine
+9s
+3eat
+6s
+3ia
+5c
+5s
+6t
+7ic
+9ally
+7s
+4c
+4es
+4llous
+3one
+6s
+3ue
+5s
+4lous
+2ibatid
+8s
+4i
+5s
+3calche
+9s
+4halc
+8eous
+8s
+3el
+5led
+5s
+4ncies
+6y
+5t
+6al
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9ties
+9ty
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+7te
+9d
+9s
+8ing
+9on
+9onal
+9onally
+9ons
+8or
+9rs
+6ed
+7er
+9ed
+9ing
+9ings
+9s
+7r
+8s
+6ing
+6s
+3fex
+6es
+4ice
+7s
+6ial
+4lamme
+9s
+3gami
+7s
+5n
+6e
+7s
+6s
+6um
+8s
+4in
+6al
+8ities
+9ty
+8ly
+8s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9vely
+8or
+9rs
+6s
+3hou
+6s
+3llion
+8s
+3nasal
+8ly
+8s
+3ole
+6s
+3sha
+6s
+4mological
+9ies
+9y
+4on
+6s
+3xa
+5s
+2le
+4ans
+7es
+4s
+3istat
+8s
+3on
+5s
+4p
+5s
+2mer
+5s
+3olu
+6s
+2nament
+8al
+9lly
+9ls
+9tion
+9tions
+8ed
+9r
+9rs
+8ing
+9st
+9sts
+8s
+4te
+6ly
+6ness
+9ses
+6r
+6st
+3erier
+7st
+6ness
+9ses
+5y
+3is
+5es
+4thes
+6ic
+8hnite
+9nites
+7ne
+9s
+7schian
+9hians
+6odelphian
+9lphic
+9lphous
+7galum
+9lums
+7id
+7logic
+9gical
+9gies
+9gist
+9gists
+9gy
+7mancies
+9ncy
+9ntic
+8orph
+9rphic
+9rphs
+7philies
+9ilous
+9ily
+9obia
+9obias
+8od
+9ds
+8ter
+9ers
+7rhynchus
+7saur
+9urs
+8copies
+9opy
+8es
+8is
+2obanchaceous
+3gen
+6eses
+8is
+7tic
+9cally
+6ic
+8ally
+7es
+6s
+6y
+4rapher
+9rs
+8ic
+9cal
+9cally
+9es
+8y
+3ide
+6s
+3logical
+9lly
+7es
+7st
+9s
+6y
+3meter
+8s
+3nasal
+3pesa
+7s
+4haryngeal
+9ges
+9x
+9xes
+3rotundities
+9ity
+3tund
+7ities
+9y
+2phan
+6age
+9s
+6ed
+6hood
+9ds
+6ing
+7sm
+9s
+6s
+5rion
+9s
+4eoreon
+9ns
+4ic
+6al
+8ly
+5sm
+7s
+4rey
+7ed
+7s
+3iment
+8s
+4n
+5e
+6s
+5s
+2ra
+4man
+5en
+3eries
+5y
+3ice
+6s
+4s
+5es
+5root
+9s
+2s
+3eille
+8s
+4llic
+2t
+3anique
+9s
+3hian
+5con
+8s
+4o
+5axes
+7is
+5borate
+9tes
+8ic
+5caine
+9es
+6enter
+9ers
+9re
+9res
+7phalic
+9alies
+9alous
+9aly
+6hromatic
+9matism
+6lase
+9es
+5diagonal
+9onals
+6ontia
+9ias
+9ic
+9ically
+9ics
+9ist
+9ists
+7x
+8es
+8ies
+8ly
+8y
+6romic
+9ics
+9ies
+9y
+5epic
+9al
+9ally
+8es
+8st
+9ts
+7y
+5geneses
+9sis
+9tic
+8ic
+9cally
+9cs
+6nathic
+9hies
+9hism
+9hisms
+9hous
+9hy
+6onal
+9lise
+9lised
+9lises
+9lising
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lly
+6rade
+8ph
+9her
+9hers
+9hic
+9hical
+9hies
+9hist
+9hists
+9hs
+9hy
+5hydrogen
+9ogens
+5logy
+5molecular
+7rphic
+5normal
+5paedic
+9ical
+9ically
+9ics
+9ies
+9ist
+9ists
+9y
+6edia
+9as
+9c
+9cal
+9cally
+9cs
+9es
+9st
+9sts
+8y
+6hosphate
+9phates
+9phoric
+7yre
+9es
+9ic
+6inakoid
+9koids
+6noea
+9as
+6od
+8s
+6raxes
+9ies
+9is
+9y
+7ism
+9ms
+6sychiatry
+6ter
+9a
+9an
+9ans
+9ist
+9ists
+9oid
+9oids
+9ology
+9on
+9ous
+9s
+7ic
+9s
+8st
+9ts
+6yroxene
+9xenes
+5rexia
+9as
+6hombic
+5s
+6cope
+9es
+9ic
+6es
+6ilicate
+9cates
+7s
+6tatic
+7ichies
+9hous
+9hy
+5tic
+8s
+7st
+9s
+6one
+9s
+9ses
+9sis
+8ic
+7pic
+6ropic
+9ies
+9ism
+9isms
+9ous
+9y
+6ungstic
+5vanadic
+4ros
+7es
+3olan
+7s
+3s
+2val
+5s
+2yctologies
+9y
+3x
+4es
+2zo
+4s
+1s
+2ar
+2car
+5s
+3heal
+3illate
+9d
+9s
+8ing
+9on
+9onal
+9ons
+9ve
+8or
+9rs
+9ry
+6ogram
+9ams
+9aph
+9aphic
+9aphies
+9aphs
+9aphy
+7scope
+9opes
+9opic
+4ne
+6s
+5ine
+4tance
+9s
+8ies
+8y
+7t
+8ly
+6te
+8d
+8s
+7ing
+8on
+9ns
+3ula
+6nt
+6r
+6te
+8d
+8s
+7ing
+8on
+9ns
+7ories
+9y
+5e
+6s
+5um
+2e
+3s
+3tra
+6s
+2hac
+5s
+2ier
+5ed
+5ies
+5s
+5y
+2mate
+6s
+5ic
+3eteria
+8um
+3iate
+7s
+4c
+5ally
+5s
+4droses
+8is
+4ous
+4ridium
+9ms
+4um
+6s
+3ol
+5al
+7ities
+9y
+6r
+7ities
+9y
+5e
+6s
+5s
+4meter
+9s
+7ric
+9cally
+9es
+8y
+4regulation
+9ations
+9atory
+4se
+6d
+6s
+5ing
+6s
+4tic
+7ally
+4us
+3und
+6a
+7s
+6ine
+9s
+6s
+2naburg
+8s
+2prey
+6s
+2sa
+4rium
+8s
+4ture
+8s
+3ein
+6s
+4let
+7s
+4ous
+7ly
+4ter
+7s
+5ra
+7s
+3ia
+4cle
+7s
+5ular
+4ferous
+5ic
+7ation
+9ions
+6ed
+7r
+8s
+7s
+5raga
+9s
+8e
+9s
+5y
+6ing
+4vorous
+3obuco
+8s
+3uaries
+6y
+2teal
+4ichthyan
+9yans
+5tic
+7des
+7s
+8es
+4nsibilities
+9lity
+8le
+9y
+7ve
+9ly
+6oria
+9es
+9um
+8y
+5t
+6ation
+9ons
+9ous
+9ously
+6s
+4oarthritic
+9ritics
+9ritis
+9roses
+9rosis
+5blast
+9tic
+9ts
+5clases
+9is
+9t
+9tic
+9ts
+6olla
+9as
+6yte
+9s
+5derm
+9al
+9atous
+9ic
+9ous
+9s
+5fibroses
+9osis
+5gen
+8eses
+9sis
+9tic
+8ic
+9es
+8ous
+8s
+8y
+6raphies
+9hy
+5id
+7s
+5logical
+9cally
+9es
+9st
+9sts
+8y
+5ma
+7lacia
+9cial
+9cias
+9cic
+7s
+7ta
+6yelitides
+9itis
+9itises
+5path
+9ic
+9ically
+9ies
+9ist
+9ists
+9s
+9y
+6etroses
+9osis
+6hyte
+9es
+9ic
+6lastic
+9ties
+9ty
+6oroses
+9sis
+9tic
+5sarcoma
+9omas
+9omata
+6es
+6is
+8es
+5tome
+9s
+8ies
+8y
+3ia
+5l
+5ries
+6y
+5te
+4nati
+7o
+8s
+4olar
+7te
+6e
+7s
+4um
+3ler
+6ess
+9es
+6s
+3mark
+7s
+3omate
+8s
+5ies
+5y
+4ses
+5is
+7es
+3raca
+6ean
+7ous
+6isable
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+7zable
+8e
+9d
+9r
+9rs
+9s
+8ing
+6od
+8an
+8e
+9rm
+9rms
+9s
+8ous
+8s
+7n
+5ka
+6on
+4eaceous
+5ger
+8s
+5iculture
+9tures
+9turist
+5ophage
+9ges
+9gies
+9gous
+9gy
+4ich
+7es
+7ism
+9ms
+7like
+1taku
+3lgia
+7s
+6c
+6es
+5y
+3ries
+5ne
+4y
+2her
+5gates
+6uess
+5ness
+9es
+5s
+5where
+7ile
+9es
+6ise
+6orld
+9dish
+9dly
+9ds
+2ic
+3ose
+6ly
+6ness
+9ses
+5ities
+7y
+3tic
+5des
+5s
+6es
+2ocyst
+7ic
+7s
+3laryngology
+4ith
+7ic
+7s
+4ogical
+7es
+7st
+9s
+6y
+3plasties
+8y
+3rrhoea
+9s
+3scleroses
+9sis
+5ope
+8s
+7ic
+8es
+7y
+3toxic
+8ities
+9ty
+2tar
+5s
+4va
+6s
+5ino
+8s
+3er
+5ed
+5ing
+5s
+3o
+4man
+7s
+4s
+3relite
+9s
+1u
+2abain
+7s
+3kari
+7s
+3naniche
+9es
+2baas
+6es
+3it
+5s
+3liette
+9s
+2ch
+4ed
+5s
+4ing
+4t
+5s
+2d
+3s
+2ens
+2ghlied
+7s
+5y
+6ing
+4t
+5ed
+5ing
+5lings
+5ness
+9es
+5s
+3lie
+6d
+6ing
+6s
+3uiya
+7s
+2ija
+5s
+3stiti
+8s
+2k
+3s
+2lachon
+8s
+4kan
+7s
+3d
+4er
+5st
+3k
+4s
+3ong
+6s
+2ma
+4s
+2nce
+5s
+3dy
+2p
+3a
+4s
+3ed
+3h
+4e
+5s
+4s
+3ing
+3s
+2r
+3ali
+6s
+4ng
+6s
+4ri
+6s
+3ebi
+6s
+3ie
+5r
+5st
+3n
+3oboros
+9es
+4logies
+7y
+4scopies
+8y
+3s
+4elf
+6ves
+2s
+3el
+5s
+3t
+4ed
+5r
+6s
+4ing
+5ti
+7s
+4s
+2t
+3achieve
+9ed
+9es
+9ing
+5t
+6ed
+6ing
+6s
+4dd
+6ed
+6ing
+6s
+4ge
+6s
+4rgue
+8d
+8s
+7ing
+4sight
+5k
+6ed
+6ing
+6s
+4te
+3back
+7er
+9s
+7s
+5ke
+7d
+7s
+6ing
+5lance
+9ed
+9es
+9ing
+5r
+6gain
+9ned
+9ning
+9ns
+6k
+7ed
+7ing
+7s
+6red
+7ing
+6s
+5wl
+7ed
+7ing
+7s
+4eam
+7ed
+7ing
+7s
+5g
+6ged
+7ing
+6s
+4id
+6den
+8r
+9s
+7ing
+6s
+4laze
+8d
+8s
+7ing
+5eat
+8ed
+8ing
+8s
+6ss
+8ed
+9s
+8ing
+5oom
+8ed
+8ing
+8s
+5uff
+8ed
+8ing
+8s
+6sh
+8ed
+9s
+8ing
+7ter
+9red
+9ring
+9rs
+4oard
+8s
+6st
+8ed
+8ing
+8s
+5ught
+6nd
+8s
+5x
+6ed
+7s
+6ing
+4rag
+7ged
+8ing
+7s
+6ve
+8d
+8s
+7ing
+6wl
+8ed
+8ing
+8s
+6zen
+9ed
+9ing
+9s
+5eak
+8ing
+8s
+7the
+9ed
+9es
+9ing
+6d
+6ed
+8ing
+9ngs
+8s
+5ibe
+8d
+8s
+7ing
+5oke
+8n
+4uild
+8ing
+9ngs
+8s
+7t
+5lge
+8d
+8s
+7ing
+6k
+7ed
+7ing
+7s
+6lied
+9s
+7y
+8ing
+5rn
+7ed
+7ing
+7s
+7t
+6st
+8ing
+8s
+5y
+6ing
+6s
+4y
+5e
+3call
+7s
+5per
+8ed
+8ing
+8s
+5st
+7e
+8d
+8s
+7ing
+7s
+5tch
+8es
+8ing
+5ught
+5vil
+8ed
+8ing
+8led
+9ing
+8s
+4harge
+9d
+9s
+8ing
+7m
+8ed
+8ing
+8s
+5eat
+8ed
+8ing
+8s
+5id
+7den
+7e
+8d
+8s
+7ing
+4ities
+6y
+4lass
+8ed
+9s
+8ing
+5imb
+8ed
+8ing
+8s
+5omb
+4oach
+8ed
+9s
+8ing
+5me
+7s
+6pete
+9ed
+9es
+9ing
+5ok
+7ed
+7ing
+7s
+5unt
+8ed
+8ing
+8s
+4raftied
+9es
+8y
+9ing
+6wl
+8ed
+8ing
+8s
+5ied
+7s
+5op
+7ped
+8ing
+9ngs
+7s
+6ss
+8ed
+9s
+8ing
+9ngs
+6w
+7d
+8ed
+8ing
+8s
+7ed
+7ing
+7s
+5y
+6ing
+4urse
+8d
+8s
+7ing
+6ve
+8s
+3dacious
+5nce
+8d
+8s
+7ing
+5re
+7d
+7s
+6ing
+5te
+7d
+8ly
+8ness
+9esses
+7s
+6ing
+5zzle
+9d
+9s
+8ing
+4ebate
+9d
+9s
+8ing
+5liver
+9red
+9ring
+9rs
+5sign
+9ed
+9ing
+9s
+4id
+5stance
+9ced
+9ces
+9cing
+4o
+5dge
+8d
+8s
+7ing
+5er
+7s
+6s
+5ing
+5ne
+5or
+7s
+8man
+9anship
+9en
+8y
+4rag
+7ged
+8ing
+7s
+6nk
+6w
+7ing
+7n
+7s
+5eam
+8ed
+8ing
+8s
+8t
+6ss
+8ed
+9s
+8ing
+6w
+5ink
+8ing
+8s
+6ve
+8n
+8s
+7ing
+5op
+7ped
+8ing
+7s
+6ve
+5unk
+4uel
+7ed
+7ing
+7led
+8ing
+7s
+5re
+7d
+7s
+6ing
+4well
+8ed
+8ing
+8s
+7t
+3earn
+7ed
+7ing
+7s
+5t
+6en
+6ing
+6s
+4cho
+7ed
+8s
+7ing
+4d
+5ge
+7s
+4r
+5coat
+9s
+7urse
+9ses
+5most
+5s
+5wear
+9s
+3fable
+8d
+8s
+7ing
+5ce
+7d
+7s
+6ing
+5ll
+7s
+5ngthief
+9ieves
+5st
+7ed
+7ing
+7s
+5wn
+7ed
+7ing
+7s
+4east
+8ed
+8ing
+8s
+5el
+7ing
+7s
+5lt
+5nce
+8d
+8s
+7ing
+4ield
+8er
+9rs
+8s
+5ght
+8ing
+9ngs
+8s
+6ure
+9d
+9s
+8ing
+5nd
+7ing
+7s
+5re
+7d
+7s
+6ing
+5sh
+7ed
+8s
+7ing
+5t
+6s
+6ted
+8r
+9s
+7ing
+9gs
+4lank
+8ed
+8ing
+8s
+6sh
+8ed
+9s
+8ing
+5ew
+5ies
+6ng
+8s
+5oat
+8ed
+8ing
+8s
+6w
+7ed
+7ing
+9gs
+7n
+7s
+5ush
+8ed
+9s
+8ing
+5y
+6ing
+4ool
+7ed
+7ing
+7s
+6t
+7ed
+7ing
+7s
+5ught
+6nd
+5x
+6ed
+7s
+6ing
+4rown
+8ed
+8ing
+8s
+4umble
+9d
+9s
+8ing
+3gain
+7ed
+7ing
+7s
+5llop
+9ed
+9ing
+9s
+5mble
+9d
+9s
+8ing
+5s
+6es
+6sed
+8s
+7ing
+9gs
+5te
+7s
+5ve
+5ze
+7d
+7s
+6ing
+4eneral
+9led
+9ling
+9lled
+9lling
+9ls
+4ive
+7n
+7s
+6ing
+9s
+4lare
+8d
+8s
+7ing
+5eam
+8ed
+8ing
+8s
+5itter
+9red
+9ring
+9rs
+5ow
+7ed
+7ing
+7s
+4naw
+7ed
+7ing
+7n
+7s
+4o
+5er
+7s
+6s
+5ing
+8ness
+9esses
+8s
+5ne
+4rew
+5in
+7ned
+8ing
+7s
+5oss
+8ed
+9s
+8ing
+6up
+8s
+6w
+7ing
+7n
+7s
+7th
+9s
+4uard
+8s
+5ess
+8ed
+9s
+8ing
+5ide
+8d
+8s
+7ing
+5n
+6ned
+7ing
+6s
+5sh
+7ed
+8s
+7ing
+3handle
+9d
+9s
+8ing
+5ul
+7er
+9s
+7s
+4ear
+7d
+7ing
+7s
+5r
+4ire
+7d
+7s
+6ing
+5t
+6s
+6ting
+4omer
+8ed
+8ing
+8s
+5use
+8s
+5wl
+7ed
+7ing
+7s
+4umor
+8ed
+8ing
+8s
+5nt
+7ed
+7ing
+7s
+5stle
+9d
+9s
+8ing
+4yre
+7d
+7s
+6ing
+3ing
+6s
+5trigue
+9ued
+9ues
+9uing
+3jest
+7ed
+7ing
+7s
+5t
+6s
+6ting
+9gs
+4inx
+7ed
+8s
+7ing
+4ockey
+9ed
+9ing
+9s
+4uggle
+9d
+9s
+8ing
+5mp
+7ed
+7ing
+7s
+5t
+6s
+6ted
+7ing
+9gs
+3keep
+7ing
+7s
+5pt
+4ick
+7ed
+7ing
+7s
+5ll
+7ed
+7ing
+7s
+5ss
+7ed
+8s
+7ing
+3laid
+6n
+5nd
+7er
+9s
+7ish
+9hly
+9hness
+7s
+5sh
+7es
+6t
+7ed
+7ing
+7s
+5ugh
+8ed
+8ing
+8s
+6nce
+9d
+9s
+8h
+9ed
+9es
+9ing
+8ing
+5w
+6ed
+6ing
+6ries
+7y
+6s
+5y
+6ing
+6s
+4ead
+7ing
+7s
+6p
+7ed
+7ing
+7s
+7t
+6rn
+8ed
+8ing
+8s
+8t
+5d
+5r
+6s
+5t
+6s
+4ie
+6d
+6r
+7s
+6s
+5ne
+7ar
+7d
+7r
+8s
+7s
+6ing
+5ve
+7d
+7r
+8s
+7s
+6ing
+4odging
+9gs
+5ok
+7ed
+7ing
+7s
+5ve
+7d
+7s
+6ing
+4ustre
+9d
+9s
+8ing
+4ying
+3man
+6euver
+9ered
+9ering
+9ers
+6ipulate
+9lated
+9lates
+9lating
+6ned
+7ing
+6oeuvre
+9vred
+9vres
+9vring
+6s
+6tle
+9d
+9s
+8ing
+5rch
+8ed
+9s
+8ing
+6riage
+9ges
+5ster
+9ed
+9ing
+9s
+5tch
+8ed
+9s
+8ing
+4easure
+9ed
+9es
+9ing
+4ode
+7d
+8ly
+8ness
+9esses
+7s
+6ing
+5st
+5ve
+7d
+7s
+6ing
+4uscle
+9d
+9s
+8ing
+3name
+7d
+7s
+6ing
+4ess
+7es
+4ight
+8ed
+8ing
+8s
+4umber
+9ed
+9ing
+9s
+3office
+9s
+4rganise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+3pace
+7d
+7s
+6ing
+5int
+8ed
+8ing
+8s
+5rt
+7s
+5ss
+7ed
+8s
+7ing
+8on
+9ned
+9ning
+9ns
+5tient
+9ts
+4eep
+7ed
+7ing
+7s
+6r
+7ed
+7ing
+7s
+5ople
+9d
+9s
+8ing
+5rform
+9med
+9ming
+9ms
+4itch
+8ed
+9s
+8ing
+6ied
+8s
+6y
+7ing
+4lace
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+6n
+7ned
+8ing
+7s
+6y
+7ed
+7ing
+7s
+5od
+7ded
+8ing
+7s
+6t
+7s
+7ted
+8ing
+4oint
+8ed
+8ing
+8s
+5litick
+9cked
+9cking
+9cks
+6l
+7ed
+7ing
+7s
+5pulate
+9ted
+9tes
+9ting
+5rt
+7er
+9s
+7s
+5st
+7s
+5ur
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5wer
+8ed
+8ing
+8s
+4ray
+7ed
+7ing
+7s
+5each
+9ed
+9es
+9ing
+6en
+8ed
+8ing
+8s
+6ss
+8ed
+9s
+8ing
+5ice
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5oduce
+9ed
+9es
+9ing
+6mise
+9ed
+9es
+9ing
+4ull
+7ed
+7ing
+7s
+5nch
+8ed
+9s
+8ing
+5pil
+8s
+5rsue
+9d
+9s
+8ing
+5sh
+7ed
+8s
+7ing
+5t
+6s
+6ted
+7ing
+3quarters
+5ote
+8d
+8s
+7ing
+3race
+7d
+7s
+6ing
+5ge
+7d
+7ous
+9sly
+9sness
+7s
+6ing
+5ise
+8d
+8s
+7ing
+5n
+6ce
+8s
+6g
+7e
+8d
+8s
+7ing
+6k
+7ed
+7ing
+7s
+5te
+7d
+7s
+6ing
+5ve
+7d
+7s
+6ing
+4e
+5ach
+8ed
+9s
+8ing
+6d
+7ing
+7s
+6son
+9ed
+9ing
+9s
+5bound
+9ded
+9ding
+9ds
+5ckon
+9ed
+9ing
+9s
+6uidance
+9ances
+5d
+6ded
+8n
+9ed
+9ing
+9s
+7ing
+6s
+5ign
+8ed
+8ing
+8s
+5lief
+9s
+5mer
+8s
+5produce
+9uced
+9uces
+9ucing
+4idden
+6e
+7r
+8s
+7s
+6ing
+5g
+6ged
+8r
+9s
+7ing
+6ht
+8ly
+6s
+5ng
+7ing
+7s
+5val
+8ed
+8ing
+8led
+9ing
+8s
+4o
+5ar
+7ed
+7ing
+7s
+5ck
+7ed
+7ing
+7s
+5de
+5ll
+7ed
+7ing
+7s
+5op
+7er
+9s
+7s
+6t
+7ed
+7ing
+7s
+5pe
+7r
+8s
+7s
+5s
+5w
+6ed
+6ing
+6s
+4un
+6g
+6ner
+9s
+7ing
+6s
+5sh
+7ed
+8s
+7ing
+3s
+4aid
+6l
+7ed
+7ing
+7s
+5ng
+5t
+5vor
+8ed
+8ing
+8s
+5w
+5y
+6ing
+6s
+4cheme
+9d
+9s
+8ing
+5old
+8ed
+8ing
+8s
+6op
+8ed
+8ing
+8s
+6re
+8d
+8s
+7ing
+7n
+8ed
+8ing
+8s
+5ream
+9ed
+9ing
+9s
+4ee
+6ing
+6n
+6s
+5ll
+7ing
+7s
+5rt
+7s
+6ve
+8d
+8s
+7ing
+5t
+6s
+6ting
+9gs
+7lement
+9ments
+4hame
+8d
+8s
+7ing
+5ine
+8d
+8s
+7ing
+5one
+6ot
+8ing
+8s
+6t
+7s
+6ut
+8ed
+8ing
+8s
+4ide
+7r
+8ness
+9esses
+8s
+7s
+5ght
+8s
+5n
+6g
+7ing
+7s
+6ned
+7ing
+6s
+5t
+6s
+6ting
+5ze
+7d
+7s
+4kate
+8d
+8s
+7ing
+5irt
+8s
+4leep
+8ing
+8s
+6pt
+5ick
+8ed
+8ing
+8s
+4mart
+8ed
+8ing
+8s
+5ell
+8ed
+8ing
+8s
+7t
+5ile
+8d
+8s
+7ing
+5oke
+8d
+8s
+7ing
+4nore
+8d
+8s
+7ing
+4oar
+7ed
+7ing
+7s
+5ld
+6e
+7s
+5urce
+9d
+9s
+8ing
+9ngs
+4pan
+7ned
+8ing
+7s
+6rkle
+9ed
+9es
+9ing
+5eak
+8ing
+8s
+6ckle
+9es
+6d
+6ed
+8ed
+8ing
+8s
+6ll
+8ed
+8ing
+8s
+7t
+6nd
+8ing
+8s
+7t
+5oke
+8n
+9ly
+9ness
+9nesses
+6rt
+8ed
+8ing
+8s
+5rang
+6ead
+9ing
+9s
+6ing
+9ing
+9s
+8t
+9ed
+9ing
+9s
+6ung
+4tand
+8ing
+9ngly
+8s
+6re
+8d
+8s
+7ing
+7t
+8ed
+8ing
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+6y
+7ed
+7ing
+7s
+5eer
+8ed
+8ing
+8s
+6p
+7ped
+8ing
+7s
+5ood
+5rain
+9ed
+9ing
+9s
+6etch
+9hed
+9hes
+9hing
+6idden
+8e
+9s
+8ing
+7ke
+9s
+8ing
+7p
+8ped
+9ing
+8s
+7ve
+9n
+9s
+8ing
+6ode
+7ke
+9s
+7ve
+6uck
+5udied
+9s
+7y
+8ing
+6nt
+8ed
+8ing
+8s
+4ulk
+7ed
+7ing
+7s
+5m
+6med
+7ing
+6s
+5ng
+4wam
+6re
+5ear
+8ing
+8s
+6ep
+8ing
+8s
+7ten
+9ned
+9ning
+9ns
+6ll
+8ed
+8ing
+8s
+6pt
+5im
+7ming
+7s
+6ng
+8er
+9rs
+8ing
+8s
+5ollen
+6re
+7n
+5um
+6ng
+3take
+7n
+7s
+6ing
+5lk
+7ed
+7ing
+7s
+5sk
+7ed
+7ing
+7s
+4ell
+7ing
+7s
+4hank
+8ed
+8ing
+8s
+5ieve
+9d
+9s
+8ing
+6nk
+8ing
+8s
+5ought
+5rew
+6ob
+8bed
+9ing
+8s
+7w
+8ing
+8n
+8s
+6ust
+9ed
+9ing
+9s
+4old
+5ngue
+9d
+9s
+8ing
+5ok
+5p
+6ped
+7ing
+6s
+5wer
+8ed
+8ing
+8s
+4rade
+8d
+8s
+7ing
+6vel
+9ed
+9ing
+9led
+9ling
+9s
+5ick
+8ed
+8ing
+8s
+5ot
+7s
+7ted
+8ing
+5ump
+8ed
+8ing
+8s
+4urn
+7s
+3value
+8d
+8s
+7ing
+5unt
+8ed
+8ing
+8s
+4enom
+8ed
+8ing
+8s
+4ie
+6d
+6s
+5llain
+9ned
+9ning
+9ns
+4oice
+8d
+8s
+7ing
+5te
+7d
+7r
+8s
+7s
+6ing
+4ying
+3wait
+7ed
+7ing
+7s
+5lk
+7ed
+7ing
+7s
+5r
+6d
+7ly
+7ness
+9sses
+7s
+6red
+7ing
+6s
+5sh
+7es
+6te
+8d
+8s
+7ing
+5tch
+8ed
+9s
+8ing
+4ear
+7ied
+9s
+8ng
+7s
+7y
+8ing
+5ed
+7ed
+7ing
+7s
+6p
+7ing
+7s
+5igh
+8ed
+8ing
+8s
+5ll
+7ed
+7ing
+7s
+5nt
+5pt
+4hirl
+8ed
+8ing
+8s
+4ick
+7ed
+7ing
+7s
+5le
+7d
+7s
+6ing
+6l
+7ed
+7ing
+7s
+5n
+6d
+7ed
+7ing
+7s
+6g
+7ed
+7ing
+7s
+6ning
+6s
+5sh
+7ed
+8s
+7ing
+5t
+6h
+6s
+6ted
+7ing
+4on
+5re
+6k
+7ed
+8r
+9s
+7ing
+7s
+6n
+6th
+8ed
+8ing
+8s
+5und
+4rest
+8ed
+8ing
+8le
+9ed
+9es
+9ing
+8s
+5it
+7e
+8s
+7ing
+7ten
+5ote
+6ught
+3yell
+7ed
+7ing
+7s
+6p
+7ed
+7ing
+7s
+4ield
+8ed
+8ing
+8s
+2vert
+6e
+3irandra
+9as
+3rage
+7s
+4ier
+7e
+8s
+7s
+2zel
+5s
+3o
+4s
+1va
+3l
+4bumin
+9s
+4ities
+6y
+4ly
+4ness
+8es
+4s
+3rial
+6n
+5ectomies
+9mised
+9mized
+9my
+6s
+5ole
+8s
+6tomies
+9ist
+9ists
+9y
+6us
+5tides
+7s
+8es
+4y
+3te
+5d
+5ly
+5s
+4ing
+5on
+7al
+7s
+4or
+6s
+2el
+4s
+3n
+4able
+4bird
+8s
+4ed
+4ing
+4like
+4proof
+4s
+4ware
+8s
+5ood
+8s
+3r
+4able
+6ound
+9ded
+9ding
+9ds
+6stract
+9acted
+9acting
+9acts
+6undance
+9ances
+9ant
+5ccentuate
+9tuated
+9tuates
+6hieve
+9ved
+9vement
+9ver
+9vers
+9ves
+9ving
+6t
+7ed
+7ing
+8on
+9ns
+8ve
+9ities
+9ity
+7s
+6ute
+5djustment
+9tments
+6vertise
+9tised
+9tises
+9tising
+9tize
+9tized
+9tizes
+9tizing
+5ge
+7d
+7s
+6gressive
+5lert
+6l
+7ed
+7s
+5mbitious
+6plified
+5nalyse
+9sed
+9ses
+9sing
+9sis
+9tical
+9ze
+9zed
+9zes
+9zing
+6xieties
+9ty
+8ous
+5pplication
+6t
+5rch
+8ed
+9s
+8ing
+6m
+7ed
+7ing
+7s
+6ousal
+9als
+6range
+9ged
+9ges
+9ging
+6ticulate
+9ulated
+9ulates
+5ssert
+9ted
+9ting
+9tion
+9tions
+9tive
+9ts
+8ssment
+9sments
+5te
+6tention
+9tions
+9tive
+5we
+7d
+7s
+6ing
+4bake
+8d
+8s
+7ing
+6lance
+9ced
+9ces
+9cing
+6nk
+8s
+5ear
+8ing
+9ngly
+9ngness
+8s
+7t
+8en
+8ing
+8s
+6d
+6jeweled
+6t
+7s
+7ted
+8ing
+5id
+7den
+9r
+9rs
+8ing
+9ngs
+7s
+6g
+6ll
+8ed
+8ing
+8s
+6te
+8s
+5lanket
+9ets
+6each
+9hed
+9hes
+9hing
+7w
+6ouse
+9es
+7w
+8ing
+8n
+8s
+5oard
+6il
+8ed
+8ing
+8s
+6ld
+8ly
+6ok
+8ed
+8ing
+8s
+7t
+8s
+6re
+7n
+8e
+7row
+9wed
+9wing
+9ws
+6ught
+7nd
+9ed
+9ing
+9s
+5rake
+9d
+9s
+8ing
+6eathing
+9hings
+7d
+7ed
+9ing
+9s
+6idge
+9ed
+9es
+9ing
+7ef
+9ed
+9ing
+9s
+7ght
+7m
+8med
+9ing
+8s
+6oad
+7w
+8ed
+8ing
+8s
+9e
+9ed
+9es
+9ing
+6utal
+5uild
+9ing
+9s
+8t
+6lk
+8ed
+8ing
+8s
+6rden
+9ned
+9ning
+9ns
+9nsome
+7n
+8ed
+8ing
+8s
+8t
+7then
+9ened
+9ening
+9ens
+6sied
+9s
+7y
+8ing
+6y
+7ing
+7s
+5y
+4call
+8ed
+8ing
+8s
+6me
+6nopied
+9ies
+9y
+9ying
+6pacities
+9ity
+7italise
+9alised
+9alises
+9alize
+9alized
+9alizes
+6reful
+7ried
+9es
+8y
+9ing
+6st
+8ed
+8ing
+9ngs
+8s
+6tch
+9es
+9ing
+6ught
+7tion
+9oned
+9oning
+9ons
+9ous
+5entralise
+9alised
+9alises
+9alize
+9alized
+9alizes
+5harge
+9ed
+9es
+9ing
+6eap
+7ck
+9s
+6ill
+9ed
+9ing
+9s
+5ivil
+9ised
+9ized
+5lad
+7im
+9ed
+9ing
+9s
+7ss
+9es
+9ified
+9ifies
+9ify
+9ifying
+6ean
+9ed
+9ing
+9s
+8r
+9ed
+9ing
+9s
+6ock
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+7se
+7ud
+9ed
+9ing
+9s
+7y
+8ed
+8ing
+8s
+6ub
+8bed
+9ing
+8s
+5oach
+9ed
+9es
+9ing
+7t
+8ing
+9ngs
+8s
+6ld
+7or
+9ed
+9ing
+9s
+8ur
+9red
+9ring
+9rs
+6me
+8r
+9s
+8s
+7ing
+7mit
+9tment
+9tments
+9ts
+9tted
+9tting
+8unicate
+7pensate
+9nsated
+9nsates
+8lex
+9iance
+9iances
+9icate
+9icated
+9icates
+8ress
+9essed
+9esses
+9essing
+6ncern
+9rned
+9rning
+9rns
+7fidence
+9dences
+9dent
+9dently
+7scious
+8truct
+9ructed
+9ructs
+8ume
+9med
+9mes
+9ming
+9mption
+7trol
+9olled
+9olling
+9ols
+6ok
+8ed
+8ing
+8s
+7l
+8ed
+8ing
+8s
+6rrect
+9cted
+9cting
+9ction
+9ctions
+9cts
+6unt
+9ed
+9ing
+9s
+6ver
+9ed
+9ing
+9s
+6y
+5ram
+8med
+9ing
+8s
+7w
+8ed
+8ing
+8s
+6edulities
+9lity
+9lous
+6itical
+6op
+8ped
+9ing
+8s
+7w
+8d
+9ed
+9ing
+9ings
+9s
+8ed
+8ing
+8s
+5ultivation
+6re
+8d
+8s
+7ing
+6t
+7s
+7ting
+4dare
+8d
+8s
+7ing
+6ted
+5ear
+6ck
+8ed
+8ing
+8s
+7orate
+9ated
+9ates
+9ating
+9ation
+9ations
+6manding
+6pendence
+9dences
+9dent
+6sign
+9ned
+9ning
+9ns
+6termined
+6velop
+9oped
+9oping
+9opment
+9ops
+7iate
+9ted
+9tes
+9ting
+5id
+6ght
+6rect
+9ted
+9ting
+9ts
+6scount
+9unted
+9unting
+9unts
+6versities
+9sity
+5o
+6cument
+9ented
+9enting
+9ents
+6er
+8s
+7s
+6g
+7s
+6ing
+6minance
+9ances
+9ant
+6ne
+6sage
+9es
+7e
+8d
+8s
+7ing
+5raft
+9s
+7matic
+9tise
+9tised
+9tises
+9tising
+9tize
+9tized
+9tizes
+9tizing
+7nk
+7ught
+9hts
+7w
+8ing
+8n
+8s
+6ess
+9ed
+9es
+9ing
+7w
+6ied
+8s
+7nk
+9ing
+9s
+7ve
+9n
+9s
+8ing
+6ove
+6unk
+6y
+7ing
+5ub
+7bed
+8ing
+7s
+6e
+6st
+8ed
+8ing
+8s
+5ye
+7d
+7ing
+7r
+8s
+7s
+4eager
+9ness
+9nesses
+6rnest
+6sy
+6t
+7en
+8r
+9s
+7ing
+7s
+5d
+6it
+8ed
+8ing
+8s
+6ucate
+9ted
+9tes
+9ting
+9tion
+9tions
+5gg
+7ed
+7ing
+7s
+5laborate
+9rated
+9rates
+9rating
+9ration
+5mbellish
+9lished
+9lishes
+6ote
+9d
+9s
+8ing
+9onal
+6phases
+9sis
+9sise
+9sised
+9sises
+9sising
+9size
+9sized
+9sizes
+9sizing
+9tic
+5namored
+6courage
+9raged
+9rages
+9raging
+6ergetic
+6gineer
+9eered
+9eering
+9eers
+6rolled
+6tertained
+7husiasm
+9siasms
+5quipped
+5stimate
+9ated
+9ates
+9ating
+9ation
+9ations
+5valuation
+9ations
+5xaggerate
+9erated
+9erates
+6citable
+9e
+9ed
+9es
+9ing
+6ercise
+9ised
+9ises
+9ising
+8t
+9ed
+9ing
+9ion
+9ions
+9s
+6pand
+9ded
+9ding
+9ds
+9sion
+9sions
+7ectation
+7lain
+9ined
+9ining
+9ins
+8icit
+8oit
+9ited
+9iting
+9its
+7ose
+9ed
+9es
+9ing
+9ure
+9ures
+6tend
+9ded
+9ding
+9ds
+9sion
+9sions
+7raction
+9ctions
+9vagant
+6uberant
+5ye
+7d
+7ing
+7s
+6ing
+4facile
+6ll
+8en
+8ing
+8s
+6miliar
+9iarity
+6r
+6st
+8idious
+6t
+7igue
+9ued
+9ues
+6vor
+9ed
+9ing
+9s
+5ear
+8ed
+8ing
+8s
+6d
+6ed
+8ing
+8s
+6ll
+6rtilise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+5ill
+8ed
+8ing
+8s
+6ne
+8ness
+9esses
+7ished
+6sh
+8ed
+9s
+8ing
+6t
+5lew
+6ies
+7ght
+9ts
+6ood
+9ed
+9ing
+9s
+7urish
+9ished
+9ishes
+9ishing
+7w
+8ed
+8ing
+9ngly
+9ngs
+8n
+8s
+6ush
+9es
+6y
+7ing
+5ocus
+9ed
+9es
+9ing
+9sed
+9ses
+9sing
+6ld
+8ed
+8ing
+8s
+6nd
+8ly
+8ness
+9esses
+6rward
+9rdness
+6ul
+5rank
+7ught
+6ee
+8dom
+9oms
+8ly
+7ight
+9hting
+9hts
+5ulfill
+9lled
+9lling
+9lls
+7l
+8ness
+9esses
+7ness
+9sses
+6nd
+8ed
+8ing
+9ngs
+8s
+6ssy
+4gall
+8ed
+8ing
+8s
+6ng
+8ing
+8s
+6rment
+9nts
+6ve
+5ear
+8ed
+8ing
+8s
+6neralise
+9alised
+9alises
+9alize
+9alized
+9alizes
+9osity
+9ous
+9ously
+6t
+7s
+7ting
+5ild
+8ed
+8ing
+8s
+7t
+6rd
+8ed
+8ing
+8s
+7t
+6ve
+8n
+8s
+7ing
+5lad
+7morise
+9rised
+9rises
+9rising
+9rize
+9rized
+9rizes
+9rizing
+7nce
+9ed
+9es
+9ing
+7ze
+9d
+9s
+8ing
+6oom
+9ed
+9ing
+9s
+5o
+6ad
+8ed
+8ing
+8s
+6es
+6ing
+9s
+6ne
+6rge
+9d
+9s
+8ing
+6t
+6vern
+9ned
+9ning
+9ns
+5rade
+9d
+9s
+8ing
+7in
+9ed
+9er
+9ers
+9ing
+9s
+7ss
+9ed
+9es
+9ing
+7ze
+9d
+9s
+8ing
+9ngs
+6eat
+7edy
+8n
+9ed
+9ing
+9s
+7w
+6ound
+7w
+8ing
+8n
+8s
+8th
+9hs
+4haile
+9d
+9s
+8ing
+7r
+8s
+6le
+8d
+8s
+7ing
+6nd
+8ed
+8ing
+8le
+9ed
+9es
+9ing
+8s
+7g
+8ing
+8s
+6ppy
+6rd
+7vest
+9sted
+9sting
+9sts
+6ste
+9s
+8ily
+9ness
+9nesses
+8y
+6te
+8d
+8s
+7ing
+6ul
+8ed
+8ing
+8s
+5ead
+8s
+7p
+8ed
+8ing
+8s
+7r
+8d
+8ing
+8s
+7t
+8ed
+8ing
+9ngs
+8s
+6ld
+6nt
+8ing
+8s
+5igh
+6t
+7s
+7ting
+5old
+8ing
+8s
+7y
+6mogenise
+9enised
+9enises
+9enize
+9enized
+9enizes
+6nor
+9ed
+9ing
+9s
+6pe
+8d
+8s
+7ing
+6t
+5ung
+7t
+8ed
+8ing
+9ngs
+8s
+5ype
+8d
+8s
+7ing
+4idealise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+7ntified
+9ifies
+9ify
+9ifying
+6le
+5maginative
+6press
+9ssed
+9sses
+9ssing
+5nclined
+6dulge
+9ged
+9gence
+9gences
+9gent
+9ges
+9ging
+6flate
+9ted
+9tes
+9ting
+9tion
+9tions
+7orm
+9med
+9ming
+9ms
+6g
+7enious
+9uities
+9uity
+6ked
+6sistent
+7urance
+9ances
+9e
+9ed
+9es
+9ing
+6tense
+9sities
+9sity
+6vestment
+9tments
+5ssuance
+9nces
+8e
+9d
+9s
+8ing
+4joy
+7ed
+7ing
+7s
+5ump
+8ed
+8ing
+8s
+6st
+4keen
+7p
+8ing
+8s
+6pt
+6st
+5ill
+8ed
+8ing
+8s
+6nd
+8ness
+9esses
+7g
+8s
+5nee
+4labor
+9ed
+9ing
+9s
+8ur
+9red
+9ring
+9rs
+6de
+8d
+8n
+8s
+7ing
+6id
+7n
+6nd
+8ed
+9r
+9rs
+8ing
+8s
+6p
+7ped
+8ing
+7s
+6rd
+8ed
+8ing
+8s
+7ge
+6te
+6unch
+9hed
+9hes
+9hing
+6vish
+6x
+6y
+7ing
+9gs
+7s
+5eaf
+7p
+8ed
+8ing
+8s
+8t
+7rn
+9ed
+9ing
+9s
+9t
+7ther
+9ers
+7ven
+9ned
+9ning
+9ns
+6nd
+8ing
+8s
+7gth
+9hen
+9hened
+9hening
+9hens
+9hs
+7t
+6t
+7s
+7ting
+6wd
+5ie
+7r
+8s
+7s
+6ght
+9ed
+9ing
+9s
+6t
+7eral
+9ary
+6ve
+8d
+8s
+7ing
+5oad
+8ed
+8ing
+8s
+6ck
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+6ng
+6ok
+8ed
+9r
+9rs
+8ing
+8s
+6rd
+8ed
+8ing
+8s
+9hip
+9hips
+6ud
+6ve
+8d
+8s
+7ing
+5ush
+7ty
+5y
+6ing
+4man
+7age
+9ed
+9es
+9ing
+7ned
+9red
+8ing
+7s
+7tel
+9ls
+7y
+6st
+8ed
+9r
+9red
+9ring
+9rs
+8ing
+8s
+6tch
+9ed
+9es
+9ing
+7ter
+9rs
+7ure
+9ities
+9ity
+5easure
+9red
+9res
+9ring
+6dicate
+9ated
+9ates
+9ating
+9ation
+9ations
+6ek
+6lt
+8ed
+8ing
+8s
+6n
+6rry
+5ighty
+6ld
+7k
+8ed
+8ing
+8s
+6ne
+8d
+8s
+7ing
+6x
+7ed
+8s
+7ing
+5odest
+9tly
+7ulated
+6unt
+9ed
+9ing
+9s
+5uch
+8es
+6ltiplied
+9plies
+9ply
+9plying
+9tude
+9tuded
+9tudes
+9tuding
+6scled
+4name
+8d
+8s
+7ing
+5ear
+7t
+6t
+7s
+7ted
+8ing
+6w
+5ice
+8ly
+8ness
+9esses
+6ght
+9ed
+9er
+9ers
+9ing
+9s
+5ourish
+9shed
+9shes
+9shing
+5utrition
+9tions
+4obvious
+5ffice
+9ed
+9es
+9ing
+5perate
+9ted
+9tes
+9ting
+6inionated
+6timism
+9isms
+9ist
+9istic
+9ists
+5rchestrate
+6ganise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+6nament
+9ented
+9enting
+9ents
+4pack
+8age
+9ged
+9ges
+9ging
+8ed
+8ing
+8s
+6ge
+6id
+7nt
+9ed
+9ing
+9s
+6rt
+8ed
+8icular
+9ng
+8s
+6ss
+8ed
+9s
+8ing
+7t
+6y
+7ing
+7ment
+9nts
+7s
+5edal
+9ed
+9ing
+9led
+9ling
+9s
+6er
+8ed
+8ing
+8s
+6ople
+9ed
+9es
+9ing
+6rch
+9ed
+9es
+9ing
+7suade
+9aded
+9ades
+9ading
+9asion
+9asions
+7t
+5icture
+9red
+9res
+9ring
+6tch
+9ed
+9es
+9ing
+5laced
+7id
+9ed
+9s
+7n
+8ned
+9ing
+8s
+8t
+9ed
+9ing
+9s
+7st
+7y
+8ed
+8ing
+8s
+6ied
+8s
+6ot
+8s
+8ted
+9ing
+6us
+8es
+8ses
+6y
+7ing
+5oise
+9d
+9s
+8ing
+6pulate
+9ated
+9ates
+9ating
+9ation
+9ations
+6st
+8ed
+8ing
+8s
+6tent
+6wer
+9ed
+9ing
+9ingly
+9s
+5raise
+9ed
+9es
+9ing
+6ecise
+7paration
+9re
+9red
+9res
+9ring
+7scribe
+9ribed
+9ribes
+9ribing
+8s
+9ed
+9es
+9ing
+9ure
+9ures
+6ice
+9d
+9s
+8ing
+7nt
+9ed
+9ing
+9s
+7vileged
+7ze
+9d
+9s
+8ing
+6ocess
+9ssed
+9sses
+9ssing
+7duce
+9ced
+9ces
+9cing
+9ction
+9ctions
+7gram
+9amed
+9aming
+9ammed
+9amming
+9ams
+7mise
+9sed
+9ses
+9sing
+8ote
+9ted
+9tes
+9ting
+7of
+7portion
+9rtions
+7tect
+9cted
+9cting
+9ction
+9ctions
+9ctive
+9cts
+7ud
+5ump
+8ed
+8ing
+8s
+4qualified
+6ick
+4rack
+8ed
+8ing
+8s
+6ke
+8d
+8s
+7ing
+6n
+7k
+6sh
+8ly
+8ness
+9esses
+6te
+8d
+8s
+7ing
+6ught
+5each
+9ed
+9er
+9ers
+9es
+9ing
+8t
+9ed
+9ing
+9ion
+9ions
+9s
+7d
+8ing
+8s
+6ckon
+9ned
+9ning
+9ns
+6d
+7ded
+8ing
+7s
+6fine
+9ed
+9ement
+9ements
+9es
+9ing
+6gulate
+9ated
+9ates
+9ating
+9ation
+9ations
+6liance
+9nces
+6n
+7ning
+7s
+6port
+9ted
+9ting
+9ts
+7resented
+6spond
+9nded
+9nding
+9nds
+5ich
+6dden
+7e
+8r
+9s
+8s
+7ing
+6fe
+6gid
+6pe
+8n
+9ed
+9ess
+9esses
+9ing
+9s
+5oast
+9ed
+9ing
+9s
+6de
+5ude
+6ff
+8ed
+8ing
+8s
+6le
+8d
+8r
+9s
+8s
+7ing
+9gs
+6n
+7ner
+9rs
+8ing
+7s
+4s
+5ad
+6il
+8ed
+8ing
+8s
+6le
+8s
+7t
+8ed
+8ing
+8s
+6nguine
+6turate
+9ated
+9ates
+9ating
+9ation
+9ations
+6uce
+9d
+9s
+8ing
+6ve
+8d
+8s
+7ing
+6w
+5cale
+9d
+6hutcht
+6ore
+9d
+9s
+8ing
+6rupulous
+6utched
+5ea
+7s
+6cretion
+9tions
+6e
+7d
+8ed
+8ing
+8s
+7ing
+7n
+7r
+8s
+7s
+6ll
+8ing
+8s
+6nsitive
+9tivity
+6rious
+9usly
+7vice
+9ced
+9ces
+9cing
+6t
+7s
+7ting
+6w
+7ed
+7ing
+7n
+7s
+6xed
+5hade
+9d
+9s
+8ing
+8ow
+9wed
+9wing
+9ws
+7rp
+6ine
+9s
+8ing
+7rt
+9s
+6oe
+8s
+7ne
+7ot
+9ing
+9s
+7t
+8s
+7wer
+9red
+9ring
+9rs
+5ick
+6de
+8s
+6ght
+9s
+6mple
+9ified
+9ifies
+9ify
+9ifying
+9istic
+9y
+6ze
+8d
+8s
+7ing
+5kip
+8ped
+9ing
+8s
+7rt
+9s
+5laugh
+9hed
+9hing
+9hs
+6eep
+9ing
+9s
+8ve
+9es
+7pt
+6ip
+8ped
+9ing
+8s
+8t
+6ow
+5man
+6en
+6oke
+9d
+9s
+8ing
+5oak
+8ed
+8ing
+8s
+6ft
+6ld
+7icitous
+6on
+6ul
+8s
+6w
+7ed
+7ing
+7n
+7s
+5pecialise
+9alised
+9alises
+9alize
+9alized
+9alizes
+8ulate
+9lated
+9lates
+9lating
+9lation
+7nd
+9er
+9ers
+9ing
+9s
+8t
+6ice
+9d
+9s
+8ing
+7ll
+9ed
+9ing
+9s
+8t
+7n
+8s
+6read
+9ding
+9ds
+5tabilities
+9lity
+7ff
+9ed
+9ing
+9s
+7in
+9ed
+9ing
+9s
+7nd
+9ing
+9s
+8k
+7re
+9d
+9s
+8ing
+7te
+9d
+9ment
+9ments
+9s
+8ing
+7y
+8ed
+9r
+9rs
+8ing
+8s
+6eer
+9ed
+9ing
+9s
+7p
+8ped
+9ing
+8s
+6imulate
+9lated
+9lates
+9lating
+9lation
+7nk
+9ing
+9s
+7r
+8red
+9ing
+8s
+6ock
+9ed
+9ing
+9s
+7od
+7ries
+8y
+6rain
+9ned
+9ning
+9ns
+7ess
+9sed
+9ses
+9sing
+8tch
+9ched
+9ches
+9ching
+8w
+9ed
+9ing
+9n
+9s
+7idden
+9e
+9es
+9ing
+8ke
+9es
+9ing
+7ode
+8ng
+8oke
+7uck
+9tured
+8ng
+6udied
+9es
+8y
+9ing
+7ff
+9ed
+9ing
+9s
+7nk
+5ubscribe
+9ribed
+9ribes
+9ribing
+7tle
+9eties
+9ety
+6ds
+8ed
+9s
+8ing
+6p
+7ped
+8ing
+8lied
+9ies
+9y
+9ying
+7s
+6re
+6spicious
+5wam
+7y
+8ed
+8ing
+8s
+6ear
+9ing
+9s
+7et
+9en
+9ened
+9ening
+9ens
+9ness
+9nesses
+7ll
+9ed
+9ing
+9s
+6im
+8ming
+8s
+7ng
+9ing
+9s
+6ollen
+7re
+8n
+6um
+7ng
+4t
+5ake
+8n
+8s
+7ing
+6lk
+8ative
+8ed
+8ing
+8s
+6me
+6rt
+6sk
+8ed
+8ing
+8s
+6ught
+6x
+7ation
+9ions
+7ed
+8s
+7ing
+5each
+9es
+9ing
+6dious
+6em
+8ed
+8ing
+8s
+5hick
+7n
+8k
+9ing
+9s
+6ought
+6rew
+7ow
+9er
+9ers
+9ing
+9n
+9s
+7ust
+9ts
+6wart
+9ted
+9ting
+9ts
+5ight
+9en
+9ened
+9ening
+9ens
+6me
+8d
+8ly
+8r
+9s
+8s
+7id
+8ng
+6p
+7ped
+8ing
+7s
+6re
+8d
+8s
+7ing
+5ly
+5ness
+9es
+5oil
+8ed
+8ing
+8s
+6ne
+8s
+6ok
+6p
+7ped
+8ing
+9ngs
+7s
+6wer
+9ed
+9ing
+9s
+5rade
+9d
+9s
+8ing
+9ngs
+7in
+9ed
+9ing
+9s
+6eat
+9ed
+9ing
+9ment
+9ments
+9s
+6ick
+9s
+7m
+8med
+9ing
+8s
+7p
+8ped
+9ing
+8s
+6ump
+9ed
+9ing
+9s
+7st
+9ed
+9ing
+9s
+5ure
+8d
+8s
+7ing
+7n
+8ed
+9r
+9rs
+8ing
+8s
+5ype
+8d
+8s
+7ing
+4urge
+8d
+8s
+7ing
+5se
+7d
+7s
+6ing
+5tilisation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+4valuation
+9tions
+8e
+9d
+9s
+8ing
+5eil
+8ed
+8ing
+8s
+5iew
+8s
+6olent
+6vid
+5oltage
+9ges
+6te
+8d
+8s
+7ing
+4warm
+8ed
+8ing
+8s
+7y
+6sh
+8es
+6tch
+9ed
+9es
+9ing
+7er
+9ed
+9ing
+9s
+5eak
+7r
+8ied
+9es
+9ng
+8s
+8y
+9ing
+7ther
+9ered
+9ering
+9ers
+6en
+8ed
+8ing
+9ngly
+9ngness
+9ngs
+8s
+6igh
+9ed
+9ing
+9s
+9t
+9ted
+9ting
+9ts
+6nt
+6t
+7s
+7ted
+8ing
+5helm
+9ed
+9ing
+9ingly
+9ings
+9s
+5ide
+6ly
+6nd
+8ing
+8s
+7g
+8ed
+8ing
+8s
+7ter
+9red
+9ring
+9rs
+6se
+8ly
+6thheld
+9old
+9olding
+9olds
+5ord
+8s
+7e
+7k
+8ed
+8ing
+8s
+7n
+6und
+5rap
+8ped
+9ing
+8s
+6est
+9ed
+9ing
+9le
+9led
+9les
+9ling
+9s
+6ite
+9s
+8ing
+8ten
+6ote
+7ught
+4year
+8ed
+8ing
+8s
+4zeal
+8ous
+9usly
+9usness
+8s
+2ibos
+6es
+5vine
+3cidal
+6e
+7s
+3ducal
+6t
+7al
+7s
+3ferous
+4orm
+3gerous
+3ne
+5s
+3para
+6ities
+8y
+6ous
+9ly
+4osit
+8ed
+8ing
+9on
+9onal
+9ons
+8or
+9rs
+8s
+3raptor
+9s
+3sac
+6s
+4t
+5s
+2oid
+5al
+7s
+5s
+3li
+4o
+5s
+3nic
+6s
+3testes
+7is
+3viviparities
+9rity
+9rous
+9rously
+2ular
+6y
+5te
+7d
+7s
+6ing
+7on
+9s
+6ory
+4e
+5s
+4iferous
+3m
+1w
+2che
+5s
+2e
+3d
+3lties
+5y
+3r
+4by
+4loup
+8en
+8ing
+9t
+8s
+3s
+2ing
+2l
+3ed
+4r
+5ies
+5s
+5y
+4t
+5s
+3ier
+5st
+4ng
+4sh
+6ly
+6ness
+9ses
+3like
+3s
+3y
+2n
+3able
+3ed
+4r
+5less
+5s
+6hip
+9s
+3ing
+3s
+2re
+4come
+8s
+4lay
+7s
+4s
+4word
+8s
+3ie
+5r
+5st
+2se
+4n
+2t
+3s
+1x
+2acillin
+9s
+3lacetate
+9tes
+5te
+7d
+7s
+6ing
+4ic
+5s
+6es
+4oacetate
+9ates
+3zepam
+8s
+4ine
+7s
+2blood
+7s
+3ow
+5s
+2cart
+6s
+2en
+3r
+4s
+3s
+3ye
+5s
+2ford
+6s
+2gang
+6s
+4te
+6s
+2head
+6s
+5rt
+7s
+3ide
+6s
+2id
+4able
+5nt
+7s
+5se
+7s
+6ic
+5te
+7d
+7s
+6ing
+7on
+9al
+9s
+7ve
+9ly
+4e
+5s
+4ic
+5metric
+9ies
+9y
+5sable
+7tion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+5zable
+7tion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+4oreductase
+9ctases
+4s
+3es
+3m
+4e
+5s
+5ter
+8s
+6ries
+7y
+4s
+2land
+6s
+3ike
+4p
+5s
+2o
+3nium
+7s
+2pecker
+8s
+2slip
+6s
+2tail
+6s
+3er
+5ed
+5ing
+5s
+3ongue
+8s
+2y
+3acetylene
+9enes
+5id
+7s
+3cephalic
+9ies
+9ous
+9y
+4odone
+9s
+3gen
+6ase
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6ic
+7se
+9d
+9r
+9rs
+9s
+8ing
+7ze
+9d
+9r
+9rs
+9s
+8ing
+6less
+6ous
+6s
+3haemoglobin
+9lobins
+4emoglobin
+9obins
+4ydrogen
+3mel
+6s
+4ora
+6on
+8ic
+9cally
+8s
+3ntic
+3phenbutazone
+5il
+7e
+8s
+7ic
+7s
+3rhynchus
+9uses
+3salt
+7s
+4ome
+7s
+4ulphide
+9des
+3tetracycline
+4ocic
+8s
+7n
+8s
+5ne
+7s
+6ic
+3uriases
+8is
+1y
+2e
+3r
+4s
+3s
+4es
+4ses
+3z
+4es
+2s
+3ter
+6catcher
+9chers
+6ed
+7r
+8s
+6ing
+9s
+6man
+7en
+6s
+4rige
+8s
+1zaena
+6s
+3lid
+6s
+2eki
+5s
+2ocerite
+9s
+3kerite
+9s
+3nate
+7d
+7s
+6ing
+7on
+9s
+4e
+5s
+4ic
+5de
+7s
+5ferous
+5sation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+5zation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+4olyses
+8is
+5sphere
+9res
+5us
+2zie
+5s
+0pa
+2al
+4s
+3n
+4s
+2blum
+6s
+3ouche
+8s
+3ular
+5ous
+5um
+7s
+2c
+3a
+4ble
+4s
+4tion
+8s
+3e
+4d
+4maker
+9s
+7ing
+9gs
+6n
+5en
+4r
+5s
+4s
+5etter
+9rs
+8ing
+4way
+7s
+4y
+3ha
+5dom
+8s
+5k
+6s
+5lic
+8s
+5s
+4inko
+8s
+5si
+7s
+4ouli
+8s
+4uco
+7s
+4ycarpous
+5dactyl
+9ylous
+6erm
+9al
+9atous
+9ia
+9ias
+9ic
+9ous
+9s
+5meningitis
+7ter
+9rs
+5sandra
+9ras
+5tene
+9s
+3ier
+5st
+4fiable
+6c
+7ae
+8l
+9ly
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+9ory
+7ism
+9ms
+9t
+9ts
+6ed
+7r
+8s
+7s
+6sm
+8s
+7t
+8ic
+9cally
+8s
+5y
+6ing
+4ng
+3k
+4abilities
+9ty
+6le
+5ge
+7d
+7r
+8s
+7s
+6ing
+9s
+4board
+9s
+4cloth
+9s
+4ed
+5r
+6s
+5t
+6ed
+6ing
+6s
+4fong
+8s
+5rame
+9s
+4horse
+9s
+4ing
+7house
+9uses
+7s
+4ly
+4man
+5en
+5ule
+8s
+4ness
+8es
+4rat
+7s
+4s
+5ack
+8s
+6ddle
+9es
+5heet
+9s
+5taff
+9s
+4thread
+9ds
+4wax
+7es
+6y
+7s
+3litaxel
+9ls
+3o
+4s
+3s
+3t
+4a
+4ion
+7al
+7ed
+7ing
+7s
+4s
+4um
+3y
+2d
+3ang
+6s
+4uk
+6s
+3ded
+5r
+6s
+4ies
+5ng
+7s
+4le
+6ball
+9ls
+7oard
+9rds
+9t
+9ts
+6d
+6fish
+9hes
+6r
+7s
+6s
+5ing
+8s
+4ock
+7ed
+7ing
+7s
+4y
+5melon
+9ns
+5wack
+9ed
+9ing
+9s
+6hack
+9ks
+3ella
+7s
+4melon
+9s
+4rero
+8es
+8s
+3i
+4s
+5hah
+8s
+3kos
+3le
+5s
+4ock
+7ed
+7ing
+7s
+3ma
+5s
+3nag
+6s
+3ouk
+6s
+3re
+5s
+4i
+4one
+7s
+6i
+7sm
+9s
+3s
+4aw
+6s
+4hah
+7s
+3uasoy
+8s
+3ymelon
+9s
+2ean
+5ism
+8s
+5s
+3dagogic
+8ue
+9es
+4erast
+9ic
+9ies
+9s
+9y
+5utic
+9s
+4iatric
+9cian
+9cians
+9cs
+9es
+9st
+9sts
+8y
+4o
+5baptism
+9isms
+9ist
+9ists
+5dontic
+9ics
+5geneses
+9sis
+9tic
+8ic
+5logical
+9es
+9st
+9sts
+8y
+5morphic
+9hism
+9hisms
+9hoses
+9hosis
+5s
+5tribe
+9es
+7ophies
+9hy
+3lla
+6s
+3nula
+7e
+7s
+3on
+5ic
+7s
+6es
+5s
+5y
+3san
+6i
+6o
+7s
+6s
+2gan
+5dom
+8s
+5isation
+9ions
+7e
+8d
+8r
+9s
+8s
+7h
+7ing
+7m
+8s
+7t
+8ic
+9cally
+8s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5s
+3e
+4ant
+7ries
+8y
+7s
+4boy
+7s
+4d
+4ful
+7s
+4hood
+8s
+4r
+5s
+4s
+4view
+8s
+3inal
+6te
+8d
+8s
+7ing
+8on
+9ns
+5g
+6s
+3le
+5s
+3od
+5a
+6s
+5s
+3ri
+5s
+3urian
+8s
+6d
+7s
+2h
+3autea
+8s
+3lavi
+7s
+3oehoe
+8s
+3s
+2id
+4eutic
+9s
+4le
+6s
+3gle
+6s
+3k
+4ed
+4ing
+4s
+3l
+4ful
+7s
+4lard
+8s
+6sse
+9s
+5ette
+9s
+5on
+7s
+4s
+5ful
+3n
+4ch
+6es
+4ed
+4ful
+7ler
+9st
+8y
+7ness
+9sses
+4im
+6s
+5ng
+4killer
+9rs
+8ing
+4less
+8ly
+8ness
+9esses
+4s
+5taker
+9rs
+8ing
+9ngly
+9ngness
+9ngs
+4t
+5able
+5ball
+9s
+6ox
+8es
+6rush
+9hes
+5ed
+6r
+7liness
+9nesses
+8y
+7s
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5ress
+9es
+5s
+5ure
+8s
+5work
+9s
+5y
+3ock
+6e
+7s
+6s
+3r
+4e
+5d
+5r
+5s
+6t
+4ial
+7s
+5ng
+7s
+4s
+4wise
+3s
+4a
+5n
+6a
+7s
+6o
+7s
+6s
+5s
+4e
+4ley
+7s
+3trick
+8s
+2jama
+6ed
+6s
+3ock
+6e
+7s
+6s
+2kahi
+6s
+4poo
+7s
+3eha
+6s
+3fong
+7s
+3ihi
+6s
+4rikiri
+9is
+3ka
+3oko
+6s
+4ra
+6s
+3thong
+8s
+4ong
+7s
+2l
+3abra
+7s
+4ce
+6d
+6s
+4din
+7s
+4eanthropic
+5biologies
+9ogist
+9ogists
+9ogy
+5ethnology
+5oanthropic
+6biologic
+9logies
+9logist
+9logy
+7otanic
+9anical
+9anies
+9anist
+9anists
+9any
+6climate
+9mates
+9matic
+7rystic
+7urrent
+9rents
+6ecologic
+9logies
+9logist
+9logy
+7thnology
+6gaea
+9as
+7eography
+7rapher
+9phers
+9phic
+9phical
+9phies
+9phist
+9phists
+9phy
+6limnology
+8th
+9hic
+9hs
+6magnetic
+9netism
+6ntography
+9logies
+9logist
+9logy
+6pathology
+7edology
+7hytology
+6type
+9es
+9ic
+6zoologies
+9logist
+9logy
+5stra
+9e
+9l
+9s
+8ic
+9cal
+4fitte
+9s
+4gi
+6s
+5onite
+9es
+4is
+4ma
+6e
+6te
+5ino
+8s
+5pore
+9s
+4nkeen
+9s
+5quin
+9s
+4pa
+6s
+4s
+5es
+4tabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6l
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7s
+5e
+6d
+6s
+5ial
+8ly
+8ness
+9esses
+6nate
+9es
+7e
+8s
+7g
+4ver
+7ed
+8r
+9s
+7ing
+7s
+4y
+5s
+4zzi
+6o
+7s
+3e
+4a
+5ceous
+5e
+5l
+5te
+4buck
+8s
+4d
+4face
+8s
+4ly
+4mpore
+9s
+4ness
+8es
+4obiologic
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+6otanic
+9nical
+9nies
+9nist
+9nists
+9ny
+5cene
+5ecologic
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+5gene
+7ographic
+9raphy
+6rapher
+9hers
+9hic
+9hical
+9hies
+9hy
+5lith
+9s
+6ogies
+8y
+5magnetic
+9etism
+9etisms
+9etist
+9etists
+5ntologic
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+5pathology
+5sol
+8s
+5zoic
+7ological
+9ogies
+9ogist
+9ogists
+9ogy
+4r
+4s
+5t
+6ra
+8e
+8l
+8s
+4t
+5ot
+7s
+5s
+5te
+7s
+4ways
+5ise
+3frenier
+9rs
+6y
+7ed
+7s
+3ier
+5st
+4fication
+9ions
+5orm
+4kar
+7s
+4lalia
+9s
+5logies
+8y
+4monies
+7y
+5psest
+9ts
+4ndrome
+9es
+9ic
+9ical
+9ist
+9ists
+5g
+6eneses
+9sia
+9sias
+9sies
+9sis
+9sist
+9sists
+9sy
+9tic
+9tical
+6s
+5ka
+7s
+5ode
+8s
+7ies
+7y
+6pia
+9s
+7sia
+9as
+4sade
+8d
+8s
+7ing
+7o
+8ed
+9s
+8ing
+6nder
+9rs
+5h
+3kee
+6s
+4i
+5s
+3l
+4a
+5dia
+7c
+7ous
+7um
+9s
+6ous
+5e
+5h
+6s
+4bearer
+9rs
+4ed
+5scence
+9ces
+9t
+5t
+6ed
+6ing
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6s
+6te
+8s
+4ia
+6l
+6ment
+9ts
+6rd
+8s
+6sse
+9s
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+9es
+7or
+9s
+9y
+5d
+6er
+7st
+6ities
+8y
+6ly
+6ness
+9ses
+5ed
+6r
+6s
+7t
+5ng
+5um
+7s
+4one
+7s
+5r
+6s
+4s
+4y
+5ing
+3m
+4aceous
+5r
+6ian
+6y
+5te
+7d
+7ly
+6ifid
+7on
+9s
+7partite
+7sect
+4corder
+9rs
+4ed
+5r
+6s
+6worm
+9ms
+5tte
+8s
+7o
+8es
+8s
+4ful
+7s
+4house
+9s
+4ie
+6r
+6s
+7t
+6t
+7s
+5fication
+9tions
+5ng
+5ped
+8e
+9s
+8s
+5st
+7er
+9s
+7ries
+8y
+7s
+5tate
+9s
+6ic
+7n
+8s
+4like
+4s
+4top
+7s
+4y
+5ra
+7s
+3olo
+6s
+4mino
+8s
+4oka
+7s
+4verde
+9s
+3p
+4abilities
+9ty
+6le
+8ness
+9esses
+7y
+5l
+5te
+7d
+7s
+6ing
+7on
+9s
+6or
+8s
+8y
+4ebra
+8e
+8l
+8s
+8te
+9ed
+9es
+9ing
+5d
+4i
+5ng
+5tant
+7te
+9d
+9s
+8ing
+9on
+9ons
+4s
+4us
+3s
+4grave
+9s
+8ine
+9nes
+4hip
+7s
+4ied
+6r
+6s
+7t
+4taff
+8s
+6ve
+8s
+4y
+5ing
+5like
+3ter
+6ed
+7r
+8s
+6ing
+6s
+4rier
+7st
+6ly
+6ness
+9ses
+5y
+3udal
+6ment
+9ta
+9ts
+9tum
+9tums
+5ic
+7olous
+6nal
+7e
+7ous
+6sm
+8s
+5ose
+6us
+4stral
+7ian
+8ne
+3y
+4nologic
+9ical
+9ically
+9ies
+9ist
+9ists
+9y
+2m
+3pa
+5s
+6es
+4ean
+7s
+5lmoose
+9ses
+8use
+9ses
+5r
+6ed
+8ness
+9esses
+7r
+8s
+6ing
+6o
+7s
+6s
+4hlet
+8eer
+9ered
+9ering
+9erings
+9ers
+8s
+5rey
+8s
+4oen
+7s
+5otie
+9s
+3s
+2n
+3acea
+7n
+7s
+5haea
+9s
+6e
+7s
+4da
+6s
+4esthesia
+9sias
+9tism
+9tisms
+4ma
+6s
+4ries
+6tium
+9ms
+5thritis
+9tises
+5y
+4tela
+8s
+7la
+9s
+4x
+5es
+3broil
+8ed
+8ing
+8s
+3cake
+7d
+7s
+6ing
+4e
+5s
+5tta
+8s
+4hax
+7es
+6yat
+9s
+5eon
+8s
+5ion
+8s
+5romatic
+9tism
+9tisms
+4osmic
+8sm
+9ms
+4ratia
+9n
+9st
+9sts
+8c
+8st
+9ts
+8um
+9ms
+5eas
+8es
+7tectomy
+8ic
+9n
+9ns
+9tides
+9tis
+9tises
+6ozymin
+9mins
+4ytopenia
+9nias
+3d
+4a
+5emonium
+9iums
+5naceous
+6i
+6us
+8es
+5r
+6ed
+6ing
+6s
+5s
+5tion
+9s
+4ect
+7ist
+9ts
+7s
+5mia
+8n
+8s
+7c
+8s
+6oniac
+9acal
+9an
+9c
+9um
+9ums
+5r
+6ed
+7r
+8s
+7ss
+9es
+6ing
+7sm
+9s
+6ly
+6mite
+9es
+6ous
+6s
+4iculation
+9tions
+5ed
+6s
+5t
+6s
+4oor
+7s
+5ra
+7s
+6e
+7s
+5ur
+7s
+5wdies
+7y
+4s
+4ura
+7s
+7te
+9d
+6iform
+4y
+5ing
+3e
+4d
+4er
+6s
+4goism
+9s
+5yric
+9a
+9al
+9ally
+9on
+9s
+8es
+8se
+9ed
+9es
+9ing
+9t
+9ts
+8ze
+9ed
+9es
+9ing
+7y
+4ities
+6y
+4l
+5ed
+6ss
+5ing
+8s
+6sed
+7t
+8s
+6zed
+5led
+6ing
+9s
+7st
+9s
+5s
+4ntheism
+9sms
+9st
+9sts
+4s
+5thesia
+9ias
+4tela
+8s
+7la
+9s
+5tone
+9s
+8i
+3fish
+7es
+4ried
+7s
+5y
+6ing
+4ul
+6s
+3g
+4a
+5mic
+7es
+6y
+5s
+4ed
+5n
+6e
+7s
+8es
+8is
+7tic
+9cally
+6s
+4ing
+4less
+4olin
+8s
+4ram
+7matist
+9tists
+7s
+4s
+3handle
+9d
+9r
+9rs
+9s
+8ing
+5rmonicon
+9icons
+4ellenic
+9ion
+9ions
+9ium
+9iums
+4uman
+3ic
+5ally
+5k
+6ed
+6ier
+8st
+7ng
+6s
+6y
+5le
+7d
+7s
+5monger
+9ers
+5s
+5ulate
+9ed
+9ely
+6m
+7s
+4diomorphic
+4er
+6s
+4fication
+9ions
+4m
+5s
+4ng
+5i
+6s
+5o
+4sc
+6s
+5k
+6s
+3jandarum
+9ums
+7ra
+8um
+9ms
+3ko
+5s
+3leucopenia
+9enias
+6kopenia
+9enias
+4ogism
+9s
+3mictic
+5xes
+6ia
+8s
+7s
+8es
+3nage
+7s
+4e
+5d
+5lled
+5r
+6s
+5s
+4ick
+7s
+6le
+8s
+6ulus
+9ses
+5er
+7ed
+7s
+5kel
+8l
+9s
+8s
+6in
+8s
+5ng
+7s
+4ose
+4us
+6es
+3ocha
+7s
+6e
+7s
+4istic
+4mphaean
+4phobia
+9as
+6thalmia
+9lmias
+9lmitis
+5lied
+8s
+6y
+5tic
+8al
+9lly
+8on
+9ns
+4rama
+8s
+7ic
+9ally
+3pharmacon
+9cons
+4ipe
+7s
+4sychism
+9sms
+9st
+9stic
+9sts
+3radiometer
+9eters
+3s
+4exual
+9ism
+9isms
+9ist
+9ists
+9ities
+9ity
+9s
+4ied
+6s
+4ophic
+9al
+9ally
+8es
+8sm
+9ms
+9t
+9ts
+7y
+4permatic
+9tism
+9tisms
+9tist
+9tists
+8ia
+9as
+9c
+9es
+9sm
+9sms
+9st
+9sts
+8y
+4tick
+8s
+4y
+3t
+4able
+8s
+5gamies
+8y
+6raph
+9hs
+5leon
+9s
+7t
+8s
+8ted
+9es
+6on
+8e
+9s
+8s
+7on
+9ed
+9eries
+9ery
+9s
+4dress
+9es
+4echnicon
+9cons
+5d
+5r
+6s
+4heism
+9s
+8t
+9ic
+9ical
+9ically
+9s
+6nol
+9s
+6ologies
+9gist
+9gists
+9gy
+7n
+8s
+6r
+7ess
+9ses
+7ine
+8sh
+7s
+4ie
+5hose
+5le
+7d
+7s
+6ing
+9s
+5ne
+7s
+6g
+7ly
+7s
+5socracies
+9acy
+9at
+9atic
+9atical
+9atist
+9atists
+9ats
+4ler
+7s
+4o
+5ffle
+9s
+6le
+8s
+5graph
+9her
+9hers
+9hic
+9hical
+9hies
+9hs
+9hy
+5mime
+9d
+9s
+8ic
+9cal
+9cally
+9ng
+9st
+9sts
+5n
+6s
+5phagies
+9ist
+9ists
+9ous
+9y
+7obia
+9ias
+6ragmatic
+9matics
+5s
+6cope
+9es
+9ic
+5thenate
+9ates
+9ic
+5ufle
+9s
+6m
+7s
+4ries
+5opic
+9al
+5y
+6maid
+9ds
+8n
+7en
+4s
+5uit
+8ed
+8s
+4un
+6s
+4yhose
+5waist
+9ts
+3zer
+6otto
+9os
+6s
+4ootic
+9s
+2oli
+4o
+2p
+3a
+4ble
+4cies
+5y
+4dam
+7s
+5om
+7s
+5um
+7s
+4in
+6s
+4l
+5ise
+8d
+8s
+7ing
+7m
+8s
+7t
+8s
+6ze
+8d
+8s
+7ing
+5ly
+4prelatist
+9tists
+4razzi
+8o
+4s
+4uma
+7s
+4veraceous
+7ine
+9es
+7ous
+4w
+5s
+4ya
+6n
+6s
+3e
+4r
+5back
+9ed
+9er
+9ers
+9ing
+9s
+7rk
+9s
+6oard
+9ds
+7und
+9ds
+7y
+8s
+5clip
+9s
+5ed
+6r
+7s
+5girl
+9s
+5hanger
+9ers
+9ing
+9ings
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5knife
+8ves
+5less
+5maker
+9rs
+8ing
+9ngs
+5s
+5ware
+9s
+6eight
+9hts
+6ork
+9s
+5y
+4s
+4terie
+9s
+3hian
+7s
+3ilio
+7naceous
+7s
+5la
+7e
+7r
+8y
+7te
+9d
+6iferous
+8orm
+7tis
+9ses
+6oma
+9s
+9ta
+9toses
+9tosis
+9tous
+9virus
+7n
+8s
+7se
+7te
+9s
+7us
+6ulate
+8e
+9s
+4sh
+6er
+8s
+7s
+5m
+6s
+5t
+6ic
+8al
+9lly
+6ries
+7y
+6s
+3oose
+7s
+4vavirus
+9uses
+3padam
+8s
+6om
+8s
+5rdelle
+9les
+4ed
+4i
+5er
+6s
+7t
+5ng
+4oose
+8s
+5se
+5us
+4us
+6es
+4y
+3rica
+7s
+5ka
+7s
+3s
+3ula
+6e
+6r
+6tion
+9ns
+5e
+6s
+5iferous
+5ose
+6us
+3yraceous
+6l
+5i
+6an
+6ne
+5ological
+9ies
+9ist
+9ists
+9y
+5us
+7es
+2r
+3a
+4baptism
+9sms
+6ses
+7is
+5ema
+8ta
+9ic
+6n
+7s
+5ioses
+8is
+7tic
+9cally
+5last
+9ic
+9s
+6e
+7d
+7pses
+9ies
+9is
+9y
+8tic
+7s
+6ing
+5ola
+8nus
+9uses
+8s
+7e
+8s
+7ic
+9al
+9ally
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9t
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7oid
+9dal
+9ds
+5rake
+9s
+4casein
+9ns
+5enteses
+9sis
+6tamol
+9ols
+5hor
+8s
+6ronism
+9isms
+6ute
+9d
+9s
+8ic
+9ng
+9st
+9sts
+5lete
+9s
+5me
+7s
+5rine
+6ostic
+9ics
+5uses
+7is
+5yanogen
+9gens
+4de
+6d
+6r
+7s
+6s
+5iddle
+9es
+6gm
+8atic
+9tical
+8s
+6ng
+6saic
+9cal
+9cally
+8l
+7e
+8an
+8s
+7iac
+9cal
+9cally
+9l
+9n
+8c
+9al
+5octor
+9rs
+6r
+7es
+7s
+6s
+7es
+6x
+7al
+7er
+9s
+8s
+7ical
+9ality
+9ally
+9alness
+8dian
+8es
+8st
+9ts
+7ologies
+9ogy
+7ure
+9es
+9ine
+7y
+5rop
+8ped
+9ing
+8s
+4e
+5neses
+8is
+7tic
+9cal
+5sthesia
+9sias
+9tic
+4ffin
+8e
+9d
+9s
+8ic
+9ng
+8oid
+8s
+8y
+6le
+8s
+5le
+7s
+5oil
+8s
+6rm
+8s
+4ge
+6neses
+9ia
+9ias
+9is
+8tic
+9ically
+6s
+5lide
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+6ossa
+9ae
+9al
+9ate
+5nathism
+9isms
+9ous
+6oses
+8is
+5oge
+8s
+7ic
+9al
+9ally
+7ue
+9s
+6n
+7ed
+7ing
+8te
+9es
+7s
+5ram
+8matist
+9atists
+8s
+7ph
+9ed
+9er
+9ers
+9ia
+9ias
+9ic
+9ical
+9ically
+9ing
+9ist
+9ists
+9s
+4heliotropic
+5ydrogen
+9gens
+4influenza
+9enzas
+4journalism
+9alisms
+4keelya
+9as
+7t
+8s
+6lia
+9s
+5ite
+8s
+7ing
+9gs
+4lalia
+9s
+6nguage
+9ages
+5dehyde
+9des
+5egal
+9s
+6ipomena
+9menon
+8ses
+9is
+6xia
+9s
+8c
+5imnion
+9ons
+6nguistic
+9istics
+6pomena
+9enon
+7ses
+8is
+5lactic
+9ical
+9ically
+7x
+8es
+6el
+8ed
+9piped
+9pipeda
+9pipeds
+8ing
+9ngs
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9stic
+9sts
+9ze
+9zed
+9zes
+9zing
+8led
+9ing
+9y
+8ogram
+9grams
+9piped
+9pipeda
+9pipeds
+8s
+8wise
+5ogia
+9s
+8es
+8se
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ze
+9ed
+9es
+9ing
+7ue
+9s
+7y
+5ympic
+9cs
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+9gly
+8s
+6tic
+9ally
+9s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+9gly
+4magnet
+9tic
+9tism
+9tisms
+9ts
+6stoid
+9ids
+6tta
+9s
+5ecia
+8um
+9ms
+6dic
+9al
+9als
+9o
+9os
+9s
+6nstrua
+9ruum
+9ruums
+7t
+8a
+8s
+6se
+8s
+6ter
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9s
+7ral
+8ic
+9cal
+9cally
+9sation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+5ilitaries
+9ary
+5nesia
+9as
+5o
+6rph
+9ic
+9ine
+9ines
+9ism
+9isms
+9ous
+9s
+6s
+6uncies
+9y
+8t
+9cies
+9cy
+9ly
+9s
+7r
+8s
+5ylum
+9s
+6xovirus
+9iruses
+4nephric
+9os
+9oses
+6te
+8s
+5g
+6s
+5oea
+8s
+7ic
+9s
+6ia
+8c
+9s
+8s
+7c
+8ally
+8s
+7d
+8al
+8s
+6rmal
+9lities
+9lity
+9lly
+9ls
+5thelia
+9ion
+7ropus
+9puses
+5ym
+7ph
+9s
+7s
+4para
+8s
+7eses
+9is
+8tic
+5ente
+9s
+8ing
+9ngs
+6riodic
+6t
+7ed
+7s
+5h
+6asia
+9as
+9c
+6ed
+7rnalia
+6ilia
+9ac
+9acs
+9as
+7moses
+9sis
+7ng
+6onia
+9as
+9c
+6rasable
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9t
+9tic
+9tical
+9ts
+8xes
+9ia
+9ias
+9is
+7enia
+9ias
+6s
+6ysate
+8es
+8is
+5ineal
+5lanner
+9ers
+6egia
+9as
+9c
+9cs
+5odia
+9l
+8um
+6physes
+9sial
+9sis
+5raxes
+8is
+5sychic
+9ical
+9ism
+9isms
+9ology
+9oses
+9osis
+4quadrate
+9ates
+7t
+8s
+6et
+8s
+6ito
+9s
+4rhyme
+9s
+5osaniline
+9ilines
+5thria
+9as
+4s
+5ail
+8ed
+8ing
+9ngs
+8s
+6ng
+8s
+5cending
+9ings
+8ia
+9um
+7ve
+9s
+6ience
+9ces
+5elenae
+9e
+9ic
+6xual
+9lities
+9lity
+5hah
+8s
+6ioth
+6ot
+8h
+5itaemia
+9mias
+7e
+8s
+7ic
+9al
+9ally
+9alness
+9idal
+9ide
+9ides
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7oid
+9ds
+8logic
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+8ses
+9is
+5kiing
+9gs
+5ol
+7ed
+7s
+5phenoid
+9oids
+5tatal
+9ls
+6ichies
+9ous
+9y
+5uicide
+9des
+5ymbiont
+9onts
+9oses
+9osis
+9otic
+7pathetic
+6napses
+9sis
+9tic
+7theses
+9esis
+9eta
+9etic
+9eton
+4tactic
+9cal
+9cally
+6niwha
+9has
+6xes
+7is
+5ha
+7s
+6eses
+8is
+6ion
+9s
+6ormone
+9ones
+6yroid
+9ids
+5onic
+5roop
+9er
+9ers
+9s
+5ungstic
+5yphoid
+9ids
+4vail
+6ne
+8s
+7t
+6unt
+4walker
+9rs
+5ing
+8s
+4xial
+4zoa
+7n
+8s
+6on
+3bake
+7d
+7s
+6ing
+4oil
+7ed
+7ing
+7s
+4reak
+8ed
+8ing
+8s
+4uckle
+9d
+9s
+8ing
+3cel
+6ed
+6ing
+6led
+7ing
+6s
+6wise
+5naries
+8y
+6er
+8s
+4h
+5ed
+7ly
+7ness
+9sses
+6esi
+9s
+6s
+7i
+8s
+5ing
+6si
+8s
+5ment
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9s
+9y
+4imonies
+8y
+4lose
+8s
+3d
+4ah
+6s
+5l
+6e
+7s
+6is
+8es
+6ote
+9s
+6s
+4ed
+5e
+4i
+5e
+5ne
+4ner
+7s
+4on
+6able
+9eness
+9y
+6ed
+7r
+8s
+6ing
+9s
+6less
+6s
+4s
+4y
+3e
+4cious
+6sm
+8s
+4d
+4goric
+9s
+4idolia
+9as
+5ra
+7s
+4lla
+7s
+6e
+7s
+4ncephala
+9alon
+6hyma
+9al
+9as
+9ata
+9atous
+5eses
+7is
+5t
+6age
+9s
+7l
+8ly
+6ed
+7ral
+9lly
+6heses
+9is
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+8tic
+9ical
+9ically
+7ood
+9ds
+6ing
+9s
+6less
+6s
+4o
+5s
+4r
+5a
+6s
+5ga
+6on
+5s
+4s
+5es
+5is
+5thesia
+9ias
+8tic
+4tic
+7s
+4u
+5s
+4v
+5e
+3fait
+7s
+4leche
+9s
+6sh
+8es
+4ocal
+8ise
+9sed
+9ses
+9sing
+9ties
+9ty
+9ze
+9zed
+9zes
+9zing
+3gana
+7s
+5site
+9s
+4e
+5d
+5s
+5t
+6ed
+7r
+8s
+6ing
+9s
+6s
+6ted
+8r
+9s
+7ing
+9gs
+4ing
+7s
+4o
+5s
+4yline
+9s
+3helia
+8cal
+7c
+7on
+4ypate
+9s
+3iah
+6s
+5l
+6s
+5n
+6s
+4es
+5tal
+8s
+6es
+4mutuel
+4ng
+6s
+4pinnate
+4s
+5chan
+9e
+9es
+9s
+5es
+5h
+6ad
+8s
+6en
+8s
+7s
+6ioner
+9ers
+5on
+7s
+5yllabic
+4ties
+5or
+7s
+5y
+3k
+4a
+5de
+7s
+5s
+4ed
+5e
+6s
+5r
+6s
+5tte
+8s
+4i
+5e
+6r
+6s
+7t
+5n
+6g
+7s
+6s
+7onian
+9ism
+9isms
+5s
+6h
+4land
+8s
+5eaves
+5ike
+5y
+4our
+7s
+4s
+4ward
+8s
+6y
+7s
+4y
+3lance
+8s
+6do
+6te
+5y
+6ed
+6ing
+6s
+4e
+5d
+5ment
+9s
+5s
+5y
+6ed
+7r
+8s
+6ing
+6s
+6voo
+9ed
+9ing
+9s
+4iament
+9tarian
+9tarily
+9tarism
+9tary
+9ting
+9tings
+9ts
+5es
+5ng
+4or
+6s
+5ur
+7s
+6s
+7ly
+7ness
+9sses
+4y
+3macitie
+9es
+4esan
+8s
+4igiana
+9o
+3occipital
+5hial
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+9ly
+7n
+8e
+9s
+8s
+4dic
+7al
+6ed
+7s
+6st
+8ic
+8s
+5oi
+6s
+5y
+6ing
+4ecious
+5mia
+8c
+9s
+8l
+8s
+7ographer
+9raphy
+8logies
+9ogy
+4icous
+4l
+5able
+5e
+6d
+6e
+7s
+6s
+5ing
+5s
+4nomasia
+9ias
+9ies
+9tic
+9tical
+9y
+5ychia
+9al
+9as
+6m
+7ic
+8es
+7ous
+9sly
+7s
+7y
+4quet
+8s
+4re
+6s
+4smia
+8s
+4tic
+6d
+7es
+7itic
+9is
+9ises
+7s
+6s
+6tic
+8s
+9es
+5oid
+8s
+4us
+6ia
+8s
+4xetine
+9es
+5ysm
+8al
+9lly
+8ic
+8s
+6tone
+9es
+9ic
+3p
+4ane
+7s
+4ed
+5n
+6d
+7s
+6s
+6t
+7s
+4ing
+4oint
+8s
+4s
+3quet
+7ed
+7ing
+7ries
+8y
+7s
+7ted
+8ing
+3r
+4a
+5keet
+9s
+5l
+6s
+5matta
+9as
+5s
+4ed
+5l
+6s
+4hesia
+9s
+4icidal
+8e
+9s
+5dge
+8s
+5ed
+6r
+7s
+6s
+5ng
+5tch
+8es
+4ock
+7ed
+7ing
+7s
+5ket
+8s
+5quet
+9s
+5t
+6ed
+7r
+8s
+6fish
+9hes
+6ing
+6ries
+7y
+6s
+6y
+4s
+4y
+5ing
+3s
+4able
+4e
+5c
+6s
+5d
+5r
+6s
+5s
+4imonies
+9ous
+9ously
+8y
+5ng
+7s
+4ley
+7ed
+7s
+5ied
+4nep
+7s
+5ip
+7s
+4on
+6age
+9s
+6ic
+8al
+7sh
+6s
+3t
+4ake
+7n
+7r
+8s
+7s
+6ing
+9s
+5n
+6s
+4ed
+5r
+6re
+8s
+6s
+4henocarpic
+9arpies
+9arpous
+9arpy
+8geneses
+9enesis
+9enetic
+8spore
+9pores
+4i
+5al
+7ise
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9ts
+8ties
+9y
+8ze
+9ed
+9es
+9ing
+7led
+8ing
+8y
+7ness
+9sses
+7s
+5bilities
+9ty
+6le
+5cipable
+9nt
+9ntly
+9nts
+9te
+9ted
+9tes
+9ting
+9tion
+9tional
+9tions
+9tive
+9tor
+9tors
+9tory
+8ial
+9ally
+9als
+8le
+9es
+6le
+8board
+9oards
+8s
+6ular
+9rise
+9rised
+9riser
+9risers
+9rises
+9rising
+9rism
+9risms
+9rist
+9ristic
+9rists
+9rities
+9rity
+9rize
+9rized
+9rizer
+9rizers
+9rizes
+9rizing
+9rly
+9rness
+9rs
+9te
+9tes
+5ed
+6r
+7s
+6s
+5m
+5ng
+7s
+5s
+6an
+8ly
+8s
+9hip
+9hips
+5ta
+7s
+6e
+6ion
+9ed
+9er
+9ers
+9ing
+9ist
+9ists
+9ment
+9ments
+9s
+7ve
+9ly
+9s
+6ura
+9s
+5zan
+8s
+9hip
+9hips
+4let
+7s
+5y
+4ner
+7ed
+7ing
+7less
+7s
+8hip
+9ips
+4on
+6s
+5ok
+4ridge
+9berry
+9s
+4s
+4ure
+7s
+6iencies
+9cy
+9t
+9ts
+7facient
+7tion
+9ons
+4way
+5ork
+8s
+4y
+5er
+7s
+5goer
+9s
+5ing
+6sm
+8s
+3ulides
+6s
+7es
+4ra
+6s
+5e
+6s
+7es
+7is
+3vanimities
+9ty
+4e
+5nu
+7e
+8s
+7s
+4ifoliate
+5s
+6e
+7s
+4o
+5lin
+8e
+9s
+8s
+5s
+5virus
+9ses
+2s
+3cal
+6s
+4hal
+7s
+4ual
+3e
+4ar
+6ed
+6ing
+6s
+4la
+6s
+4o
+5s
+4s
+3h
+4a
+5dom
+8s
+5lic
+8s
+7k
+8s
+5s
+4ed
+5s
+4im
+6s
+5ng
+4ka
+6s
+4m
+5ina
+8s
+5s
+3igraphic
+9ical
+9ies
+9y
+3odoble
+9s
+3palum
+8s
+4ies
+4y
+3queflower
+9wers
+5il
+7ant
+9ts
+7er
+9s
+7led
+8ing
+7s
+6nade
+9ed
+9er
+9ers
+9es
+9ing
+3s
+4able
+8ness
+9esses
+7y
+5caglia
+9ias
+5de
+7s
+6o
+7es
+7s
+5ge
+7d
+7r
+7s
+7way
+9ys
+8ork
+9rks
+6ing
+5long
+9s
+5ment
+9ed
+9ing
+9s
+7zzo
+9os
+5nt
+5ta
+7s
+4band
+8s
+5ook
+8s
+4e
+5d
+5e
+5l
+6s
+5measure
+9ures
+7nt
+9ed
+9erie
+9eries
+9ing
+9s
+5nger
+9s
+5pied
+9s
+5r
+6by
+6ine
+9s
+6s
+7by
+5s
+4ibilities
+9ty
+6le
+8ness
+9esses
+7y
+5flora
+9aceous
+9as
+5m
+6eter
+9rs
+5ng
+7ly
+7s
+5on
+7al
+9s
+8ries
+9y
+8te
+9ed
+9ely
+9eness
+9es
+9ing
+7ed
+7flower
+9owers
+7ing
+7less
+9ssly
+9ssness
+7s
+5vate
+9d
+9s
+8ing
+9on
+9ons
+6e
+7ly
+7ness
+9sses
+7s
+6ism
+9s
+8t
+9s
+7ties
+8y
+4key
+7s
+4less
+4man
+5en
+7t
+8ed
+8ing
+8s
+4out
+7s
+5ver
+8s
+4port
+8s
+4us
+6es
+4word
+8s
+3t
+4a
+5like
+5nce
+8s
+5s
+4e
+5board
+9ds
+5d
+6own
+9s
+5l
+6ist
+9s
+6list
+9ts
+6s
+5r
+6n
+7s
+6s
+5s
+5up
+7s
+6rella
+9lae
+9las
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+4icci
+8o
+9s
+6he
+8s
+8ur
+9rs
+5e
+6r
+6s
+7t
+5l
+6le
+8s
+6s
+6y
+5me
+7s
+5na
+7s
+6ess
+9es
+6g
+7s
+5s
+6es
+5tsio
+9s
+7o
+8s
+4less
+4ness
+8es
+4or
+6al
+8e
+9s
+8i
+9sm
+9sms
+9st
+9sts
+8ly
+8ness
+9esses
+8s
+7te
+9s
+6ed
+6ing
+7um
+9s
+6ly
+6s
+7hip
+9ps
+5urelle
+9les
+4rami
+8s
+5ies
+5omi
+8s
+5y
+6cook
+9ks
+4s
+4urable
+7ge
+9s
+7l
+6e
+7d
+7land
+9nds
+8ess
+7r
+8s
+7s
+6ing
+4y
+2t
+3aca
+6s
+4gia
+7l
+6um
+4ka
+6s
+4mar
+7s
+4physics
+3ball
+7s
+3ch
+5able
+5board
+9ds
+5cocke
+9es
+5ed
+6r
+7ies
+7s
+7y
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5ocke
+9s
+6uli
+9es
+9s
+8y
+5work
+9ed
+9ing
+9s
+5y
+3e
+4d
+4lla
+7e
+7r
+7s
+7te
+6ectomies
+9omy
+6iform
+4n
+5cies
+6y
+5s
+5t
+6abilities
+9lity
+8le
+6ed
+7e
+8s
+6ing
+6ly
+6or
+8s
+6s
+4r
+5a
+6e
+5cove
+9s
+5ero
+8es
+8s
+5familias
+9liases
+5nal
+8ism
+9sms
+9st
+9stic
+9sts
+8ly
+6ities
+8y
+6oster
+9ers
+5s
+4s
+3h
+4breaking
+4ed
+5tic
+8al
+9lly
+8s
+4finder
+9rs
+8ing
+9ngs
+4ic
+6s
+5ng
+4less
+8ness
+9esses
+4name
+8s
+4obiologies
+9ogy
+5gen
+8e
+9s
+9ses
+9sis
+9tic
+8ic
+9cities
+9city
+9es
+8ous
+8s
+8y
+6nomies
+9onic
+9y
+6raphies
+9hy
+5logic
+9cal
+9cally
+9es
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+8y
+5phobia
+9ias
+7ysiology
+5s
+6es
+4s
+4way
+7s
+3ible
+5ulary
+4ence
+8s
+6t
+7ed
+8r
+8st
+7ing
+7ly
+7s
+4ki
+6s
+4n
+5a
+6e
+7d
+6s
+6te
+8d
+8s
+7ing
+8on
+9ns
+5e
+6d
+6s
+5ing
+6se
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5s
+4o
+5s
+4sserie
+9es
+6ier
+9s
+3ka
+5s
+3ly
+3ness
+7es
+3ois
+4nce
+4otie
+8s
+3resfamilias
+4ial
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7s
+6rch
+9al
+9alism
+9alisms
+9ally
+9ate
+9ates
+9ies
+9ism
+9isms
+9s
+9y
+6te
+8d
+8s
+7ing
+8on
+9ns
+5cian
+9ly
+9s
+8te
+9es
+7dal
+8e
+9s
+6k
+7s
+6linic
+9ous
+6o
+7es
+5focal
+9lities
+9lity
+5lineage
+9ages
+9al
+9ally
+9ar
+9arly
+8ies
+8y
+6ocal
+9lly
+5monial
+9ally
+9es
+8y
+5ot
+7ic
+9ally
+8sm
+9ms
+7s
+5stic
+9al
+9ally
+9ism
+9isms
+9s
+4oclinal
+9ic
+9ies
+9ous
+9y
+5l
+6led
+8r
+9s
+7ing
+6man
+7en
+6ogical
+9es
+9st
+9sts
+8y
+6s
+6woman
+9en
+5n
+6age
+9d
+9s
+8ing
+7l
+6ess
+9es
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+6less
+7y
+6ne
+8s
+6s
+6ymic
+9cs
+5on
+7s
+8hip
+9ips
+3s
+4ies
+4y
+3tamar
+8s
+4e
+5d
+5e
+5n
+6ed
+6ing
+6s
+5r
+6ed
+7r
+8s
+6ing
+6n
+7ed
+7ing
+9gs
+7less
+7s
+6s
+5s
+4ie
+6s
+5ng
+4le
+6s
+4ress
+8es
+4y
+5pan
+8s
+3u
+4lent
+5in
+7s
+5ous
+8ly
+8ness
+9esses
+4s
+4tuki
+8s
+3y
+3zer
+6s
+2ua
+4s
+3cal
+6s
+4iloquent
+5ties
+6y
+3ghtier
+8st
+6y
+3l
+4dron
+8s
+4in
+6s
+4ownia
+9s
+4s
+3nce
+6s
+5h
+6ed
+7s
+6ier
+8st
+7ness
+9sses
+8g
+6y
+3per
+6ed
+7ss
+9es
+6ing
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+4iette
+9s
+3ropod
+8s
+3sal
+4e
+5d
+5ful
+8ly
+5less
+9ly
+5r
+6s
+5s
+4ing
+7ly
+7s
+2v
+3age
+6s
+4n
+5e
+6s
+5s
+3e
+4d
+4ed
+4ment
+8ed
+8ing
+8s
+4n
+5s
+4r
+5s
+4s
+3id
+4lion
+8ed
+8ing
+8s
+5lon
+8s
+4n
+5g
+6s
+5s
+4or
+6s
+5ur
+7s
+4s
+5e
+6r
+7s
+6s
+5se
+7s
+3lova
+7s
+3onazzo
+9s
+5e
+6s
+5ian
+6ne
+3s
+2w
+3a
+4s
+4w
+5ed
+5ing
+5s
+3ed
+4r
+5s
+3ing
+3k
+4ier
+6st
+5ly
+5ness
+9es
+4s
+4y
+3l
+4s
+3nable
+5ge
+7s
+4broker
+9rs
+8ing
+9ngs
+4ce
+6s
+4ed
+5e
+6s
+5r
+6s
+4ing
+4or
+6s
+4s
+5hop
+8s
+4ticket
+9ts
+3paw
+6s
+3s
+2x
+3es
+3iuba
+7s
+3wax
+6es
+2y
+3able
+7s
+6y
+3back
+7s
+3check
+8s
+3day
+6s
+3ed
+4e
+5s
+4r
+5s
+3fone
+7s
+3grade
+8s
+3ing
+6s
+3list
+7s
+4oad
+7s
+3master
+9s
+4ent
+7s
+3nim
+6ries
+7y
+6s
+3off
+6s
+4la
+6s
+4r
+5s
+4ut
+6s
+3phone
+8s
+3roll
+7s
+3s
+4age
+7s
+6ist
+9s
+4d
+4lip
+7s
+2zazz
+6es
+3zazz
+7es
+1e
+2a
+3berries
+7y
+3ce
+5able
+9ness
+9nesses
+8y
+5d
+5ful
+8ler
+9est
+9y
+8ness
+9esses
+5keeper
+9ers
+9ing
+9ings
+5less
+9ness
+9nesses
+5maker
+9rs
+8ing
+9ngs
+5nik
+8s
+5s
+5time
+9s
+4h
+5blow
+9s
+5ed
+6r
+7ino
+9os
+7s
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5y
+4ing
+4oat
+7s
+5ck
+7ed
+8ries
+9y
+7ier
+9st
+8ng
+8sh
+7s
+7y
+5d
+6s
+3fowl
+7s
+3g
+4e
+5s
+4s
+3hen
+6s
+3k
+4ed
+6ness
+9ses
+4ier
+6st
+5ng
+5sh
+4less
+5ike
+4s
+4y
+3l
+4ed
+4ike
+5ng
+4s
+3n
+4ed
+4ing
+4s
+4ut
+6s
+3pod
+6s
+3r
+4ce
+6d
+6s
+5ing
+4e
+5s
+4l
+5ash
+8es
+5ed
+6r
+7s
+6scence
+9nces
+9nt
+5ier
+7s
+8t
+6n
+7ess
+9ses
+7g
+8s
+7s
+6sed
+6te
+8s
+7ic
+6zed
+5s
+5wort
+9s
+5y
+4main
+8s
+5onger
+9rs
+4s
+5t
+4t
+5er
+6st
+5ly
+5ness
+9es
+4wood
+8s
+3s
+4ant
+7ries
+8y
+7s
+7y
+4cod
+7s
+4e
+5cod
+8s
+5d
+5n
+5s
+4hooter
+9rs
+4ing
+4on
+5uper
+9s
+3t
+4aries
+6y
+4eries
+6y
+4ier
+6st
+4land
+8s
+4man
+5en
+4s
+5hip
+8s
+4y
+3vey
+6s
+4ies
+4y
+3ze
+5d
+5s
+4ing
+2ba
+4s
+3ble
+6d
+7ash
+9hed
+9hes
+9hing
+6s
+5ier
+7st
+6ng
+8s
+5y
+3rine
+7s
+2c
+3an
+5s
+3cabilities
+9ty
+6le
+5dillo
+9oes
+9os
+5ncies
+7y
+6t
+7ly
+5ries
+6y
+5vi
+7s
+3h
+4an
+6s
+4ed
+4ing
+4s
+3k
+4e
+5d
+5rwood
+9ds
+5s
+4ier
+6st
+5ng
+7s
+5sh
+7ly
+7ness
+9sses
+4s
+4y
+3orini
+7o
+8s
+3s
+3tase
+7s
+5te
+7s
+4en
+6s
+4ic
+5n
+6aceous
+7l
+7te
+9d
+9ly
+8ion
+9ons
+6eal
+7s
+8terase
+9erases
+6ous
+6s
+5sable
+7tion
+9ons
+6e
+7d
+7s
+6ing
+5zable
+7tion
+9ons
+6e
+7d
+7s
+6ing
+4olite
+9s
+5ral
+8ly
+8s
+6iloquies
+9quy
+5se
+7s
+3ulate
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5ia
+7r
+8ise
+9sed
+9ses
+9sing
+9ties
+9ty
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+6um
+4niarily
+8y
+6ous
+2d
+3agog
+7ic
+9al
+9ally
+9s
+8es
+8sm
+9ms
+7s
+7ue
+9d
+9ries
+9ry
+9s
+8ing
+9sh
+9shness
+9sm
+9sms
+7y
+4l
+5ed
+6r
+7s
+5fer
+8s
+5ier
+8s
+6ng
+5led
+7r
+8s
+6ing
+9s
+5o
+6es
+6s
+5s
+4nt
+6ic
+8al
+9lly
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+7se
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+6ocracies
+9acy
+9at
+9atic
+9ats
+6ries
+7y
+6s
+4te
+6ly
+5ifid
+3der
+6s
+4le
+6d
+6r
+7ies
+7s
+7y
+6s
+5ing
+8s
+3erast
+8ic
+9es
+8s
+8y
+5ero
+8es
+8s
+4s
+5es
+5is
+5tal
+8ed
+8ing
+8led
+9ing
+8s
+6rian
+9nise
+9nised
+9nises
+9nising
+9nism
+9nisms
+9nize
+9nized
+9nizes
+9nizing
+9ns
+4tentous
+5ic
+3iatric
+9ian
+9ians
+9s
+8st
+9ts
+4cab
+7s
+5el
+7laria
+9riae
+9te
+7s
+5le
+7d
+7s
+5ular
+8te
+9ed
+9es
+9ion
+9ions
+7i
+7oses
+9is
+9ises
+8us
+7us
+6re
+8d
+8s
+7ing
+8st
+9ts
+4form
+4gree
+8d
+8s
+4ment
+8al
+8ed
+8s
+4palp
+8i
+8s
+8us
+3lar
+6ies
+6s
+6y
+4er
+6ies
+6s
+6y
+3ocal
+7ic
+7s
+4geneses
+9is
+8tic
+7ic
+4logic
+9al
+8es
+8st
+9ts
+7y
+4meter
+9s
+4rthic
+3rail
+7s
+4ero
+7es
+7s
+4o
+5s
+3s
+3uncle
+8d
+8s
+6ular
+9te
+9ted
+9tion
+9tions
+2e
+3been
+7s
+3ce
+5s
+3d
+3ing
+3k
+4abo
+7o
+8s
+7s
+5poo
+8s
+4ed
+4ing
+4s
+3l
+4able
+4ed
+5r
+6s
+4garlic
+9cs
+4ing
+7s
+4s
+3n
+4ed
+4ge
+6d
+6ing
+6s
+5ing
+4ing
+4s
+3oy
+5s
+3p
+4e
+5d
+5r
+6s
+5s
+4hole
+8s
+4ing
+4s
+5how
+8s
+4ul
+6s
+3r
+4age
+7s
+4ed
+5ss
+7es
+4ie
+6r
+6s
+7t
+5ng
+4less
+8ly
+8ness
+9esses
+4s
+4y
+3s
+4weep
+8s
+3tweet
+8s
+3ve
+5d
+5r
+6s
+5s
+4ing
+5sh
+7ly
+7ness
+9sses
+3wee
+6s
+4it
+6s
+2g
+3asus
+7es
+3board
+8s
+5x
+6es
+3ged
+4ies
+4y
+3h
+4ed
+4ing
+4s
+3legged
+5ss
+4ike
+3matite
+9s
+8ic
+3s
+2h
+3s
+2ignoir
+8s
+3n
+4ct
+6ed
+6ing
+6s
+4ed
+4ing
+4s
+3rastic
+9ally
+3se
+5d
+5s
+4hwa
+7h
+8s
+7s
+4ing
+3ze
+5d
+5s
+4ing
+2jorate
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+9es
+2kan
+5s
+3e
+4poo
+7s
+4s
+3in
+5s
+3oe
+5s
+2l
+3a
+4ge
+6s
+5ial
+7n
+8s
+6c
+7s
+4rgonic
+9um
+9ums
+4s
+3e
+4cypod
+9s
+4rine
+8s
+4s
+3f
+4s
+3ham
+6s
+3ican
+7s
+4sse
+7s
+4te
+6s
+5ic
+3l
+4ach
+7s
+6k
+7s
+5gra
+8s
+7in
+9s
+7ous
+4et
+6al
+6ed
+6ified
+9es
+8y
+9ing
+7ng
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6s
+4icle
+8s
+6ular
+5tories
+8y
+4mell
+8s
+4ock
+7s
+4s
+4ucid
+8ities
+9ty
+8ly
+8ness
+9esses
+5m
+6s
+3ma
+5nism
+9s
+5s
+5tic
+4et
+6s
+3oid
+6s
+4logies
+7y
+4n
+4ria
+7n
+7s
+6c
+6es
+6sed
+7m
+8s
+6zed
+5us
+7es
+5y
+4ta
+6s
+5herapies
+9py
+5on
+7s
+3s
+3t
+4a
+5e
+5s
+6t
+7s
+5te
+7ly
+6ion
+9s
+4ed
+5r
+6ed
+6ing
+6s
+4ing
+7ly
+7s
+4less
+4monger
+9rs
+4ries
+5y
+4s
+3ves
+4ic
+6s
+5form
+5meter
+9rs
+8ries
+9y
+5s
+6es
+3ycosaur
+9rs
+2mbina
+7s
+4roke
+8s
+3ican
+7s
+3mican
+8s
+3oline
+8s
+3phigoid
+8us
+7us
+9es
+6x
+7es
+2n
+3al
+5isation
+9ions
+7e
+8d
+8s
+7ing
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ly
+5ties
+6y
+4nce
+7d
+7s
+6ing
+5g
+6s
+5nular
+4tes
+3ce
+5l
+6s
+5s
+4hant
+8s
+4il
+6ed
+7r
+8s
+6ing
+9s
+6led
+8r
+9s
+7ing
+9gs
+6s
+4raft
+8s
+3d
+4ant
+7ly
+7s
+4ed
+5ncies
+7y
+6t
+7ive
+9es
+7ly
+7s
+4icle
+8r
+9s
+8s
+5ng
+4ragon
+9s
+9ship
+9ships
+4s
+4u
+5lar
+7te
+9d
+9s
+8ing
+6e
+7s
+6ine
+6osities
+9ty
+7us
+9ly
+9ness
+9nesses
+6um
+8s
+3e
+4d
+4lopise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+4plain
+9s
+7nation
+9tions
+8e
+9s
+4s
+4trabilities
+9lity
+8le
+9eness
+9y
+7lia
+9an
+7nce
+9es
+9ies
+9y
+8t
+9s
+7te
+9d
+9s
+8ing
+9ngly
+9on
+9ons
+9ve
+9vely
+9veness
+8or
+9rs
+6ometer
+9ters
+3fold
+7s
+4ul
+6s
+3go
+5s
+4uin
+7eries
+9y
+7ries
+8y
+7s
+3holder
+9s
+3i
+4al
+4cil
+7lamine
+9mines
+9te
+9tely
+9tion
+9tions
+8ia
+9form
+9n
+9nase
+9nases
+9ns
+9um
+9ums
+7s
+4e
+5s
+4le
+5l
+6ion
+4ng
+5sula
+9r
+9rities
+9rity
+9s
+9te
+9ted
+9tes
+9ting
+4stone
+9s
+4tence
+9s
+8ies
+8y
+7t
+8ial
+9ally
+9als
+9aries
+9ary
+8ly
+8s
+3k
+4nife
+6ves
+4s
+3light
+8s
+5te
+7s
+3man
+6ship
+9ps
+4en
+3na
+5ceous
+5e
+5l
+6ism
+9s
+6s
+5me
+7s
+5nt
+7s
+5te
+7d
+6ula
+9ceous
+9e
+9s
+4e
+5d
+5ech
+8s
+7k
+8s
+5r
+6s
+5s
+4i
+5a
+5ed
+6s
+5form
+5less
+9ly
+9ness
+9nesses
+6l
+7ion
+5ne
+7s
+6g
+6ite
+9s
+5s
+4on
+6cel
+9le
+9les
+9s
+6ed
+6s
+4y
+5boy
+8s
+5cress
+9ses
+5fee
+8s
+5land
+9s
+5royal
+9ls
+5weight
+9hts
+6histle
+9tles
+6inkle
+9les
+7se
+6ort
+9h
+9hs
+9s
+3oche
+7s
+4logical
+9ally
+8es
+8st
+9ts
+7y
+4ncel
+8le
+9es
+8s
+3point
+8s
+4usher
+9s
+7ing
+9gs
+3s
+4ee
+6s
+5l
+6s
+4ieroso
+5l
+6e
+7ness
+9sses
+6ities
+8y
+6s
+5on
+7able
+8ries
+9y
+7e
+8d
+8er
+8r
+9s
+8s
+7ing
+7less
+7nat
+9ts
+7s
+5ve
+7ly
+7ness
+9sses
+4temon
+9s
+6r
+7s
+5ock
+8s
+4um
+6s
+3t
+4abarbital
+9itals
+5chord
+9ds
+6le
+8s
+6rinoid
+9oids
+6t
+7inal
+7s
+6yclic
+5d
+6actyl
+9yle
+9yles
+9ylic
+9ylies
+9ylism
+9ylisms
+9ylous
+9yls
+9yly
+6elphous
+6ic
+6s
+5gon
+8al
+9lly
+9ls
+8s
+6ram
+9s
+8ph
+9hs
+6ynian
+8ous
+5hedra
+9al
+9on
+9ons
+5logies
+8y
+6pha
+9s
+5meries
+9sm
+9sms
+8ous
+8y
+7ter
+9rs
+6idine
+9nes
+5ndrian
+8ous
+6e
+7s
+6gle
+9s
+7ular
+6oic
+7l
+8s
+5peptide
+9ides
+6loid
+9dies
+9ds
+9dy
+6odic
+9es
+8y
+7lis
+9ses
+9tan
+6rism
+9ms
+5quark
+9ks
+5rch
+8ical
+9es
+8s
+8y
+5stich
+9hous
+9hs
+7yle
+9es
+6yllabic
+5teuchal
+6hla
+8ete
+9tes
+8on
+9ns
+8um
+9ms
+6omic
+7nic
+5valent
+5zocine
+9nes
+4econter
+9ers
+5ne
+7s
+5teric
+4hemimer
+9eral
+9ers
+5ia
+7s
+5ouse
+9d
+9s
+8ing
+4ice
+7d
+7s
+6ing
+5menti
+9o
+5se
+7d
+7s
+6ing
+5ti
+6o
+4landite
+9tes
+4obarbital
+9itals
+9itone
+9itones
+5de
+7s
+5mic
+5san
+8e
+9s
+8s
+6e
+7s
+6ide
+9s
+5xide
+9s
+4roof
+8s
+4s
+5temon
+9ns
+4yl
+6ene
+9s
+6s
+3uche
+7s
+6i
+7s
+6le
+8s
+5kle
+8s
+4lt
+6ima
+9s
+9te
+9tely
+9tes
+6s
+4mbra
+8e
+8l
+8s
+7ous
+4ries
+6ous
+9ly
+9ness
+9nesses
+5y
+3woman
+6en
+2on
+4age
+7s
+4es
+4ies
+5sm
+7s
+4s
+4y
+3ple
+6d
+6hood
+9ds
+6less
+6r
+7s
+6s
+5ing
+2p
+3erino
+8s
+5omia
+9s
+6ni
+8s
+3ful
+3ino
+6s
+3la
+4os
+6es
+4um
+6ed
+6s
+5s
+6es
+3o
+4nida
+8s
+6um
+8s
+4s
+3ped
+5r
+6box
+9es
+6corn
+9ns
+9ny
+6ed
+7r
+8s
+6grass
+9sses
+6idge
+9es
+7er
+8st
+7ness
+9sses
+8g
+9s
+6mill
+9ls
+8nt
+9ts
+9ty
+6oni
+9s
+6s
+6tree
+9es
+6wort
+9ts
+6y
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4y
+3s
+4in
+6ate
+9d
+9s
+8ing
+6e
+7s
+6ogen
+9ns
+6s
+3talk
+7ed
+7ing
+7s
+4ic
+6ities
+8y
+6s
+5d
+6ase
+9s
+6e
+7s
+6ic
+6oglycan
+9ycans
+6s
+5sable
+7tion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+5zable
+7tion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+4one
+7s
+6ic
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+2quiste
+8s
+2r
+3acid
+7ities
+9y
+7s
+5ute
+4dventure
+9ures
+4ea
+5on
+7s
+6pod
+9s
+4i
+5s
+4mbulate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+9tory
+3borate
+9s
+3cale
+7s
+6ine
+9s
+5se
+4e
+5able
+6nt
+5d
+5ivability
+9le
+9ly
+7e
+8d
+8r
+9s
+8s
+7ing
+9gs
+5n
+6t
+7age
+9es
+8l
+7ile
+9es
+7s
+5pt
+7ibility
+9le
+9ly
+8on
+9nal
+9ns
+8ve
+9ely
+9eness
+9ities
+9ity
+7s
+7ual
+9lly
+5s
+4h
+5ance
+5ed
+6r
+7ies
+7on
+9s
+7s
+7y
+6s
+5ing
+8s
+5lorate
+9tes
+8ic
+9de
+9des
+8oethene
+4iform
+5ne
+6g
+5pience
+9ces
+9cies
+9cy
+9t
+9tly
+9ts
+4oct
+5id
+7ean
+9ns
+7s
+5lable
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+6in
+8s
+4urrent
+6sory
+5ss
+7ant
+7ed
+8s
+7ing
+8on
+9nal
+9nist
+9nists
+9ns
+8ve
+9ely
+9eness
+7or
+9s
+5taneous
+9ously
+6ient
+9ts
+3dendo
+8si
+4ie
+5tion
+9able
+9s
+4u
+5e
+6llion
+9ons
+6s
+5rabilities
+9lity
+8le
+9y
+7nce
+9es
+7tion
+9ons
+6e
+7d
+7s
+6ing
+5s
+4y
+3e
+4a
+4gal
+7s
+5rin
+8ate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+9tory
+8e
+9s
+8ities
+9ty
+8s
+4ia
+5on
+7s
+6pod
+9s
+5ra
+7s
+4mptorily
+9iness
+9y
+4nnate
+9d
+9s
+8ing
+9on
+9ons
+6ial
+9ities
+9ity
+9ly
+9s
+7branch
+9anchs
+7ties
+8y
+5tie
+8s
+6y
+4on
+6s
+5pod
+8s
+4s
+5troika
+9kas
+3fay
+4ect
+7a
+8s
+8tion
+9ions
+7ed
+8r
+9s
+8st
+7i
+8bilian
+9ilians
+9ilism
+9ilisms
+9ilist
+9ilists
+9ility
+9le
+8ng
+8on
+9nate
+9nated
+9nates
+9nating
+9nism
+9nisms
+9nist
+9nistic
+9nists
+9ns
+8ve
+9ely
+9eness
+9es
+9ities
+9ity
+7ly
+7ness
+9sses
+7o
+8r
+9s
+8s
+7s
+5rvid
+9ities
+9ity
+9ly
+9ness
+9nesses
+7or
+9s
+8ur
+9rs
+5t
+4icient
+5dies
+7ous
+9sly
+9sness
+6y
+5n
+6g
+7s
+6s
+4luorocarbon
+4oliate
+9ion
+9ions
+5rable
+7ns
+9es
+8t
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+8us
+9ses
+6ce
+6m
+7ability
+9le
+8nce
+9ces
+8tive
+9ively
+9ives
+9ory
+7ed
+8r
+9s
+7ing
+9gs
+7s
+4ume
+7d
+7less
+7r
+8ies
+8s
+8y
+7s
+6ier
+9s
+7ng
+6y
+5nctorily
+9riness
+9ry
+5sate
+9s
+6e
+7d
+7s
+6ing
+7on
+9ist
+9ists
+9s
+7ve
+3gameneous
+8taceous
+4ola
+7s
+4unnah
+9s
+3haps
+7es
+3i
+4agua
+8s
+5ktoi
+8s
+5nth
+8s
+5pses
+7is
+6t
+7s
+5stron
+9ns
+4blast
+9s
+6em
+8s
+5oli
+7oi
+8s
+7us
+4cardia
+9ac
+9al
+9an
+9tic
+9tides
+9tis
+9tises
+9um
+9ums
+7p
+8ial
+9c
+8s
+5enter
+9rs
+8ral
+9e
+9es
+9ic
+5haetia
+9ial
+9ium
+6ondral
+9ria
+9rial
+9rium
+7reses
+9sis
+6ylous
+5lase
+9s
+8tic
+6inal
+8e
+9s
+7tate
+9ted
+9tes
+9ting
+5on
+7es
+6pae
+8l
+7e
+8s
+7ic
+5rania
+9al
+9um
+9ums
+5ulous
+5ycle
+9s
+8ic
+6nthia
+9ion
+9ions
+4derm
+8al
+8ic
+8s
+6smia
+9um
+5ia
+7l
+6nia
+9n
+9ns
+8um
+9ms
+6um
+8s
+5ot
+7e
+8s
+7ic
+8te
+9es
+9ic
+7s
+5rome
+9s
+4egeses
+8is
+4gastric
+9itis
+9itises
+5eal
+7n
+6e
+7s
+6neses
+9is
+5lacial
+5on
+7e
+8s
+7ia
+9l
+8um
+7s
+5ynies
+7ous
+7y
+4helia
+9l
+8on
+6patic
+9itis
+9itises
+4karya
+9l
+8on
+4l
+5ed
+5ing
+5la
+7s
+6ed
+6ing
+5ous
+8ly
+8ness
+9esses
+5s
+5une
+8s
+5ymph
+9s
+4menopausal
+9ause
+9auses
+6ter
+9s
+7ral
+8ic
+9cal
+9cally
+9es
+8y
+5orph
+9ic
+9ism
+9isms
+9ous
+9s
+5ysia
+8um
+9ms
+4naeum
+9s
+6tal
+9ly
+5ea
+7l
+6phria
+9ic
+9itis
+9itises
+9ium
+6um
+8s
+7ral
+8ia
+9al
+9tic
+9tis
+9tises
+9um
+4od
+6ate
+9s
+6ed
+6ic
+8al
+9list
+9lists
+9lly
+9ls
+8ities
+9ty
+7d
+8e
+9s
+8s
+7ng
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ontal
+9ally
+9ia
+9ias
+9ic
+9ically
+9ics
+9ist
+9ists
+9itis
+9itises
+9ology
+6s
+5nychia
+9ium
+5st
+7ea
+9l
+8um
+7ites
+9ic
+9ides
+9is
+9ises
+7racum
+9cums
+7s
+5tic
+8s
+4patetic
+9ical
+9ically
+9icism
+9icisms
+9ics
+7us
+9es
+5eteia
+9an
+9as
+7ia
+9n
+9s
+8es
+7y
+5heral
+9lities
+9lity
+9lly
+9ls
+8ic
+9cal
+9es
+8y
+6onic
+6rase
+9ed
+9es
+9ing
+9is
+9tic
+9tical
+6ytic
+8on
+9ns
+5lasm
+9s
+8t
+9s
+6us
+8es
+5roct
+9s
+5ter
+8al
+8ies
+8s
+8y
+4que
+7s
+4s
+5arc
+8al
+8ous
+8s
+5cian
+9s
+6ope
+9s
+8ic
+9cally
+5elenia
+9ium
+5h
+6abilities
+9lity
+8le
+9eness
+9es
+9y
+6ed
+7r
+8s
+7s
+6ing
+9ly
+5perm
+9al
+9ic
+9s
+6omenon
+9nons
+5sodactyl
+9ctyle
+9ctyles
+9ctylic
+9ctyls
+7logies
+9gy
+7syllabic
+5talith
+9ths
+8ses
+9is
+8tic
+9ically
+6erite
+9tes
+8onic
+6omal
+9tic
+8e
+9s
+8ial
+6rephic
+6ylar
+8e
+9s
+4tectic
+5hecia
+9al
+9um
+5i
+5onaea
+9al
+9um
+9ums
+7ea
+9l
+9lly
+8oscopy
+8um
+9ms
+7ites
+9ic
+9ides
+9is
+9ises
+5rack
+9s
+6ich
+9a
+9ous
+9ously
+9s
+5us
+5yphlitis
+9itises
+4vitelline
+4wig
+7ged
+8ing
+7s
+6nkle
+9es
+3jink
+7ety
+7ities
+9y
+4ure
+7d
+7r
+8s
+7s
+6ies
+7ng
+7ous
+9sly
+6ous
+6y
+3k
+4ed
+4ier
+6st
+5ly
+5n
+6ess
+9es
+6g
+6s
+5sh
+4s
+4y
+3lemoen
+9s
+4ite
+7s
+6ic
+4ocution
+9onary
+9ons
+5us
+4ustrate
+9ted
+9tes
+9ting
+9tion
+9tions
+3m
+4aculture
+9ures
+5frost
+9ts
+5link
+9s
+6loy
+9s
+5nence
+9es
+9ies
+9y
+8t
+9ly
+9ness
+9nesses
+9s
+6ganate
+9ates
+9ic
+5tan
+8s
+4eabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6meter
+9ers
+6nce
+9s
+7t
+8s
+6se
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+5d
+5thrin
+9ns
+4ian
+5e
+6s
+5llage
+9es
+5ng
+5ssibility
+9le
+9leness
+9ly
+8on
+9ns
+8ve
+9ely
+9eness
+5t
+6s
+6tance
+9ces
+7ed
+8e
+9s
+8r
+9s
+7ing
+8vities
+9ity
+4s
+4utabilities
+9lity
+8le
+9eness
+9y
+7te
+9d
+9s
+8ing
+9on
+9onal
+9ons
+6e
+7d
+7s
+6ing
+3n
+4ancies
+7y
+4icious
+9sly
+9sness
+6ketiness
+9y
+5o
+6nes
+4octate
+9ed
+9es
+9ing
+9ion
+9ions
+5d
+6s
+4s
+3ogi
+6es
+4ne
+6al
+6s
+6us
+8es
+4ral
+7ly
+6te
+8d
+8s
+7ing
+8on
+9nal
+9ns
+7or
+9s
+4vskia
+9s
+8te
+9es
+4xid
+7ase
+9es
+8tion
+9ions
+7e
+8d
+8s
+7ic
+8ng
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7s
+6somal
+9e
+9es
+5o
+5y
+6sulphuric
+3p
+4end
+7ed
+7icular
+9ularly
+9ulars
+8ng
+7s
+6t
+7s
+5trable
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+6uable
+8l
+9ism
+9isms
+9ist
+9ists
+9ities
+9ity
+9ly
+9s
+8nce
+9ces
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7ities
+9y
+4henazine
+9ines
+4lex
+7ed
+9ly
+9ness
+9nesses
+8r
+9s
+8s
+7ing
+9gly
+8ties
+9y
+4s
+3quisite
+9es
+9ion
+9ions
+9or
+9ors
+3radial
+7i
+7us
+4ier
+7s
+6s
+4on
+6s
+4uque
+8s
+7ier
+9rs
+4y
+3salt
+7s
+5nt
+5unt
+4crutation
+9tions
+4e
+5cute
+9d
+9e
+9es
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+5ities
+7y
+5line
+9s
+5s
+5verance
+9nces
+9nt
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+8e
+9d
+9s
+8ing
+9ngly
+4icaria
+9as
+6o
+7s
+7t
+8s
+5enne
+9s
+5flage
+9es
+7eur
+9rs
+5mmon
+9s
+5ng
+5st
+7ed
+8nce
+9ces
+9cies
+9cy
+9t
+9tly
+9ts
+8r
+9s
+7ing
+9gly
+8ve
+7s
+4nicketiness
+9ty
+4on
+6a
+7ble
+9eness
+9y
+7e
+7ge
+9s
+7l
+8ia
+9sation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9stic
+9sts
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+8ties
+9y
+7s
+7te
+9d
+9s
+8ing
+9ngs
+9on
+9ons
+9ve
+8or
+9rs
+6hood
+9ds
+6ifiable
+9cation
+9ed
+9er
+9ers
+9es
+8y
+9ing
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6ned
+8l
+9s
+6power
+9ers
+6s
+4pectival
+9ve
+9vely
+9ves
+9vism
+9visms
+9vist
+9vists
+6x
+7es
+5icacious
+9iously
+9ities
+9ity
+7uities
+9ty
+8ous
+9usly
+9usness
+6rable
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ory
+7e
+8d
+8s
+7ing
+9gly
+7y
+4t
+5ringe
+9ed
+9es
+9ing
+4uadability
+9le
+7e
+8d
+8r
+9s
+8s
+7ing
+6sibility
+9le
+8on
+9ns
+8ve
+9ely
+9eness
+9es
+7ory
+5e
+6d
+6s
+5ing
+5lfuric
+6phate
+9tes
+8uric
+4wade
+8d
+8s
+7ing
+3t
+4ain
+7ed
+7ing
+7s
+5ke
+7n
+7s
+6ing
+4er
+5st
+4hite
+8s
+7ic
+4inacious
+9ously
+9ties
+9ty
+6ence
+9es
+9ies
+9y
+8t
+9ly
+9s
+4ly
+4ness
+8es
+4ook
+4s
+4urb
+7able
+9ly
+8nce
+9ces
+9t
+9ts
+8te
+9ed
+9es
+9ing
+9ion
+9ional
+9ions
+9ive
+9or
+9ories
+9ors
+9ory
+7ed
+9ly
+8r
+9s
+7ing
+9gly
+7s
+5sate
+6e
+7d
+6ion
+9s
+6sal
+7es
+7is
+9es
+3uke
+6d
+6s
+4sable
+6l
+7s
+5e
+6d
+6r
+7s
+6s
+5ing
+3v
+4ade
+7d
+7r
+8s
+7s
+6ing
+5sion
+9s
+7ve
+9ly
+9ness
+9nesses
+4e
+5d
+5rse
+8ly
+8ness
+9esses
+8r
+8st
+7ion
+9ns
+8ties
+9y
+8ve
+6t
+7ed
+9ly
+9ness
+9nesses
+8r
+9s
+7ible
+8ng
+7s
+5s
+4iate
+8d
+8s
+7ing
+5cacies
+9ous
+9ties
+9ty
+8y
+5er
+6st
+5ng
+5ous
+8ly
+8ness
+9esses
+4s
+4y
+2s
+3ade
+6s
+4nt
+6e
+6s
+4unt
+7s
+3eta
+6s
+4wa
+6s
+3hwa
+6s
+3kier
+6st
+5ly
+5ness
+9es
+4y
+3o
+4s
+3saries
+6y
+4ima
+7l
+6ism
+9s
+8t
+9ic
+9ical
+9ically
+9s
+6um
+3t
+4er
+6ed
+7r
+8s
+6ing
+9ly
+6ment
+9ts
+6ous
+6s
+4ful
+4hole
+8s
+6use
+9s
+4icidal
+8e
+9s
+5er
+6st
+5ferous
+9usly
+9usness
+5lence
+9es
+8t
+9ial
+9ially
+9ly
+4le
+6d
+6s
+5ing
+4o
+5logical
+9es
+9st
+9sts
+8y
+5s
+4s
+4y
+2t
+3abyte
+8s
+4flop
+8s
+4hertz
+9es
+4l
+5ed
+5iferous
+6ne
+6sm
+8s
+5led
+6ike
+5odic
+8es
+7y
+6id
+6mania
+9ias
+6us
+5s
+4nque
+8s
+4r
+5a
+6s
+5d
+6s
+5ies
+5s
+5y
+4sos
+7es
+5us
+7es
+4urine
+7st
+9s
+3charies
+7y
+4ock
+7s
+3echia
+8e
+8l
+4r
+5ed
+5ing
+5man
+6en
+5s
+6ham
+9s
+3her
+6s
+4idine
+9s
+3illant
+4olar
+7te
+9d
+6e
+7d
+7s
+6ule
+9s
+4t
+5e
+6ness
+9ses
+6s
+5ion
+8ary
+8ed
+9r
+9rs
+8ing
+9ngs
+9st
+9sts
+8s
+5ory
+3nap
+6er
+8s
+6ing
+9s
+6ped
+8r
+9s
+7ing
+6s
+3rale
+7s
+5ries
+6y
+4e
+5l
+6s
+5s
+4i
+5faction
+9ions
+9ive
+6ic
+8ation
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5ssage
+9es
+4ochemical
+9ically
+9icals
+9istry
+6urrencies
+9ency
+5dollar
+9ars
+6rome
+9es
+5geneses
+9sis
+9tic
+8ies
+8y
+6lyph
+9hic
+9hies
+9hs
+9hy
+6ram
+9s
+8pher
+9hers
+9hic
+9hical
+9hies
+9hy
+5l
+6age
+9s
+7tum
+9ms
+6eous
+7um
+9s
+8r
+9s
+8se
+9es
+6head
+9ds
+6ic
+7ferous
+6led
+7ing
+6ogic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+6s
+5money
+9ys
+8ies
+5nel
+8la
+9as
+8s
+5physical
+9icist
+9icists
+9ics
+6ounds
+5sal
+8s
+6tate
+9es
+5us
+3s
+4ai
+6s
+3table
+4ed
+6ly
+6ness
+9ses
+5r
+6s
+4i
+5chaps
+9ses
+6oat
+9ed
+9s
+5er
+6s
+7t
+5fog
+8ged
+9er
+9eries
+9ers
+9ery
+9ing
+9ings
+8s
+5ly
+5ness
+9es
+6g
+7s
+5sh
+7ly
+7ness
+9sses
+5toes
+4le
+6d
+6s
+5ing
+4o
+4y
+3ulance
+9s
+8ies
+8y
+7t
+8ly
+4nia
+7s
+5tse
+8s
+6ze
+8s
+2w
+3ee
+5s
+3holder
+9s
+3it
+5s
+3s
+3ter
+6er
+8s
+6s
+2yote
+6s
+5ism
+8s
+7t
+8s
+5l
+6s
+3se
+5d
+5s
+4ing
+3tral
+7s
+5el
+7s
+2zant
+6s
+3izoid
+1fennig
+7e
+7s
+6ng
+8s
+2ft
+2ui
+1hacelia
+8s
+4oid
+7al
+5lite
+9s
+8h
+9s
+3eic
+5sm
+7s
+4lonion
+9ns
+4nogam
+9ic
+9ous
+9s
+6logies
+9y
+6mena
+9on
+6type
+9ed
+9es
+9ing
+4omelanin
+9nins
+4ton
+7s
+3ge
+5daena
+9as
+9ic
+6ena
+9s
+8ic
+5s
+4ocyte
+9s
+8ic
+9cal
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+8ose
+9sed
+9ses
+9sing
+9sis
+9tic
+5mania
+9ac
+9acs
+9as
+5phobia
+9ias
+5some
+9s
+3langal
+7e
+8al
+8r
+9s
+8s
+7id
+9s
+8st
+9ts
+6sterian
+9ries
+9rism
+9risms
+9rist
+9rists
+9ry
+6x
+7es
+5rope
+9s
+4li
+6c
+7ally
+7ism
+9ms
+9t
+9ts
+6n
+7s
+6sm
+8s
+7t
+8s
+5ocentric
+9trism
+9trisms
+7rat
+9tic
+9ts
+6id
+8in
+9ns
+5us
+7es
+3nerogam
+9mic
+9mous
+9ms
+7phyte
+9ytes
+4g
+5ed
+5ing
+5s
+4sigar
+9s
+4tasiast
+9sts
+8ed
+9s
+8m
+9e
+9es
+9s
+7m
+8a
+9goria
+9gorial
+9gorias
+9goric
+9gories
+9gory
+9l
+9lian
+9lities
+9lity
+9lly
+9ta
+8ic
+9cal
+9cally
+8s
+7t
+8ic
+9cs
+8ries
+9y
+8s
+7y
+8ing
+5om
+7atic
+7ish
+7like
+7s
+7y
+6sme
+9s
+3raoh
+7s
+6nic
+4e
+5s
+4isaic
+9al
+9ally
+9alness
+8sm
+9ms
+6ee
+8ism
+9sms
+8s
+4m
+5a
+6ceutic
+9tical
+9ticals
+9tics
+9tist
+9tists
+7ies
+8st
+9ts
+7odynamic
+8genomic
+9nosies
+9nosist
+9nostic
+9nosy
+8kinetic
+8logic
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+8peia
+9eial
+9eias
+9oeia
+9oeial
+9oeian
+9oeias
+9oeic
+9oeist
+9oeists
+9olist
+9olists
+8therapy
+7y
+6s
+5ed
+5ing
+8s
+5s
+4os
+6es
+4yngal
+9s
+7eal
+8s
+7itic
+9ides
+9is
+9ises
+7ological
+9ogies
+9ogist
+9ogists
+9ogy
+8scope
+9copes
+9copic
+9copies
+9copy
+8tomies
+9omy
+6x
+7es
+3scogale
+9es
+4e
+5al
+5d
+6own
+9s
+5less
+5olin
+9s
+6ut
+8s
+5s
+4ic
+5ng
+7s
+5s
+4mid
+7s
+4or
+6s
+3t
+4ic
+6ally
+4ter
+6st
+2easant
+8ries
+9y
+8s
+4zar
+7s
+3er
+5e
+6s
+5s
+4se
+6d
+6s
+5ing
+4ze
+6d
+6s
+5ing
+3llem
+7s
+5oderm
+9mal
+9ms
+6gen
+9etic
+9ic
+9s
+6id
+6plastic
+9stics
+4onia
+7on
+9s
+3nacaine
+9es
+6etin
+9ns
+6ite
+9s
+5kism
+9s
+8toscope
+7te
+9s
+5nthrene
+9enes
+5rsazine
+9ines
+5te
+7s
+5zin
+8e
+9s
+8s
+4cyclidine
+9dines
+4e
+5s
+5tic
+8ist
+9sts
+8s
+7dine
+9nes
+6ol
+8e
+9s
+8s
+4formin
+9ns
+4gite
+8s
+5ophobia
+9bias
+4ic
+5x
+6es
+4metrazine
+9zines
+4obarbital
+9itals
+9itone
+9itones
+5copies
+8y
+6ryst
+9tic
+9ts
+5gam
+8s
+5l
+6ate
+9d
+9s
+8ing
+6ic
+8s
+6ogical
+9cally
+9es
+9st
+9sts
+8y
+6phthalein
+6s
+5m
+6ena
+9l
+9lise
+9lised
+9lises
+9lising
+9lism
+9lisms
+9list
+9listic
+9lists
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9s
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+8ologies
+9logist
+9logy
+9n
+9ns
+6s
+5thiazine
+9zines
+6ype
+9d
+9s
+8ic
+9cal
+9cally
+9ng
+5xide
+9s
+6y
+4tolamine
+9ines
+4yl
+6alanin
+9nine
+9nines
+9nins
+7mine
+9nes
+6butazone
+9azones
+6ene
+9s
+7phrine
+9rines
+6ic
+6ketonuria
+9onuric
+6methyl
+9hyls
+6s
+6thiourea
+9oureas
+5toin
+9s
+3on
+5s
+3reses
+6is
+4omonal
+8e
+9s
+3se
+5d
+5s
+4ing
+3w
+2i
+3al
+5iform
+5led
+6ing
+5s
+3labeg
+8s
+5delphus
+9huses
+5mot
+8s
+5nder
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+6thrope
+9opes
+9opic
+9opical
+9opies
+9opist
+9opists
+9opoid
+9opoids
+9opy
+5telic
+9cally
+9es
+9st
+9sts
+8y
+4harmonic
+9nics
+5ellene
+9nes
+9nic
+9nism
+9nisms
+9nist
+9nists
+5orse
+9s
+4ibeg
+8s
+5ppic
+9s
+8na
+9as
+9e
+9es
+5stia
+9s
+8ne
+9es
+9ism
+9isms
+4labeg
+9s
+5ibeg
+9s
+6psite
+9tes
+5umenies
+9ist
+9ists
+9y
+4odendra
+9ron
+9rons
+5gynies
+9st
+9sts
+8ous
+8y
+5loger
+9rs
+8ian
+9ans
+9c
+9cal
+9cally
+9es
+9st
+9sts
+8ue
+9es
+8y
+5math
+9ic
+9ical
+9ies
+9s
+9y
+6el
+8a
+9s
+8s
+6ot
+8s
+5pena
+9s
+6oena
+9as
+5sophaster
+9asters
+9e
+9er
+9eress
+9ers
+9es
+9ess
+9esses
+9ic
+9ical
+9ically
+9ies
+9ise
+9ised
+9iser
+9isers
+9ises
+9ising
+9ism
+9isms
+9ist
+9istic
+9ists
+9ize
+9ized
+9izer
+9izers
+9izes
+9izing
+9y
+5xenia
+9as
+4ter
+7ed
+7ing
+7s
+5ra
+6e
+7d
+7s
+6ing
+6um
+3moses
+6is
+5tic
+3nnock
+8s
+3s
+4hing
+8s
+4nomies
+7y
+3z
+4es
+4og
+6s
+4zes
+2lebectomies
+9my
+5itic
+8des
+8s
+9es
+5ogram
+9ms
+9phic
+9phies
+9phy
+6lite
+9es
+7ogies
+9y
+6scleroses
+9erosis
+6tomic
+9ical
+9ies
+9ise
+9ised
+9ises
+9ising
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+9y
+4gm
+6agogic
+9gue
+9gues
+7sia
+9as
+7tic
+9cal
+9cally
+9cness
+6ier
+8st
+6on
+8ic
+8oid
+9us
+8s
+6s
+6y
+3oem
+6s
+4gistic
+9cate
+9cated
+9cates
+9cating
+8on
+9ns
+5opite
+9es
+4mis
+7es
+4rizin
+9s
+4x
+5es
+3yctaena
+9ae
+6ena
+9e
+2o
+3bia
+6s
+5c
+6s
+5sm
+7s
+6t
+7s
+3ca
+5e
+5s
+4ine
+4omelia
+9as
+9c
+9es
+8y
+3ebe
+6s
+5us
+7es
+4nix
+7es
+7ism
+9ms
+7like
+3h
+3lades
+5s
+4idoses
+8is
+3n
+4al
+5sthenia
+9nias
+5te
+7d
+7s
+6hon
+9s
+6ing
+7on
+9s
+6ory
+5utograph
+9raphic
+9raphs
+4e
+5cam
+8s
+7rd
+9s
+5d
+5matic
+9cally
+6e
+7s
+6ic
+8ally
+8isation
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+5ndoscope
+9copes
+5r
+6s
+5s
+5tic
+8al
+9lly
+8ian
+9ans
+9sation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+5y
+6ed
+6ing
+6ness
+9ses
+6s
+4ic
+6ally
+6s
+5ed
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+4meter
+9s
+4o
+5camptic
+9tics
+7rdiogram
+6hemistry
+5fiddle
+9les
+5gram
+9ic
+9ically
+9mic
+9s
+8ph
+9her
+9hers
+9hic
+9hies
+9hist
+9hists
+9hs
+9hy
+5lite
+9s
+8ic
+6ogic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+5meter
+9rs
+8ric
+9ical
+5n
+6s
+5phobia
+9ias
+8re
+9es
+6ore
+9s
+5s
+6cope
+9es
+5tactic
+9ics
+6ype
+9d
+9r
+9rs
+9s
+8ic
+9cal
+9es
+9ng
+9st
+9sts
+8y
+4s
+4y
+5ing
+3oey
+3rate
+7s
+4esies
+6y
+4minges
+7x
+6um
+8s
+4onid
+8s
+3s
+4gene
+8s
+7ite
+9es
+4phatase
+9ses
+8e
+9d
+9s
+8ic
+9de
+9des
+9dic
+9dyl
+9dyls
+9ng
+9sation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8uria
+9rias
+9ric
+6ene
+9s
+6id
+8e
+9s
+8s
+7n
+8e
+9s
+8s
+7te
+9s
+6ocreatin
+9eatine
+9eatins
+7kinase
+9nases
+7lipase
+9pases
+9pid
+9pids
+7nic
+9um
+9ums
+7protein
+9oteins
+7r
+8ate
+9ted
+9tes
+9ting
+8e
+9s
+9sce
+9sced
+9scence
+9scent
+9sces
+9scing
+9t
+9ts
+9tted
+8i
+9c
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9te
+9tes
+9tic
+9ze
+9zed
+9zes
+9zing
+8olyses
+9lysis
+9lytic
+9scope
+9scopes
+9us
+8s
+8us
+9ses
+8yl
+9lase
+9lases
+9late
+9lated
+9lates
+9lating
+9lation
+9lative
+9ls
+6uret
+9ts
+9tted
+4sy
+3t
+4ic
+6ally
+6s
+5nia
+8s
+5sm
+7s
+4o
+5actinic
+9ve
+6utotroph
+9trophs
+5bathic
+6iologic
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+5card
+9s
+7talyses
+9lysis
+9lytic
+8hode
+9odes
+6ell
+9s
+6hemical
+9ically
+9ist
+9istry
+9ists
+7romic
+9mics
+9mies
+9mism
+9misms
+9my
+6ompose
+9osed
+9oser
+9osers
+9oses
+9osing
+7nducting
+9uction
+9uctive
+9uctor
+9uctors
+7piable
+9ed
+9er
+9ers
+9es
+8y
+9ing
+9ings
+6urrent
+9ents
+5degradable
+7tector
+9ctors
+6iode
+9es
+7ssociate
+6uplicate
+9icated
+9icates
+6ynamic
+9mics
+5ed
+6lastic
+9ticity
+7ectric
+9trical
+9trode
+9trodes
+9tron
+9tronic
+9trons
+6mission
+9sions
+9sive
+6ngrave
+9aved
+9aver
+9avers
+9aves
+9aving
+9avings
+6xcitation
+9ted
+5finisher
+9shers
+9shing
+9shings
+7ssion
+9ions
+7t
+8s
+6lash
+9hes
+7ood
+9ds
+7uorogram
+5g
+6elatine
+7n
+8e
+9s
+8ic
+9cally
+9es
+8s
+8y
+7ologic
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+6lyph
+9hic
+9hies
+9hs
+9hy
+6ram
+9metric
+9metry
+9s
+8ph
+9hed
+9her
+9hers
+9hic
+9hical
+9hies
+9hing
+9hist
+9hists
+9hs
+9hy
+8vure
+9ures
+6s
+5induced
+9ction
+9ctions
+9ctive
+7g
+6onisation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+5journalism
+9nalist
+5kineses
+9sis
+9tic
+5litho
+9ograph
+9os
+6uminesce
+9nesced
+9nesces
+6ysable
+8e
+9d
+9s
+8ing
+9s
+7tic
+9cally
+7zable
+8e
+9d
+9s
+8ing
+5macrograph
+7p
+8ped
+9ing
+8s
+7sk
+9s
+6echanical
+7ter
+9rs
+8ric
+9ically
+9ies
+9ist
+9ists
+9y
+6icrograph
+6ontage
+9ages
+7saic
+9ics
+6ultiplier
+7ral
+9ls
+5n
+6astic
+9ies
+9y
+6egative
+7utron
+9rons
+6ic
+8s
+6ovel
+9ls
+6s
+6uclear
+5oxidation
+9ations
+9ative
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+5period
+9odic
+9odism
+9odisms
+9ods
+6hase
+9es
+7il
+9ic
+9ies
+9ous
+9s
+9y
+7obe
+9es
+9ia
+9ias
+9ic
+8ne
+9es
+9ic
+9ies
+9y
+8re
+9es
+9eses
+9esis
+6ia
+8s
+7c
+6lay
+9s
+6olymer
+9mers
+7sitive
+6roduct
+9uction
+9ucts
+6sia
+9s
+8es
+7y
+5reaction
+9tions
+8lism
+9isms
+9ist
+9istic
+9ists
+7ception
+9ptions
+9ptive
+9ptor
+9ptors
+7duce
+9ced
+9ces
+9cing
+9ction
+9ctions
+7fractive
+7sist
+9sts
+5s
+6can
+9ned
+9ning
+9s
+6ensitise
+9itised
+9itiser
+9itises
+9itive
+9itize
+9itized
+9itizer
+9itizes
+7t
+8s
+8ter
+9ers
+9ing
+9ings
+6hoot
+9ts
+8p
+9ped
+9ping
+9s
+6phere
+9res
+9ric
+6tat
+9ed
+9ic
+9ing
+9s
+9ted
+9ting
+6ynthate
+9hates
+9heses
+9hesis
+9hesise
+9hesize
+9hetic
+7stem
+9ems
+5tactic
+9ically
+7xes
+8ies
+9s
+8y
+6elegraph
+9graphs
+9graphy
+6herapies
+9apy
+9mal
+9mally
+9mic
+6onic
+8us
+9ses
+7pography
+7xic
+9cities
+9city
+6ransistor
+7ope
+9es
+9h
+9hic
+9hs
+9ic
+9ically
+9ies
+9ism
+9isms
+9y
+6ube
+9s
+6ype
+9d
+9s
+9set
+9sets
+9setter
+8ic
+9cally
+9es
+9ng
+8ography
+8y
+5voltaic
+9aics
+5xylography
+5zincograph
+4s
+2pht
+2ragmoplast
+9asts
+4sal
+7ly
+5e
+6d
+6less
+6maker
+9ers
+9ing
+9ings
+8n
+7en
+7onger
+9gering
+9gers
+6ogram
+9ams
+9aph
+9aphic
+9aphies
+9aphs
+9aphy
+7logic
+9gical
+9gies
+9gist
+9gists
+9gy
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5y
+4tral
+6ic
+7es
+6y
+3eak
+6ed
+7r
+8s
+6ing
+9s
+6s
+5tic
+6ophyte
+9ytes
+9ytic
+4neses
+7iac
+8s
+6tic
+9al
+9ally
+9ness
+9nesses
+9s
+5ic
+7s
+6sm
+8s
+6tic
+8des
+8s
+9es
+5ologic
+9ical
+9ically
+9ies
+9ise
+9ised
+9ises
+9ising
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+9y
+5sical
+7ed
+8s
+6y
+7ing
+5tick
+3ontisteries
+9ery
+3ygana
+8s
+2t
+3halate
+9s
+6ein
+9s
+6ic
+7n
+8s
+6ocyanin
+9anine
+9anines
+9anins
+4iriases
+9is
+5ses
+6ic
+8al
+8ky
+8s
+7s
+2ut
+4s
+4ted
+5ing
+2woah
+5r
+2ycobilin
+9ns
+7ont
+9ts
+5cyan
+9in
+9ins
+9s
+5erythrin
+9hrins
+5logical
+9es
+9st
+9sts
+8y
+5mycete
+9tes
+9tous
+5phaein
+9ins
+5xanthin
+9hins
+3la
+5cteric
+9ical
+9ies
+9y
+5e
+5r
+6ch
+8ies
+8s
+8y
+5xis
+8es
+4e
+5ses
+6is
+8es
+5tic
+8ally
+8s
+4ic
+4laries
+7y
+5id
+7s
+6te
+8s
+7ic
+5o
+6clad
+9de
+9des
+9ds
+6de
+8s
+7ia
+9l
+8es
+8um
+7y
+6id
+8s
+6mania
+9ias
+7e
+8s
+7ic
+6phagous
+7lane
+9nes
+7od
+9s
+6quinone
+9nones
+6s
+7ilicate
+9icates
+7phere
+9eres
+6tactic
+9tical
+8xes
+9ies
+9is
+9y
+6xera
+9ae
+9as
+4ogeneses
+9sis
+9tic
+8ic
+9es
+8y
+5n
+4um
+3salia
+8s
+7s
+8es
+4ed
+6s
+5s
+5ter
+8s
+4harmonica
+9nicas
+4iatric
+9cal
+9cs
+9es
+9st
+9sts
+8y
+5c
+6al
+8ism
+9sms
+9st
+9stic
+9sts
+9ties
+9ty
+8ly
+8ness
+9esses
+8s
+6ian
+9cies
+9cy
+9er
+9ers
+9s
+9ship
+9ships
+7sm
+9s
+8t
+9s
+6ked
+7ing
+7y
+6ochemical
+6s
+5o
+6cracies
+9cy
+9t
+9tic
+9ts
+6gnomic
+9mical
+9mies
+9mist
+9mists
+9my
+7rapher
+9phers
+9phic
+9phical
+9phies
+9phy
+6later
+9ers
+9ries
+9ry
+7ogic
+9ical
+9ically
+9ies
+9ist
+9ists
+9us
+9uses
+9y
+6pathology
+6s
+6therapies
+9rapist
+9rapy
+5que
+8d
+8s
+5s
+5theism
+9sms
+9stic
+4oclistous
+5stigmin
+9mine
+9mines
+9mins
+7omous
+3tane
+7s
+4in
+6s
+4oalexin
+9ins
+5benthos
+9hoses
+5chemical
+9ically
+9icals
+9ist
+9istry
+9ists
+7rome
+9mes
+5estrogen
+9ogens
+5flagellate
+5geneses
+9sis
+9tic
+9tical
+8ic
+9es
+8y
+7ographer
+9raphic
+9raphy
+6rapher
+9hers
+9hic
+9hies
+9hy
+5hormone
+9ones
+5id
+5l
+6ith
+9s
+6ogical
+9cally
+9es
+9st
+9sts
+8y
+6s
+5n
+6adione
+9ones
+6ic
+6s
+5pathogen
+9ogenic
+9ogens
+9ology
+6hagic
+9ies
+9ous
+9y
+6lankter
+9kters
+9kton
+9ktonic
+9ktons
+5sanitary
+6es
+6is
+6ociology
+6terol
+9ols
+5therapies
+9apy
+6omies
+9st
+9sts
+8y
+7xic
+9cities
+9city
+9n
+9ns
+6ron
+9s
+1i
+2a
+3cevole
+4ular
+8ities
+9ty
+3ffe
+6d
+6r
+7s
+6s
+5ing
+3l
+3n
+4ette
+8s
+4i
+5c
+5no
+7s
+5sm
+7s
+6simi
+9o
+9os
+8ssimo
+6t
+7e
+8s
+7ic
+9ally
+7s
+4o
+5forte
+9es
+5list
+9s
+5s
+4s
+3rist
+7s
+3s
+4aba
+7s
+5va
+7s
+4saba
+8s
+6va
+8s
+4ter
+7s
+5re
+7s
+3zza
+6s
+5e
+5ian
+2bal
+5s
+3roch
+7s
+2c
+3a
+4cho
+7s
+4dillo
+9s
+5or
+7es
+7s
+4l
+4mar
+7s
+4ninnies
+8y
+5te
+4ra
+6s
+5esque
+9es
+5ian
+8s
+5o
+6on
+8ed
+8ing
+8s
+6s
+4s
+4yune
+8s
+7ish
+9hly
+9hness
+3cadill
+9ies
+9o
+9oes
+9s
+9y
+5lilli
+9is
+5nin
+8nies
+9y
+8s
+5ta
+4ies
+4olo
+7ist
+9ts
+7s
+4y
+3e
+4ne
+6s
+4ous
+3hiciego
+9os
+4oline
+9s
+4urim
+8s
+3iform
+4ne
+3k
+4aback
+9ed
+9ing
+9s
+6le
+5dil
+8l
+9ies
+9o
+9oes
+9s
+9y
+8s
+5ninnies
+9y
+5pack
+9ed
+9ing
+9s
+5roon
+9s
+5x
+6e
+7d
+7s
+6ing
+4back
+8ed
+8ing
+8s
+4ed
+6ness
+9ses
+5er
+7ed
+8r
+9s
+7ing
+7s
+5lhaube
+9bes
+5r
+6el
+8s
+8weed
+9eeds
+6ies
+6s
+6y
+5t
+6boat
+9ts
+6ed
+7r
+8s
+6ing
+9s
+6s
+4ier
+6st
+5ly
+5n
+6ess
+9es
+6g
+7s
+6s
+4le
+6d
+6r
+7s
+6s
+5ing
+5ock
+8s
+4maw
+7s
+4off
+7s
+4pocket
+9ts
+5roof
+4s
+4thank
+9s
+4up
+6s
+4wick
+8s
+4y
+3loram
+8s
+3nic
+6ked
+8r
+9s
+7ing
+7y
+6s
+3ocurie
+9s
+4farad
+9s
+4gram
+8s
+4lin
+7e
+8s
+7ic
+7s
+4meter
+9s
+7re
+9s
+5ole
+8s
+4ng
+6s
+4rnavirus
+9ruses
+4second
+9ds
+4t
+5e
+6d
+6e
+7s
+5ing
+6te
+8s
+5s
+4wave
+8d
+8s
+7ing
+3quet
+7ed
+7ing
+7s
+3ra
+5s
+5te
+7d
+7s
+4ic
+5te
+7s
+6ic
+4ocarmine
+9ines
+5toxin
+9ns
+3s
+3tarnie
+9s
+4ogram
+9s
+8ph
+9hic
+9hies
+9hs
+9hy
+5rial
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+9ly
+9ness
+9nesses
+9s
+7cal
+9lly
+4ural
+8s
+6e
+7d
+7goer
+9ers
+7phone
+9ones
+7s
+8que
+9uely
+9ueness
+6ing
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+3ul
+5et
+7s
+5s
+2ddle
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8ly
+5y
+4ock
+7s
+3geon
+7s
+4in
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+2e
+3bald
+7s
+3ce
+5d
+5less
+5meal
+9ed
+9ing
+9s
+5n
+6ed
+7r
+8s
+6ing
+6s
+5r
+6s
+5s
+5wise
+6ork
+9er
+9ers
+9s
+4ing
+7s
+4rust
+8s
+3d
+4fort
+8s
+4ish
+7es
+4mont
+8ite
+9tes
+8s
+4ness
+8es
+3fort
+7s
+3hole
+7s
+3ing
+3man
+4en
+4ontite
+9es
+3nd
+5s
+3plant
+8s
+4owder
+9s
+3r
+4age
+7s
+4ce
+6able
+6d
+6r
+7s
+6s
+5ing
+8ly
+8ness
+9esses
+8s
+4head
+8s
+4id
+6ine
+6s
+5s
+6es
+4ogi
+7es
+4rette
+9s
+5ot
+7s
+4s
+5t
+4t
+5s
+3s
+3t
+4a
+5s
+4ies
+5sm
+7s
+6t
+7ic
+9al
+9ally
+7s
+4s
+4y
+3zo
+5chemistry
+5electric
+5magnetic
+9etism
+9etisms
+6eter
+9rs
+8ric
+9ically
+9ies
+9y
+2fferari
+8o
+6o
+7s
+4le
+6d
+6r
+7s
+6s
+5ing
+2g
+3boat
+7s
+3eon
+6ed
+6hole
+9ed
+9er
+9ers
+9es
+9ing
+6ing
+7te
+9s
+6ries
+7y
+6s
+6wing
+9gs
+3face
+7s
+4eed
+7s
+4ish
+7es
+3ged
+5ries
+6y
+4ie
+6r
+6s
+7t
+5n
+6ess
+9es
+6g
+7s
+6s
+5sh
+7ly
+7ness
+9sses
+4y
+5back
+9ed
+9ing
+9s
+3headed
+9ly
+9ness
+9nesses
+4t
+5ed
+5ing
+5le
+7s
+5s
+3let
+6s
+4ike
+5ng
+7s
+3maean
+4ean
+6t
+7s
+5nt
+7al
+8ry
+8tion
+9ions
+7ed
+7ing
+7osa
+9as
+7s
+4ies
+4oid
+4y
+3nerate
+9d
+9s
+8ing
+4oli
+7a
+8s
+7s
+5ra
+7te
+9d
+9s
+8ing
+9on
+9ons
+4us
+5t
+6s
+3out
+6s
+3pen
+6s
+3s
+4conce
+9s
+4kin
+7s
+4ney
+7s
+5ie
+7s
+5y
+4tick
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+6es
+5uck
+5y
+4will
+8s
+3tail
+7ed
+7s
+3wash
+7es
+4eed
+7s
+2hoihoi
+8s
+2ing
+2ka
+4ke
+6s
+4s
+4u
+5s
+3e
+4d
+4let
+7s
+4man
+5en
+4perch
+9es
+4r
+5s
+4s
+5taff
+9s
+7ves
+4y
+5s
+3i
+4ng
+6s
+4s
+3ul
+5s
+2la
+4f
+5f
+6s
+5s
+4o
+5s
+4r
+4ster
+8ed
+8s
+4u
+5s
+4w
+5s
+3ch
+5ard
+8s
+5er
+7s
+6s
+4orn
+7s
+4row
+7s
+3e
+4a
+5s
+5te
+7d
+4d
+4i
+4less
+4orhiza
+9as
+5us
+4r
+5s
+4s
+4um
+5p
+6s
+5s
+4work
+8s
+7t
+8s
+3fer
+6able
+7ge
+9s
+6ed
+7r
+8s
+6ies
+7ng
+9ly
+9s
+6proof
+6s
+6y
+3garlic
+9k
+9ks
+9ky
+9s
+4rim
+7age
+9ed
+9er
+9ers
+9es
+9ing
+7er
+9s
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7s
+3i
+4ferous
+5orm
+4ng
+6s
+5ut
+7s
+4s
+3l
+4age
+7d
+7r
+8s
+7s
+6ing
+5r
+6ed
+6ing
+7st
+9s
+6less
+6s
+5u
+6s
+4box
+7es
+4ed
+4head
+8s
+4icock
+9s
+5e
+6s
+5ng
+7s
+5on
+7ed
+7ing
+8st
+9ts
+7s
+5winks
+4ock
+7s
+5ried
+8s
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6y
+7ing
+5w
+6case
+9es
+6ed
+6ing
+6s
+7lip
+9ps
+6y
+4s
+4worm
+8s
+7t
+8s
+3niewinks
+3ocarpin
+9ne
+9nes
+9ns
+4motor
+4nidal
+4se
+5ities
+7y
+4t
+5age
+8s
+5ed
+5fish
+9es
+5house
+9es
+5ing
+8s
+6s
+5less
+5man
+6en
+5s
+4us
+4w
+5s
+3sener
+8s
+4ner
+7s
+3ula
+6e
+6r
+6s
+5e
+6s
+4m
+4s
+3y
+2ma
+4s
+3ent
+6o
+7n
+8s
+7s
+6s
+3iento
+8s
+3p
+4ed
+5rnel
+9s
+4ing
+7s
+4le
+6d
+6s
+5ier
+7st
+6ness
+9ses
+5y
+4mobile
+9es
+4s
+2n
+3a
+4ceous
+5oid
+8al
+8s
+6theca
+9cae
+4fore
+8d
+8s
+4koid
+8al
+8s
+6thek
+9ks
+4ng
+6s
+4s
+5ter
+8s
+4ta
+6s
+3ball
+7ed
+7ing
+7s
+4oard
+8s
+5ne
+7s
+3case
+7s
+4er
+6ed
+6ing
+6like
+6s
+4h
+5beck
+9s
+6ug
+8s
+5cock
+9s
+7mmons
+9onses
+5eck
+8s
+6d
+6r
+7s
+6s
+5fist
+9s
+5gut
+8s
+5ing
+8ly
+8s
+5pennies
+9y
+6oint
+9ts
+4ushion
+9ns
+3dan
+6s
+5ree
+8s
+6i
+7s
+4er
+6s
+4ling
+4own
+7s
+3e
+4al
+6ectomies
+9omise
+9omised
+9omises
+9omize
+9omized
+9omizes
+9omy
+6s
+5pple
+9s
+4cone
+8s
+4d
+5rops
+4land
+8s
+5ike
+4ne
+6s
+4ries
+5y
+4s
+5ap
+7s
+4ta
+5um
+4wood
+8s
+4y
+3fall
+7s
+4eather
+9rs
+4ish
+7es
+4old
+7ed
+7ing
+7s
+3g
+4ed
+5r
+6s
+4ing
+4le
+6d
+6r
+7s
+6s
+5ing
+4o
+5es
+5s
+4pong
+8s
+4rass
+8es
+4s
+4uefied
+9s
+7y
+8ing
+5id
+7ities
+9y
+6n
+7s
+6tude
+9es
+3head
+7ed
+9ness
+9nesses
+7s
+4ole
+7s
+5oker
+9s
+3ier
+5s
+6t
+4ng
+4on
+6ed
+6ing
+6s
+4te
+6s
+5ol
+7s
+3k
+4ed
+5n
+6ed
+6ing
+6s
+5r
+6s
+6ton
+9s
+5st
+5y
+6e
+7s
+6s
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+7s
+5sh
+7ness
+9sses
+4ly
+4ness
+8es
+4o
+5es
+5s
+4root
+8s
+4s
+4y
+3na
+5ce
+7s
+6le
+8d
+8s
+7ing
+5e
+5l
+5s
+5te
+7d
+7ly
+6ifid
+9dly
+7on
+9s
+7partite
+8ed
+7sect
+4ed
+5r
+6s
+5t
+6s
+4ie
+6s
+6winkle
+9kles
+5ng
+7s
+5ped
+8e
+9s
+8ian
+9ans
+8s
+4ock
+7s
+5ed
+4ula
+7e
+7r
+7s
+7te
+9d
+6e
+7s
+4y
+5winkle
+9les
+3ochle
+8s
+5le
+7s
+5ytic
+7oses
+9is
+8tic
+9ically
+4le
+6s
+4n
+5es
+5s
+4t
+5age
+8s
+5s
+3point
+8ed
+8ing
+8s
+4rick
+8ed
+8ing
+8s
+3s
+4cher
+8s
+4etter
+9s
+4potter
+9rs
+4tripe
+9d
+9s
+4well
+8s
+3t
+4a
+5ble
+8s
+5da
+7s
+6era
+9s
+6o
+7es
+7s
+5il
+7ed
+7s
+5no
+7s
+5s
+4le
+6s
+4o
+5es
+5s
+4s
+5ize
+8d
+3up
+5s
+3wale
+7s
+4eed
+7s
+4heel
+8ed
+8ing
+8s
+4ork
+7s
+6m
+7s
+4rench
+9es
+3xit
+3y
+4in
+4on
+6s
+2olet
+6s
+3n
+4ed
+5er
+7ed
+7ing
+7s
+5r
+6s
+5y
+6s
+4ic
+5es
+5ng
+7s
+4s
+4y
+3pio
+6s
+3sities
+6y
+3ted
+3us
+5ly
+5ness
+9es
+3y
+4e
+5s
+4s
+2p
+3a
+4ge
+6s
+4l
+5s
+4s
+3e
+4age
+7s
+4clay
+8ed
+8ing
+8s
+4d
+4fish
+8es
+6tter
+9rs
+8ing
+9ngs
+5ul
+7s
+4less
+5ike
+6ne
+8d
+8s
+7ing
+9gs
+4r
+5aceous
+6zine
+9es
+5ic
+6dine
+9es
+6ne
+8s
+5onal
+9s
+5s
+4s
+5tem
+8s
+6one
+9s
+4t
+5s
+5te
+7d
+7s
+6ing
+4work
+8s
+7t
+8s
+3i
+4er
+5st
+4ness
+8es
+5g
+6ly
+6s
+4s
+5trel
+9le
+9les
+9s
+4t
+5s
+4wharauroa
+9uroas
+3kin
+6s
+3less
+3ped
+4ier
+6st
+5n
+6g
+6s
+4y
+3s
+4issewa
+9as
+4queak
+9s
+3ul
+5s
+3y
+2quance
+8s
+7ies
+7y
+6t
+7ly
+7ness
+9sses
+4e
+5d
+5s
+5t
+6ed
+6ing
+6s
+4illo
+8s
+5ng
+2r
+3acetam
+9s
+5ies
+5y
+4gua
+7s
+4i
+5s
+4na
+6s
+5ha
+7s
+4rucu
+8s
+4te
+6d
+6s
+5ic
+7al
+9ly
+6ng
+4ya
+6s
+3iform
+3l
+4icue
+8d
+8s
+7ing
+4s
+3n
+4ie
+6s
+5t
+4s
+3og
+5en
+5hi
+5i
+6es
+5ue
+7s
+4jki
+4plasm
+9a
+9ata
+9s
+4que
+7s
+4shki
+4uette
+9d
+9r
+9rs
+9s
+8ing
+4zhki
+6ok
+3s
+2s
+3caries
+6y
+5tor
+8ial
+9ally
+8s
+8y
+6rix
+9es
+4icolous
+6ultural
+9urally
+9ure
+9ures
+9urist
+9urists
+5fauna
+9ae
+9as
+6orm
+5na
+7e
+7l
+7s
+6e
+7s
+5vore
+9s
+8ous
+4o
+5s
+3e
+4s
+3h
+4ed
+5og
+7s
+5r
+6s
+5s
+4ing
+4oge
+7s
+6ue
+8s
+3iform
+8s
+3kies
+4y
+3mire
+7s
+3o
+4lite
+8s
+7h
+8s
+7ic
+4s
+3sant
+7s
+5sphalt
+9lts
+3tache
+8s
+7io
+9s
+5reen
+9s
+4e
+5s
+4il
+6lary
+8te
+7ode
+9es
+6s
+4ol
+6e
+7d
+7er
+9s
+7ro
+9s
+7s
+7t
+8s
+6ier
+9s
+7ng
+6led
+7ing
+6s
+5n
+6s
+5u
+6s
+2t
+3a
+4haya
+8s
+4pat
+7s
+7ted
+8ing
+4ra
+6h
+7s
+6s
+4s
+4ya
+6s
+3ch
+5bend
+9s
+6lende
+9des
+5ed
+6r
+7ful
+9ls
+7s
+8ful
+6s
+5fork
+9ed
+9ing
+9s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5man
+6en
+5ometer
+9ers
+6ut
+8s
+5person
+9ons
+6ine
+9s
+7pe
+9s
+6ole
+9d
+9s
+8ing
+5stone
+9es
+5woman
+8en
+5y
+3eous
+7ly
+7ness
+9sses
+3fall
+7s
+3h
+4ball
+8s
+4ead
+7s
+5canthropi
+9hropus
+6oid
+5d
+4ful
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4less
+5ike
+4oi
+5s
+4s
+4y
+3iable
+8ness
+9esses
+7y
+4ed
+5r
+6s
+5s
+5th
+4ful
+7ler
+9st
+8y
+7ness
+9sses
+4kins
+4less
+8ly
+8ness
+9esses
+3man
+6s
+4en
+3on
+5s
+3prop
+7s
+3s
+4aw
+6s
+3ta
+5nce
+8s
+5s
+4ed
+5n
+5r
+6ed
+6ing
+6s
+4ing
+7s
+5te
+7s
+4osporum
+9ums
+3uita
+7ries
+8y
+7s
+6e
+7s
+6rin
+9s
+4ri
+6s
+3y
+4ing
+7ly
+4riases
+8is
+5oid
+6sporum
+9rums
+2u
+3m
+4s
+3piu
+6s
+2vot
+5able
+6l
+7ly
+5ed
+6r
+7s
+5ing
+8s
+5man
+6en
+5s
+2wakawaka
+9as
+2x
+3el
+5ate
+8d
+7ing
+8on
+9ns
+5lated
+5s
+4s
+3ie
+5ish
+5s
+4lated
+7ion
+9ns
+5lated
+8ion
+9ons
+4ness
+8es
+3y
+4ish
+2zazz
+6es
+6y
+3e
+4d
+4s
+3ing
+3za
+5iola
+5like
+5s
+5z
+6es
+6z
+7es
+7y
+4elle
+8s
+5ria
+8s
+4icati
+8o
+9s
+4le
+6s
+1laas
+5es
+3cabilities
+9ty
+6le
+8ness
+9esses
+7y
+5rd
+7ed
+7ing
+7s
+5te
+7d
+7r
+8s
+7s
+6ing
+9ly
+7on
+9s
+7ve
+6ory
+4cat
+7e
+8s
+7s
+4e
+5able
+5bo
+7es
+7s
+5d
+5holder
+9ers
+5kick
+9ed
+9er
+9ers
+9ing
+9s
+5less
+9ly
+5man
+6en
+8t
+9s
+5nta
+8e
+8l
+9s
+8s
+8te
+9ion
+9ions
+7iform
+7ologies
+9ogy
+5r
+6s
+5s
+5t
+6s
+4id
+6er
+7st
+6ities
+8y
+6ly
+6ness
+9ses
+5ng
+7s
+5t
+6a
+6ory
+6s
+6um
+4k
+5et
+7s
+5less
+5s
+4oderm
+9s
+5id
+7s
+3fond
+7s
+3gal
+4e
+5s
+4iaries
+8se
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ze
+9ed
+9er
+9ers
+9es
+9ing
+7y
+5ocephalies
+9haly
+7lase
+9ses
+9stic
+8imax
+9maxes
+6stomatous
+9me
+9mes
+9mous
+6tropic
+9pism
+9pisms
+9pous
+5um
+7s
+4ue
+6d
+6r
+7s
+6s
+7ome
+6y
+5ier
+7st
+6ly
+6ng
+5y
+3ice
+6s
+4d
+5ed
+5ing
+8s
+5man
+6en
+5s
+4n
+5ant
+8s
+5chant
+9ts
+6lothes
+9hesman
+9hesmen
+5ed
+6r
+6st
+5ful
+5ing
+8s
+6sh
+5ly
+5ness
+9es
+5s
+6man
+7en
+6ong
+9s
+6poken
+9enness
+6tanes
+7ones
+5t
+6ext
+9s
+6ful
+6iff
+9s
+7ve
+9ly
+9ness
+9nesses
+6less
+6s
+5work
+9s
+4ster
+8ed
+8ing
+8s
+4t
+5ed
+6r
+7s
+5ing
+8s
+5s
+3n
+4ar
+6ia
+8n
+9s
+8s
+7ties
+8y
+5te
+6ion
+9s
+4ch
+6e
+7d
+7s
+7t
+8s
+8te
+9es
+6ing
+4e
+5d
+5load
+9s
+5ness
+9es
+5r
+6s
+5s
+6ide
+9s
+5t
+6aria
+9es
+9um
+9ums
+8y
+6esimal
+9mals
+6ic
+8al
+6like
+6oid
+9al
+9s
+7logical
+9gies
+9gist
+9gists
+9gy
+6s
+6wide
+4form
+8s
+4gencies
+8y
+7t
+8ly
+4igraph
+9hs
+5meter
+9rs
+8ric
+9ical
+9ically
+9ies
+9y
+5ng
+5sh
+7ed
+8r
+9s
+8s
+7ing
+6phere
+9res
+9ric
+4k
+5ed
+5ing
+8s
+5s
+5ter
+8s
+6on
+8ic
+8s
+4less
+8ly
+8ness
+9esses
+4ned
+6r
+7s
+5ing
+8s
+4oblast
+9ts
+5gamete
+9tes
+6raphic
+9hies
+9hy
+5meter
+9rs
+8ric
+9ically
+9ies
+9y
+5sol
+8s
+4s
+4t
+5a
+6ble
+6e
+6ge
+8s
+7inaceous
+6in
+8s
+6r
+6s
+6tion
+9ns
+5ed
+6r
+7s
+5igrade
+9des
+6ng
+8s
+5less
+7t
+8s
+6ike
+7ng
+9s
+5ocracies
+9cy
+5s
+6man
+7en
+6woman
+9en
+5ule
+8s
+4ula
+7e
+7r
+7te
+6iform
+6oid
+5ria
+8s
+7es
+6y
+4xties
+6y
+3p
+4ped
+5ing
+4s
+3que
+6s
+6tte
+9s
+3sh
+5ed
+6r
+7s
+6s
+6t
+7s
+5ier
+7st
+6ng
+8s
+5y
+4m
+5a
+6gel
+9s
+8ne
+9es
+9ic
+6lemma
+9mas
+6phereses
+9resis
+6s
+7ol
+9s
+6tic
+9al
+5ic
+6d
+7s
+6n
+7ogen
+9ens
+7s
+5odesm
+9ma
+9mas
+9mata
+9ms
+7ia
+9l
+8um
+6gamies
+9y
+6id
+8s
+6lyse
+9ed
+9es
+9ing
+9is
+8tic
+9ically
+8ze
+9ed
+9es
+9ing
+6n
+7s
+6soma
+9ata
+9e
+9es
+5s
+4t
+5e
+6r
+7board
+9ards
+7ed
+8r
+9s
+7iness
+9esses
+9g
+9gs
+7s
+8tone
+9ones
+7work
+9rks
+7y
+5ic
+7ally
+7ene
+9es
+7ine
+9es
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7ky
+7ly
+7s
+6d
+7ial
+7s
+7ule
+9es
+6lina
+9as
+6que
+9s
+6sol
+9s
+5ocyanin
+9nins
+6gamies
+9y
+6meter
+9ers
+9ric
+9ries
+9ry
+6quinone
+9nones
+5ral
+6on
+8s
+6um
+8s
+3t
+4an
+6aceous
+6e
+7s
+6na
+8s
+6s
+4band
+8s
+4e
+5asm
+8s
+6u
+7ed
+7ing
+7s
+7x
+5d
+5ful
+8s
+5glass
+5layer
+9rs
+6et
+8s
+6ike
+5maker
+9rs
+8ing
+9ngs
+7n
+7rk
+9ed
+9ing
+9s
+6en
+5n
+6s
+5r
+6esque
+6s
+5s
+6ful
+4form
+8ed
+8ing
+9ngs
+8s
+4ier
+6s
+7t
+5na
+7s
+6g
+7s
+6ic
+7ferous
+7ridium
+9diums
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ocyanic
+9anide
+9anides
+7id
+9s
+7type
+9pes
+7us
+6um
+8s
+5tude
+9s
+8inal
+9narian
+9nise
+9nised
+9niser
+9nisers
+9nises
+9nising
+9nize
+9nized
+9nizer
+9nizers
+9nizes
+9nizing
+9nous
+9nously
+4onic
+8ally
+8s
+7sm
+9s
+5on
+7ed
+7ing
+7s
+4s
+4ted
+6land
+9ds
+6r
+7ful
+9ls
+7s
+8ful
+5ing
+8s
+4y
+5cephalic
+9alous
+5fish
+9es
+5helminth
+9inthic
+9inths
+5kurtic
+5pi
+6us
+8es
+5rrhine
+9nes
+9nian
+9nians
+5s
+6ma
+8s
+3udit
+7e
+7ory
+7s
+4sibilities
+9ity
+7le
+9ness
+9nesses
+8y
+6ve
+5tral
+3y
+4a
+5bilities
+9ty
+6le
+5ct
+7ed
+7ing
+9gs
+7or
+9s
+7s
+5s
+4back
+8s
+5ill
+8s
+5ook
+8s
+4date
+8s
+6y
+7s
+5ough
+9s
+6wn
+8s
+4ed
+5r
+6s
+4fellow
+9ws
+5ield
+9s
+5ul
+7ly
+7ness
+9sses
+4girl
+8s
+5oer
+8s
+6ing
+9s
+5round
+9ds
+8p
+9s
+4house
+9s
+4ing
+4land
+8s
+5eader
+9rs
+6ss
+6t
+7s
+5ike
+6st
+8ed
+8ing
+8s
+4maker
+9s
+7ing
+9gs
+6te
+8s
+4off
+7s
+4pen
+7s
+4room
+8s
+4s
+5chool
+9ls
+5lip
+8s
+5ome
+5uit
+8s
+4thing
+9s
+5ime
+8s
+4wear
+5right
+9ting
+9tings
+9ts
+7ting
+9ngs
+3za
+5s
+2ea
+4ch
+6ed
+7s
+6ing
+4d
+5able
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5s
+4ed
+4ing
+4s
+5able
+6nce
+9s
+7t
+8er
+9st
+8ly
+8ness
+9esses
+8ries
+9y
+5e
+6d
+7ly
+6man
+7en
+6r
+7s
+6s
+6th
+5ing
+8ly
+8ness
+9esses
+8s
+5urability
+9le
+9leness
+9ly
+7e
+8d
+8ful
+8less
+8r
+9s
+8s
+7ing
+4t
+5ed
+6r
+7s
+5her
+8s
+5ing
+5less
+5s
+3b
+4bier
+7st
+5y
+4e
+5an
+5ian
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+5s
+4ian
+5fication
+9tions
+7ed
+8s
+6y
+7ing
+5scitary
+9e
+9es
+4s
+3copteran
+9ans
+9ous
+4tognath
+9thic
+9thous
+9ths
+6pterous
+5ra
+6e
+7s
+6on
+8s
+6um
+8s
+3d
+4gable
+5e
+6able
+6d
+6e
+7s
+6or
+8s
+6r
+7s
+6s
+6t
+7s
+5ing
+5or
+7s
+3iad
+6es
+6s
+4nairism
+9sms
+9st
+9sts
+4ocene
+6hasia
+9ium
+5meries
+8ous
+8y
+5taxies
+8y
+6ropic
+9ies
+9ism
+9isms
+9y
+3na
+5ries
+7ly
+6ties
+7y
+6y
+4ch
+6es
+4ilunar
+8e
+9s
+5po
+7es
+7s
+7tence
+9nces
+9ncies
+9ncy
+9nt
+9ntial
+9ntiary
+5sh
+7ed
+8r
+9s
+8s
+7ing
+9gs
+7ment
+9nts
+6m
+7s
+6t
+7s
+5tude
+9s
+8inous
+4teous
+9ly
+9ness
+9nesses
+5ies
+6ful
+9ly
+9ness
+9nesses
+6tude
+9es
+5y
+4um
+6s
+3ochroic
+9sm
+9sms
+4morphic
+9ies
+9ism
+9isms
+9ous
+9y
+4n
+5al
+6sm
+8s
+7t
+8e
+9s
+8ic
+9cal
+9cally
+8s
+5ectic
+6xia
+9s
+5ic
+5s
+4pod
+7s
+3rion
+7s
+4ocercoid
+9oids
+5ma
+7s
+7tic
+6e
+7s
+5phoria
+9ias
+9ies
+9y
+3sh
+5es
+4iosaur
+9rian
+9rs
+4simeter
+9ers
+9ric
+9ries
+9ry
+5or
+7s
+3thora
+8s
+7ic
+9al
+9ally
+5ysmogram
+9grams
+9graph
+9graphs
+9graphy
+3uch
+6ed
+6ing
+6s
+4gh
+6ed
+6ing
+6s
+4ra
+6e
+6l
+6pophyses
+9hysis
+6s
+5isies
+7y
+6tic
+9al
+9s
+8s
+9es
+5ocarpous
+7enteses
+9tesis
+6dont
+9ts
+7ynia
+9ias
+6n
+7ia
+9s
+6pneumonia
+6tomies
+9y
+4ston
+8ic
+8s
+3w
+4s
+3x
+4al
+4es
+4iform
+5glass
+9ses
+5meter
+9rs
+8ric
+9ies
+9y
+4or
+6s
+4ure
+7s
+5s
+6es
+2iabilities
+9y
+5le
+7ness
+9sses
+6y
+4ncies
+6y
+5t
+6ly
+6ness
+9ses
+3ca
+5e
+5l
+5te
+7d
+7ly
+7ness
+9sses
+7s
+6ing
+7on
+9s
+6ure
+9s
+3e
+4d
+4r
+5s
+4s
+3ght
+6ed
+7r
+8s
+6ful
+6ing
+6s
+3m
+4med
+5ing
+4s
+5ol
+7e
+8s
+7l
+8s
+7s
+3ng
+5s
+4k
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8s
+5s
+5y
+4th
+6s
+3ocene
+4film
+8s
+4saur
+8s
+4tron
+8s
+3skie
+7s
+5y
+4se
+6s
+2oat
+5ed
+5ing
+5s
+3d
+4ded
+6r
+7s
+5ing
+8ly
+8ness
+9esses
+8s
+4ge
+6d
+6s
+5ing
+4s
+3idies
+5y
+3ng
+5d
+5e
+6d
+6s
+5ing
+5s
+4k
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8s
+5o
+6s
+5s
+5y
+3ok
+5ie
+7r
+7st
+5s
+5y
+3p
+4ped
+5ing
+4s
+3sion
+7s
+5ve
+7s
+3t
+4ful
+4less
+8ness
+9esses
+5ine
+8s
+4s
+4tage
+8s
+5ed
+6r
+7ed
+7ing
+7s
+5ie
+7r
+7s
+8t
+6ng
+8ly
+8s
+5y
+4z
+5ed
+6s
+5ing
+3ugh
+6able
+6boy
+9s
+6ed
+7r
+8s
+6gate
+9es
+6ing
+9s
+6land
+9ds
+6man
+9ship
+9ships
+7en
+6s
+7hare
+9res
+7taff
+9ffs
+6tail
+9ls
+6wise
+7right
+9ghts
+4k
+5ie
+7r
+7st
+5s
+5y
+4ter
+7ed
+7ing
+7s
+3ver
+6s
+6y
+3w
+4able
+4back
+8s
+5oy
+7s
+4ed
+5r
+6s
+4head
+8s
+4ing
+4land
+8s
+4man
+7ship
+9ips
+5en
+4s
+5hare
+9s
+5taff
+9s
+4ter
+7ed
+7ing
+7s
+3y
+4ed
+4ing
+4s
+2u
+3ck
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5s
+5y
+3e
+4s
+3ff
+5ed
+5ier
+7st
+6ng
+5s
+5y
+3g
+4board
+9s
+4ged
+6r
+7s
+5ing
+8s
+4hole
+8s
+4less
+4ola
+7s
+4s
+4uglies
+7y
+3m
+4age
+7d
+7s
+5ssier
+9rs
+5te
+4b
+5able
+6ginaceous
+9ous
+7o
+8s
+6te
+8s
+5ed
+6ous
+6r
+7ies
+7s
+7y
+5ic
+6ferous
+6ng
+8s
+6sm
+8s
+7olvency
+9vent
+6te
+8s
+5less
+5ness
+9es
+5osolvency
+9vent
+6us
+5s
+5um
+7s
+4cot
+7s
+4damas
+9es
+4e
+5d
+5less
+7t
+8s
+6ike
+5ria
+8s
+7es
+6y
+5s
+4ier
+6st
+5gerous
+5ng
+5ped
+8s
+5st
+7s
+4like
+4mer
+6st
+6t
+7ed
+7ing
+7s
+5ier
+7st
+5y
+4ose
+7ly
+6ities
+8y
+5us
+4p
+5ed
+6n
+7ed
+7ing
+7s
+6r
+7s
+6st
+5ie
+7r
+7st
+6ng
+6sh
+5ly
+5ness
+9es
+5s
+5y
+4s
+4ula
+7ceous
+7e
+7r
+8ian
+9ans
+7te
+6e
+7s
+6ose
+4y
+3nder
+7able
+8ge
+9es
+7ed
+8r
+9s
+7ing
+7ous
+7s
+4ge
+6d
+6r
+7s
+6s
+5ing
+8s
+4k
+5ed
+6r
+7s
+5ier
+7st
+6ng
+5s
+5y
+3perfect
+9ts
+3ral
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ically
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ly
+6s
+4iliteral
+6ocular
+5para
+9e
+9s
+6otent
+6resence
+9ences
+5serial
+9ate
+6ie
+8s
+4ry
+3s
+4age
+7s
+4ed
+5s
+4h
+5er
+6s
+7t
+5ier
+7st
+6ly
+6ness
+9ses
+5ly
+5ness
+9es
+5y
+4ing
+4sage
+8s
+5ed
+6s
+5ing
+3teal
+5i
+5us
+7es
+4ocracies
+9y
+8t
+9ic
+9ical
+9ically
+9s
+5latries
+9y
+6ogies
+9st
+9sts
+8y
+5n
+6ian
+7c
+7sm
+9s
+7um
+9s
+6omies
+9st
+9sts
+8y
+6s
+3vial
+7s
+6n
+5ometer
+9ers
+9ric
+9rical
+9ries
+9ry
+6se
+6us
+5us
+2y
+3er
+5s
+3ing
+6ly
+3ometric
+9cs
+3wood
+7s
+1neuma
+6s
+6thode
+9des
+7ic
+9al
+9ally
+9ities
+9ity
+9s
+7ological
+9ogies
+9ogist
+9ogists
+9ogy
+9yses
+9ysis
+9ytic
+8meter
+9eters
+9etries
+9etry
+8phore
+9hores
+5ectomies
+9my
+5obacilli
+9illus
+6coccal
+9ci
+9cus
+8nioses
+9iosis
+9iotic
+9iotics
+7ystis
+9tises
+6dynamics
+6gastric
+9trics
+7ram
+9ms
+9ph
+9phs
+6konioses
+9iosis
+6nectomies
+9tomy
+7ia
+9s
+8c
+9s
+8tes
+9ides
+9is
+9ises
+6thoraces
+9rax
+9raxes
+1o
+2a
+3ceous
+4h
+5able
+5ed
+6r
+7s
+6s
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5y
+3ka
+5s
+4e
+5s
+3s
+2blano
+7s
+3oy
+5s
+2chard
+7s
+5y
+6s
+4ette
+8s
+4oir
+7s
+3k
+4ard
+7s
+4ed
+5t
+6able
+6bike
+9es
+7ook
+9ks
+6ed
+7r
+8s
+6ful
+9s
+6ing
+6knife
+9ves
+6less
+6s
+7ful
+4ier
+6s
+7t
+5ly
+5ng
+4mankies
+8y
+7tie
+9es
+6rk
+8ed
+8ing
+8s
+4pit
+7s
+7ted
+4s
+4y
+3o
+4curante
+9teism
+9teisms
+9tes
+9tism
+9tisms
+9tist
+9tists
+4sen
+7s
+5in
+7s
+5on
+7s
+3uliform
+2d
+3agra
+7l
+7s
+6ic
+8al
+6ous
+4l
+5ic
+4rgus
+8es
+3cast
+7ed
+8r
+9s
+7ing
+9gs
+7s
+3ded
+4ie
+6r
+6s
+7t
+5ng
+4le
+6d
+6s
+5ing
+4y
+3esta
+7s
+4x
+5es
+3ge
+5s
+4ier
+6st
+5ly
+5ness
+9es
+4y
+3ia
+5l
+5tric
+8es
+8st
+9ts
+7y
+4te
+6s
+5ic
+4um
+6s
+3ley
+6s
+4ike
+3ocarp
+8s
+5onioses
+9sis
+4logies
+8st
+9ts
+7y
+4mere
+8s
+4phthalmous
+6ylin
+9ns
+8li
+9in
+9ins
+9um
+9ums
+4sphere
+9es
+3s
+4ol
+6ic
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+3zol
+6ic
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+2echore
+8s
+3m
+4atic
+4s
+3nologies
+8y
+3p
+4ol
+6s
+4s
+3sied
+6s
+4y
+5ing
+3t
+4aster
+9ies
+9ing
+9ings
+9s
+9y
+7ries
+8y
+4ess
+7es
+4ic
+6al
+8ly
+8ness
+9esses
+8s
+6ise
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+6s
+6ule
+9s
+5se
+7d
+7r
+8s
+7s
+6ing
+5ze
+7d
+7r
+8s
+7s
+6ing
+4less
+5ike
+4resse
+9s
+5ies
+5y
+4s
+5hip
+8s
+2ffle
+6s
+2gey
+5s
+3ge
+5s
+3ies
+3o
+4ed
+5r
+6s
+4ing
+4nia
+7s
+6p
+7s
+5ophoran
+9rans
+6tomies
+9y
+4s
+3rom
+6ed
+6ing
+7st
+9s
+6s
+3y
+2h
+3iri
+6s
+3utukawa
+9as
+2i
+3gnado
+8es
+6nce
+9s
+8ies
+8y
+7t
+8ly
+3kilitic
+6ocyte
+9tes
+7therm
+9ermal
+9ermic
+9ermies
+9ermism
+9erms
+9ermy
+3lu
+5s
+3nado
+7es
+4ciana
+9s
+4d
+5ed
+6r
+7s
+5ing
+8s
+5s
+4settia
+9as
+4t
+5able
+5e
+6d
+7ly
+7ness
+9sses
+6l
+7le
+9s
+7s
+6r
+7s
+6s
+5ier
+7st
+6lle
+8ism
+9sme
+9smes
+9sms
+9st
+9ste
+9stes
+9stic
+9sts
+6ng
+8s
+5less
+9ly
+9ness
+9nesses
+5man
+6en
+5s
+6man
+7en
+5tillist
+5y
+3s
+4e
+5d
+5r
+6s
+5s
+4ha
+4ing
+4on
+6able
+6ed
+7r
+8s
+6ing
+9s
+6ous
+9ly
+9ness
+9nesses
+6s
+6wood
+9ds
+4son
+7s
+3tin
+6s
+4rel
+7s
+5ine
+8s
+2kable
+4l
+5s
+3e
+4berries
+8y
+4d
+4ful
+7s
+4logan
+9s
+4r
+5ish
+8ly
+5oot
+8s
+5s
+5work
+9s
+4s
+4weed
+8s
+4y
+5s
+3ie
+5r
+5s
+6t
+4ly
+4ness
+8es
+5g
+3y
+2l
+3acca
+7s
+5re
+7s
+4r
+5imeter
+9ers
+9ric
+9ries
+9ry
+6sable
+8tion
+9ions
+7cope
+9pes
+9pic
+7e
+8d
+8r
+9s
+8s
+7ing
+6ties
+7y
+6zability
+9le
+8tion
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5ogram
+9ms
+9ph
+9phic
+9phies
+9phs
+9phy
+6n
+7s
+5s
+3der
+6ed
+6ing
+6s
+3e
+4ax
+6e
+7d
+7s
+6ing
+4cat
+7s
+4d
+4is
+4less
+4march
+9s
+5ic
+7al
+9ly
+7ise
+9ed
+9es
+9ing
+9t
+9ts
+8ze
+9ed
+9es
+9ing
+7s
+6se
+8d
+8s
+7ing
+7t
+8s
+6ze
+8d
+8s
+7ing
+5oniaceous
+8um
+9ms
+4nta
+7s
+4r
+5s
+4s
+5tar
+8s
+4ward
+4y
+5n
+6s
+5s
+3ianite
+9s
+4ce
+6d
+6man
+7en
+6r
+7s
+6s
+6woman
+9en
+5ies
+6ng
+8s
+5y
+6holder
+9ders
+4es
+4ng
+6s
+4o
+5myelitides
+9itis
+9itises
+5rcetic
+9ics
+5s
+5virus
+9ses
+4s
+5es
+5h
+6able
+6ed
+7r
+8s
+7s
+6ing
+9s
+6ment
+9ts
+4tburo
+9s
+5e
+6ly
+6ness
+9ses
+6r
+6sse
+9s
+7t
+5ic
+7al
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9ly
+8ster
+9ters
+7ian
+9ns
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7k
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+7ly
+7o
+8es
+8s
+7s
+6es
+6que
+9s
+5y
+3je
+5s
+3k
+4a
+5ed
+5ing
+5s
+4ed
+4ing
+4s
+3l
+4ack
+7s
+5n
+6s
+5rd
+7ed
+7ing
+7s
+5xe
+7d
+7s
+6ing
+4ed
+5e
+6s
+5n
+6ate
+9d
+9s
+8ing
+6ed
+6iferous
+7ng
+7ser
+9rs
+7zer
+9rs
+6oses
+8is
+9ses
+6s
+6t
+5r
+6s
+5x
+4ical
+6es
+6ie
+8s
+7tation
+9tions
+6y
+5es
+5nate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6g
+7s
+6ia
+7c
+7ferous
+7se
+9d
+9r
+9rs
+9s
+8ing
+7um
+7ze
+9d
+9r
+9rs
+9s
+8ing
+6oses
+8is
+9ses
+5st
+7s
+5wig
+8s
+6og
+8s
+4man
+5en
+4ock
+7s
+4s
+5ter
+8s
+4taker
+9s
+4ucite
+9s
+5sion
+9s
+5tant
+9s
+6e
+7d
+8ly
+8ness
+9esses
+7r
+8s
+7s
+6ing
+7on
+9s
+7ve
+4y
+5anna
+9ish
+9ism
+9isms
+9s
+8ish
+5wig
+8s
+6og
+8s
+3o
+4idal
+5st
+7s
+4naise
+9s
+5ie
+7s
+6se
+8d
+8s
+7ing
+7m
+8s
+6um
+8s
+6ze
+8d
+8s
+7ing
+5y
+4s
+3s
+3t
+4ed
+5rgeist
+9sts
+4feet
+5oot
+4ing
+4roon
+8eries
+9ry
+8s
+4s
+3verine
+9s
+3y
+4acid
+6rylamide
+9amides
+6t
+7inal
+9e
+5delphous
+6ic
+5lcohol
+9ols
+5mide
+9s
+7ne
+9s
+6ories
+8ous
+8y
+5ndries
+8ous
+8y
+6tha
+9s
+8i
+8us
+9ses
+5rch
+8ies
+8y
+5tomic
+5xial
+9s
+6on
+8ic
+8s
+4basic
+8te
+9es
+5rid
+8s
+5utadiene
+9ienes
+4carbonate
+9nates
+9xylate
+9xylic
+7pellary
+8ic
+9es
+8ous
+8y
+5entric
+9ism
+9isms
+5haete
+9es
+9ous
+7sia
+9um
+6ete
+9s
+6lorinated
+9oprene
+6otomies
+9mous
+9my
+6rest
+9ts
+7oic
+9sm
+9sms
+8matic
+9atism
+9atisms
+9e
+9ed
+9es
+9ic
+9ies
+9ing
+9ous
+9y
+5istronic
+5linic
+9cs
+6onal
+5onic
+6t
+7s
+7ton
+9ns
+7yledon
+9edons
+5rotic
+9sm
+9sms
+6ystal
+9alline
+9als
+5ulture
+9res
+5yclic
+9cs
+6stic
+6thaemia
+9emias
+8emia
+9mias
+9mic
+4dactyl
+9lies
+9lism
+9lisms
+9lous
+9ls
+9ly
+6emonism
+9nisms
+5emic
+7onism
+9isms
+5ipsia
+9as
+9c
+6sperse
+9rsity
+4electrolyte
+5mbryonate
+9onic
+9onies
+9ony
+5ne
+7s
+6ic
+5ster
+9s
+7rous
+5thene
+9es
+7ylene
+9enes
+4gala
+8ceous
+8s
+6m
+7ic
+8es
+8se
+9ed
+9es
+9ing
+9t
+9ts
+8ze
+9ed
+9es
+9ing
+7ous
+9sly
+7s
+7y
+5ene
+8s
+9es
+9is
+8tic
+9ically
+7ic
+8es
+8sm
+9ms
+9t
+9ts
+7ous
+7y
+5lot
+8ism
+9sms
+8s
+8t
+9al
+9ic
+9ism
+9isms
+9ous
+9s
+5on
+7aceous
+8l
+9ly
+8tum
+9ums
+7ies
+7s
+7um
+9s
+7y
+5raph
+9ed
+9er
+9ers
+9ic
+9ically
+9ies
+9ing
+9ist
+9ists
+9s
+9y
+5ynian
+8es
+8st
+9ts
+7ous
+7y
+4halite
+9es
+5edra
+9l
+8ic
+8on
+9ns
+9ses
+9sis
+5istor
+9rian
+9rians
+9ric
+9ries
+9rs
+9ry
+5ybrid
+9ds
+6dric
+8oxy
+4imide
+9s
+5soprene
+9enes
+4lemma
+9s
+5ysine
+9es
+4mastia
+9as
+9c
+9es
+9sm
+9sms
+8y
+6th
+8ic
+9es
+8s
+8y
+5er
+7ase
+9es
+7ic
+8de
+9es
+8es
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ous
+7s
+7y
+5orph
+9ic
+9ically
+9ism
+9isms
+9ous
+9ously
+9s
+5yositis
+9tises
+6xin
+9s
+4neuritides
+9tis
+9tises
+5ia
+7s
+5omial
+9lism
+9lisms
+9ls
+5uclear
+9ate
+9otide
+9otides
+5ya
+7s
+6i
+4ol
+6efin
+9ns
+6s
+5ma
+7s
+6ino
+9s
+5nym
+8ic
+9es
+8ous
+8s
+8y
+4p
+5aria
+8es
+8um
+7y
+5e
+6d
+7s
+6ptide
+9des
+9dic
+6s
+6talous
+5hagia
+9as
+9es
+8ous
+8y
+7rmacies
+9acy
+7se
+8ic
+6enol
+9lic
+9ls
+6loesboean
+8isbic
+6on
+8e
+9s
+8ic
+9cally
+9es
+9st
+9sts
+8ous
+9usly
+8s
+8y
+7sphoric
+6yletic
+8lous
+7odont
+5i
+6de
+8s
+7om
+9s
+6ll
+8s
+6ne
+6te
+8s
+5loid
+9al
+9ic
+9ies
+9s
+9y
+5nea
+8s
+7ic
+5od
+7ies
+7ous
+7s
+7y
+6id
+6re
+8s
+6ses
+7is
+6us
+5ropene
+9nes
+8ylene
+9lenes
+7todont
+9donts
+5s
+5tych
+9s
+5us
+7es
+4rhythm
+9mic
+9ms
+5ibosomal
+9ome
+9omes
+4s
+5accharide
+9arides
+9arose
+9aroses
+5emant
+9ts
+7e
+8s
+7ic
+8es
+7ous
+7y
+6palous
+5iloxane
+9anes
+5ome
+8s
+7ic
+9s
+8es
+7y
+6rbate
+9tes
+5tichous
+6ylar
+8e
+7rene
+9nes
+5ulfide
+9des
+7phide
+9ides
+5yllabic
+9bical
+9bicism
+9bism
+9bisms
+9ble
+9bles
+8ogism
+9gisms
+6naptic
+7deton
+9tons
+7theses
+9esis
+9esism
+9esisms
+9etic
+9etical
+9etism
+9etisms
+4technic
+9ical
+9ics
+6ne
+7ies
+7y
+5halamous
+6eism
+9ms
+9t
+9tic
+9tical
+9ts
+7ne
+9s
+5ocous
+6nal
+9ism
+9isms
+9ist
+9ists
+9ities
+9ity
+9ly
+5rophic
+5unnel
+9ls
+5ype
+8s
+7ic
+9al
+4unsaturated
+5rethan
+9ane
+9anes
+9ans
+6ia
+8s
+7c
+4valence
+9ces
+9cies
+9cy
+9t
+5inyl
+9idene
+9idenes
+9s
+4water
+9s
+4zoa
+7n
+8s
+7ria
+9al
+9es
+9um
+8y
+6ic
+6nal
+6oid
+7n
+2m
+3ace
+6ous
+6s
+4de
+6d
+6s
+5ing
+4nder
+8s
+4to
+6es
+5um
+7s
+3be
+5s
+3e
+4granate
+9tes
+4lo
+6s
+4roy
+7s
+4s
+3fret
+7s
+3iculture
+9res
+4ferous
+3mee
+5l
+6e
+7d
+6ing
+6led
+7ing
+6s
+5tty
+4ie
+6s
+4y
+3o
+4erium
+9s
+4logical
+9ally
+8es
+8st
+9ts
+7y
+4s
+5exual
+9ls
+3p
+4adour
+9ed
+9s
+5no
+7s
+4elmoose
+9ses
+8us
+9se
+9ses
+6o
+7s
+5y
+6ed
+6ing
+6s
+4holygous
+8x
+9es
+4ier
+5lid
+8s
+5on
+7s
+4om
+6s
+5n
+6s
+5on
+7s
+5sities
+8y
+5us
+7ly
+7ness
+9sses
+4s
+3roy
+6s
+3s
+3water
+8s
+2nce
+5au
+7s
+7x
+5d
+5s
+5y
+4ho
+6ed
+6s
+4ier
+6st
+5ng
+4y
+3d
+4age
+7s
+4ed
+5r
+6abilities
+9lity
+8le
+9es
+9y
+7l
+7nce
+9es
+9ies
+9y
+7te
+9d
+9s
+8ing
+9on
+9ons
+6ed
+7r
+8s
+6ing
+9ly
+6ment
+9ts
+6osa
+9s
+8ities
+9ty
+7us
+9ly
+9ness
+9nesses
+6s
+4ing
+4ok
+6kie
+9s
+6s
+4s
+4weed
+8s
+3e
+4nt
+4rologies
+9y
+4s
+4y
+5s
+3g
+4a
+5s
+4ed
+5e
+6s
+4id
+6s
+5er
+6st
+5ng
+4o
+5es
+5s
+4s
+4y
+3iard
+7ed
+7ing
+7s
+4ed
+5s
+3k
+4ed
+4ing
+4s
+3s
+3t
+4age
+7s
+5l
+4es
+4ianac
+9s
+8k
+9s
+5c
+6ello
+9os
+5e
+6s
+5fex
+6f
+7s
+6ic
+8al
+9lities
+9lity
+9lly
+9ls
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+8e
+9s
+7ed
+8s
+6y
+7ing
+5l
+6e
+7s
+6s
+5ne
+4levis
+9es
+4on
+6eer
+9s
+6ier
+9s
+6nier
+9rs
+6s
+5on
+7ed
+8r
+9s
+7ing
+7s
+4s
+4y
+3y
+4ing
+4skin
+8s
+4tail
+8ed
+8s
+3zu
+5s
+2och
+5ed
+6s
+5ing
+3dle
+6s
+4s
+3gye
+6s
+3h
+4ed
+4ing
+4s
+3ing
+3ja
+5h
+6s
+5s
+3k
+4a
+5s
+4ing
+5t
+4s
+3l
+4ed
+5r
+6s
+4hall
+8s
+4ing
+4room
+8s
+4s
+5ide
+8s
+3nac
+6s
+4ce
+6d
+6s
+5ing
+4s
+4tangs
+3ping
+4s
+3r
+4er
+5st
+4house
+9s
+4i
+5s
+6h
+4lier
+7st
+5y
+4mouth
+9ed
+9ing
+9s
+4ness
+8es
+4t
+5ith
+8s
+5s
+4will
+8s
+3s
+3t
+4ed
+5r
+6s
+4ing
+4le
+6d
+6s
+5ing
+4s
+3ve
+5ries
+6y
+5s
+4ier
+6st
+4y
+2p
+3adum
+7s
+3corn
+7s
+3e
+4dom
+7s
+4hood
+8s
+4less
+5ike
+6ng
+8s
+4ra
+6s
+5ies
+6n
+7s
+5y
+4s
+5eye
+5hip
+8s
+4tte
+7s
+4yed
+3gun
+6s
+3injay
+8s
+4sh
+6ly
+3joy
+6ed
+6ing
+6s
+3lar
+6s
+4in
+6ette
+9es
+6s
+5teal
+7i
+7us
+6ic
+3mobilities
+9ty
+3over
+7s
+3pa
+5dom
+8s
+6um
+8s
+5s
+4ed
+5r
+6ing
+9s
+6s
+5t
+6s
+4ied
+6r
+6s
+7t
+5ng
+5sh
+5t
+6s
+4le
+6d
+6s
+5ier
+7st
+6ng
+5y
+4y
+5cock
+9s
+5head
+9s
+3rin
+3s
+4icle
+8s
+5e
+6s
+4ock
+7s
+4ter
+7s
+5rel
+8s
+4y
+3ulace
+8s
+6r
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7ly
+7s
+6te
+8d
+8s
+7ing
+8on
+9nal
+9ns
+5ism
+8s
+7t
+8ic
+8s
+5ous
+8ly
+8ness
+9esses
+2rae
+5s
+4l
+4ngi
+3beagle
+9s
+3celain
+9eous
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9like
+9ous
+9s
+7neous
+6laneous
+9ise
+9ised
+9ises
+9ising
+9ite
+9ites
+9ize
+9ized
+9izes
+9izing
+9ous
+4h
+5es
+6tta
+9s
+4ine
+6i
+7s
+6o
+4upine
+9s
+8ish
+8y
+3e
+4d
+4r
+5s
+4s
+3ge
+5d
+5s
+4ie
+6s
+5ng
+4y
+3ier
+5st
+4fer
+7al
+8n
+9s
+7ous
+7s
+4na
+6s
+5ess
+8es
+5g
+4sm
+6atic
+9cal
+6s
+5tic
+8al
+3k
+4ed
+5r
+6s
+4ier
+6s
+7t
+5ness
+9es
+6g
+4ling
+8s
+4pie
+7s
+4s
+4wood
+8s
+4y
+3lock
+7ed
+7ing
+7s
+3ogamic
+8es
+7y
+4meric
+9s
+4scope
+9s
+8ic
+9es
+8y
+5e
+6s
+5is
+6ties
+7y
+4us
+6ly
+6ness
+9ses
+3pentine
+9es
+5ss
+7e
+8s
+4hyria
+9s
+8c
+8es
+8n
+9s
+8o
+9s
+8te
+9es
+9ic
+7ogenite
+9enites
+8id
+9ds
+8psin
+9sins
+8us
+7y
+4oise
+8d
+8s
+7ing
+5rate
+3raceous
+4ect
+7ed
+7ing
+8on
+9ns
+7s
+5nger
+9s
+4idge
+8s
+7y
+5ginous
+6o
+7s
+5nger
+9s
+3t
+4a
+5bella
+9as
+9o
+9os
+6ilities
+9ty
+6le
+8s
+7y
+5ge
+7d
+7s
+6ing
+6ue
+8s
+5l
+6ed
+6s
+5menti
+9o
+5nce
+8s
+5pack
+9s
+7k
+8s
+5s
+6es
+5te
+6ile
+7ve
+9s
+4cullis
+9sed
+9ses
+9sing
+4ed
+5nd
+7ed
+7ing
+7s
+6t
+7ous
+9sly
+9sness
+7s
+5ous
+8es
+5r
+6age
+9s
+6ed
+7ss
+9es
+6house
+9ses
+6ing
+6ly
+6s
+5ss
+7e
+8s
+4fire
+8s
+5olio
+9s
+4hole
+8s
+6rs
+8es
+6s
+7es
+6use
+9s
+4ico
+7ed
+8s
+7s
+5er
+7e
+8d
+8s
+6st
+5gue
+8s
+5ng
+5on
+7ed
+8r
+9s
+7ing
+8st
+9ts
+7less
+7s
+4land
+8s
+6st
+8s
+5ess
+5ier
+7st
+6ness
+9ses
+5y
+4man
+7teau
+9aus
+9aux
+8le
+9es
+8ua
+9as
+5en
+4obello
+9os
+5ise
+8s
+5lan
+8i
+8o
+9s
+8s
+5us
+7es
+4rait
+8ed
+8ing
+9st
+9sts
+8s
+8ure
+9res
+6y
+7able
+8l
+9s
+7ed
+8r
+9s
+7ing
+7s
+5eeve
+9s
+6ss
+8es
+4s
+5ide
+4ulaca
+9ceous
+9s
+7n
+8s
+4y
+3wiggle
+9s
+3y
+2s
+3able
+4da
+6s
+4une
+7s
+3e
+4able
+4d
+4r
+5ish
+5s
+4s
+4ur
+6s
+5se
+7s
+4y
+3h
+4ed
+5r
+5s
+6t
+4ing
+4ly
+4ness
+8es
+4o
+5s
+4teen
+8s
+3ier
+5s
+6t
+4grade
+4ng
+6ly
+6s
+4t
+5ed
+5if
+7s
+6ng
+6on
+8al
+9lly
+8ed
+8ing
+9ngs
+8s
+6ve
+8ly
+8ness
+9esses
+8r
+8s
+9t
+7ism
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+5on
+7s
+5ron
+8ium
+9ums
+8s
+5s
+3net
+6s
+3ole
+6s
+5ogic
+9al
+8es
+7y
+3s
+4e
+5d
+5r
+6s
+5s
+6s
+7able
+7ed
+9ly
+9ness
+9nesses
+8s
+7ing
+8on
+9nal
+9nary
+9nate
+9nates
+9ned
+9nless
+9ns
+8ve
+9ely
+9eness
+9es
+7or
+9s
+9ship
+9ships
+9y
+5t
+6ed
+6ing
+6s
+4ibilism
+9sms
+9st
+9sts
+9ties
+9ty
+6le
+8r
+8s
+9t
+7y
+5e
+6s
+5ng
+4um
+6ed
+6ing
+6s
+3t
+4abortion
+5ccident
+5dolescent
+9scents
+5ge
+7s
+5l
+6ly
+6s
+5mputation
+5nal
+5pocalyptic
+5rrest
+5tomic
+6tack
+5xial
+4bag
+7s
+6se
+5ellum
+5iblical
+5ourgeois
+6x
+7es
+6y
+7s
+5urn
+6s
+7es
+7ses
+4capitalist
+6rd
+8ed
+8ing
+8like
+8s
+6va
+8e
+8l
+8s
+5lassic
+9ical
+5ode
+8d
+8s
+7ing
+6ital
+6llege
+9ges
+9giate
+7onial
+6nception
+9rt
+7quest
+7sonantal
+7vention
+6pulatory
+6ronary
+6up
+5ranial
+9ally
+7sh
+6ises
+8is
+4date
+8d
+8s
+7ing
+5eadline
+6bate
+7utante
+9antes
+6livery
+6pression
+6valuation
+5iluvial
+9ian
+9ians
+6ve
+8stiture
+7orce
+5oc
+7s
+7toral
+9rate
+5rug
+4ed
+6iting
+9ngs
+5en
+7s
+5lection
+5mbryonal
+9onic
+6ergence
+9ency
+5pileptic
+5r
+6ed
+6ing
+7or
+9ities
+9ity
+9ly
+9s
+7sation
+9tions
+7ties
+8y
+7zation
+9tions
+6n
+7s
+6olateral
+6s
+6uptive
+5xercise
+6ilian
+9c
+6perience
+7osure
+4face
+8s
+6ult
+5eminism
+9isms
+9ist
+9ists
+5ire
+6x
+7al
+7ed
+8s
+7ing
+5light
+5orm
+8ed
+8ing
+8s
+5racture
+9ures
+6eeze
+4game
+6nglionic
+5lacial
+5rad
+8s
+8uate
+9ates
+9ation
+4harvest
+6ste
+9s
+5eat
+8s
+6morrhagic
+5older
+9rs
+7e
+8s
+7iday
+7ocaust
+6rse
+9s
+6spital
+6use
+9s
+5umous
+9sly
+9sness
+5ypnotic
+4ical
+6he
+8s
+6ous
+5e
+6s
+5l
+6ed
+6ing
+7on
+9s
+6late
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7ed
+8r
+9s
+7ing
+8on
+9ns
+6s
+5mpact
+7erial
+5n
+6augural
+6dustrial
+6fection
+6g
+7s
+6jection
+6oculation
+6s
+5que
+8s
+5rradiation
+5schemic
+6olation
+4landing
+6psarian
+6unch
+5iberation
+6minary
+9ia
+9iary
+9ies
+9ious
+9ium
+9ous
+9y
+6terate
+5ude
+8s
+4man
+6rital
+7k
+8ed
+8ing
+8s
+6stectomy
+9r
+9rs
+9rship
+9rships
+6ting
+5edieval
+6n
+7opausal
+7strual
+6ridian
+5idnight
+6llenarian
+9nnial
+6stress
+9esses
+5odern
+9nism
+9nisms
+9nist
+9nists
+6rtem
+9ms
+4nasal
+6tal
+9ly
+7i
+5eonatal
+5uptial
+4ocular
+5p
+6erative
+9tively
+6s
+5ral
+6bital
+4paid
+6rtum
+5erson
+9ns
+5ollination
+6nable
+7e
+8d
+8ment
+9ents
+8nce
+9ces
+8r
+9s
+8s
+7ing
+6se
+8d
+8s
+7ing
+8tion
+9ional
+9ions
+9ive
+9ively
+9ives
+5randial
+6imary
+7son
+6oduction
+9ctions
+5uberty
+8scent
+9cents
+6nk
+4race
+5ecession
+6tirement
+5ider
+9s
+6ot
+5omantic
+4s
+5cenium
+9ums
+6ript
+9ts
+5eason
+9ns
+6condary
+5how
+5timulation
+9latory
+9lus
+6rike
+5urgical
+5ynaptic
+7c
+8ed
+8ing
+8s
+4tax
+5een
+8s
+6nsion
+9oned
+9oning
+9ons
+6st
+8s
+5ransfusion
+7umatic
+6eatment
+6ial
+4ulancies
+9y
+8t
+9s
+9ship
+9ships
+7ta
+8e
+9d
+9s
+8ing
+9on
+9onal
+9onally
+9ons
+8or
+9rs
+9ry
+8um
+5ral
+6e
+7d
+7r
+8s
+7s
+6ing
+9s
+7se
+9d
+9s
+8ing
+8t
+9s
+7ze
+9d
+9s
+8ing
+4vaccinal
+9nation
+6gotomy
+6sectomy
+5iral
+5ocalic
+4war
+5eaning
+5oman
+7en
+6rkshop
+3y
+2t
+3abilities
+9y
+5le
+7ness
+9sses
+7s
+4e
+5s
+4ge
+6r
+7s
+6s
+4le
+6s
+4mic
+5ogeton
+9ons
+6logical
+9ies
+9ist
+9ists
+9y
+4sh
+6ed
+7s
+6ing
+5s
+6a
+7s
+6es
+6ic
+7um
+9s
+4tion
+8s
+5o
+6bug
+9s
+6es
+6ry
+3bellied
+9s
+7y
+4oil
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5und
+5y
+6s
+3ch
+5e
+6d
+6r
+7s
+6s
+5ing
+3e
+4d
+4en
+6s
+4nce
+7s
+6ies
+6y
+5t
+6ate
+9s
+6ial
+9ities
+9ity
+9ly
+9s
+8ries
+9y
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7lla
+9as
+7ometer
+9eters
+9etric
+9etries
+9etry
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6ly
+6ness
+9ses
+6s
+4s
+3ful
+6s
+3gun
+6s
+3head
+7s
+5caries
+8y
+5en
+7s
+5r
+6b
+7s
+6ed
+6ing
+6s
+6y
+4older
+9s
+6e
+7d
+7r
+8s
+7s
+6ing
+9s
+5ok
+7s
+5s
+5use
+8s
+4unter
+9s
+7ing
+9gs
+3icaries
+7y
+5he
+7s
+6omania
+9nias
+4n
+5g
+5s
+4on
+6s
+3jie
+6s
+3lach
+7e
+8s
+5tch
+8ed
+9s
+8ing
+4ike
+5ne
+7s
+4uck
+7s
+3man
+4en
+3ometer
+9s
+4o
+5s
+4roo
+7s
+3pie
+6s
+4ourri
+9s
+3s
+4hard
+8s
+7e
+8s
+5erd
+8s
+5op
+7s
+6t
+7s
+7ting
+4ie
+6s
+4ticker
+9rs
+5one
+8s
+4y
+3t
+4able
+5ge
+7s
+4ed
+5en
+7s
+5r
+6ed
+7r
+8s
+6ies
+7ng
+9ly
+9s
+6s
+6y
+4ier
+6s
+7t
+5ness
+9es
+6g
+7ar
+9s
+7er
+9s
+4le
+6s
+4o
+5s
+4s
+4y
+5mouth
+9hs
+3waller
+9s
+3zer
+6s
+2uch
+5ed
+6s
+5ful
+8s
+5ier
+7st
+6ng
+5y
+3der
+6s
+4re
+6s
+3f
+4ed
+4f
+5e
+6d
+6s
+5ier
+7st
+6ng
+5s
+5y
+4ing
+4s
+4tah
+7s
+5er
+7s
+3k
+4e
+5s
+4ing
+5t
+4s
+3laine
+8s
+5rd
+7e
+8s
+7s
+4der
+7s
+5re
+7s
+6on
+8s
+4e
+5s
+4p
+5e
+6s
+5s
+4t
+5er
+7er
+9s
+7s
+5ice
+8d
+8s
+7ing
+5ries
+6oone
+9es
+6y
+7man
+8en
+5s
+3nce
+6d
+6r
+7s
+6s
+6t
+7s
+5hing
+5ing
+4d
+5age
+8s
+6l
+7s
+5cake
+9s
+5ed
+6r
+7s
+5ing
+8s
+5s
+3pe
+5d
+5s
+4ing
+4t
+3r
+4able
+4boire
+9s
+4ed
+5r
+6s
+4ie
+6s
+5ng
+7ly
+7s
+4parler
+9rs
+5oint
+9s
+4s
+5ew
+7ed
+7ing
+7s
+5ue
+7d
+7s
+6ing
+7t
+8s
+4trahed
+7ict
+9ts
+7y
+8d
+8ed
+8ing
+8s
+3sada
+7s
+4owdie
+9s
+4se
+6s
+6tte
+9d
+9s
+8ing
+5ie
+7s
+6n
+7s
+3t
+4ed
+5r
+6s
+4ful
+4her
+7ed
+7ing
+7s
+4ier
+6st
+5ne
+7s
+6g
+7ly
+7s
+4s
+4y
+2verties
+6y
+2w
+3an
+5s
+3der
+6ed
+7r
+8s
+6ier
+8st
+7ng
+6less
+7ike
+6s
+6y
+3ellise
+9d
+9s
+8ing
+7te
+9s
+7ze
+9d
+9s
+8ing
+4r
+5boat
+9ing
+9ings
+9s
+6roker
+9ers
+5ed
+5ful
+8ly
+8ness
+9esses
+5house
+9es
+5ing
+5less
+9ly
+9ness
+9nesses
+6ifter
+9ers
+9ing
+9ings
+5play
+9s
+5s
+5train
+9ns
+3fagged
+3hiri
+7s
+3in
+5s
+3n
+4d
+5ed
+5ing
+5s
+4ey
+6s
+4ie
+6s
+4s
+4y
+3re
+5d
+5s
+4ing
+3s
+4owdies
+7y
+3ter
+6ed
+6ing
+6s
+3waw
+4ow
+6ed
+6ing
+6s
+2x
+3ed
+4s
+3ier
+5st
+4ng
+3virus
+8es
+3y
+2ynant
+4t
+5ed
+5ing
+5s
+3ou
+5s
+3se
+5d
+5s
+4ing
+4on
+6ed
+6ing
+6s
+2z
+3ole
+6s
+3z
+4ies
+4olan
+8a
+9s
+8ic
+8s
+4uolana
+9as
+4y
+1raam
+5s
+3bble
+7s
+3charak
+9s
+4tic
+7ability
+9le
+9leness
+9ly
+8l
+9ism
+9isms
+9ist
+9ists
+9ities
+9ity
+9ly
+9ness
+9nesses
+9s
+7e
+8d
+8r
+9s
+8s
+7ian
+9ns
+8ng
+7k
+8s
+7s
+7um
+9s
+6que
+9s
+6sant
+9ts
+7e
+8d
+8r
+9s
+8s
+7ing
+6tioner
+9ners
+6ve
+5olol
+9s
+3d
+4s
+3eamble
+9s
+4cipe
+8s
+5oces
+7ial
+6rdial
+4dial
+8ities
+9ty
+8s
+4fect
+8orial
+8s
+4lect
+8ed
+8ing
+8s
+5udia
+8um
+4munire
+9es
+4nomen
+9s
+7ina
+9al
+9ally
+4postor
+9rs
+4ses
+5idia
+8um
+9ms
+4tor
+7ial
+9n
+9ns
+8um
+9ms
+7s
+8hip
+9ips
+3gmatic
+9al
+9ality
+9ally
+9alness
+9ism
+9isms
+9ist
+9ists
+9s
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+3hu
+5s
+3irie
+7d
+7s
+4se
+6ach
+9s
+6d
+6ful
+6less
+6r
+7s
+6s
+6worthily
+9thy
+5ing
+8ly
+8s
+3jna
+6s
+3line
+7s
+4ltriller
+9lers
+3m
+4s
+3na
+5s
+5yama
+9s
+4ce
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+5k
+6e
+7d
+7s
+6ing
+6s
+4dial
+8ly
+4g
+5ed
+5ing
+5s
+4k
+5ed
+5ful
+5ier
+7st
+6ng
+8ly
+8s
+6sh
+8ly
+8ness
+9esses
+5le
+7d
+7s
+6ing
+5s
+6ome
+6ter
+9s
+5y
+3o
+4s
+3se
+5odymium
+9iums
+5s
+3t
+4e
+5d
+5r
+6s
+5s
+4fall
+8en
+8ing
+8s
+5ell
+4ie
+6s
+5ncole
+9es
+6g
+7ly
+7s
+5que
+8s
+4s
+4t
+5ed
+5ing
+5le
+7box
+9xes
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9ly
+5s
+4y
+3u
+4nce
+7d
+7s
+6ing
+4s
+3vities
+6y
+3wle
+6s
+5in
+7s
+4n
+5ed
+6r
+7s
+5ing
+5s
+3xeological
+9ies
+9y
+5s
+4inoscope
+9opes
+5s
+6es
+3y
+4ed
+5r
+6ful
+9ly
+9ness
+9nesses
+6less
+9sly
+9sness
+6s
+4ing
+7ly
+7s
+4s
+2e
+3absorb
+9ed
+9ing
+9s
+4ccuse
+9d
+9s
+8ing
+5e
+6d
+6s
+5h
+6able
+6ed
+7r
+8s
+9hip
+9hips
+7s
+6ier
+8st
+7fied
+9es
+8y
+9ing
+9ings
+7ly
+7ness
+9sses
+8g
+9ly
+9s
+6ment
+9ts
+6y
+5ing
+5quaint
+9ntance
+9nted
+9nting
+9nts
+7isition
+5t
+6ed
+6ing
+6s
+4damic
+8te
+9es
+6pt
+8ation
+9tions
+8ed
+8ing
+9ve
+8s
+5just
+9ed
+9ing
+9s
+5mission
+9ions
+7t
+8s
+8ted
+9ing
+6onish
+9shed
+9shes
+9shing
+9tion
+9tions
+5olescence
+9cences
+9cent
+9cents
+6pt
+8ed
+8ing
+8s
+5ult
+8s
+4ged
+5ricultural
+4llot
+8s
+8ted
+9ing
+5ter
+8ed
+8ing
+8s
+4mble
+8d
+8s
+7ing
+6ulary
+9te
+9ted
+9tes
+9ting
+9tory
+5p
+6lifier
+9iers
+6s
+4nal
+5esthetic
+9etics
+5nounce
+9ced
+9ces
+9cing
+4pplied
+9s
+7y
+8ing
+6oint
+9ted
+9ting
+9ts
+6rove
+9ed
+9es
+9ing
+4rm
+6ed
+6ing
+6s
+5range
+9ed
+9ement
+9ements
+9es
+9ing
+4se
+6d
+6s
+5ing
+5se
+7d
+7mbled
+7s
+6ign
+9ed
+9ing
+9s
+7ng
+6urance
+9nces
+8e
+9d
+9s
+8ing
+4tomic
+5tune
+9d
+9s
+8ing
+4udience
+9ces
+7t
+8s
+4ver
+7red
+8ing
+7s
+4xial
+8ly
+3bade
+5ke
+7d
+7s
+6ing
+5sal
+5ttle
+4end
+7al
+8ries
+9y
+7s
+4iblical
+5d
+6den
+7ing
+6s
+5ll
+7ed
+7ing
+7s
+5nd
+7ing
+7s
+5ologic
+9ical
+6tic
+9s
+5rth
+8s
+4less
+8ed
+9s
+8ing
+4oard
+8ed
+8ing
+8s
+5il
+7ed
+7ing
+7s
+5ok
+7ed
+7ing
+7s
+6m
+5rn
+5ught
+6nd
+4reakfast
+4udget
+9s
+5ild
+8ing
+8s
+7t
+5ttal
+9s
+5y
+6ing
+6s
+3calculi
+9us
+9uses
+5ncel
+9ed
+9ing
+9lation
+9led
+9ling
+9s
+8r
+9ous
+9s
+5pitalist
+9lists
+5rious
+9sly
+9sness
+5st
+7ing
+7s
+5tive
+6ory
+5udal
+6tion
+9nal
+9nary
+9ned
+9ning
+9ns
+9us
+5va
+7e
+7l
+4ede
+7d
+7nce
+9es
+9ies
+9y
+8t
+9ed
+9ial
+9ially
+9ly
+9s
+7s
+6ing
+5ese
+5nsor
+9ed
+9ing
+9s
+6t
+7ed
+7ing
+7or
+9ial
+9s
+9ship
+9ships
+7ress
+9sses
+8ices
+9x
+9xes
+7s
+5pit
+8s
+6t
+7ial
+8ve
+9ely
+7or
+9al
+9ate
+9ates
+9ial
+9ials
+9ies
+9s
+9ship
+9ships
+9y
+7ress
+9sses
+7s
+5rtified
+9ies
+9y
+9ying
+5s
+6s
+7ed
+8s
+7ing
+8on
+9nal
+9nally
+9ns
+4harge
+9d
+9s
+8ing
+5eck
+8ed
+8ing
+8s
+5ill
+8ed
+8ing
+8s
+5oose
+9s
+8ing
+6se
+8n
+5ristian
+4ieuse
+9s
+7x
+5nct
+8s
+5osities
+9y
+6us
+8es
+8ly
+8ness
+9esses
+5pe
+7s
+6ice
+9d
+9s
+7tability
+9ble
+9nce
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9ntness
+9nts
+9te
+9ted
+9tely
+9teness
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+8in
+9nogen
+9nogens
+9ns
+8ous
+9usly
+9usness
+5s
+6e
+7d
+7ly
+7ness
+9sses
+7r
+7s
+8t
+6ian
+9ism
+9isms
+9ist
+9ists
+9s
+7ng
+7on
+9ism
+9isms
+9ist
+9ists
+9s
+7ve
+5ted
+4lassical
+5ean
+8ed
+8ing
+8s
+7r
+8ance
+9nces
+8ed
+8ing
+8s
+5inical
+9ally
+5udable
+7e
+8d
+8s
+7ing
+6sion
+9ns
+8ve
+9ely
+4ocial
+9s
+7ous
+9sly
+9sness
+7ties
+8y
+5de
+7d
+7s
+6ing
+5gnisant
+9e
+9ed
+9es
+9ing
+8tion
+9ions
+9ive
+8zant
+9e
+9ed
+9es
+9ing
+7osce
+9ced
+9ces
+9cing
+5ital
+5llege
+9es
+9iate
+6onial
+5mbustion
+9tions
+6mitment
+9ments
+6petitive
+7ose
+9ed
+9es
+9ing
+7ute
+9ed
+9er
+9ers
+9es
+9ing
+5nceit
+9ts
+9ve
+9ved
+9ves
+9ving
+8ption
+9tions
+8rt
+9ted
+9tedly
+9ting
+9ts
+7iliar
+6demn
+9ned
+9ning
+9ns
+7ition
+9ioned
+9ioning
+9ions
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6quest
+6scious
+9ouses
+9ously
+7onantal
+7truct
+9ucted
+9ucting
+9uction
+9ucts
+7ume
+9ed
+9es
+9ing
+6tact
+7ract
+9cted
+9cting
+9cts
+6vention
+9tions
+7iction
+9tions
+5ok
+7ed
+8r
+9s
+7ing
+7s
+6l
+7ed
+7ing
+7s
+5pulatory
+5rdial
+5up
+4rash
+5ease
+9d
+9s
+8ing
+5isis
+6tical
+4ure
+7d
+7s
+6ing
+6rer
+9s
+6se
+8s
+7ive
+7or
+9s
+9y
+5t
+6s
+6ting
+3daceous
+9sness
+6ious
+9sness
+7ties
+8y
+5te
+7d
+7s
+6ing
+7on
+9s
+7sm
+9s
+7ve
+6or
+8ily
+9ness
+9nesses
+8s
+8y
+5wn
+7s
+4eath
+8s
+5bate
+5cease
+9ed
+9es
+9ing
+7ssor
+9ors
+5duct
+9ed
+9ing
+9s
+5fine
+9d
+9s
+8ing
+9tion
+9tions
+5liveries
+9ry
+6la
+8s
+7e
+5ntate
+5parture
+9ures
+6osit
+9ted
+9ting
+9ts
+5sign
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9atory
+9ed
+9ing
+9s
+6tinable
+9arian
+9arians
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+9ator
+9ators
+9e
+9ed
+9es
+9ies
+9ing
+9y
+5terminable
+9inate
+9ine
+9ined
+9iner
+9iners
+9ines
+9ining
+9inism
+9inisms
+5valuation
+9ations
+6elop
+9ped
+9ping
+9pment
+9pments
+9ps
+6ote
+4iabetes
+9eses
+9ic
+9ics
+6l
+7ities
+9y
+7s
+5cabilities
+9lity
+8le
+9eness
+9es
+7ment
+9ntal
+9nts
+7nt
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9vely
+8or
+9rs
+9ry
+6t
+7ability
+9le
+9leness
+9ly
+7ed
+8r
+9s
+7ing
+8on
+9ns
+8ve
+9ely
+7or
+9s
+7s
+5ed
+6s
+5gest
+9ed
+9ing
+9ion
+9ions
+9s
+5kant
+9s
+5lect
+9ed
+9ion
+9ions
+5nner
+9s
+5scharge
+9rged
+9rges
+9rging
+7overies
+9ery
+6posal
+9als
+9e
+9ed
+9es
+9ing
+9ition
+9itions
+5ve
+4nisolone
+9ones
+8ne
+9es
+4octoral
+5minance
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9te
+9ted
+9tely
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+5om
+7ed
+7ing
+7s
+4raft
+5ied
+7s
+6ll
+8ed
+8ing
+8s
+5y
+6ing
+4usk
+7s
+4y
+5ing
+5nastic
+3e
+4clampsia
+9sias
+9tic
+4d
+5it
+7ed
+7ing
+7s
+4ing
+4lect
+8ed
+8ing
+9on
+9ons
+8ric
+8s
+4mbargo
+5ergence
+9nt
+5ie
+7s
+6nence
+9ces
+9t
+9tly
+5ployment
+9ments
+6t
+7ed
+7ing
+8on
+9ns
+8ve
+9ely
+7or
+9s
+9y
+7s
+4n
+5act
+8ed
+8ing
+8s
+5ed
+6r
+7s
+5ing
+5rollment
+9ments
+5s
+4rect
+8ed
+8ing
+8s
+4s
+5tablish
+9ished
+9ishes
+9ishing
+4thical
+4ve
+6d
+6s
+5ing
+4xcite
+9d
+9s
+8ing
+5empt
+9ed
+9ing
+9s
+5ilic
+6st
+8ed
+9nce
+9nces
+9nt
+8ing
+8s
+5periment
+9ments
+6ose
+9d
+9s
+8ing
+3fab
+6bed
+7ing
+6ricate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ator
+9ators
+6s
+5ce
+7d
+7r
+8s
+7s
+6ial
+7ng
+5de
+7d
+7s
+6ing
+5rd
+5scist
+9ts
+5torial
+9ally
+9ly
+8y
+4ect
+7orial
+7s
+8hip
+9ips
+7ural
+9e
+9es
+5r
+6abilities
+9lity
+8le
+9eness
+9y
+6ence
+9es
+8tial
+9ialism
+9ialist
+9iality
+9ially
+6ment
+9ts
+6rable
+7ed
+8r
+9s
+7ing
+6s
+5udal
+4ight
+6urate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tively
+8e
+9d
+9ment
+9ments
+9s
+8ing
+5le
+7d
+7s
+6ing
+6led
+5nance
+9ed
+9es
+9ing
+5re
+7d
+7s
+6ing
+5x
+6al
+8ly
+6ed
+7s
+6ing
+7on
+9s
+6ture
+9es
+4lame
+5ight
+9ed
+9ing
+9s
+5oration
+9ions
+4ocus
+8ed
+9s
+8ing
+8sed
+9es
+9ing
+5liation
+9ions
+5rm
+7at
+9ion
+9ionism
+9ionist
+9ions
+9ive
+9s
+9ted
+9ting
+7ed
+7ing
+7s
+7ulate
+9ated
+9ates
+9ating
+4rank
+8ed
+8ing
+8s
+5eeze
+9s
+8ing
+6shman
+9en
+5ontal
+9ls
+6ze
+8n
+4ulgent
+5nd
+7ed
+7ing
+7s
+3game
+7s
+5nglionic
+4enital
+4gers
+5ier
+7st
+5y
+4lacial
+4nabilities
+9ity
+7le
+6nce
+9s
+8ies
+8y
+7t
+8ly
+5enolone
+9ones
+4rowth
+9s
+4uide
+8d
+8s
+7ing
+5station
+9ions
+3halluces
+8x
+5ndle
+9d
+9s
+8ing
+5rden
+9ed
+9ing
+9s
+6vest
+9ts
+4eadache
+6t
+7ed
+8r
+9s
+7ing
+7s
+5minence
+9nces
+5nd
+7ed
+7ing
+7s
+6sible
+8le
+9ities
+9ity
+8on
+9ns
+8ve
+7or
+9ial
+9s
+9y
+4iring
+5storian
+9ians
+9ic
+9ical
+9ically
+9ies
+9y
+4nite
+8s
+4oliday
+5minid
+9ds
+4uman
+8s
+3if
+5e
+6s
+5s
+4gnition
+9ons
+4mplantation
+6ose
+9d
+9s
+8ing
+4naugural
+5duction
+9ions
+7strial
+5form
+9ed
+9ing
+9s
+5sert
+9ed
+9ing
+9s
+5terview
+9iewed
+9iewing
+9iews
+5vasion
+6ite
+9d
+9s
+8ing
+3jink
+4udge
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+7ment
+9nts
+6icant
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+8e
+9d
+9s
+8ial
+9ally
+9alness
+9ng
+7ze
+9s
+3kindergarten
+3lacies
+6y
+5psarian
+5te
+7s
+8hip
+9ips
+8s
+9es
+6ial
+7c
+8al
+9lly
+7es
+7on
+9s
+7se
+9d
+9s
+8h
+8ing
+8m
+9s
+8t
+9s
+7ze
+9d
+9s
+8ing
+6ure
+9s
+6y
+5unch
+9ed
+9es
+9ing
+5w
+4ect
+7ed
+7ing
+8on
+9ns
+7or
+9s
+7s
+5gal
+5xical
+4ibation
+9ons
+5fe
+5m
+6inaries
+9rily
+9ry
+7t
+8ed
+8ing
+8s
+6s
+5ngual
+9lly
+5teracies
+9cy
+9ry
+9te
+9tes
+5ves
+4oad
+7ed
+7ing
+7s
+5cate
+9d
+9s
+8ing
+5gical
+5ved
+4ude
+7d
+7r
+8s
+7s
+6i
+7al
+7ng
+7o
+8us
+5nch
+8eon
+5sion
+9s
+7ve
+9ly
+6orily
+8y
+3m
+4ade
+5lignant
+5n
+6dibular
+9ulars
+6ufacture
+9ctured
+9ctures
+5rital
+9lly
+6ket
+9ed
+9ing
+9ings
+9s
+6riage
+9ges
+5ture
+9ly
+9ness
+9nesses
+9s
+8ities
+9ty
+5xilla
+9ae
+9aries
+9ary
+9as
+4eal
+6sure
+9ed
+9es
+9ing
+5d
+6ic
+8al
+9lly
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+8s
+7eval
+7tate
+9ted
+9tedly
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+6s
+5et
+5iotic
+5n
+6opausal
+6strual
+9ually
+5rger
+4ia
+5e
+6r
+7e
+8d
+8s
+7ing
+7s
+8hip
+9ips
+6s
+5gration
+5llenarian
+9arians
+9nial
+9nially
+5se
+7d
+7s
+6ing
+6s
+7ed
+8s
+7ing
+5um
+7s
+5x
+6ed
+7s
+6ing
+6t
+4odern
+6ification
+9ed
+9es
+8y
+9ing
+5isten
+9ned
+9ning
+9ns
+5lar
+8s
+6d
+7ed
+7ing
+7s
+6t
+5nish
+9ed
+9es
+9ing
+9ment
+9ments
+7tion
+9ons
+9ve
+8or
+9rily
+9rs
+9ry
+5ral
+6se
+5saic
+5tion
+9s
+5ve
+7d
+7ment
+9nts
+7s
+6ing
+4s
+4une
+6ition
+9ons
+4y
+5cotic
+3name
+7s
+5sal
+8s
+5tal
+8ly
+8s
+4eed
+5gotiate
+9ated
+9ates
+9ating
+9ation
+9ations
+4omen
+8s
+6ina
+9l
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+5on
+5tification
+9ed
+9es
+8y
+9ing
+7on
+9s
+4t
+5ed
+5ice
+8d
+8s
+9hip
+9hips
+7ing
+6ng
+5s
+4ubile
+5mber
+9ed
+9ing
+9s
+5p
+6s
+6tial
+4zie
+3obtain
+9ed
+9ing
+9s
+4ccupancies
+9ncy
+9nt
+9nts
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+8ied
+9es
+8y
+9ing
+5ular
+4n
+5s
+4p
+5ening
+6rational
+9ive
+9ively
+5s
+5tion
+9s
+4ral
+5dain
+9ed
+9ing
+9ment
+9ments
+9s
+6er
+8ed
+8ing
+8s
+6inance
+9nces
+9tion
+9tions
+4vulatory
+4wned
+3p
+4ack
+7age
+9ed
+9es
+9ing
+7ed
+7ing
+7s
+5id
+5ration
+9ons
+9ve
+9vely
+9ves
+8or
+9rily
+9rs
+9ry
+6e
+7d
+8ly
+8ness
+9esses
+7r
+8s
+7s
+6ing
+5ste
+8d
+8s
+7ing
+5tellar
+5ve
+7d
+7s
+6ing
+5y
+6able
+6ing
+6ment
+9ts
+6s
+4end
+6se
+8d
+8ly
+8s
+7ing
+8ve
+5rformance
+9mances
+4ill
+4lace
+8d
+8s
+7ing
+6n
+7ned
+8ing
+7s
+7t
+8ing
+4ollence
+9ces
+9cies
+9cy
+9t
+8x
+7ices
+5nderance
+9ances
+9ancies
+9ancy
+9ant
+9antly
+9ate
+9ated
+9ately
+9ates
+9ating
+9ation
+9ations
+6e
+7d
+7s
+6ing
+5rtion
+9ned
+9ning
+9ns
+5se
+7d
+7s
+6ing
+7tion
+9onal
+9onally
+9ons
+9ve
+9vely
+9ves
+8or
+9rs
+6sess
+9sed
+9ses
+9sing
+9singly
+9sion
+9sions
+6terous
+9ously
+7or
+9s
+5tence
+9es
+9ies
+9y
+8t
+9ly
+4ped
+5ie
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5y
+4randial
+5eg
+7s
+6pared
+6sidential
+7s
+8es
+5ice
+8d
+8s
+7ing
+6maries
+9y
+6nt
+8ed
+8ing
+8s
+5ocess
+9sed
+9ses
+9sing
+9sor
+9sors
+6duction
+9tions
+6fessional
+6gram
+9med
+9ming
+9mmed
+9mming
+9ms
+4s
+5ychedelic
+4uberal
+8tal
+9ies
+9y
+7s
+8cence
+9ences
+9ent
+9ents
+6is
+6lication
+9ations
+5ce
+7s
+5eblo
+5nch
+8ed
+9s
+8ing
+7tual
+5pa
+7e
+7l
+7s
+5rchase
+9sed
+9ses
+9sing
+5tial
+3qualified
+9ies
+9y
+9ying
+5el
+7s
+3race
+5dio
+4eading
+5cession
+6ord
+9ed
+9ing
+9s
+6tal
+5form
+5gister
+9ered
+9ering
+9ers
+9ration
+5hearsal
+5lease
+9ed
+9es
+9ing
+5nal
+5quire
+9ed
+9es
+9ing
+8site
+9ites
+5tirement
+9ments
+6urn
+5view
+7sionist
+9onists
+6olution
+4inse
+8d
+8s
+7ing
+5ot
+4ock
+5gative
+9ved
+9vely
+9ves
+5mantic
+4upt
+3sa
+5ge
+7d
+7ful
+9lly
+7ment
+9nts
+7r
+8s
+7s
+6ing
+5le
+7s
+5nctified
+9fies
+9fy
+9fying
+4byacouses
+9usis
+8uses
+9sis
+6couses
+9sis
+7uses
+9is
+6ope
+9s
+8ia
+9as
+9c
+9cs
+9es
+8y
+6te
+8r
+9al
+9ate
+9ates
+9ial
+9ially
+9ials
+9ian
+9ianise
+9ianism
+9ianize
+9ians
+9ies
+9s
+9ship
+9ships
+9y
+8s
+7ic
+8sm
+9ms
+4chedule
+9led
+9les
+9ling
+6ool
+9er
+9ers
+9s
+5ience
+9es
+8t
+9ific
+9ly
+6nd
+8ed
+9nt
+8ing
+8s
+6ous
+6ssion
+9ons
+5ore
+8d
+8s
+7ing
+5reen
+9ed
+9ing
+9s
+6ibe
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+7pt
+9ible
+9ion
+9ions
+9ive
+9ively
+9ivism
+9ivisms
+9ivist
+9ivists
+9s
+5uta
+7um
+4e
+5ason
+9s
+5lect
+9ed
+9ing
+9ion
+9ions
+9or
+9ors
+9s
+6l
+7ing
+7s
+5nce
+8s
+6ile
+6sion
+9ns
+6t
+7ability
+9le
+9leness
+9ly
+8tion
+9ional
+9ionism
+9ionist
+9ions
+9ive
+7ed
+8e
+9ism
+9isms
+9s
+8nce
+9ced
+9ces
+9cing
+9cings
+8r
+9s
+7ial
+9lities
+9lity
+9lly
+8ent
+8ment
+9ental
+9ents
+8ng
+8sm
+9ms
+9t
+8ve
+9eness
+7ly
+7ment
+9nts
+7ness
+9sses
+7s
+5rvability
+9le
+9ly
+8tion
+9ionist
+9ions
+9ive
+9ives
+9ories
+9ory
+7e
+8d
+8r
+9s
+8s
+7ice
+8ng
+5s
+5t
+6s
+6ting
+7le
+9d
+9ment
+9ments
+9s
+8ing
+4hape
+8d
+8s
+7ing
+5ip
+7ped
+8ing
+7s
+5ow
+7ed
+7ing
+7n
+7s
+5rank
+6ink
+9ing
+9s
+6unk
+9en
+4ide
+7d
+7ncies
+9y
+8t
+9ess
+9esses
+9ial
+9ially
+9s
+9ship
+9ships
+7r
+8s
+7s
+6ia
+8l
+8ry
+7ng
+7o
+8s
+7um
+9s
+5ft
+7ed
+7ing
+7s
+5gnal
+9ed
+9ing
+9led
+9ling
+9s
+7ified
+9ies
+9y
+9ying
+4laughter
+5eep
+5ice
+8d
+8s
+7ing
+4oak
+7ed
+7ing
+7s
+5ld
+6ve
+8d
+8s
+7ing
+5ng
+5rt
+7ed
+7ing
+7s
+4pecified
+9ies
+9y
+9ying
+5lit
+4s
+5board
+9ds
+5ed
+6r
+7s
+6s
+5fat
+8s
+6ul
+8s
+5gang
+9s
+5ie
+7s
+6ng
+8ly
+8ness
+9esses
+8s
+6on
+8s
+5man
+7rk
+9s
+6en
+5or
+7s
+5room
+9s
+6un
+8s
+5ure
+8d
+8less
+8s
+7ing
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+5woman
+8en
+7rk
+9s
+4t
+5amp
+8ed
+8ing
+8s
+6tion
+9ns
+5ed
+6r
+7ilise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+7na
+8um
+9ms
+7s
+5idigitator
+6ge
+8ful
+8s
+7iator
+9tors
+8ous
+9usly
+9usness
+6ng
+6ssimo
+9mos
+5o
+6rage
+9es
+7e
+8d
+8s
+7ing
+6s
+5ress
+9ed
+9es
+9ing
+6iction
+9ions
+7ke
+6ucture
+9ured
+9ures
+9uring
+5s
+4umable
+9y
+6e
+7d
+8ly
+7r
+8s
+7s
+6ing
+9ly
+6mit
+9s
+6ption
+9ons
+9ve
+9vely
+9veness
+8uous
+9ously
+5ppose
+9ed
+9es
+9ing
+9ition
+9itions
+5rgery
+6mise
+9es
+6vey
+9ed
+9ing
+9s
+4weeten
+9ned
+9ning
+9ns
+4ymptomatic
+5naptic
+9ically
+3tape
+7d
+7s
+6ing
+5ste
+8d
+8s
+7ing
+5x
+4een
+7s
+5levision
+6l
+7ing
+7s
+5nce
+8less
+8s
+6d
+7ant
+9ts
+7ed
+9ly
+8nt
+9ts
+8r
+9s
+9ship
+9ships
+7ing
+9gly
+7s
+6se
+8s
+7ion
+9ned
+9ning
+9nless
+9ns
+8ve
+6tious
+9usly
+9usness
+5rhuman
+6ist
+9s
+7t
+8e
+9ness
+9nesses
+9s
+8ion
+9ons
+9ve
+8s
+6m
+7inal
+9ation
+9ations
+8ssion
+9sions
+8t
+9s
+9ted
+9ter
+9ters
+9ting
+7s
+6natural
+9urally
+6perfect
+9fects
+5st
+7ed
+7ing
+7s
+5xt
+7ed
+7ing
+9gs
+7s
+4heater
+4old
+5nic
+5r
+6ial
+8n
+9s
+6s
+7hip
+9ps
+5urnament
+9ments
+4rain
+8ed
+8ing
+8s
+6vel
+5eat
+8ed
+8ing
+8ment
+9ents
+8s
+5ial
+8s
+6m
+7med
+8ing
+7s
+4tied
+7r
+7s
+8t
+6fication
+9ations
+8ed
+9r
+9rs
+9s
+7y
+8ing
+6ly
+6ness
+9ses
+5y
+6ing
+7sh
+8m
+9s
+4ype
+7d
+7s
+6ing
+4zel
+7s
+3unification
+6on
+8s
+6te
+8d
+8s
+7ing
+6versity
+3vail
+7ed
+8r
+9s
+7ing
+9gly
+7ment
+9nts
+7s
+5lence
+9es
+9ies
+9y
+8t
+9ly
+9ness
+9nesses
+9s
+6ue
+8d
+8s
+7ing
+5ricate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+4e
+5d
+5nancies
+9y
+6e
+7d
+7s
+6ience
+9ces
+9t
+9tly
+7ng
+6t
+7ability
+9le
+9ly
+8tive
+9ives
+7ed
+8r
+9s
+7ibility
+9le
+9ly
+8ng
+8on
+9ns
+8ve
+9ely
+9eness
+9es
+7s
+5rb
+7al
+7s
+5s
+4iable
+5ew
+7ed
+8r
+9s
+7ing
+7s
+5ng
+5ous
+8ly
+8ness
+9esses
+5se
+7d
+7s
+6ing
+7on
+9al
+9ary
+9ed
+9ing
+9s
+7t
+8ed
+8ing
+8s
+6or
+8s
+4ocalic
+9cally
+7tional
+4ue
+6d
+6s
+5ing
+3war
+6m
+7ed
+7ing
+7s
+6n
+7ed
+7ing
+7s
+5sh
+7ed
+8s
+7ing
+4eaning
+5igh
+8ed
+8ing
+8s
+4ire
+7d
+7s
+6ing
+4ork
+7ed
+7ing
+7s
+6n
+4rap
+7ped
+8ing
+7s
+5iting
+9gs
+4yn
+6s
+3x
+4es
+4ies
+4y
+3y
+4ed
+5r
+6s
+4ful
+4ing
+4s
+3z
+4es
+4zie
+7s
+2ial
+5s
+4pean
+5i
+6c
+6sm
+8s
+5us
+7es
+3bble
+7s
+3ce
+5able
+5d
+5less
+9ly
+9ness
+9nesses
+5r
+6s
+5s
+5y
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4ked
+6r
+7s
+6t
+7s
+5ier
+7st
+6ng
+8s
+5le
+7d
+7s
+6ier
+8st
+7ness
+9sses
+8g
+9s
+6y
+5wood
+9s
+5y
+4y
+3de
+5d
+5ful
+8ly
+8ness
+9esses
+5less
+5s
+4ian
+5ng
+3ed
+5ieu
+8s
+8x
+4f
+5e
+6s
+5s
+4r
+5s
+4s
+5t
+6craft
+9fts
+6ed
+7ss
+9es
+6hood
+9ds
+6ing
+6lier
+9st
+8ke
+8ness
+9esses
+9g
+9gs
+7y
+6s
+7hip
+9ps
+4ve
+6d
+6s
+5ing
+3g
+4ged
+6r
+7ies
+7s
+7y
+5ing
+8s
+6sh
+8ly
+8ness
+9esses
+7m
+8s
+4s
+3ll
+5ed
+5ing
+5s
+3m
+4a
+5cies
+6y
+5eval
+9ly
+5ge
+7s
+5l
+6ities
+8y
+6ly
+5quine
+9es
+5ries
+7ly
+7ness
+9sses
+6y
+5s
+5tal
+8s
+6e
+7s
+8hip
+9ips
+6ial
+9s
+7c
+8al
+6ological
+9gies
+9gist
+9gists
+9gy
+5vera
+9s
+4e
+5d
+5ly
+5ness
+9es
+5r
+6o
+7s
+6s
+5s
+5time
+5ur
+7s
+5val
+8ly
+4i
+5genial
+6ravida
+9idae
+9idas
+5ne
+7s
+6g
+7s
+5para
+9e
+9s
+8ities
+9ty
+8ous
+5tiae
+8l
+8s
+7ve
+9ly
+9ness
+9nesses
+9s
+8ism
+9sms
+9st
+9stic
+9sts
+9ties
+9ty
+4ly
+4med
+6r
+7s
+6st
+5ing
+4ness
+8es
+4o
+5genial
+9t
+9tal
+9tary
+9tive
+9tives
+9tor
+9tors
+9trices
+9trix
+9trixes
+9ts
+9ture
+9tures
+5rdia
+9l
+9lism
+9lisms
+9lities
+9lity
+9lly
+9ls
+8um
+5s
+4p
+5ed
+5ing
+5s
+4rose
+8d
+8s
+7ing
+7y
+4s
+5ie
+7r
+7st
+4ula
+7ceous
+7s
+6ine
+9s
+5s
+6es
+4y
+3nce
+6d
+7om
+9s
+6hood
+9ds
+6kin
+9s
+6let
+9s
+7ier
+9st
+8ke
+8ness
+9esses
+9g
+9gs
+7y
+6s
+7hip
+9ps
+7s
+8e
+9s
+8ly
+5ified
+6ng
+6pal
+9ities
+9ity
+9ly
+9ness
+9nesses
+9s
+9ship
+9ships
+8te
+9es
+7e
+7i
+8a
+9l
+8um
+7le
+9d
+9s
+8ing
+5ock
+8s
+6x
+7es
+4k
+5ed
+6r
+7s
+5ing
+5s
+4t
+5abilities
+9ity
+7le
+9ness
+9nesses
+5ed
+6r
+7ies
+7s
+7y
+5head
+9s
+5ing
+8s
+5less
+5maker
+9rs
+8ing
+9ngs
+5out
+8s
+5s
+5wheel
+9ls
+6orks
+3on
+5s
+4r
+5ate
+8s
+5ess
+8es
+5ies
+6ties
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7y
+5ly
+5s
+6hip
+9s
+5y
+3sage
+7s
+4e
+5d
+5r
+6e
+7s
+6s
+5s
+4ing
+4m
+5atic
+9al
+9ally
+7oid
+9dal
+9ds
+5oid
+8al
+8s
+5s
+5y
+4on
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6ous
+6s
+4s
+5ed
+6s
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5y
+4tane
+8s
+5ine
+8ly
+3thee
+3vacies
+6y
+5do
+7es
+7s
+5tdocent
+9ents
+8zent
+9ents
+6e
+7er
+9ed
+9ing
+9ings
+9s
+9sman
+9smen
+7ly
+7ness
+9sses
+7r
+7s
+8t
+6ion
+9s
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9s
+7ve
+9ly
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+4et
+6s
+4ier
+6s
+7t
+5lege
+9d
+9s
+8ing
+6y
+5ties
+6y
+4y
+3zable
+4e
+5d
+5fight
+9ter
+9ters
+9ting
+9tings
+9ts
+5man
+6en
+5r
+6s
+5s
+5winner
+9ers
+9ing
+6oman
+8en
+4ing
+2o
+3a
+4bortion
+4ction
+9s
+7ve
+4ireses
+8is
+4s
+3b
+4abiliorism
+9orisms
+9orist
+9orists
+9sm
+9sms
+9st
+9stic
+9sts
+9ties
+9ty
+6le
+8s
+7y
+5ll
+5nd
+7s
+6g
+7s
+5te
+7d
+7s
+6ing
+7on
+9al
+9ally
+9aries
+9ary
+9er
+9ers
+9ership
+9s
+7ve
+9ly
+6ory
+4e
+5able
+5d
+5necid
+9ds
+5r
+6s
+5s
+4ing
+7ly
+5otic
+9s
+5t
+6ies
+6s
+6y
+4lem
+7atic
+9ical
+9ically
+9ics
+7ist
+9ts
+7s
+4oscidean
+9eans
+9es
+9ian
+9ians
+8s
+9es
+5uleutic
+4s
+4usiness
+3cacious
+7ties
+8y
+5ine
+8s
+5mbia
+9l
+8um
+9ms
+5pitalist
+5rbazine
+9ines
+6p
+7s
+6yon
+9s
+8te
+9es
+9ic
+5thedral
+9rals
+4edural
+9lly
+9ls
+8e
+9s
+5ed
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5leusmatic
+9matics
+6larian
+5phalic
+5rcoid
+9ds
+6ebra
+9al
+9um
+9ums
+6ities
+8y
+5ss
+7ability
+9le
+7ed
+8r
+9s
+8s
+7ibility
+9le
+8ng
+9gs
+8on
+9nal
+9nalist
+9nally
+9nals
+9nary
+9ned
+9ner
+9ners
+9ning
+9nings
+9ns
+7or
+9s
+7ual
+4hain
+5ein
+5oice
+5ronism
+9sms
+5urch
+4idence
+9es
+8t
+5nct
+8s
+4laim
+8ant
+9nts
+8ed
+9r
+9rs
+8ing
+8s
+6mation
+9ions
+9ory
+5ises
+7is
+6tic
+9s
+6ve
+7ities
+9y
+4oelous
+5nsul
+9ar
+9ate
+9ates
+9s
+9ship
+9ships
+4rastinate
+9nated
+9nates
+9nating
+9nation
+9native
+9nator
+9nators
+9natory
+5eant
+9s
+7te
+9d
+9s
+8ing
+9on
+9onal
+9ons
+9ve
+9veness
+8or
+9rs
+5ustean
+5ypses
+8is
+7tic
+9cally
+4tal
+7gia
+9as
+5itides
+8s
+9es
+5odaea
+9al
+9um
+9ums
+7ea
+8um
+9ms
+6logic
+9ical
+9ies
+9ist
+9ists
+9y
+6r
+7age
+9es
+7ed
+7ial
+9lly
+8ng
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7s
+8hip
+9ips
+6scope
+9pes
+9pic
+9pies
+9py
+4umbent
+5rable
+7cies
+8y
+7l
+8s
+7nce
+9es
+7tion
+9ons
+8or
+9rial
+9ries
+9rs
+9rship
+9rships
+9ry
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+8s
+9es
+7ur
+9s
+6ing
+9s
+4yonid
+9s
+3d
+4ded
+6r
+7s
+5ing
+4igal
+8ise
+9sed
+9ses
+9sing
+9ties
+9ty
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+6ies
+7osities
+9ity
+8us
+9sly
+9sness
+6y
+5tor
+8ious
+8s
+8y
+4nose
+8d
+8s
+7ing
+4romal
+8ta
+7e
+8s
+7i
+8c
+7us
+5ug
+7s
+4s
+4uce
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ibilities
+9lity
+8le
+7ng
+6t
+7ibility
+8le
+8on
+9nal
+9ns
+8ve
+9ely
+9eness
+9ities
+9ity
+7s
+3em
+5bryo
+9s
+5ial
+5s
+4nzyme
+9s
+4strus
+9es
+4tte
+7s
+3f
+4ace
+5mily
+5nation
+9ons
+8ory
+6e
+7d
+7ly
+7ness
+9sses
+7r
+8s
+7s
+6ing
+7ties
+8y
+5scist
+4ectitious
+5minist
+5ss
+7ed
+9ly
+8s
+7ing
+8on
+9nal
+9nalise
+9nalism
+9nalist
+9nalize
+9nally
+9nals
+9ns
+7or
+9ate
+9ates
+9ess
+9esses
+9ial
+9ially
+9iat
+9iate
+9iates
+9iats
+9s
+9ship
+9ships
+4fer
+7ed
+8r
+9s
+7ing
+7s
+4icience
+9ces
+9cies
+9cy
+9t
+9tly
+9ts
+5le
+7d
+7r
+8s
+7s
+6ing
+9s
+7st
+9s
+5t
+6abilities
+9lity
+8le
+9eness
+9y
+6ed
+7er
+9ed
+9ing
+9ings
+9s
+7r
+8ole
+9les
+8s
+6ing
+9s
+6less
+9sly
+6s
+6wise
+4ligacies
+9y
+8te
+9ely
+9es
+5uence
+9es
+8t
+4orma
+5und
+8er
+9st
+8ly
+8ness
+9esses
+8s
+4s
+4ulgent
+5ndities
+9y
+5se
+7ly
+7ness
+9sses
+7r
+8s
+6ion
+9s
+7ve
+3g
+4enies
+7tive
+9veness
+8or
+9rial
+9rs
+9rship
+9rships
+8ress
+9esses
+9ices
+9ix
+9ixes
+8ure
+9res
+6y
+5ria
+8s
+5stational
+7erone
+9ones
+7in
+9s
+7ogen
+9enic
+9ens
+4ged
+6r
+7s
+5ing
+7s
+8es
+4lottic
+9d
+9dean
+9des
+9ds
+9s
+4nathic
+9sm
+9sms
+8ous
+5ose
+8d
+8s
+7ing
+8s
+7tic
+9cate
+9cated
+9cates
+9cating
+9cation
+9cative
+9cator
+9cators
+9cs
+4radation
+9ions
+7e
+8d
+8s
+7ing
+6m
+7able
+7ed
+8r
+9s
+7ing
+9gs
+7mability
+9ble
+9bles
+9tic
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+7s
+5ess
+8ed
+9s
+8ing
+9on
+9onal
+9onally
+9onary
+9onism
+9onisms
+9onist
+9onists
+9ons
+9sm
+9sms
+9st
+9sts
+9ve
+9vely
+9veness
+9ves
+9vism
+9visms
+9vist
+9vistic
+9vists
+9vities
+9vity
+4s
+4un
+4ymnasia
+9ium
+9iums
+3hibit
+8ed
+9r
+9rs
+8ing
+9on
+9onary
+9onism
+9onisms
+9onist
+9onists
+9ons
+9ve
+9vely
+9veness
+8or
+9rs
+9ry
+8s
+3ign
+6ed
+6ing
+6s
+4n
+5e
+6d
+6s
+5ing
+5s
+6ulin
+9ns
+3ject
+7able
+7ed
+7ile
+9es
+8ng
+9gs
+8on
+9nal
+9nist
+9nists
+9ns
+8sation
+9ations
+8ve
+9ely
+9ities
+9ity
+8zation
+9ations
+7ment
+9nts
+7or
+9s
+7s
+7ure
+9es
+5t
+6s
+3karyon
+9s
+8t
+9e
+9es
+9ic
+9s
+4e
+5d
+5r
+6s
+5s
+4ing
+3labor
+5ctin
+9s
+5min
+8e
+9s
+8s
+5n
+6s
+5pse
+8d
+8s
+7ing
+7us
+9es
+5te
+7d
+7ly
+7ness
+9sses
+7s
+6ing
+7on
+9s
+7ve
+4e
+5d
+5g
+6omena
+9nal
+9nary
+9non
+9nous
+6s
+5pses
+7is
+6tic
+9al
+9ally
+5r
+6s
+5s
+5tarian
+9anise
+9anised
+9anises
+9anism
+9anisms
+9anize
+9anized
+9anizes
+9anness
+9ans
+9at
+9ate
+9ates
+9ats
+9es
+8y
+4icidal
+8e
+9s
+5ferate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+8ous
+9usly
+6ic
+8acies
+9cy
+9l
+9lly
+9tion
+9tions
+8ities
+9ty
+8ness
+9esses
+5ne
+7s
+6g
+5x
+6ious
+7ties
+8y
+6ly
+6ness
+9ses
+4l
+5ed
+6r
+7s
+5ing
+5s
+4ocution
+9ons
+8or
+9rs
+9rship
+9rships
+8rices
+9ix
+9ixes
+5g
+6ed
+6ing
+7se
+9d
+9s
+8ing
+8t
+9s
+7ze
+9d
+9s
+8ing
+6s
+6ue
+8d
+8s
+7ing
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+5ng
+7able
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7ment
+9nts
+7s
+4usion
+9s
+6ory
+3m
+4achos
+9es
+4enade
+9d
+9r
+9rs
+9s
+8ing
+5tal
+8s
+6hazine
+9ines
+7eum
+9ms
+7ium
+9ms
+6ric
+4ilitary
+5ne
+7nce
+9es
+9ies
+9y
+8t
+9ly
+9ness
+9nesses
+7s
+5scuities
+9ty
+8ous
+9usly
+9usness
+6e
+7d
+7e
+8s
+7ful
+7less
+7r
+8s
+7s
+6ing
+9ly
+6or
+8s
+6sive
+7or
+9ily
+9s
+9y
+4mer
+7s
+4o
+5dern
+5ed
+5ing
+5narchist
+6tories
+9y
+5s
+5tabilities
+9lity
+8le
+6e
+7d
+7r
+8s
+7s
+6ing
+7on
+9al
+9s
+7ve
+9ness
+9nesses
+6or
+8s
+4pt
+6book
+9ks
+6ed
+7r
+8s
+7st
+6ing
+9s
+7tude
+9des
+6ly
+6ness
+9ses
+6s
+6uaries
+9y
+7re
+9s
+4s
+4ulgate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7e
+8d
+8s
+7ing
+5sces
+7idate
+9es
+8s
+4ycelia
+9al
+9um
+3naoi
+6s
+5te
+7d
+7s
+6ing
+7on
+9s
+6or
+8es
+8s
+4e
+5ly
+5ness
+9es
+5phra
+8ic
+8oi
+9s
+9ses
+5r
+5s
+6t
+5ur
+7s
+4g
+5buck
+9s
+5ed
+5horn
+9s
+5ing
+5s
+4k
+5ed
+5ing
+8s
+5s
+4ominal
+9lise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+9lly
+5ta
+7l
+6um
+5un
+7ce
+9able
+9d
+9dly
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+9ngs
+7s
+4to
+4uclear
+9rist
+9rists
+8i
+8us
+9ses
+5nciamento
+9mentos
+9tion
+9tional
+9tions
+8o
+9s
+3o
+4emion
+9s
+7um
+9s
+4f
+5ed
+6r
+7s
+5ing
+8s
+5less
+5read
+9er
+9ers
+9ing
+9ings
+9s
+6oom
+9s
+5s
+4tic
+7s
+3p
+4aedeutic
+9tical
+9tics
+5gabilities
+9lity
+8le
+9eness
+7nda
+9as
+9ise
+9ised
+9iser
+9isers
+9ises
+9ising
+9ism
+9isms
+9ist
+9istic
+9ists
+9ize
+9ized
+9izer
+9izers
+9izes
+9izing
+7te
+9d
+9s
+8ing
+9on
+9onal
+9ons
+9ve
+8or
+9rs
+6e
+7d
+7s
+6ing
+6ula
+8e
+9s
+8um
+5le
+7d
+7s
+6ing
+5ne
+7dioic
+7s
+6oic
+7l
+8s
+7ne
+9s
+5roxytone
+9tones
+4el
+6lant
+9ts
+7ed
+8nt
+9ts
+8r
+9s
+7ing
+7or
+9s
+6ment
+9ts
+6s
+5nal
+8s
+6d
+7ed
+8nt
+7ing
+7s
+6e
+7s
+6oic
+7l
+8s
+6se
+8ly
+8ness
+9esses
+7ion
+9ns
+8ties
+9y
+8ve
+6yl
+5r
+6din
+9s
+6er
+7st
+6ispomena
+9omenon
+6ly
+6ness
+9ses
+6s
+6tied
+9s
+7y
+8ing
+8less
+4hage
+8s
+6se
+8s
+7ic
+5ecies
+7y
+6siable
+8ed
+9r
+9rs
+9s
+7y
+8ing
+9ngs
+6t
+7ess
+9ses
+7hood
+9ods
+7ic
+9al
+9ally
+9ism
+9isms
+8sm
+9ms
+7s
+8hip
+9ips
+5ylactic
+9tics
+8xes
+9is
+7l
+8s
+4ine
+7d
+7s
+6ing
+6quities
+9ty
+5onate
+9es
+7ic
+5tiable
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ious
+9ive
+9or
+9ories
+9orily
+9ors
+9ory
+7ous
+9sly
+9sness
+4jet
+7s
+4lastid
+9ds
+4man
+5en
+4odeon
+9s
+7um
+9s
+5lis
+8es
+5ne
+7d
+7nt
+9s
+7s
+6ing
+5rtion
+9nable
+9nably
+9nal
+9nality
+9nally
+9nals
+9nate
+9nated
+9nately
+9nates
+9nating
+9ned
+9ning
+9nings
+9nless
+9nment
+9nments
+9ns
+5sable
+7l
+8s
+6e
+7d
+7r
+8s
+7s
+6ing
+7ta
+9e
+8i
+9on
+9onal
+9onally
+9oned
+9oning
+9ons
+8us
+5und
+8ed
+9r
+9rs
+8ing
+8s
+5xyphene
+9enes
+4pant
+8s
+5ed
+5ing
+4raetor
+9rial
+9rian
+9rs
+6nolol
+9ols
+5etor
+9s
+5ia
+6etaries
+9rily
+9ry
+8ies
+8or
+9rial
+9rially
+9rs
+9rship
+9rships
+8ress
+9esses
+9ices
+9ix
+9ixes
+8y
+6oception
+9ptions
+9ptive
+9ptor
+9ptors
+6um
+5octor
+9rs
+4s
+4toses
+7is
+4ugnation
+9ions
+5lsion
+9ns
+8ve
+7or
+9s
+9y
+4yl
+6a
+7ea
+8um
+7mine
+9nes
+6ene
+9s
+6ic
+7te
+9s
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+6on
+8s
+6s
+3ratable
+6e
+7d
+7s
+6ing
+7on
+9s
+4e
+5ctor
+9s
+5form
+5s
+4ogate
+9d
+9s
+8ing
+9on
+9ons
+6ue
+8d
+8s
+7ing
+3s
+4aic
+7al
+9ly
+9ness
+9nesses
+7ism
+9ms
+7ness
+9sses
+6sm
+8s
+7t
+8s
+5teur
+9s
+5uropod
+9ods
+4cenia
+8um
+9ms
+5iutti
+9o
+9os
+5ribe
+9d
+9r
+9rs
+9s
+8ing
+7pt
+9ion
+9ions
+9ive
+9ively
+9s
+4e
+5cco
+8s
+6t
+7ed
+7ing
+7or
+9ial
+9s
+9ship
+9ships
+7s
+6utable
+8e
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rial
+9rs
+8rices
+9ix
+9ixes
+5d
+5like
+6yte
+9d
+9s
+8ic
+9ng
+9sation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9sm
+9sms
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+5man
+6en
+6inar
+9rs
+5ncephala
+9halic
+9halon
+7hyma
+9mas
+9mata
+9matous
+5r
+6s
+5s
+5ucha
+9e
+8e
+4ier
+6st
+5fied
+8s
+6y
+7ing
+5liencies
+9cy
+9t
+6y
+5mian
+9s
+5ness
+9es
+6g
+7s
+5t
+4lambanomene
+6very
+4o
+5branch
+9chs
+5dial
+8n
+9s
+7c
+8al
+9lly
+7es
+7st
+9s
+6y
+5ma
+7l
+7s
+7ta
+5pagnosia
+9osias
+6ographer
+9aphers
+9aphies
+9aphy
+7n
+8s
+7peia
+9ial
+9ias
+8oeia
+9eial
+9eias
+5s
+4pect
+8ed
+8ing
+9ngs
+9on
+9ons
+9ve
+9vely
+9veness
+9ves
+8less
+8or
+9rs
+8s
+8us
+9ses
+6r
+7ed
+7ing
+8ties
+9y
+7ous
+9sly
+9sness
+7s
+4s
+5es
+5ie
+7s
+4t
+5acyclin
+9lins
+6glandin
+9ndins
+6nthera
+9eras
+6te
+8ctomies
+9tomy
+8s
+7ic
+8sm
+9ms
+8tes
+9ides
+9is
+9ises
+5erna
+8um
+9ms
+5heses
+8is
+7tic
+9cally
+9cs
+9st
+9sts
+6odontia
+9ntias
+9ntics
+9ntist
+9ntists
+5ie
+7s
+5omia
+9l
+8um
+9ms
+5rate
+9d
+9s
+8ing
+9on
+9ons
+5yle
+8s
+4umer
+8s
+4y
+5llogism
+9isms
+3tactinium
+9iums
+5gonism
+9sms
+9st
+9sts
+5min
+8e
+9s
+8s
+5ndries
+8ous
+8y
+6omalies
+9lous
+9ly
+7pe
+9s
+8ia
+9as
+9c
+5ses
+6is
+5tic
+4ea
+6ceous
+6n
+7s
+6s
+7e
+8s
+5ct
+7ant
+9ts
+7ed
+8r
+9s
+7ing
+9gly
+8on
+9nism
+9nisms
+9nist
+9nists
+9ns
+8ve
+9ely
+9eness
+9es
+7or
+9al
+9ate
+9ates
+9ial
+9ies
+9less
+9s
+9ship
+9ships
+9y
+7ress
+9sses
+8ices
+9x
+9xes
+7s
+5ge
+7e
+8s
+7s
+5i
+6d
+7e
+8s
+7s
+6form
+6n
+7aceous
+8se
+9es
+7ic
+7ous
+7s
+7uria
+9ias
+5nd
+7ed
+7ing
+7s
+6se
+8s
+7ion
+9ns
+8ties
+9y
+8ve
+9ely
+5oclastic
+6glycan
+9cans
+6lyse
+9ed
+9es
+9ing
+9is
+8tic
+9ically
+6me
+8s
+7ic
+9s
+6se
+8s
+5randries
+9rous
+9ry
+6ogynies
+9nous
+9ny
+6vities
+9y
+5st
+7ant
+9ts
+8tion
+9ions
+7ed
+8r
+9s
+7ing
+9gly
+7or
+9s
+7s
+5us
+7es
+4halamia
+9ion
+9ium
+7li
+9a
+9al
+9c
+9um
+8oid
+8us
+9ses
+5eses
+7is
+6tic
+9ally
+5onotarial
+9ariat
+9ariats
+9aries
+9ary
+6races
+9ic
+8x
+9es
+5rombin
+9ins
+5yl
+7s
+4ist
+7an
+9s
+7ic
+7ologies
+9ogist
+9ogists
+9ogy
+7s
+5um
+7s
+4o
+5actinium
+9niums
+6vis
+9es
+5chordate
+9dates
+6occal
+7l
+8ed
+8ic
+9ng
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+8led
+9ing
+8s
+6tist
+9ts
+5derm
+9s
+5galaxies
+9xy
+6enic
+6ine
+9s
+6ynies
+8ous
+8y
+5historian
+9orians
+9oric
+9ories
+9ory
+6uman
+9ns
+5language
+9uages
+6ithic
+5martyr
+9yrs
+6orphic
+5n
+6ate
+9d
+9s
+8ing
+9on
+9ons
+6ema
+9l
+9ta
+9tal
+6ic
+6otarial
+9riat
+9riats
+9ries
+9ry
+6s
+5pathic
+9ies
+9y
+6hilic
+7loem
+9ems
+7yte
+9es
+9ic
+6lanet
+9etary
+9ets
+8sm
+9mal
+9matic
+9mic
+9ms
+9t
+9tic
+9ts
+6od
+8s
+7rphyrin
+9hyrins
+5re
+7s
+5spataire
+9aires
+9haire
+9haires
+9harius
+6tar
+9s
+7ele
+9es
+9ic
+7ome
+9es
+5therian
+9ians
+6roph
+9hic
+9hies
+9hs
+9hy
+6ypal
+8e
+9d
+9s
+8ic
+9cal
+9cally
+9ng
+5xid
+8e
+9s
+8s
+6ylem
+9ms
+5zoa
+8l
+8n
+9s
+7ic
+7ological
+9ogies
+9ogist
+9ogists
+9ogy
+8n
+9s
+4ract
+8ed
+9dly
+9dness
+8ible
+9le
+9ng
+9on
+9ons
+9ve
+8or
+9rs
+8s
+6de
+5eptic
+9cal
+9cs
+5udable
+7e
+8d
+8nt
+8s
+7ing
+6sible
+8le
+8on
+9ns
+8ve
+9ely
+9eness
+4uberance
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+4yl
+6e
+7s
+6s
+3ud
+5er
+6st
+5ful
+5hearted
+5ish
+5ly
+5ness
+9es
+4l
+5ed
+6r
+7s
+5ing
+5s
+4nion
+4stite
+9s
+3vabilities
+9ty
+6le
+8ness
+9esses
+7y
+5nd
+7s
+6t
+5scular
+4e
+5able
+8y
+5ction
+9ns
+5d
+6itor
+9re
+9res
+9rs
+6or
+8e
+9s
+8s
+5n
+6ance
+9es
+6d
+7er
+9ed
+9ing
+9s
+7s
+6ience
+9ces
+6ly
+6tricular
+9culi
+9culus
+5r
+6b
+7ed
+7ial
+9lise
+9lised
+9lises
+9lising
+9lism
+9lisms
+9list
+9lists
+9lize
+9lized
+9lizes
+9lizing
+9lly
+8ng
+7s
+6s
+5s
+4iant
+8s
+5dable
+6e
+7d
+7nce
+9es
+8t
+9ial
+9ially
+9ly
+7r
+8s
+7s
+6ing
+6or
+8s
+5nce
+8s
+8wide
+7ial
+9lise
+9lised
+9lises
+9lising
+9lism
+9lisms
+9list
+9lists
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9ls
+6e
+7d
+7s
+6g
+7s
+6ing
+5ral
+6us
+8es
+5sion
+9al
+9ally
+9als
+9aries
+9ary
+9ed
+9er
+9ers
+9ing
+9s
+6o
+7es
+7r
+8ily
+8s
+8y
+7s
+5tamin
+9ns
+4ocable
+7nt
+9s
+7teur
+9urs
+8ion
+9ons
+9ve
+9vely
+9veness
+9ves
+8or
+9rs
+9ry
+5kable
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9ly
+5lone
+9s
+5st
+7ries
+8y
+7s
+8hip
+9ips
+3w
+4ar
+4er
+5ss
+7ed
+8s
+6t
+4l
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5s
+4s
+3xemic
+8s
+4ied
+6s
+5mal
+8ly
+7te
+9ly
+9ness
+9nesses
+8ion
+9ons
+6ities
+8y
+6o
+4y
+3yn
+5e
+6d
+6s
+5ing
+5s
+3zymite
+9s
+2ude
+5nce
+8s
+6t
+7ial
+9lism
+9lisms
+9list
+9lists
+9lities
+9lity
+9lly
+9ls
+7ly
+5ries
+6y
+5s
+4ish
+7ly
+7ness
+9sses
+3h
+3ina
+6s
+5e
+6s
+5ose
+3nable
+4e
+5d
+5lla
+8s
+7e
+8s
+7o
+8s
+5r
+6s
+5s
+4ing
+7s
+4t
+5ed
+5s
+4us
+6es
+3rience
+9s
+8ies
+8y
+7t
+8ly
+5ginous
+6o
+7s
+5tic
+6us
+8es
+3sik
+6ed
+6ing
+6s
+4sian
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+7te
+9s
+6c
+3ta
+5h
+4ot
+6h
+2y
+3er
+5s
+3ing
+6ly
+6s
+3s
+4e
+5d
+5s
+4ing
+3tanea
+7um
+4hee
+1saligraphies
+9hy
+4m
+5book
+9s
+5ed
+5ic
+6ng
+6st
+8s
+5odic
+9al
+8es
+8se
+9ed
+9es
+9ing
+9t
+9ts
+8ze
+9ed
+9es
+9ing
+7y
+5s
+4ter
+7ia
+9n
+8es
+8um
+7s
+7y
+5ress
+9es
+6ies
+6y
+3mmite
+8s
+7ic
+5on
+7s
+6phil
+9le
+9les
+9lous
+9ls
+8yte
+9tes
+9tic
+2chent
+7s
+2ellism
+8s
+8us
+9ses
+3phism
+8s
+6te
+8s
+7ic
+5oanalyses
+9lysis
+6logical
+9ically
+9ies
+9ist
+9ists
+9y
+3ud
+5aesthesia
+9hesias
+6rthroses
+9rosis
+6xes
+7is
+5epigraph
+9rapha
+9raphic
+9raphon
+9raphs
+9raphy
+6ries
+7y
+5imagines
+9o
+9os
+6sh
+5o
+6acid
+9ds
+7llele
+9eles
+7rthroses
+9hrosis
+6bulb
+9bs
+6carp
+9pous
+9ps
+7lassic
+9ssics
+7ode
+9es
+8el
+9lomate
+9ls
+7yeses
+9sis
+6ephedrine
+6graph
+9phies
+9phs
+9phy
+6logia
+9ias
+9ies
+9ue
+9ues
+9y
+6martyr
+9tyrs
+7embrane
+9branes
+7onad
+9ades
+9ads
+9as
+8rph
+9phic
+9phism
+9phisms
+9phous
+9phs
+7utuality
+6nym
+9ities
+9ity
+9ous
+9ously
+9s
+6pod
+9al
+9ia
+9ial
+9ium
+9s
+7regnancy
+9gnant
+6random
+6s
+7calar
+9lars
+8ience
+9ences
+9entist
+8ope
+9pes
+9rpion
+9rpions
+7olution
+9utions
+7ymmetry
+6vector
+9tors
+5s
+2haw
+5ed
+5ing
+5s
+2i
+3lanthropic
+9opies
+9opism
+9opisms
+9opist
+9opists
+9opy
+4ocin
+8s
+6ybin
+9ns
+5melane
+9nes
+5phyte
+9es
+9ic
+5ses
+6is
+5tic
+3on
+5ic
+7s
+5s
+3s
+3ttacine
+9es
+7oses
+9is
+9ises
+8tic
+2oae
+4i
+4s
+5es
+4tic
+3cid
+6s
+3ra
+5lea
+8s
+7n
+8s
+5s
+4iases
+7is
+6tic
+9s
+5c
+2st
+2t
+2ych
+5agogue
+9ues
+6sthenia
+9enias
+9enic
+9enics
+5e
+6d
+7elia
+9ias
+9ic
+9ically
+9ics
+6s
+5iater
+9rs
+8ric
+9ical
+9ically
+9ies
+9ist
+9ists
+9y
+6c
+7al
+9ly
+7ism
+9ms
+9t
+9ts
+7s
+6ng
+6sm
+8s
+7t
+8s
+5o
+6acoustic
+9ustics
+8tive
+7nalyse
+9lysed
+9lyser
+9lysers
+9lyses
+9lysing
+9lysis
+9lyst
+9lysts
+9lytic
+9lyze
+9lyzed
+9lyzer
+9lyzers
+9lyzes
+9lyzing
+6babble
+9bler
+9blers
+9bles
+7illies
+9ly
+8ography
+9logic
+9logies
+9logist
+9logy
+6chemical
+9micals
+9mistry
+6delia
+9ias
+9ic
+9ically
+7rama
+9mas
+9matic
+7ynamic
+9amics
+6galvanic
+8s
+9es
+7eneses
+9esis
+9etic
+9etical
+9etics
+9ic
+9ically
+8riatric
+7noses
+9sis
+9stic
+7onies
+9y
+7ram
+9ms
+9ph
+9phic
+9phical
+9phics
+9phies
+9phs
+9phy
+6historian
+9tories
+9tory
+6id
+8s
+6kineses
+9esis
+9etic
+6linguist
+9guists
+7ogic
+9ical
+9ically
+9ies
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9istic
+9ists
+9ize
+9ized
+9izes
+9izing
+9y
+6machia
+9hias
+9hies
+9hy
+7eter
+9ers
+9ric
+9rical
+9rician
+9rics
+9ries
+9rist
+9rists
+9ry
+7otor
+6neuroses
+9rosis
+9rotic
+9rotics
+7omic
+9ics
+6path
+9hic
+9hics
+9hies
+9hist
+9hists
+9hology
+9hs
+9hy
+7hilies
+9ly
+8ysical
+9sicist
+9sics
+7omp
+9ps
+6s
+7es
+8xual
+9uality
+9ually
+7is
+7ocial
+9ially
+8matic
+9atics
+9imetic
+7urgeon
+9geons
+9geries
+9gery
+9gical
+7yntheses
+9thesis
+6technics
+7herapies
+9rapist
+9rapy
+7ic
+9ally
+9ism
+9isms
+9s
+7omimetic
+8xic
+7ropic
+9pics
+5rometer
+9ters
+9tric
+9trical
+9tries
+9try
+7philic
+5s
+3lla
+6s
+5id
+7s
+6um
+8s
+3op
+5s
+3war
+6s
+1tarmic
+7s
+6gan
+9s
+2eranodon
+9ns
+4ia
+5dine
+9s
+6ological
+9gies
+9gist
+9gists
+9gy
+7mania
+9nias
+7philist
+9ilists
+9yte
+9ytes
+9ytic
+9ytous
+7sperm
+9erms
+5n
+6s
+5on
+4odactyl
+9yle
+9yles
+9yls
+5ic
+5pod
+8s
+5saur
+9ian
+9ians
+9s
+4ygia
+8l
+9s
+7um
+9s
+6oid
+9s
+5la
+7e
+6ographic
+9aphies
+9aphy
+7ses
+8is
+2iloses
+6is
+3san
+6s
+2ochocracies
+9cy
+3main
+7e
+8s
+7ic
+7s
+3oey
+3ses
+4is
+3tic
+2ui
+2yalagogic
+9ue
+9ues
+5in
+7s
+6se
+8d
+8s
+7ing
+7m
+8s
+6ze
+8d
+8s
+7ing
+3xes
+4is
+6es
+1ub
+3bed
+4ing
+7s
+3co
+5s
+4rawler
+9rs
+3eral
+5tal
+6ies
+6y
+5ulent
+7ous
+4scence
+9es
+8t
+3ic
+4s
+5es
+3lic
+6ally
+7n
+8s
+7tion
+9ons
+6ise
+9d
+9s
+8ing
+8t
+9s
+7ties
+8y
+7ze
+9d
+9s
+8ing
+6ly
+6ness
+9ses
+6s
+5sh
+7able
+7ed
+8r
+9s
+8s
+7ing
+9gs
+7ment
+9nts
+3s
+2can
+5s
+3ciniaceous
+4oon
+7s
+3e
+4lage
+8s
+5le
+7s
+4r
+4s
+5t
+3k
+4a
+4ed
+5r
+6ed
+7r
+8s
+6ier
+8st
+7ng
+6ooed
+6s
+6y
+4fist
+8s
+4ing
+5sh
+7ly
+7ness
+9sses
+4le
+6s
+4out
+7s
+4s
+2d
+3den
+6ing
+9s
+6s
+5r
+6ed
+6ing
+6s
+4ies
+5ng
+7s
+7y
+4le
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5y
+4ock
+7s
+4y
+3encies
+6y
+5da
+7l
+6ous
+6um
+5t
+3ge
+5s
+4ier
+6st
+5ly
+5ness
+9es
+4y
+3ibund
+8ities
+9ty
+4c
+5ities
+7y
+3or
+5s
+3s
+4ey
+4ier
+6st
+4y
+3u
+4s
+2eblo
+6s
+3r
+4ed
+4ile
+7ly
+6ism
+9s
+7ties
+8y
+5ng
+4pera
+8e
+8l
+9ly
+7ia
+8um
+9ms
+4s
+2ff
+4ball
+8s
+5ird
+8s
+4ed
+5r
+6ies
+6s
+6y
+4ier
+6st
+5ly
+5n
+6ess
+9es
+6g
+7ly
+7s
+6s
+4s
+4taloonas
+4y
+3taloon
+9ies
+9s
+2g
+3aree
+7s
+3garee
+8s
+4ed
+5ries
+6y
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+7s
+5sh
+4le
+6d
+6s
+5ing
+4ree
+7s
+5ies
+5y
+4y
+3h
+3il
+5ism
+8s
+7t
+8ic
+9cal
+9cally
+8s
+5s
+3mark
+7s
+3nacious
+9sly
+9sness
+7ties
+8y
+3ree
+6s
+3s
+2h
+3a
+4s
+2ir
+4er
+5st
+4tith
+8s
+3sne
+6s
+5y
+4sance
+9s
+7t
+8ly
+6unce
+9es
+8t
+2ja
+4h
+5s
+4ri
+6s
+4s
+2ka
+4s
+4tea
+7s
+3e
+4d
+4ko
+6s
+4r
+5s
+4s
+4y
+3ier
+5st
+4ng
+3ka
+3u
+4s
+3y
+2l
+3a
+4o
+5s
+4s
+3chritude
+9des
+9dinous
+3dron
+7s
+3e
+4d
+4r
+5s
+4s
+3i
+4cene
+5ide
+8s
+4er
+5st
+4k
+4ng
+6ly
+6s
+4s
+3k
+4a
+5s
+4ha
+6s
+4s
+3l
+4back
+8s
+4ed
+5r
+6s
+5t
+6s
+5y
+6ed
+6ing
+6s
+4i
+5ng
+4man
+7s
+4orum
+5ut
+7s
+5ver
+8s
+4s
+4ulate
+9d
+9s
+8ing
+9on
+9ons
+5p
+6s
+5s
+3mo
+5branch
+9chiate
+9chs
+5nary
+7te
+9s
+6es
+6ic
+8s
+5tor
+8s
+3p
+4al
+6ly
+4board
+9s
+4ed
+5r
+6s
+4ier
+6st
+5fied
+8s
+6y
+7ing
+5ly
+5ness
+9es
+6g
+5t
+6al
+6ed
+7er
+9s
+7r
+8s
+6ries
+7y
+6s
+6um
+8s
+4less
+4mill
+8s
+4ous
+4s
+5tone
+9s
+4wood
+8s
+4y
+3que
+6s
+3s
+4ant
+5r
+6s
+5tance
+9es
+6e
+7d
+7s
+6ile
+8ities
+9ty
+8la
+9as
+7ng
+7on
+9s
+7ve
+9ly
+6or
+8s
+8y
+4e
+5d
+5jet
+8s
+5less
+9ness
+9nesses
+5r
+6s
+5s
+4idge
+8s
+5fic
+5meter
+9rs
+5ng
+5on
+7s
+4ojet
+8s
+5meter
+9rs
+3taceous
+5n
+6s
+4on
+6s
+5on
+7s
+4rusion
+9ns
+4un
+6s
+5re
+7s
+3u
+4s
+3ver
+6able
+7tion
+9ons
+6ed
+6ine
+9s
+8g
+7sable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ous
+6s
+6ulence
+9nces
+9nt
+4il
+6io
+8s
+7sed
+7zed
+6lar
+7e
+8d
+8s
+7i
+8form
+8ng
+8o
+9s
+7us
+6s
+5nar
+8s
+7te
+9d
+6i
+6ule
+9s
+7s
+3war
+6s
+3y
+2ma
+4s
+3elo
+6s
+3icate
+8d
+8s
+7ing
+5e
+6d
+6ous
+6r
+7s
+6s
+5ing
+6te
+8s
+4e
+5s
+3mel
+6ed
+6ing
+6led
+7ing
+6o
+7s
+6s
+3p
+4ed
+5r
+6nickel
+9kels
+6s
+4hood
+8s
+4ing
+7s
+5on
+7s
+4kin
+7g
+8s
+7s
+8eed
+9eds
+4less
+5ike
+4s
+3y
+2n
+3a
+4ani
+6y
+4lua
+7n
+7s
+4ni
+4s
+3ce
+5d
+5s
+4h
+5bag
+8s
+7ll
+9s
+6oard
+9ds
+7wl
+9s
+5ed
+6on
+8s
+6r
+7s
+6s
+5ier
+7st
+6ly
+6nello
+9loes
+9los
+8ss
+9ses
+7g
+5less
+6ine
+9s
+5y
+4ing
+4ta
+6te
+8d
+7ion
+9ns
+7or
+9s
+5ilio
+9s
+9us
+9usly
+9usness
+5o
+6s
+5ual
+8ist
+9sts
+9ties
+9ty
+8ly
+7te
+9d
+9s
+8ing
+9on
+9onist
+9onists
+9ons
+9ve
+8or
+9rs
+6late
+9ed
+9ion
+9ions
+7e
+8s
+6m
+6rable
+8tion
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+3digrion
+9ns
+5t
+6ic
+6ries
+7y
+6s
+4onor
+8es
+3g
+4a
+5s
+4ence
+8s
+7ies
+7y
+6t
+7ly
+4le
+6d
+6s
+5ing
+4s
+3icaceous
+4er
+5st
+4ly
+4ness
+8es
+4sh
+6abilities
+9lity
+8le
+6ed
+7r
+8s
+7s
+6ing
+9ly
+6ment
+9ts
+4tion
+8s
+6ve
+8ly
+8ness
+9esses
+5ory
+3ji
+5s
+3k
+4a
+5h
+6s
+5s
+4er
+6s
+5st
+5y
+6s
+4ie
+6r
+6s
+7t
+5n
+6ess
+9es
+6s
+5sh
+4s
+4y
+3ned
+5r
+6s
+5t
+6s
+4ier
+6st
+5ng
+7ly
+7s
+4y
+3s
+4ter
+7s
+3t
+4ed
+5e
+6s
+5r
+6s
+4ies
+5ng
+4o
+5s
+4s
+5man
+6en
+4y
+3y
+2p
+3a
+4e
+4l
+4ria
+7l
+6um
+4s
+4te
+6d
+6s
+5ing
+6on
+8s
+3fish
+7es
+3igerous
+4l
+5abilities
+9ity
+6ge
+8s
+6r
+7ities
+9y
+7y
+5lage
+9s
+7r
+8ities
+9ty
+8y
+7te
+5s
+6hip
+9s
+4parous
+3ped
+5t
+6eer
+9ed
+9ing
+9s
+6like
+6ries
+7y
+6s
+4ied
+6s
+5ng
+4odum
+8s
+4y
+5dom
+8s
+5hood
+9s
+5ing
+6sh
+7m
+8s
+5like
+3s
+3u
+4nha
+7s
+4s
+2r
+3ana
+6s
+5ic
+3blind
+8ly
+8ness
+9esses
+3chasability
+9le
+7e
+8d
+8r
+9s
+8s
+7ing
+9gs
+3da
+5h
+6ed
+6s
+5s
+4onium
+9s
+3e
+4blood
+9s
+5red
+8s
+4d
+4e
+5d
+5ing
+5s
+4ly
+4ness
+8es
+4r
+4s
+5t
+3fle
+6d
+6r
+7s
+6s
+5ing
+8s
+5y
+3gation
+9s
+7ve
+9ly
+9s
+6orial
+9ally
+9an
+9es
+8y
+4e
+5able
+5d
+5r
+6s
+5s
+4ing
+7s
+3i
+4fication
+9ions
+9ive
+9or
+9ors
+9ory
+6ed
+7r
+8s
+7s
+5y
+6ing
+4n
+5e
+6s
+5g
+5s
+4ri
+6s
+4s
+5m
+6s
+5t
+6ic
+8al
+9lly
+6s
+4tan
+7ic
+9al
+9ally
+9alness
+8se
+9ed
+9es
+9ing
+9m
+9ms
+8ze
+9ed
+9es
+9ing
+7s
+5ies
+5y
+3l
+4ed
+5r
+6s
+4icue
+8d
+8s
+7ing
+5eu
+7s
+5n
+6e
+7s
+6g
+7s
+6s
+4oin
+7ed
+8r
+9s
+7ing
+7s
+4s
+3omycin
+9s
+3pie
+6s
+4le
+6d
+6heart
+9rts
+6ness
+9ses
+6r
+6s
+7t
+5ier
+7st
+6ng
+6sh
+5y
+4ort
+7ed
+9ly
+7ing
+7less
+7s
+5se
+7d
+7ful
+9lly
+9lness
+7less
+9ssly
+9ssness
+8y
+7s
+6ing
+7ve
+9ly
+9ness
+9nesses
+4resture
+9res
+4ura
+7s
+6e
+7al
+7s
+6ic
+7n
+8s
+4y
+3r
+4ed
+4ing
+7ly
+7s
+4s
+3s
+4e
+5d
+5ful
+8s
+5like
+5r
+6s
+7hip
+9ps
+5s
+5w
+6ed
+6ing
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4lain
+8s
+6ne
+8s
+4uable
+6l
+7s
+6nce
+9s
+7t
+8ly
+5e
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+6t
+7s
+6vant
+9ts
+4y
+3tenance
+9es
+4ier
+6st
+4raid
+6yd
+4y
+3ulence
+9s
+8ies
+8y
+7t
+8ly
+3vey
+6ance
+9es
+6ed
+6ing
+6or
+8s
+6s
+4iew
+7s
+2s
+3chkinia
+9as
+3es
+3h
+4back
+6ll
+8s
+5ike
+8s
+4cart
+8s
+5hair
+9s
+4down
+8s
+4ed
+5r
+6s
+5s
+4ful
+7ly
+7ness
+9sses
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7ly
+7ness
+9sses
+4over
+8s
+4pin
+7s
+6t
+7s
+4rod
+7s
+4up
+6s
+4y
+3illanimities
+9mity
+9mous
+9mously
+3le
+5d
+5s
+5y
+6s
+4ike
+5ng
+3s
+4el
+6s
+5r
+6s
+5s
+4ier
+6st
+4ley
+7s
+5ies
+6ke
+5y
+4ycat
+8s
+5foot
+9ed
+9er
+9ers
+9ing
+9s
+5toes
+3tulant
+9s
+7r
+7te
+9d
+9s
+8ing
+9on
+9ons
+6e
+7d
+7s
+6ous
+2t
+3amen
+5ina
+4ngitangi
+9ngis
+4tive
+8ly
+3cheon
+8s
+6r
+7s
+5ock
+8s
+5uk
+7s
+3down
+7s
+3eal
+6s
+4li
+6s
+3id
+3lock
+7s
+5g
+6s
+3off
+6s
+4is
+4n
+5ghua
+9s
+5s
+4ut
+6s
+3refacient
+8tion
+9ions
+9ive
+6iable
+7ed
+8r
+9s
+8s
+6y
+7ing
+5scence
+9ces
+9t
+7ibility
+9le
+9les
+8ne
+9es
+4id
+6er
+7st
+6ities
+8y
+6ly
+6ness
+9ses
+3s
+4ch
+6es
+6ist
+9s
+3t
+4ed
+5e
+6s
+5n
+5r
+6ed
+7r
+8s
+6ing
+6s
+4i
+5e
+6d
+6r
+7s
+6s
+5ng
+7s
+4o
+5ck
+7s
+4s
+4y
+5ing
+5less
+6ike
+5root
+9s
+3ure
+6s
+3z
+4ed
+5s
+4ing
+2y
+3s
+2zel
+5s
+3zel
+6s
+4le
+6d
+7ly
+7om
+9s
+6headed
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+4olana
+9s
+1ya
+3emia
+7s
+6c
+3s
+3t
+4s
+2cnic
+5dia
+8l
+7ospore
+9pores
+7um
+5te
+7s
+4oconidia
+9dium
+5dysostoses
+9stosis
+5gonid
+9ds
+8oid
+5meter
+9rs
+8ric
+5n
+6s
+5ses
+6is
+6pore
+9es
+6tyle
+9es
+5tic
+2e
+3bald
+7s
+3ing
+3litic
+7s
+8es
+4ogram
+9s
+8phic
+9hies
+9hy
+5nephritic
+9ritis
+3mia
+6s
+5c
+3ngadu
+8s
+3s
+3t
+4s
+2gal
+5s
+4rg
+6s
+3idia
+7l
+6um
+8s
+3maean
+4ean
+4ies
+4oid
+4y
+5ish
+7m
+8s
+3ostyle
+9s
+2ic
+3n
+4kado
+8s
+4s
+2jama
+6ed
+6s
+2knic
+6s
+4odysostoses
+9stosis
+5meter
+9rs
+5ses
+6is
+6ome
+9s
+5tic
+2lon
+5s
+4rectomies
+9my
+5i
+6c
+5us
+7es
+2ne
+4d
+4s
+3ing
+2oderma
+8s
+7ic
+3geneses
+8is
+6ic
+3id
+3ner
+6s
+4ings
+3rrhea
+8l
+8s
+7ic
+6oea
+9l
+9s
+8ic
+3ses
+4is
+3t
+4s
+2racanth
+9a
+9as
+9s
+4l
+5id
+7id
+9s
+7s
+6s
+7es
+4mid
+7al
+9ly
+7ed
+8s
+7ia
+8c
+9al
+9ally
+8ng
+8on
+9ns
+8st
+9ts
+7ologies
+9ogist
+9ogists
+9ogy
+8n
+9s
+7s
+6s
+7es
+4n
+5oid
+6meter
+9ers
+6se
+8s
+7ide
+9es
+5s
+4rgyrite
+9tes
+4zole
+8s
+3e
+4ne
+6ite
+9s
+6s
+5ocarp
+9ps
+6id
+8s
+6mycetous
+4s
+4thrin
+9s
+7oid
+9ds
+7um
+9s
+5ic
+5ologies
+9y
+6therapies
+9rapy
+4x
+5es
+5ia
+7l
+7s
+6c
+3geometer
+9ers
+3heliometer
+9eters
+9etric
+3ic
+4dic
+6ne
+8s
+5oxal
+9s
+8mine
+9ines
+7in
+9e
+9es
+9s
+4form
+4methamine
+9mines
+5idine
+9es
+4te
+6s
+5hiamine
+9ines
+5ic
+7al
+6ferous
+6se
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5ohedra
+9ral
+9ron
+6us
+3o
+4ballogies
+9gy
+4catechin
+9hins
+9hol
+9hols
+5eram
+9s
+5hemical
+9cally
+5last
+9ic
+9ics
+9s
+4electric
+9ricity
+9rics
+4gallate
+9tes
+8ic
+8ol
+9ls
+5en
+7etic
+7ic
+9ities
+9ity
+7ous
+7s
+5nostic
+9ics
+5rapher
+9ers
+9ic
+9ies
+9y
+7vure
+9res
+4kineses
+9is
+4la
+6s
+6ter
+9s
+7ries
+8y
+5igneous
+8ic
+6se
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5ogies
+7y
+5usite
+9es
+5ysable
+8te
+9es
+7e
+8d
+8r
+9s
+8s
+7ing
+8s
+6tic
+9ally
+6zable
+8te
+9es
+7e
+8d
+8r
+9s
+8s
+7ing
+4magnetic
+6ncer
+9rs
+8ies
+8y
+7ia
+9c
+9cal
+9cs
+9s
+7tic
+5eride
+9es
+6tallurgy
+7er
+9s
+7ric
+9cal
+9cally
+9es
+8y
+5orphite
+9ites
+4ne
+6s
+5ine
+8s
+7ophilic
+4pe
+6s
+5hobia
+9as
+9c
+9cs
+7ne
+9s
+7ric
+8ous
+8us
+9ses
+7sphate
+9hates
+9horic
+7tograph
+9graphs
+9graphy
+9meter
+9meters
+9metry
+6yllite
+9ites
+5us
+7es
+4s
+5cope
+9s
+5es
+5is
+7es
+5ome
+8s
+5tat
+8ic
+8s
+5ulphate
+9ates
+9uric
+4tartrate
+9ates
+5echnic
+9ical
+9ically
+9ician
+9icians
+9ics
+9ies
+9ist
+9ists
+9y
+4vanadic
+4xene
+8s
+7ic
+8te
+9es
+9ic
+7oid
+9ds
+5yle
+8s
+7ic
+8n
+9e
+9es
+9s
+3rhic
+7ist
+9ts
+7s
+5otine
+9es
+8te
+9es
+6us
+5uloxia
+9ias
+4ol
+6e
+7s
+6ic
+7dine
+9nes
+6s
+3uvate
+8s
+5ic
+2thium
+7s
+4ogenic
+5n
+6ess
+9es
+6ic
+6omorph
+9rphs
+6s
+2uria
+6s
+2x
+3ed
+4s
+3ides
+5ia
+6um
+4e
+5s
+4ng
+4s
+1zazz
+5es
+0qabala
+6h
+7s
+6s
+5ism
+8s
+7t
+8ic
+8s
+2di
+4s
+2id
+4s
+3maqam
+8s
+2lamdan
+8s
+2nat
+5s
+2sida
+6s
+2t
+3s
+2wwal
+6i
+7s
+6s
+1i
+2bla
+5s
+2gong
+6s
+2n
+3dar
+6ka
+6s
+3ghaosu
+9s
+3s
+3tar
+6ka
+6s
+2s
+2viut
+6s
+1oph
+4s
+2rma
+5s
+1ua
+3alude
+8s
+3ck
+5ed
+6r
+7ies
+7s
+7y
+5ier
+7st
+6ng
+6sh
+7m
+8s
+5le
+7d
+7s
+6ing
+5s
+6alver
+9ers
+9ing
+5y
+3d
+4ded
+5ing
+4play
+8s
+6ex
+8es
+4ragenarian
+9arians
+8simal
+6ngle
+9es
+8ular
+9larly
+7s
+7t
+8al
+8es
+8s
+6phonic
+9nics
+9nies
+9ny
+7legia
+9gias
+9gic
+9gics
+6t
+7e
+8d
+8s
+7ic
+9al
+9ally
+9s
+8ng
+7rix
+9xes
+7s
+7ura
+9e
+9es
+8s
+9es
+5ella
+9s
+6nnia
+9al
+9ally
+9als
+9um
+9ums
+5ic
+7ep
+9s
+9ses
+7ipital
+7one
+9es
+7s
+6ennia
+9ial
+9ium
+6farious
+7id
+7oliate
+8rm
+6ga
+8e
+8s
+7eminal
+9inate
+9inous
+6lateral
+9erals
+7ingual
+8teral
+9erals
+7le
+9d
+9r
+9rs
+9s
+8ing
+9on
+9ons
+9onth
+9onths
+7ocular
+6ngenaries
+9nary
+7omial
+9ials
+6partite
+9tition
+7honic
+9nics
+7legia
+9gias
+9gic
+9gics
+7ole
+9es
+6reme
+9es
+6sect
+9ted
+9ting
+9tion
+9tions
+9ts
+7yllabic
+9lable
+9lables
+6valence
+9ences
+9encies
+9ency
+9ent
+9ents
+7ia
+9l
+8um
+9ms
+5oon
+8s
+6phonic
+9nics
+9nies
+9ny
+5uman
+9e
+9es
+9ous
+9s
+7vir
+9rate
+9rates
+9rs
+6ped
+9al
+9s
+7le
+9d
+9s
+9t
+9ts
+9x
+9xed
+9xes
+9xing
+8icate
+9cated
+9cates
+9cating
+9cation
+9cities
+9city
+9es
+9ng
+8y
+7ole
+9es
+4s
+3ere
+6d
+6ing
+6s
+5itur
+4situm
+9s
+5tionaries
+9ary
+6or
+8ial
+8s
+9hip
+9hips
+6uaries
+9y
+3ff
+5able
+5ed
+6r
+7s
+5ing
+5s
+3g
+4ga
+6s
+5ier
+7st
+6ness
+9ses
+5y
+4mire
+8d
+8s
+7ier
+9st
+8ng
+7y
+4s
+3haug
+7s
+4og
+6s
+3i
+4ch
+6es
+6s
+4gh
+6s
+4l
+5ed
+5ing
+8s
+5s
+4nt
+6er
+7st
+6ly
+6ness
+9ses
+4r
+5s
+4s
+3ke
+5d
+5r
+6s
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7ly
+7s
+4y
+3le
+4ia
+5fiable
+7cation
+9tions
+9tive
+9tives
+9tor
+9tors
+9tory
+7ed
+9ly
+8r
+9s
+8s
+6y
+7ing
+9gs
+5tative
+9vely
+6ied
+8s
+6y
+4m
+5ier
+7st
+6ng
+6sh
+8ly
+8ness
+9esses
+5less
+5s
+5y
+3mash
+7es
+3ndang
+8s
+6ries
+7y
+5ong
+8s
+4go
+6cracies
+9cy
+6s
+4net
+7s
+4t
+5a
+6l
+7ly
+5ed
+5ic
+7al
+7s
+6fiable
+8cation
+9ations
+8ed
+9r
+9rs
+9s
+7y
+8ing
+6le
+8s
+6ng
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+6tate
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9ively
+7ies
+8ve
+9ely
+7y
+6valence
+9ences
+9ent
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5ometer
+9ers
+6ng
+8s
+5s
+5um
+7s
+3quaversal
+9sally
+3rantine
+9ed
+9es
+9ing
+4e
+5nden
+9s
+8r
+9s
+5r
+5st
+4k
+5s
+4rel
+7ed
+8r
+9s
+7ing
+7led
+9r
+9rs
+8ing
+9ngs
+8ous
+7s
+8ome
+9mely
+9meness
+6nder
+9rs
+5iable
+7n
+8s
+6ed
+7r
+8s
+7s
+6ngton
+9ons
+6on
+8s
+5y
+6ing
+9s
+6man
+8ster
+9ters
+7en
+4t
+5an
+7s
+6tion
+9ns
+5e
+6r
+7age
+9es
+7back
+9cked
+9cking
+9ckings
+9cks
+7deck
+9cker
+9ckers
+9cks
+7ed
+8r
+9s
+7final
+9nalist
+9nals
+7ing
+9gs
+7lies
+9fe
+9ght
+9ghts
+8y
+7master
+9sters
+8istress
+7n
+8s
+7oon
+9ns
+7s
+8aw
+9wed
+9wing
+9wn
+9ws
+8taff
+9affs
+9aves
+6s
+6t
+7s
+7t
+8e
+9s
+8i
+8o
+8s
+5ic
+7s
+6er
+8s
+6le
+8s
+5o
+6deciman
+9imans
+6s
+5s
+5z
+6es
+6ier
+8st
+7ferous
+7te
+9s
+8ic
+6ose
+7us
+6y
+3sar
+6s
+4h
+5ed
+6e
+7s
+6r
+7s
+6s
+5ie
+7s
+6ng
+4i
+5crystal
+9tals
+5particle
+9icles
+6eriodic
+4s
+5es
+5ia
+7s
+6n
+7s
+3t
+4ch
+6ed
+7s
+6ing
+4e
+5rcentenary
+6naries
+9y
+8te
+7ion
+9nist
+9nists
+9ns
+8ties
+9y
+4orzain
+9ns
+7e
+8s
+4rain
+8s
+5e
+6feuille
+9illes
+7oil
+9ls
+6s
+4s
+4trocentism
+9ntisms
+9ntist
+9ntists
+9nto
+9ntos
+3ver
+6ed
+7r
+8s
+6ier
+8st
+7ng
+9ly
+9s
+6s
+6y
+3y
+4age
+7s
+4d
+4like
+4s
+5ide
+8s
+3zzier
+7st
+5y
+2bit
+5s
+3yte
+6s
+2each
+6es
+6ier
+8st
+6y
+4n
+5s
+4sier
+7st
+6ly
+6ness
+9ses
+5y
+4zier
+7st
+5y
+3bec
+6s
+4racho
+9s
+3echier
+8st
+6y
+4n
+5cake
+9s
+6raft
+9ts
+5dom
+8s
+5ed
+5fish
+9es
+5hood
+9s
+5ie
+7r
+7s
+8t
+6ng
+8s
+6te
+8s
+5less
+7t
+8s
+6ier
+8st
+7ness
+9sses
+6y
+5s
+6hip
+9s
+6ide
+9s
+5y
+4r
+5dom
+8s
+5ed
+6r
+6st
+5ing
+6sh
+6ties
+7y
+5ly
+5ness
+9es
+5s
+4st
+6s
+3int
+3lch
+6ed
+7s
+6ing
+4ea
+6s
+4l
+5able
+5ed
+6r
+7s
+5ing
+5s
+4quechose
+9oses
+3me
+5d
+5s
+4ing
+3na
+5s
+4ch
+6able
+6ed
+7r
+8s
+7s
+6ing
+9s
+6less
+9sly
+4elle
+8s
+3p
+3rcetic
+8n
+9s
+7um
+9s
+5ine
+6tin
+9s
+7ron
+9ns
+4ida
+7s
+5ed
+6r
+7s
+6s
+5monies
+9ous
+9ously
+8y
+5st
+7s
+4n
+5s
+6tone
+9es
+4sprung
+9gs
+4ulous
+9ly
+9ness
+9nesses
+4y
+5ing
+8ly
+8s
+3sadilla
+9as
+4t
+5ant
+8s
+5ed
+6r
+7s
+5ing
+8ly
+8s
+6on
+8ability
+9ble
+9bly
+9ries
+9ry
+8ed
+9e
+9es
+9r
+9rs
+8ing
+9ngly
+9ngs
+9st
+9sts
+8less
+9essly
+8naire
+9aires
+8s
+5or
+7ial
+7s
+8hip
+9ips
+5rist
+9s
+5s
+3tch
+6ed
+7s
+6ing
+4he
+6s
+5ing
+4sch
+7es
+4zal
+7es
+7s
+3ue
+5d
+5ing
+8s
+5r
+6s
+5s
+4ing
+7s
+3y
+4n
+5ie
+7s
+5s
+4s
+3zal
+6es
+6s
+2ibble
+7d
+7r
+8s
+7s
+6ing
+9ly
+9s
+4lin
+7s
+3ch
+5e
+6d
+6s
+5ing
+4k
+5beam
+9s
+5en
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6r
+6st
+5ie
+7s
+5lime
+9s
+6y
+5ness
+9es
+5s
+6and
+9s
+6et
+8s
+6ilver
+9ered
+9ering
+9erings
+9erish
+9ers
+9ery
+6tep
+9ped
+9ping
+9s
+5thorn
+9ns
+5y
+3d
+4am
+6s
+4danies
+7y
+5it
+7ative
+7ch
+9es
+7ies
+7s
+7y
+5le
+7d
+7r
+8s
+7s
+6ing
+4nunc
+8s
+4s
+3esce
+7d
+7nce
+9es
+9ies
+9y
+8t
+9ly
+7s
+6ing
+4t
+5ed
+6n
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6r
+7s
+6st
+5ing
+8s
+6sm
+8s
+7t
+8ic
+8s
+6ve
+8s
+5ly
+5ness
+9es
+5s
+6ome
+5ude
+8s
+6s
+7es
+3ff
+5s
+3ght
+6ed
+6ing
+6s
+3ll
+5ai
+7a
+8s
+7s
+6ja
+8s
+5back
+9s
+5ed
+6t
+7s
+5ing
+8s
+5man
+6en
+5on
+7s
+5s
+5work
+9s
+8t
+9s
+4t
+5ed
+6r
+7s
+5ing
+8s
+5s
+3n
+4a
+5crine
+9es
+5quina
+9as
+5ries
+6y
+5s
+5te
+4ce
+6ntenaries
+9nary
+9nnial
+9nnials
+6s
+5he
+7d
+7s
+6ing
+5uncial
+9ally
+7x
+8es
+8ial
+4decagon
+9ons
+8plet
+9lets
+7ennial
+9nials
+7illion
+9lions
+4e
+5la
+7s
+6la
+8s
+5s
+4gentenaries
+9nary
+4ic
+5dine
+9s
+5e
+6la
+8s
+6s
+5n
+6a
+7s
+6e
+7s
+6s
+4nat
+7s
+4o
+5a
+6s
+5id
+7al
+7s
+5l
+6in
+8e
+9s
+8s
+6one
+9s
+6s
+5ne
+7s
+6oid
+5s
+4quagenarian
+9simal
+6ecostate
+7farious
+8oliate
+7nnia
+9iad
+9iads
+9ial
+9ially
+9ials
+9ium
+9iums
+7partite
+7reme
+9mes
+7valence
+9lences
+9lency
+9lent
+6ina
+9s
+7valent
+4s
+5ied
+7s
+5y
+4t
+5a
+6in
+8s
+6l
+7s
+6n
+7s
+6r
+7s
+6s
+5e
+6s
+7sence
+9nces
+9ntial
+6t
+7s
+7t
+8e
+9s
+8i
+8o
+8s
+5ic
+7s
+6le
+8s
+7lion
+9ons
+9onth
+9onths
+6n
+7s
+5roon
+9s
+5s
+5uple
+9d
+9s
+9t
+9ts
+8icate
+9cated
+9cates
+9cating
+9cation
+9ng
+8y
+4ze
+6s
+3p
+4o
+5s
+4ped
+6r
+7s
+5ier
+7st
+6ng
+6sh
+5u
+6s
+5y
+4s
+5ter
+8s
+4u
+5s
+3re
+5d
+5s
+4ing
+5ster
+9s
+4k
+5ed
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+6sh
+5s
+5y
+4t
+5ed
+5ing
+5s
+3sling
+8ism
+9sms
+8s
+4t
+5s
+3t
+4ch
+6ed
+7s
+6ing
+5laim
+9ed
+9ing
+9s
+4e
+5d
+5s
+4ing
+4rent
+8s
+4s
+4tal
+7s
+6nce
+9d
+9s
+8ing
+5ed
+6r
+7s
+5ing
+5or
+7s
+3ver
+6ed
+7r
+8s
+6ful
+9s
+6ier
+8st
+7ng
+9ly
+9s
+7sh
+6s
+6y
+3xote
+7s
+6ic
+8al
+9lly
+7sm
+9s
+6ries
+7y
+3z
+4master
+9rs
+4zed
+6r
+7ies
+7s
+7y
+6s
+5ical
+9ities
+9ity
+9ly
+6fication
+9ations
+8ed
+9s
+7y
+8ing
+6ness
+9ses
+7g
+8s
+2oad
+3d
+4ded
+5ing
+4libet
+9arian
+9arians
+9ic
+9ical
+9ically
+9s
+6n
+7s
+4s
+3hog
+6s
+3if
+5ed
+5ing
+5s
+4n
+5ed
+5ing
+8s
+5s
+4st
+6s
+4t
+5ed
+6r
+7s
+5ing
+5s
+3kka
+6s
+3ll
+5s
+3modo
+7s
+3ndam
+4k
+5ed
+5ing
+5s
+3oke
+3p
+4ped
+5ing
+4s
+3rate
+4um
+6s
+3ta
+5bilities
+9ty
+6le
+8ness
+9esses
+7y
+5s
+5tion
+9s
+8us
+7ve
+4e
+5d
+5r
+6s
+5s
+5worthy
+4h
+5a
+4idian
+9s
+5ent
+8s
+5ng
+5tion
+9s
+4um
+6s
+2rsh
+5es
+3ush
+6es
+2yte
+5d
+5s
+4ing
+1werties
+5y
+6s
+0rabanna
+7s
+4t
+5ine
+8s
+5ment
+9s
+5o
+6es
+6s
+5s
+5te
+7d
+7ment
+9nts
+7s
+6ing
+9s
+3bet
+6ed
+6ing
+6s
+4i
+5es
+5n
+6ate
+9s
+6ic
+8al
+9lly
+8s
+7sm
+9s
+8t
+9ic
+9s
+7te
+9s
+6s
+5s
+5t
+6brush
+9shes
+6ed
+7r
+8s
+6fish
+9hes
+6ing
+9s
+6o
+7h
+8s
+7s
+6ries
+7y
+6s
+6y
+4le
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8s
+4oni
+7s
+3i
+4c
+4d
+5er
+6st
+5ities
+7y
+5ly
+5ness
+9es
+4es
+5tic
+4s
+2ca
+4hout
+8s
+3cahout
+9s
+4oon
+7s
+3e
+4able
+4card
+8s
+5ourse
+9es
+4d
+4goer
+8s
+6ing
+9s
+4horse
+9s
+4mate
+8s
+7ion
+9ns
+5e
+6d
+6s
+5ic
+6sation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5oid
+6se
+8ly
+6us
+8ly
+4path
+8s
+4r
+5s
+4s
+4track
+9er
+9ers
+9s
+4walk
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+6y
+7s
+3h
+4e
+5s
+5t
+6ed
+6ing
+6s
+4ial
+5des
+6ial
+8n
+5lla
+8e
+8s
+5otomies
+9y
+5s
+6chises
+9sis
+6es
+5tic
+7des
+7s
+8es
+3ial
+6ise
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7ze
+9d
+9s
+8ing
+6ly
+5tion
+9s
+4er
+5st
+4ly
+4ness
+8es
+5g
+6s
+5o
+6s
+4sm
+6s
+5t
+6s
+3k
+4abones
+4ed
+5r
+6s
+5t
+6ed
+7er
+9ed
+9ing
+9ings
+9s
+7r
+8s
+6ier
+8st
+7ng
+6ries
+7y
+6s
+6t
+7s
+6y
+4ful
+7s
+4ing
+7ly
+7s
+4le
+4s
+4work
+8s
+3lette
+8s
+4oir
+7s
+3on
+5s
+5teur
+9ing
+9ings
+9s
+8se
+9es
+4on
+6s
+3quet
+7ball
+9lls
+7ed
+7ing
+7s
+3y
+2d
+3ar
+5s
+6cope
+9es
+3ded
+5r
+5st
+4ing
+4le
+6d
+6man
+7en
+6s
+5ing
+4ocke
+8s
+3e
+3ge
+5r
+5s
+6t
+3iable
+5l
+6e
+6ia
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+6s
+5n
+6ce
+8s
+7ies
+7y
+6s
+6t
+7ly
+7s
+5ta
+7s
+6e
+7d
+7ly
+7s
+6ing
+7on
+9al
+9less
+9s
+7ve
+6or
+8s
+8y
+4cal
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9tic
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7ness
+9sses
+7s
+6nd
+8s
+7t
+6te
+8d
+8s
+7ing
+8on
+9ns
+5chio
+9s
+5el
+7lose
+7s
+6s
+5icolous
+6form
+6vorous
+5le
+7s
+5ular
+7e
+8s
+7ose
+4esthesia
+9sias
+9sist
+9sists
+9tic
+4i
+4o
+5activate
+9vated
+9vates
+9vating
+9vation
+9ve
+9vely
+9vities
+9vity
+6utograph
+9graphs
+9graphy
+5biologic
+9ogical
+9ogies
+9ogist
+9ogists
+9ogy
+5carbon
+9ons
+6hemical
+9ically
+9ist
+9istry
+9ists
+5ecologies
+9ogy
+6d
+6lement
+9ents
+5genic
+6old
+9s
+7niometer
+6ram
+9s
+8ph
+9hed
+9her
+9hers
+9hic
+9hies
+9hing
+9hs
+9hy
+5ing
+6odine
+9nes
+6sotope
+9opes
+9opic
+5label
+9led
+9ling
+9lled
+9lling
+9ls
+7rian
+9ans
+6ocation
+9tional
+9tions
+7gic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+6ucencies
+9ncy
+9nt
+6yses
+8is
+7tic
+5man
+6en
+7ter
+9rs
+8ric
+9ically
+9ies
+9y
+6icrometer
+7metic
+5nics
+6uclide
+9ides
+5pacities
+9ty
+7ger
+9rs
+8ing
+9ngs
+7que
+6hone
+9es
+9ic
+9ically
+9ics
+9ies
+9ist
+9ists
+9y
+8sphorus
+8to
+9os
+6rotection
+9ective
+5resistant
+5s
+6cope
+9es
+9ic
+9ically
+9ies
+9y
+6ensitise
+9itised
+9itises
+9itive
+9itize
+9itized
+9itizes
+6onde
+9es
+6trontium
+9ntiums
+5telegram
+9grams
+9graph
+9graphs
+9graphy
+9meter
+9meters
+9metric
+9metry
+9phone
+9phones
+9phonic
+9phony
+9type
+9types
+6herapies
+9apist
+9apists
+9apy
+9mies
+9my
+7on
+9s
+8rium
+9iums
+6oxic
+6racer
+9ers
+4sh
+6es
+4um
+6s
+5s
+6es
+4x
+5es
+3ome
+6s
+4n
+5s
+3s
+3ula
+6e
+6r
+6s
+6te
+5iform
+3waste
+8s
+2fale
+6s
+3f
+4ia
+6s
+5nate
+9s
+6ose
+9s
+5sh
+7ly
+7ness
+9sses
+4le
+6d
+6r
+7s
+6s
+7ia
+9s
+5ing
+4s
+3t
+4ed
+5r
+6ed
+6ing
+9s
+6s
+4ing
+7s
+4man
+5en
+4s
+5man
+6en
+2g
+3a
+4muffin
+9ns
+4s
+3bag
+6s
+4olt
+7s
+3de
+3e
+4d
+4e
+5s
+4ful
+4r
+5s
+4s
+3g
+4a
+5muffin
+9ins
+5s
+4ed
+6er
+7st
+6ier
+8st
+6ly
+6ness
+9ses
+6y
+5e
+6s
+5ries
+6y
+4ier
+6s
+7t
+5ng
+7s
+4le
+6d
+6s
+5ing
+4s
+4y
+3i
+4ng
+6ly
+6s
+5i
+6s
+4s
+3lan
+6s
+3man
+6s
+5tical
+4en
+6t
+7s
+3out
+6ed
+6ing
+6s
+3picker
+9s
+3s
+4tone
+8s
+3tag
+6s
+4ime
+7r
+8s
+7s
+4op
+6s
+3u
+4led
+5y
+4s
+3weed
+7s
+4heel
+8s
+4ork
+7s
+6m
+7s
+6t
+7s
+2h
+3ed
+3ing
+3s
+3ui
+5s
+2i
+3a
+4s
+3d
+4ed
+5r
+6s
+4ing
+7s
+4s
+3k
+4ed
+4ing
+4s
+3l
+4age
+7s
+4bed
+7s
+5ird
+8s
+5us
+7es
+7ses
+4car
+7d
+8s
+7s
+4e
+5d
+5r
+6s
+5s
+4head
+8s
+4ing
+7ly
+7s
+4leries
+7y
+6ss
+5ies
+5y
+4man
+5en
+4road
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+4s
+4way
+7man
+8en
+7s
+5oman
+7en
+3ment
+7s
+3n
+4band
+8s
+5ird
+8s
+5ow
+7ed
+7like
+7s
+7y
+4check
+9s
+5oat
+8s
+4date
+8s
+5rop
+8s
+4e
+5d
+5s
+4fall
+8s
+5orest
+9ts
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4less
+4maker
+9s
+7ing
+9gs
+4out
+7s
+4proof
+9ed
+9ing
+9s
+4s
+5pout
+9s
+5quall
+9ls
+5torm
+9s
+4tight
+4wash
+8ed
+9s
+8ing
+6ter
+9s
+5ear
+8s
+4y
+3rd
+5s
+3s
+4able
+4e
+5able
+5d
+5r
+6s
+5s
+4in
+6g
+7s
+6s
+6y
+4onne
+8ur
+9rs
+3t
+4a
+5s
+4ed
+4ing
+4s
+3yat
+6s
+6wari
+9is
+2j
+3a
+4h
+5s
+6hip
+9s
+4s
+5hip
+8s
+3es
+3pramukh
+9hs
+2ke
+4d
+4e
+5s
+4hell
+8s
+8y
+4off
+7s
+4r
+5ies
+5s
+5y
+4s
+5hame
+9s
+3i
+4a
+5s
+4ja
+6s
+4ng
+6s
+4s
+5h
+6ly
+6ness
+9ses
+3shas
+7a
+8s
+7es
+3u
+4s
+2le
+4s
+3lentandi
+9do
+9dos
+4ied
+6r
+7s
+6s
+5form
+5ne
+4y
+5cross
+9ses
+5e
+6s
+5ing
+8ly
+8s
+6st
+8s
+3ph
+5ed
+5ing
+5s
+2m
+3ada
+6s
+4kin
+7s
+4l
+4pithecine
+9cines
+4te
+3bla
+6s
+5e
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+4ouillet
+9ets
+4unctious
+9ously
+5tan
+8s
+3cat
+6s
+3eal
+4e
+5s
+4kin
+7s
+4n
+5s
+5ta
+7ceous
+6um
+4ous
+4quin
+8s
+4t
+5s
+3gunshoch
+3i
+4e
+5s
+4fication
+9ions
+6ed
+7s
+5orm
+5y
+6ing
+4lie
+7s
+5lie
+8s
+4n
+5s
+4s
+3jet
+6s
+3med
+5l
+6s
+5r
+6s
+4ier
+6s
+7t
+5ng
+5sh
+7ly
+7ness
+9sses
+4le
+6s
+4y
+3ona
+6s
+4se
+6ly
+5ities
+7y
+4us
+6ly
+3p
+4acious
+5ge
+7d
+7ous
+9sly
+9sness
+7r
+8s
+7s
+6ing
+9s
+5llian
+9ns
+5ncies
+7y
+6t
+7ly
+5rt
+7ed
+7ing
+7s
+5uge
+8d
+8s
+7ing
+4ed
+5r
+6s
+4ick
+7ed
+7s
+5ke
+7s
+5ng
+7s
+5on
+7s
+5re
+7d
+7s
+4ole
+7s
+4s
+5man
+6en
+3rod
+6ded
+7ing
+6s
+3s
+4hackle
+5orn
+8s
+4on
+6s
+4tam
+3til
+6la
+8s
+6s
+3ular
+5i
+5ose
+6us
+5us
+4s
+2n
+3a
+4rian
+6um
+8s
+4s
+3ce
+5d
+5l
+6s
+5s
+4h
+5ed
+6r
+7ia
+9s
+8e
+9s
+7o
+8s
+7s
+6s
+5ing
+8s
+5less
+6ike
+5man
+6en
+5o
+6s
+4id
+6er
+7st
+6ities
+8y
+6ly
+6ness
+9ses
+5ng
+4or
+6ed
+6ous
+9ly
+9ness
+9nesses
+6s
+5ur
+7ed
+7s
+3d
+4an
+6s
+4ed
+5m
+6s
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+4lord
+8s
+4om
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ly
+6ness
+9ses
+6s
+6wise
+5n
+6s
+4s
+4y
+3ee
+5s
+3g
+4a
+5s
+5tira
+9s
+9tanga
+9tangas
+4e
+5d
+5finder
+9ers
+9ing
+9ings
+5land
+9s
+5r
+6s
+7hip
+9ps
+5s
+4i
+5er
+6st
+5ly
+5ness
+9es
+6g
+7s
+5ora
+8s
+5s
+4oli
+7s
+4y
+3i
+4d
+5s
+4form
+4ne
+4s
+4vorous
+3k
+4e
+5d
+5r
+6s
+5s
+6t
+4ing
+7s
+5sh
+6m
+7s
+4le
+6d
+6s
+7s
+5ing
+5y
+4ness
+8es
+4s
+5hift
+9ed
+9ing
+9s
+3pike
+7s
+3sack
+7ed
+8r
+9s
+7ing
+7s
+4el
+6s
+4hackle
+9ed
+9es
+9ing
+6kle
+9d
+9s
+8ing
+4om
+6able
+6ed
+7r
+8s
+6ing
+6less
+6s
+3t
+4ed
+5r
+6ism
+9s
+6s
+4ing
+7ly
+7s
+5pole
+9d
+9s
+8ing
+4s
+3ula
+6r
+6s
+4nculaceous
+8i
+8us
+9ses
+3zel
+6man
+7en
+6s
+2oulia
+7s
+2p
+3acious
+9ly
+9ness
+9nesses
+6ties
+7y
+3eseed
+8s
+3hae
+5nia
+8s
+4e
+5s
+4ia
+6s
+5de
+7s
+5s
+3id
+5er
+6st
+5ities
+7y
+5ly
+5ness
+9es
+5s
+4er
+6ed
+6like
+6s
+4ne
+6s
+5i
+3loch
+7s
+3paree
+8s
+4e
+5d
+5e
+6s
+5l
+6ed
+6ing
+6led
+7ing
+9gs
+6s
+5n
+5r
+6s
+5s
+4ing
+7s
+6i
+4ort
+7age
+9es
+7eur
+9rs
+7s
+4rochement
+9ments
+3s
+4callion
+9ons
+3t
+4atorial
+4ly
+4ness
+8es
+4or
+6ial
+6s
+4ure
+7d
+7less
+7s
+6ing
+7se
+9d
+9s
+8ing
+8t
+9s
+7ze
+9d
+9s
+8ing
+6ous
+9ly
+9ness
+9nesses
+2re
+4bit
+7s
+4d
+4e
+4faction
+9onal
+9ons
+9ve
+5iable
+6cation
+9ional
+9ions
+6ed
+7r
+8s
+7s
+5y
+6ing
+4ly
+4ness
+8es
+4r
+5ipe
+8s
+4s
+5t
+3ified
+7s
+5y
+6ing
+4ng
+4ties
+5y
+3k
+4ed
+4ing
+4s
+2s
+3bora
+7s
+3caille
+9s
+5l
+6dom
+9s
+6ism
+9s
+7ties
+8y
+6liest
+8on
+9ns
+7y
+6s
+5sse
+8s
+4hel
+7s
+3e
+4d
+4r
+5s
+4s
+3h
+4ed
+5r
+6s
+5s
+6t
+4ie
+6s
+5ng
+4like
+5y
+4ness
+8es
+3ing
+3malai
+8s
+3orial
+3p
+4atories
+8y
+4berries
+8y
+4ed
+5r
+6s
+4ier
+6st
+5ness
+9es
+6g
+7ly
+7s
+5sh
+4s
+4y
+3se
+5s
+4le
+6d
+6s
+5ing
+3t
+4a
+5fari
+9an
+9ans
+4er
+6ed
+6ing
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6s
+4rum
+7s
+3ure
+6s
+2t
+3a
+4bilities
+9y
+5le
+7ness
+9sses
+7s
+6y
+4fee
+7s
+5ia
+7s
+4l
+5s
+4n
+5ies
+5s
+5y
+4plan
+8ned
+9ing
+8s
+4s
+4tat
+7s
+5ouille
+9les
+3bag
+6geries
+9y
+6s
+4ite
+3ch
+5ed
+6s
+6t
+7ed
+7ing
+7s
+5ing
+3e
+4abilities
+9ty
+6le
+8ness
+9esses
+7y
+4d
+4en
+6s
+4l
+5s
+4meter
+9s
+4payer
+9s
+4r
+5s
+4s
+3fink
+7s
+5sh
+7es
+3h
+4a
+5s
+4e
+5r
+6est
+6ipe
+9s
+7sh
+5st
+4ole
+7s
+5use
+8s
+4ripe
+8s
+4s
+5keller
+9ers
+3icide
+8s
+4fiable
+6cation
+9ions
+6ed
+7r
+8s
+7s
+5y
+6ing
+4ne
+6s
+5g
+6s
+4o
+5cinate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+9tory
+5n
+6al
+8e
+9s
+8isable
+9sation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9sm
+9sms
+9st
+9stic
+9sts
+9ties
+9ty
+9zable
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8ly
+8ness
+9esses
+8s
+6ed
+6ing
+6s
+5s
+4te
+6s
+3like
+5n
+6e
+7s
+6g
+7s
+6s
+3o
+4o
+5n
+6ed
+7r
+8s
+6ing
+6s
+5s
+4s
+3pack
+7s
+4roof
+3s
+4bane
+8s
+3tail
+7ed
+7s
+5n
+6s
+4ed
+5en
+7s
+5n
+6ed
+7r
+8s
+6ing
+9s
+6s
+5r
+6ies
+6s
+6y
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+5sh
+4le
+6bag
+9s
+7ox
+9es
+7rain
+9ined
+9ins
+6d
+6r
+7s
+6s
+7nake
+9kes
+6trap
+9ps
+5ier
+7st
+6n
+7e
+8s
+7g
+8ly
+8s
+7s
+5y
+4on
+6s
+5on
+7ed
+7ing
+7s
+4rap
+7s
+4y
+3u
+4s
+2ucid
+5ties
+6y
+4le
+6r
+6st
+4ous
+7ly
+7ness
+9sses
+3ght
+3n
+4ch
+6ed
+7s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6y
+4ge
+6d
+6s
+5ing
+4s
+3patu
+7s
+4o
+5s
+3riki
+7s
+3wolfia
+9s
+2v
+3age
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+3e
+4d
+4l
+5ed
+6r
+7s
+5in
+7g
+8s
+7s
+5led
+7r
+8s
+6ing
+9s
+6y
+5ment
+9s
+5s
+4n
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5like
+5ous
+8ly
+8ness
+9esses
+5s
+4r
+5s
+4s
+3igote
+8s
+7te
+9s
+4n
+5e
+6d
+6s
+5g
+6ly
+6s
+5ing
+5s
+4oli
+7s
+4sh
+6ed
+7r
+8s
+7s
+6ing
+9ly
+6ment
+9ts
+3s
+2w
+3aru
+6s
+3bone
+7d
+3er
+4st
+3head
+7s
+4ide
+7d
+7s
+6ing
+3in
+5g
+6s
+5s
+6onde
+9es
+4sh
+3ly
+3maish
+8es
+3n
+4ess
+7es
+4s
+3s
+2x
+3ed
+4s
+3ing
+2y
+3a
+4h
+5s
+4s
+3ed
+3grass
+8es
+3ing
+3le
+5d
+5s
+6s
+7ly
+7ness
+9sses
+5t
+6s
+4ike
+5ng
+3ne
+5s
+3on
+5s
+3s
+2ze
+4d
+4e
+5d
+5ing
+5s
+4r
+5s
+4s
+3ing
+3mataz
+8es
+3oo
+5s
+4r
+5able
+5back
+9s
+6ill
+9s
+5clam
+9s
+5ed
+5fish
+9es
+5ing
+5s
+3ure
+6s
+3z
+4amatazz
+9zzes
+4berries
+8y
+4ed
+5s
+4ia
+6s
+5ng
+4le
+6s
+4matazz
+9zes
+1e
+2absorb
+8ed
+8ing
+8s
+7ption
+9ions
+3ccede
+8d
+8s
+7ing
+6lerate
+9ated
+9ates
+9ating
+6nt
+8ed
+8ing
+8s
+6pt
+8ed
+8ing
+8s
+6ssion
+9ons
+5laim
+9ed
+9ing
+9s
+6imatise
+9tised
+9tises
+9tising
+9tize
+9tized
+9tizes
+9tizing
+5redit
+9tation
+9ted
+9ting
+9ts
+5use
+8d
+8s
+7ing
+7tom
+9med
+9ming
+9ms
+4h
+5able
+5ed
+6r
+7s
+6s
+5ing
+5less
+4quaint
+9tance
+9tances
+9ted
+9ting
+9ts
+6ire
+9d
+9s
+8ing
+7sition
+9tions
+4t
+5ance
+9s
+7t
+8s
+5ed
+5ing
+6on
+8al
+9ries
+9rism
+9risms
+9rist
+9rists
+9ry
+9ryism
+9ryisms
+8ism
+9sms
+9st
+9sts
+8s
+6vate
+9ed
+9es
+9ing
+9ion
+9ions
+7e
+8ly
+8ness
+9esses
+7ities
+9y
+5or
+7s
+5s
+5uate
+9d
+9s
+8ing
+3d
+4abilities
+9ty
+6le
+8ness
+9esses
+7y
+5pt
+7ation
+9ions
+7ed
+7ing
+7s
+4d
+5ed
+5ict
+8ed
+8ing
+8s
+6ng
+5ress
+9ed
+9es
+9ing
+5s
+4er
+6ly
+6s
+7hip
+9ps
+4ied
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+4just
+8able
+8ed
+9r
+9rs
+8ing
+8ment
+9ents
+8s
+4me
+5ission
+9ons
+6t
+7s
+7tance
+9nces
+8ed
+8ing
+4opt
+7ed
+7ing
+8on
+9ns
+7s
+5rn
+7ed
+7ing
+7s
+5ut
+7s
+4s
+4vance
+9d
+9s
+8ing
+5ertise
+9sed
+9sement
+9ses
+9sing
+9ze
+9zed
+9zement
+9zes
+9zing
+5ise
+8d
+8s
+7ing
+4y
+5ing
+5made
+9s
+3edified
+9s
+7y
+8e
+9d
+9s
+8ing
+3ffirm
+8ation
+9tions
+8ed
+8ing
+8s
+6x
+7ed
+8s
+7ing
+5orest
+9tation
+9ted
+9ting
+9ts
+3gencies
+7y
+6t
+7s
+4gregate
+9ted
+9tes
+9ting
+9tion
+9tions
+4in
+6ic
+6s
+3k
+4ed
+4ing
+4s
+3l
+4er
+5s
+6t
+4gar
+7s
+4ia
+5gn
+7ed
+7ing
+7ment
+9nts
+7s
+5sabilities
+9lity
+8le
+9y
+7tion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+6m
+7s
+6t
+7ic
+9ally
+7s
+5ties
+6y
+5zabilities
+9lity
+8le
+9y
+7tion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+4lie
+7d
+7s
+5ocate
+9ed
+9es
+9ing
+9ion
+9ions
+6t
+7ment
+9nts
+7s
+7ted
+8ing
+5y
+6ing
+4m
+5less
+5s
+4ness
+8es
+4o
+5s
+4politik
+9iker
+9ikers
+9iks
+4s
+4ter
+7ed
+7ing
+7s
+5ie
+7s
+6me
+5one
+8s
+6r
+7s
+5y
+3m
+4e
+5d
+5nd
+7ed
+7ing
+7ment
+9nts
+7s
+5r
+6s
+5s
+4ier
+6st
+5ng
+4s
+4y
+3n
+4alyse
+9d
+9s
+8ing
+9s
+7ze
+9d
+9s
+8ing
+4imate
+9d
+9s
+8ing
+9on
+9ons
+4nex
+7ation
+9ions
+7ed
+8s
+7ing
+4oint
+8ed
+8ing
+8s
+4s
+5wer
+8ed
+8ing
+8s
+3p
+4able
+4ed
+5r
+6s
+4hook
+8s
+4ing
+4parel
+9led
+9ling
+9s
+5ear
+8ance
+9nces
+8ed
+8ing
+8s
+5lication
+9tions
+7ed
+8s
+6y
+7ing
+5oint
+9ed
+9ing
+9ment
+9ments
+9s
+6rtion
+9oned
+9oning
+9onment
+9ons
+5raisal
+9als
+9e
+9ed
+9ement
+9ements
+9er
+9ers
+9es
+9ing
+6opriate
+9iated
+9iates
+9iating
+7ve
+9d
+9s
+8ing
+4s
+3r
+4ed
+5r
+6s
+4guard
+9s
+6e
+7d
+7s
+6ing
+6ment
+9ts
+4horse
+9s
+4ing
+5se
+7n
+7s
+6ing
+4ly
+4m
+5ament
+9ts
+5ed
+5ice
+6ng
+5ost
+6use
+5s
+4ose
+5usal
+9s
+7e
+8d
+8s
+7ing
+4range
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+5est
+8ed
+8ing
+8s
+4s
+4ticulate
+9ated
+9ates
+9ating
+4ward
+8s
+3scend
+8ed
+8ing
+8s
+7sion
+9ons
+7t
+8s
+4on
+6abilities
+9lity
+8le
+9eness
+9y
+6ed
+8ly
+7r
+8s
+6ing
+9s
+6less
+9sly
+6s
+4sail
+8ed
+8ing
+8s
+5emblage
+9ages
+9e
+9ed
+9es
+9ies
+9ing
+9y
+6rt
+8ed
+8ing
+9on
+9ons
+8s
+6ss
+8ed
+9s
+8ing
+8ment
+9ents
+5ign
+8ed
+8ing
+8ment
+9ents
+8s
+5ort
+8ed
+8ing
+8ment
+9ents
+8s
+5ume
+8d
+8s
+7ing
+7ption
+9ions
+6rance
+9ces
+7e
+8d
+8r
+9s
+8s
+7ing
+9gly
+4t
+5ed
+5ier
+7st
+6ness
+9ses
+7g
+5s
+5y
+3ta
+5s
+4e
+5s
+4tach
+8ed
+9s
+8ing
+8ment
+9ents
+7k
+8ed
+8ing
+8s
+6in
+8ed
+8ing
+8s
+5empt
+9ed
+9ing
+9s
+5ribute
+9ted
+9tes
+9ting
+9tion
+9tions
+3uthorisation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+3vail
+7ed
+7ing
+7s
+4e
+5d
+5r
+6s
+5s
+4ing
+4ow
+6ed
+6ing
+6s
+3wake
+7d
+7n
+8ed
+8ing
+9ngs
+8s
+7s
+6ing
+4oke
+7n
+2b
+3ack
+6ed
+6ing
+6s
+4dge
+7d
+7s
+6ing
+4it
+6ed
+6ing
+6s
+4lance
+9d
+9s
+8ing
+4ptise
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+4r
+5bative
+9vely
+5s
+4table
+5e
+6able
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+5o
+6es
+6s
+3be
+5s
+5tzin
+9s
+3ec
+5k
+6s
+5s
+4gan
+5in
+7ning
+7s
+5un
+4l
+5dom
+8s
+5led
+7r
+8s
+6ing
+7on
+9s
+8us
+9sly
+9sness
+6ow
+8ed
+8ing
+8s
+5s
+3id
+5den
+6ing
+5s
+4ll
+6ed
+6ing
+6s
+4nd
+6ing
+6s
+4rth
+7er
+9s
+7ing
+9gs
+7s
+4t
+5e
+6s
+5ing
+5ten
+3lend
+7ed
+7ing
+7s
+6t
+4ochon
+9s
+5om
+7ed
+7ing
+7s
+5ssom
+9ed
+9ing
+9s
+3oant
+5rd
+7ed
+7ing
+7s
+5tion
+9s
+4died
+7s
+5y
+6ing
+4il
+6ed
+6ing
+6s
+4ok
+6ed
+6ing
+6s
+5t
+6ed
+6ing
+6s
+4p
+5s
+4re
+6d
+6s
+5ing
+5n
+5row
+8ed
+8ing
+8s
+4ttle
+8d
+8s
+7ing
+4ught
+5nd
+7ed
+8r
+9s
+7ing
+7s
+4zo
+6s
+3race
+7d
+7s
+6ing
+5nch
+8ed
+9s
+8ing
+6d
+7ed
+7ing
+7s
+4ed
+5ed
+7ing
+7s
+4oadcast
+9sted
+9sting
+9sts
+3s
+3uff
+6ed
+6ing
+6s
+4ild
+7ed
+7ing
+7s
+6t
+4kable
+5e
+6d
+6ful
+9ly
+6r
+7s
+6s
+5ing
+8ly
+4rial
+8s
+6ed
+7s
+5y
+6ing
+4s
+5es
+4t
+5ment
+9s
+5s
+5table
+7l
+8s
+6ed
+7r
+8s
+6ing
+6on
+8ed
+8ing
+8s
+4y
+5ing
+5s
+2c
+3al
+5citrance
+9ances
+9ancies
+9ancy
+9ant
+9ants
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+6ulate
+9ted
+9tes
+9ting
+9tion
+9tions
+5esce
+9d
+9nce
+9nces
+9nt
+9s
+8ing
+5ibrate
+9ted
+9tes
+9ting
+9tion
+9tions
+5l
+6abilities
+9lity
+8le
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+5ment
+9s
+5s
+4mier
+8s
+4nalisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5e
+6d
+6s
+5ing
+5t
+6ation
+9ons
+6ed
+7r
+8s
+6ing
+6s
+4p
+5italise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+7ulate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+9atory
+5pable
+6ed
+6ing
+5s
+5tion
+9s
+6or
+8s
+6ure
+9d
+9r
+9rs
+9s
+8ing
+4rpet
+8ed
+8ing
+8s
+5ried
+8s
+6y
+7ing
+4st
+6ing
+6s
+4talog
+9ed
+9ing
+9s
+5ch
+7es
+7ing
+4ught
+5tion
+9ed
+9ing
+9s
+3ce
+5d
+5ed
+5ing
+5s
+4ied
+6s
+4o
+5s
+4y
+5ing
+3ede
+6d
+6s
+5ing
+4ipt
+7ed
+7ing
+7or
+9s
+7s
+5vabilities
+9lity
+8le
+9eness
+9es
+7l
+8s
+6e
+7d
+7r
+8s
+9hip
+9hips
+7s
+6ing
+9s
+4ment
+8ed
+8ing
+8s
+4ncies
+6y
+5se
+7d
+7s
+6ing
+7on
+9s
+6or
+8ed
+8ing
+8s
+5t
+6er
+7st
+6ly
+6ness
+9ses
+6re
+8d
+8s
+7ifuge
+9uged
+9uges
+9uging
+8ng
+4pt
+6acle
+9es
+8ula
+9lar
+9lum
+6ibilities
+9lity
+8le
+7on
+9ist
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+8ities
+9ty
+6or
+8s
+6s
+4rtification
+9ed
+9es
+8y
+9ing
+4ss
+6ed
+7s
+6ing
+7on
+9al
+9als
+9ary
+9ista
+9istas
+9s
+7ve
+9ly
+9ness
+9nesses
+9s
+3hallenge
+9ged
+9ges
+9ging
+5nge
+8d
+8s
+7ing
+6nel
+9ed
+9ing
+9led
+9ling
+9s
+5rge
+8able
+8d
+8r
+9s
+8s
+7ing
+6t
+7ed
+8r
+9ed
+9ing
+9s
+7ing
+7s
+5te
+7s
+5uffe
+9s
+4eat
+7ed
+7ing
+7s
+5ck
+7ed
+7ing
+7s
+5rche
+5w
+6ed
+6ing
+6s
+4ie
+5p
+6ped
+7ing
+9gs
+6s
+4lesse
+4oose
+8s
+7ing
+5reograph
+9raphed
+9raphs
+5se
+7n
+4risten
+9ned
+9ning
+9ns
+5omatograph
+3idivism
+9ms
+9t
+9tic
+9ts
+7ous
+4pe
+6s
+5ience
+9es
+9ies
+9y
+8t
+9s
+5rocal
+9lities
+9lity
+9lly
+9ls
+9nt
+9nts
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+9tory
+8ities
+9ty
+4rcle
+8d
+8s
+7ing
+6ulate
+9ted
+9tes
+9ting
+9tion
+9tions
+4sion
+8s
+4t
+5able
+6l
+7ist
+9ts
+7s
+6tion
+9nist
+9nists
+9ns
+8ve
+9es
+9i
+9o
+9os
+5e
+6d
+6r
+7s
+6s
+5ing
+5s
+3k
+4an
+4ed
+4ing
+4less
+8ly
+8ness
+9esses
+5ing
+8s
+4on
+6ed
+7r
+8s
+6ing
+9s
+6s
+4s
+3lad
+6ded
+7ing
+6s
+5im
+7able
+9ly
+8nt
+9ts
+7ed
+8r
+9s
+7ing
+7s
+5mation
+9ons
+6e
+7s
+5sp
+7ed
+7ing
+7s
+6sified
+9ies
+9y
+9ying
+4ean
+7ed
+7ing
+7s
+4imb
+7ed
+7ing
+7s
+5nable
+7te
+8ion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+4osable
+6e
+7d
+7s
+6ing
+5the
+8d
+8s
+7ing
+4use
+7ly
+7ness
+9sses
+7s
+6ion
+9s
+7ve
+9ly
+9ness
+9nesses
+6ories
+8y
+3oal
+6ed
+6ing
+6s
+5t
+6ed
+6ing
+6s
+4ck
+6ed
+6ing
+6s
+4de
+6d
+6s
+5ification
+9ations
+8ed
+9s
+7y
+8ing
+6ng
+4gnisability
+9ble
+9bly
+9nce
+9nces
+9nt
+8e
+9d
+9e
+9es
+9r
+9rs
+9s
+8ing
+8or
+9rs
+7tion
+9ons
+9ve
+8ory
+7zability
+9ble
+9bly
+9nce
+9nces
+9nt
+8e
+9d
+9e
+9es
+9r
+9rs
+9s
+8ing
+8or
+9rs
+4il
+6ed
+7r
+8s
+6ing
+6less
+6s
+5n
+6age
+9s
+6ed
+6ing
+6s
+4llect
+9ed
+9edly
+9edness
+9ing
+9ion
+9ions
+9ive
+9ively
+9s
+7t
+8s
+5onisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+6r
+7ed
+7ing
+7s
+4mb
+6ed
+6inant
+9nts
+9tion
+9tional
+9tions
+8e
+9d
+9s
+8g
+8ing
+6s
+5fort
+9ed
+9ing
+9less
+9s
+9ure
+9ures
+5mence
+9ed
+9ement
+9ements
+9es
+9ing
+8d
+9able
+9ably
+9ation
+9ations
+9atory
+9ed
+9er
+9ers
+9ing
+9s
+6ission
+9ioned
+9ioning
+9ions
+7t
+8ment
+9ents
+8s
+8tal
+9als
+9ed
+9ing
+5pact
+9ed
+9ing
+9s
+6ence
+9es
+8sable
+9e
+9ed
+9er
+9ers
+9es
+9ing
+6ilation
+9tions
+8e
+9d
+9s
+8ing
+6ose
+9d
+9s
+8ing
+9tion
+9tions
+6ress
+9sed
+9ses
+9sing
+9sion
+9sions
+6utation
+9tions
+8e
+9d
+9s
+8ing
+4n
+5ceive
+9ed
+9es
+9ing
+7ntrate
+9rated
+9rates
+9rating
+9ration
+7ption
+9ions
+9ualise
+9ualize
+6ilability
+9ble
+9bly
+8e
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8iation
+9ations
+9atory
+9ng
+5densation
+9ations
+9e
+9ed
+9es
+9ing
+6ite
+9ly
+9ness
+9nesses
+8ion
+9oned
+9oning
+9ons
+6uct
+9ed
+9ing
+9s
+5fer
+8red
+9ing
+8s
+6igurable
+9ration
+9re
+9red
+9res
+9ring
+7ne
+9d
+9s
+8ing
+7rm
+9ation
+9ations
+9ed
+9ing
+9s
+5naissance
+9sances
+6ect
+9ed
+9ing
+9ion
+9ions
+9s
+7d
+6ing
+6oissance
+9sances
+8ter
+9ered
+9erer
+9erers
+9ering
+9ers
+9re
+9red
+9rer
+9rers
+9res
+9ring
+5quer
+9ed
+9ing
+9s
+8st
+9ts
+5s
+6ecrate
+9ated
+9ates
+9ating
+9ation
+9ations
+6ider
+9ration
+9red
+9ring
+9rs
+7gn
+9ed
+9ing
+9s
+6ole
+9d
+9s
+8idate
+9dated
+9dates
+9dating
+9dation
+9ng
+6tituent
+9uents
+9utable
+9ute
+9uted
+9utes
+9uting
+9ution
+9utions
+7ruct
+9cted
+9ctible
+9cting
+9ction
+9ctions
+9ctive
+9ctor
+9ctors
+9cts
+6ult
+9ed
+9ing
+9s
+5tact
+9ed
+9ing
+9s
+7minate
+9nated
+9nates
+9nating
+9nation
+6extualise
+9ualize
+6inue
+9ed
+9es
+9ing
+6our
+9ed
+9ing
+9s
+5valescence
+6ene
+9d
+9s
+8ing
+7rsion
+9ions
+8t
+9ed
+9ing
+9s
+7y
+8ance
+9nces
+8ed
+8ing
+8s
+6ict
+9ed
+9ing
+9ion
+9ions
+9s
+7nce
+9ed
+9es
+9ing
+4ok
+6ed
+6ing
+6s
+4pied
+7s
+5y
+6ing
+4rd
+6able
+7tion
+9ons
+6ed
+7r
+8s
+9hip
+9hips
+6ing
+9s
+7st
+9s
+6s
+5k
+6ed
+6ing
+6s
+4unt
+7al
+9s
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+5p
+6able
+6e
+7d
+6ing
+6le
+8d
+8s
+7ing
+6ment
+9ts
+6s
+5re
+7d
+7s
+6ing
+6se
+8d
+8s
+7ing
+4ver
+7ability
+9le
+9leness
+7ed
+8e
+9s
+8r
+9s
+7ies
+8ng
+7or
+9s
+7s
+7y
+4wer
+7ed
+7ing
+7s
+4yle
+7d
+7s
+6ing
+3rate
+7d
+7s
+6ing
+4eance
+9s
+8ies
+8y
+7t
+8ly
+8s
+6te
+8d
+8s
+7ing
+8on
+9nal
+9nist
+9nists
+9ns
+8ve
+9ely
+7or
+9s
+5ment
+9al
+9itial
+9itious
+9s
+4iminate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+9tory
+4oss
+7ed
+8s
+7ing
+5wn
+7ed
+7ing
+7s
+4udesce
+9ed
+9ence
+9ences
+9encies
+9ency
+9ent
+9es
+9ing
+5it
+7able
+8l
+9s
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+4ystallise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+3s
+3ta
+5l
+6ly
+5ngle
+9d
+9s
+7ular
+9arity
+9arly
+4i
+5fiability
+9le
+7cation
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5lineal
+9ally
+9ar
+9arity
+9arly
+5on
+7s
+5petalies
+9lities
+9lity
+9ly
+5rostral
+5serial
+5tic
+7s
+8es
+6ude
+9s
+8inous
+4o
+5cele
+9s
+5r
+6al
+7te
+9s
+6ess
+9es
+6ial
+9s
+7es
+6s
+7hip
+9ps
+6y
+5s
+4ress
+8es
+5ices
+7ial
+6x
+4us
+3uile
+7d
+7s
+6ing
+4le
+6d
+6s
+5ing
+5tivate
+9ted
+9tes
+9ting
+4mbence
+9es
+9ies
+9y
+8t
+9ly
+4perable
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+9ory
+4r
+5e
+6d
+6less
+6s
+5ing
+5red
+7nce
+9es
+9ies
+9y
+8t
+9ly
+6ing
+9ly
+5s
+6e
+7d
+7s
+6ing
+7on
+9s
+7ve
+9ly
+9ness
+9nesses
+5vate
+6e
+7d
+7s
+6ing
+7rostral
+4sal
+7s
+6nce
+9s
+8ies
+8y
+7t
+8s
+6tion
+9ns
+5e
+6d
+6s
+5ing
+4t
+5s
+5ting
+3yclable
+9es
+7te
+9s
+6e
+7able
+9les
+7d
+7r
+8s
+7s
+6ing
+7st
+9s
+2d
+3act
+6ed
+6ing
+7on
+9al
+9s
+6or
+8ial
+8s
+6s
+4mage
+8d
+8s
+7ing
+4n
+5s
+4rgue
+8d
+8s
+7ing
+4te
+6d
+6s
+5ing
+3back
+7s
+5it
+7ed
+8r
+9s
+7ing
+7s
+5y
+6s
+4ellies
+7y
+4ird
+7s
+4one
+7s
+4reast
+9s
+5ick
+8s
+4ud
+6s
+5g
+6s
+3cap
+6s
+4oat
+7s
+4urrant
+9ts
+3d
+4ed
+5n
+6da
+7o
+8s
+7um
+6ed
+6ing
+6s
+5r
+6s
+5st
+4ier
+6st
+5ng
+7s
+5sh
+7ly
+7ness
+9sses
+4le
+6d
+6man
+7en
+6s
+5ing
+4s
+4y
+3e
+4al
+6ing
+6s
+6t
+5r
+6s
+4cide
+8d
+8s
+7ing
+5orate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+5raft
+9s
+4d
+5icate
+9ed
+9es
+9ing
+9ion
+9ions
+4em
+6abilities
+9lity
+8le
+9eness
+9y
+6ed
+7r
+8s
+6ing
+6less
+6s
+4feat
+8ed
+8ing
+8s
+6ct
+8ed
+8ing
+8s
+5ied
+7s
+6ne
+8d
+8s
+7ing
+8tion
+9ions
+5y
+6ing
+4less
+5iver
+9ance
+9ances
+9ed
+9er
+9ers
+9ies
+9ing
+9s
+9y
+4mand
+8ed
+8ing
+8s
+5ptible
+8on
+9nal
+9ner
+9ners
+9ns
+8ve
+9ely
+7ory
+4nied
+7s
+5y
+6ing
+4ploy
+8ed
+8ing
+8ment
+9ents
+8s
+5osit
+9ed
+9ing
+9s
+4s
+5cend
+9ed
+9ing
+9s
+6ribe
+9ed
+9es
+9ing
+8ption
+9tions
+5ign
+8ed
+8ing
+8s
+4termination
+9ne
+9ned
+9nes
+9ning
+4velop
+9ed
+9er
+9ers
+9ing
+9ment
+9ments
+9s
+4ye
+6s
+3fin
+6s
+5sh
+7es
+4oot
+7s
+3handed
+4ead
+7ed
+7s
+4orse
+8s
+3ia
+5e
+5l
+6ed
+6ing
+6led
+7ing
+6s
+5s
+4ctate
+9d
+9s
+8ing
+4d
+4gest
+8ed
+8ing
+9on
+9ons
+8s
+5ress
+9ed
+9es
+9ing
+4ng
+6ote
+9s
+5tegrate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+4p
+5ped
+6ing
+5s
+5t
+4rect
+8ed
+8ing
+9on
+9ons
+8s
+4sburse
+9ed
+9es
+9ing
+5count
+9table
+9ted
+9ting
+9ts
+7ver
+9red
+9rer
+9rers
+9ries
+9ring
+9rs
+9ry
+6uss
+9ed
+9es
+9ing
+5play
+9ed
+9ing
+9s
+6ose
+9d
+9s
+8ing
+9tion
+9tions
+5solution
+9tions
+8ve
+9ed
+9es
+9ing
+5til
+8l
+9ation
+9ations
+9ed
+9ing
+9s
+8s
+6ribute
+9uted
+9utes
+9uting
+9ution
+9utions
+9utive
+8ct
+9ted
+9ting
+9ts
+4vide
+8d
+8s
+7ing
+6sion
+9ns
+6vus
+5orce
+9d
+9s
+8ing
+3leg
+6s
+4ine
+7d
+7r
+8s
+7s
+6ing
+9s
+4y
+3neck
+7ed
+7s
+5ss
+7es
+3o
+4ck
+6ed
+6ing
+6s
+4es
+4ing
+4lence
+9s
+8ies
+8y
+7t
+8ly
+4n
+5e
+5ned
+6ing
+5s
+4s
+4uble
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+6t
+7able
+9leness
+9ly
+7ed
+7ing
+7s
+5nd
+7ed
+7ing
+9gs
+7s
+5t
+6s
+4wa
+6s
+4x
+5es
+3poll
+7s
+3raft
+7ed
+7ing
+7s
+5w
+6er
+8s
+6ing
+6n
+6s
+4eam
+7ed
+7ing
+7s
+7t
+5ss
+7able
+8l
+9s
+7ed
+8r
+9s
+8s
+7ible
+8ng
+8ve
+7or
+9s
+5w
+4ied
+6s
+5ll
+7ed
+7ing
+7s
+5ve
+7n
+7s
+6ing
+4oot
+7s
+5ve
+4uthite
+9es
+4y
+5ing
+3s
+4ear
+4hank
+8s
+6re
+5ift
+8ed
+8s
+6re
+7t
+8ed
+8ing
+8s
+5ort
+4kin
+7s
+4tart
+8s
+5reak
+9s
+3tail
+7s
+4op
+6s
+3ub
+5bed
+6ing
+5s
+4ce
+6d
+6r
+7s
+6s
+5ibilities
+9ity
+7le
+9ness
+9nesses
+8y
+6ng
+5tant
+9s
+7se
+9s
+6ion
+9al
+9ism
+9isms
+9ist
+9istic
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+6or
+8s
+4it
+6s
+4ndance
+9es
+9ies
+9y
+8t
+9ly
+4plicate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tively
+4viid
+8s
+4x
+3ware
+7s
+5ter
+8s
+4ing
+7s
+4ood
+7s
+3ye
+5d
+5ing
+5s
+2e
+3arn
+6ed
+6ing
+6s
+3bok
+6s
+3ch
+5ed
+6s
+5ie
+7r
+7st
+6ng
+5o
+6ed
+7s
+6ing
+5y
+3d
+4bed
+7s
+5ird
+8s
+5uck
+8s
+4e
+5d
+5n
+5r
+6s
+5s
+4ier
+6st
+5fied
+8s
+6y
+7ing
+5ly
+5ness
+9es
+6g
+7s
+5t
+6ed
+6ing
+7on
+9s
+6s
+4like
+6ng
+8s
+4man
+5en
+4s
+4ucate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+4y
+3f
+4able
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7s
+4s
+4y
+3ject
+7ed
+7ing
+7s
+3k
+4ed
+5r
+6s
+4ie
+6r
+6st
+5ng
+7ly
+4s
+4y
+3l
+4able
+4ect
+7ed
+7ing
+8on
+9ns
+7s
+5d
+5r
+6s
+5vate
+9d
+9s
+8ing
+4igibilities
+9lity
+8le
+5ng
+7ly
+7s
+4man
+5en
+4s
+3mbark
+8ed
+8ing
+8s
+5odied
+9s
+7y
+8ing
+5race
+9d
+9s
+8ing
+6oider
+9ered
+9ering
+9ers
+4erge
+8d
+8nce
+9ces
+8s
+7ing
+4ission
+9ns
+5t
+6s
+6ted
+7ing
+4phases
+8is
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+5loy
+8ed
+8ing
+8ment
+9ents
+8s
+3n
+4act
+7ed
+7ing
+7ment
+9nts
+7or
+9s
+7s
+4counter
+9ered
+9ering
+9ers
+4dow
+7ed
+7ing
+7s
+4ergise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+4force
+9d
+9s
+8ing
+4gage
+8d
+8ment
+9ents
+8s
+7ing
+5ineer
+9red
+9ring
+9rs
+5rave
+9d
+9s
+8ing
+4joy
+7ed
+7ing
+7s
+4large
+9d
+9s
+8ing
+5ist
+8ed
+8ing
+8ment
+9ents
+8s
+4roll
+8ed
+8ing
+8s
+4s
+5lave
+9d
+9s
+8ing
+4ter
+7ed
+7ing
+7s
+5hrone
+9ed
+9es
+9ing
+5rance
+9es
+8t
+9s
+6ies
+6y
+3quip
+7ment
+9nts
+7ped
+8ing
+7s
+3rect
+7ed
+7ing
+7s
+3s
+4calate
+9ed
+9es
+9ing
+9ion
+9ions
+4t
+5ablish
+9shed
+9shes
+9shing
+9shment
+5ed
+5ier
+7st
+6mate
+9ed
+9es
+9ing
+6ng
+5s
+5y
+3valuate
+9ed
+9es
+9ing
+9ion
+9ions
+4e
+5d
+5s
+4ing
+4oke
+7d
+7s
+6ing
+3xamination
+9tions
+8e
+9d
+9s
+8ing
+4ecute
+9d
+9s
+8ing
+4hibit
+9ed
+9ing
+9s
+4pel
+7led
+8ing
+7s
+6rience
+9nced
+9nces
+9ncing
+5lain
+9ed
+9ing
+9s
+6ore
+9d
+9s
+8ing
+5ort
+8ation
+9tions
+8ed
+8ing
+8s
+6se
+8d
+8s
+7ing
+7ure
+9es
+5ress
+9ed
+9es
+9ing
+2f
+3ace
+6d
+6s
+5ing
+4ll
+6en
+6ing
+6s
+4shion
+9ed
+9ing
+9ment
+9ments
+9s
+5ten
+8ed
+8ing
+8s
+3ect
+6ed
+6ing
+7on
+9er
+9ers
+9s
+7ve
+6orian
+9ans
+9es
+8y
+6s
+4d
+4ed
+6ing
+6s
+5l
+6ing
+6s
+4l
+5l
+6ed
+6ing
+5s
+5t
+4nce
+7d
+7s
+6ing
+4r
+5able
+5ee
+7d
+7ing
+7s
+6nce
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+7da
+9ries
+9ry
+8um
+9ms
+7t
+8ial
+9ality
+9ally
+8s
+5rable
+7l
+8s
+6ed
+7r
+8s
+6ible
+7ng
+5s
+3fed
+4ing
+4o
+5s
+3ight
+7ing
+7s
+5ure
+8d
+8s
+7ing
+4le
+6d
+6s
+5ing
+5l
+6able
+6ed
+6ing
+6s
+5m
+6ed
+6ing
+6s
+5ter
+8ed
+8ing
+8s
+4nable
+6nce
+9d
+9s
+8ing
+9ngs
+5d
+6ing
+6s
+5e
+6d
+7ly
+7ness
+9sses
+6ment
+9ts
+6r
+7ies
+7s
+7y
+6s
+5ing
+8s
+6sh
+8ed
+9r
+9rs
+9s
+8ing
+4re
+6d
+6s
+5ing
+4t
+5ment
+9s
+5s
+5ted
+6ing
+9s
+4x
+5ed
+6s
+5ing
+3lag
+6ged
+7ing
+6s
+5te
+7d
+7s
+6ing
+7on
+9ary
+9s
+4ect
+7ance
+9ces
+7ed
+8r
+9s
+7ing
+9gly
+8on
+9nal
+9nless
+9ns
+8ve
+9ely
+9eness
+9ities
+9ity
+7ogram
+9rams
+9raph
+9raphs
+9raphy
+8meter
+9eters
+9etries
+9etry
+8r
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9s
+7s
+5t
+6s
+5w
+5x
+6ed
+7s
+6ibilities
+9lity
+8le
+7ng
+7on
+9al
+9s
+7ve
+9ly
+9ness
+9nesses
+9s
+8ities
+9ty
+6ly
+6ological
+9gies
+9gist
+9gists
+9gy
+4ies
+4oat
+7ed
+7ing
+7s
+5od
+7ed
+7ing
+7s
+5w
+6ed
+7r
+8ed
+8ing
+9ngs
+8s
+6ing
+9s
+6n
+6s
+4uence
+9s
+7t
+5x
+6ed
+7s
+6ing
+4y
+5ing
+3ocillate
+9ted
+9tes
+9ting
+9tion
+9tions
+5us
+7ed
+8s
+7ing
+7sed
+9s
+8ing
+4ld
+6ed
+6ing
+6s
+4ot
+6ed
+6ing
+6s
+4rest
+8ation
+9tions
+8ed
+8ing
+8s
+5ge
+7d
+7s
+6ing
+5m
+6abilities
+9lity
+8le
+7de
+9s
+8o
+9es
+9s
+7t
+8e
+9s
+8ion
+9onal
+9onist
+9onists
+9ons
+9ve
+8ories
+9ry
+8s
+8ted
+9ing
+6ed
+7r
+8s
+6ing
+9s
+7sm
+9s
+8t
+9s
+6s
+6ulate
+9ted
+9tes
+9ting
+9tion
+9tions
+5tification
+9ed
+9es
+8y
+9ing
+4ught
+5nd
+7ation
+9ions
+7ed
+8r
+9s
+7ing
+7s
+3ract
+7able
+8ries
+9y
+7ed
+7ile
+8ng
+8on
+9ns
+8ve
+9ely
+9eness
+9ities
+9ity
+7ometer
+9eters
+9etric
+9etries
+9etry
+8r
+9ies
+9ily
+9iness
+9s
+9y
+7s
+7ure
+9ed
+9es
+9ing
+5in
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+5me
+7d
+7s
+6ing
+5ngibility
+9le
+9leness
+4eeze
+8s
+7ing
+5sh
+7ed
+8n
+9ed
+9er
+9ers
+9ing
+9s
+8r
+9s
+8s
+7ful
+9lly
+7ing
+9gly
+7ment
+9nts
+4ied
+6s
+5gerant
+9nts
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tories
+9tors
+9tory
+5nge
+8d
+8nce
+9ces
+9cies
+9cy
+9t
+8s
+7ing
+4ont
+7ed
+7ing
+7s
+5ze
+7n
+4y
+5ing
+3s
+3t
+3uel
+6able
+6ed
+6ing
+6lable
+7ed
+7ing
+6s
+4ge
+6d
+6e
+7ism
+9ms
+7s
+6s
+5ia
+6ng
+6um
+4lgence
+9es
+9ies
+9y
+8t
+9ly
+4nd
+6abilities
+9lity
+8le
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4rbish
+9ed
+9er
+9ers
+9es
+9ing
+9ings
+9ment
+9ments
+5nish
+9ed
+9es
+9ing
+4sable
+6l
+7s
+5e
+6d
+6nik
+9s
+6r
+7s
+6s
+5ing
+6on
+8s
+5nik
+8s
+4tabilities
+9ity
+7le
+8y
+6l
+7s
+6tion
+9ns
+5e
+6d
+6r
+7s
+6s
+5ing
+2g
+3ain
+6able
+6ed
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4l
+5e
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ia
+7n
+7s
+6ng
+6sm
+8s
+7t
+8s
+6ties
+7y
+5ly
+5ness
+9es
+5s
+4r
+5d
+6able
+7nt
+6ed
+7r
+8s
+6ful
+9ly
+9ness
+9nesses
+6ing
+6less
+9sly
+9sness
+6s
+5s
+4ther
+8ed
+8ing
+8s
+5ta
+7s
+4uge
+7d
+7s
+6ing
+4ve
+3ear
+6ed
+6ing
+6s
+4late
+8d
+8s
+7ing
+8on
+9ns
+4nce
+7s
+6ies
+6y
+5erable
+8cies
+9y
+8te
+9ed
+9ely
+9eness
+9es
+9ing
+9ion
+9ions
+9ive
+9ively
+9or
+9ors
+9ory
+5t
+6al
+6s
+7hip
+9ps
+4s
+5t
+6s
+3gae
+6s
+6ton
+9s
+4o
+5s
+3icidal
+7e
+8s
+4e
+5s
+4ft
+6ed
+6ing
+6s
+4ld
+6ed
+6ing
+6s
+5t
+4me
+6n
+7s
+7t
+8al
+9lly
+9ls
+9tion
+9tions
+8ed
+8ing
+8s
+6s
+5inal
+4na
+6e
+6l
+6s
+4on
+6al
+8isation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9stic
+9sts
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+7ry
+6s
+4sseur
+9s
+5ter
+8able
+8ed
+9r
+9rs
+8ing
+8s
+6rable
+8nt
+9ts
+8r
+9ies
+9s
+9ship
+9ships
+9y
+8tion
+9ional
+9ions
+7ies
+7y
+4us
+4ve
+6n
+6s
+5ing
+3laze
+7d
+7s
+6ing
+4et
+6s
+4orified
+9es
+8y
+9ing
+5ss
+7ed
+8s
+7ing
+5w
+6ed
+6ing
+6s
+4ue
+6d
+6s
+5ing
+3ma
+5ker
+8s
+5ta
+3na
+5l
+5ncies
+7y
+6t
+4um
+3o
+4lith
+8s
+4rge
+7d
+7s
+6ing
+4s
+5ol
+7s
+3rade
+7d
+7s
+6ing
+5ft
+7ed
+7ing
+7s
+5nt
+7ed
+7ing
+7s
+5te
+7d
+7r
+8s
+7s
+6ing
+9s
+6or
+8s
+4ede
+7d
+7s
+6ience
+9ces
+7ng
+5en
+7ed
+7ing
+7s
+6t
+7ed
+7ing
+7s
+5ss
+7ed
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+9eness
+9ities
+9ity
+7or
+9s
+5t
+6ful
+9ly
+9ness
+9nesses
+6s
+6table
+9ly
+7ed
+8r
+9s
+7ing
+5w
+4ind
+7ing
+7s
+4oom
+7ed
+7ing
+7s
+6ve
+8d
+8s
+7ing
+5und
+6p
+7ed
+7ing
+7s
+5w
+6ing
+6n
+6s
+6th
+8s
+3s
+3uerdon
+9ed
+9ing
+9s
+4la
+6ble
+6e
+6r
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7s
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+7or
+9s
+9y
+5i
+6ne
+6se
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5o
+6s
+5us
+7es
+4r
+5gitant
+9nts
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+5s
+2h
+3ab
+5bed
+7r
+8s
+6ing
+5ilitant
+9ants
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+9ator
+9ators
+5s
+4mmer
+8ed
+8ing
+8s
+4ndle
+8d
+8s
+7ing
+9gs
+5g
+6ed
+6ing
+6s
+4rden
+8ed
+8ing
+8s
+4sh
+6ed
+7s
+6ing
+3ear
+6d
+6ing
+9s
+6s
+7al
+9s
+7e
+8d
+8r
+9s
+8s
+7ing
+9gs
+5t
+6ed
+7r
+8s
+6ing
+9s
+6s
+4el
+6ed
+6ing
+6s
+4m
+5med
+6ing
+5s
+3inge
+7d
+7s
+6ing
+4re
+6d
+6s
+5ing
+3oboam
+8s
+4me
+6d
+6s
+5ing
+4spitalise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+4use
+7d
+7s
+6ing
+9s
+3s
+3umanise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+4ng
+3ydratable
+8e
+9d
+9s
+8ing
+9on
+9ons
+4pnotise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+2i
+3chsmark
+9ks
+3dentified
+9ies
+9y
+9ying
+3f
+4ication
+9ons
+8ory
+5ed
+6r
+7s
+6s
+4s
+4y
+5ing
+3gn
+5ed
+5ing
+6te
+8d
+8s
+7ing
+8on
+9ns
+5s
+3k
+4i
+5s
+4s
+3llume
+8d
+8s
+7ine
+9ed
+9es
+9g
+9ing
+3mage
+7d
+7s
+6ine
+9d
+9s
+8g
+8ing
+4bursable
+8e
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+4merse
+9d
+9s
+8ing
+4plant
+9ation
+9ations
+9ed
+9ing
+9s
+5ort
+8ation
+9tions
+8ed
+9r
+9rs
+8ing
+8s
+6se
+8d
+8s
+7ing
+8tion
+9ions
+5ression
+9ions
+3n
+4carnate
+9ted
+9tes
+9ting
+9tion
+9tions
+5ite
+8d
+8s
+7ing
+5orporate
+9rated
+9rates
+9rating
+9ration
+5rease
+9ed
+9es
+9ing
+5ur
+7red
+8ing
+7s
+4deer
+8s
+6x
+7ed
+8s
+7ing
+5ict
+8ed
+8ing
+8ment
+9ents
+8s
+5uce
+8d
+8s
+7ing
+7t
+8ed
+8ing
+8s
+6strialise
+9ialize
+4ed
+5tte
+8s
+4fect
+8ed
+8ing
+9on
+9ons
+8s
+6station
+9tions
+5lame
+9d
+9s
+8ing
+7te
+9d
+9s
+8ing
+9on
+9ons
+5orce
+9able
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+7m
+8ed
+8ing
+8s
+5und
+8ed
+8ing
+8s
+6se
+8d
+8s
+7ing
+4habit
+9ed
+9ing
+9s
+4ing
+5tiate
+9ed
+9es
+9ing
+4ject
+8ed
+8ing
+9on
+9ons
+8s
+5ure
+8d
+8s
+7ies
+8ng
+7y
+4k
+5ed
+5ing
+5s
+4less
+4nervate
+9ted
+9tes
+9ting
+9tion
+9tions
+4oculate
+9ted
+9tes
+9ting
+9tion
+9tions
+4s
+5ert
+8ed
+8ing
+9on
+9ons
+8s
+5man
+6en
+5pect
+9ed
+9ing
+9ion
+9ions
+9s
+6ire
+9d
+9s
+8ing
+9t
+9ted
+9ting
+9ts
+5tal
+8l
+9ation
+9ations
+9ed
+9ing
+9s
+8ment
+9ents
+8s
+7te
+9d
+9ment
+9ments
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6itute
+9ted
+9tes
+9ting
+5urance
+9ces
+7e
+8d
+8r
+9s
+8s
+7ing
+4tegrate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+6r
+7ment
+9nts
+7pret
+9eted
+9eting
+9ets
+7red
+8ing
+8ogate
+9gated
+9gates
+9gating
+9gation
+7s
+7view
+9ewed
+9ewing
+9ews
+5roduce
+9ced
+9ces
+9cing
+9ction
+9ctions
+4vade
+8d
+8s
+7ing
+6sion
+9ns
+5ent
+8ed
+8ing
+9on
+9ons
+8s
+6st
+8ed
+8igate
+9gated
+9gates
+9gating
+9gation
+9ng
+8ment
+9ents
+8s
+5igorate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ator
+9ators
+6te
+8d
+8s
+7ing
+5oke
+8d
+8s
+7ing
+6lve
+9d
+9s
+8ing
+3oyndure
+9es
+3rd
+5s
+3s
+4es
+4suable
+6e
+7d
+7r
+8s
+7s
+6ing
+4t
+5afel
+9s
+5ed
+5ing
+5s
+3tbok
+7s
+4er
+6ance
+9es
+8t
+7te
+9d
+9dly
+9s
+8ing
+9on
+9ons
+9ve
+9vely
+9ves
+6s
+3ve
+5d
+5r
+6s
+5s
+4ing
+2jacket
+8ed
+8ing
+8s
+3ect
+6able
+7menta
+6ed
+7e
+8s
+7r
+8s
+6ible
+7ng
+9ly
+7on
+9ist
+9ists
+9s
+7ve
+6or
+8s
+6s
+3ig
+5ged
+7r
+8ed
+8ing
+8s
+6ing
+5s
+3oice
+7d
+7ful
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9ly
+9s
+5n
+6der
+9s
+7ure
+9es
+6ed
+6ing
+6s
+4n
+5eador
+9ra
+9ras
+9res
+6o
+7s
+6s
+4urn
+7ed
+7ing
+7s
+3udge
+7d
+7s
+6ing
+4ggle
+8d
+8s
+7ing
+4stified
+9es
+8y
+9ing
+4venate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7esce
+9ced
+9cence
+9cences
+9cent
+9ces
+9cing
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+2ke
+4d
+4s
+4y
+5board
+9ded
+9ding
+9ds
+5ed
+5ing
+5s
+3indle
+8d
+8s
+7ing
+5g
+3nit
+6s
+6ted
+7ing
+4ot
+6s
+6ted
+7ing
+2label
+7ed
+7ing
+7led
+8ing
+7s
+4ce
+6d
+6s
+5he
+7s
+5ing
+5quer
+9ed
+9ing
+9s
+4id
+4nd
+6ed
+6ing
+6s
+7cape
+9ped
+9pes
+9ping
+4pse
+7d
+7r
+8s
+7s
+6ing
+4ta
+6ble
+5e
+6d
+7ly
+7ness
+9sses
+6r
+7s
+6s
+5ing
+6on
+8al
+9lly
+8ism
+9sms
+9st
+9sts
+8less
+8s
+9hip
+9hips
+6val
+7e
+8ly
+8ness
+9esses
+8s
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ties
+9ist
+9ists
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5or
+7s
+5um
+4unch
+8ed
+9s
+8ing
+6der
+9ed
+9ing
+9s
+4x
+5able
+6nt
+8s
+6tion
+9ns
+8ve
+5ed
+7ly
+7ness
+9sses
+6r
+7s
+6s
+5in
+7g
+7s
+4y
+5ed
+5ing
+5s
+3earn
+7ed
+7ing
+7s
+7t
+5sable
+6e
+7d
+7e
+8s
+7ment
+9nts
+7r
+8s
+7s
+6ing
+6or
+8s
+4gable
+6table
+7e
+8d
+8s
+7ing
+8on
+9ns
+4nd
+6ing
+6s
+5t
+6ed
+6ing
+9s
+6less
+9sly
+9sness
+6ment
+9ts
+6s
+4t
+5s
+5ter
+8ed
+8ing
+8s
+6ing
+4vance
+9s
+8ies
+8y
+7t
+8ly
+5e
+6s
+3iabilities
+9ty
+6le
+8ness
+9esses
+8s
+7y
+5nce
+8s
+6t
+7ly
+4c
+5ense
+9d
+9s
+8ing
+8ure
+9res
+5s
+5t
+6ion
+9s
+6s
+4de
+4e
+5d
+5f
+6less
+6s
+5r
+6s
+5s
+5vable
+6e
+7d
+8ly
+7r
+8s
+7s
+6ing
+6o
+7s
+4ght
+7ed
+7ing
+7s
+5ieuse
+9es
+8x
+6on
+8aries
+9ry
+8er
+9rs
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+8less
+8s
+7se
+9ly
+8ities
+9ty
+8o
+7us
+9es
+9ly
+9ness
+9nesses
+4ne
+6d
+6s
+5ing
+5k
+6ed
+6ing
+6s
+5quish
+9hed
+9her
+9hers
+9hes
+9hing
+9hment
+9hments
+4quaire
+9es
+7ries
+8y
+6e
+7fied
+9es
+8y
+9ing
+7s
+6iae
+4sh
+6able
+6ed
+7s
+6ing
+5t
+6ed
+6ing
+6s
+4t
+4vable
+5e
+6d
+6r
+7ed
+7ing
+7s
+6s
+5ing
+3leno
+7s
+4ie
+6s
+5sh
+7ed
+8s
+7ing
+3oad
+6ed
+7r
+8s
+6ing
+6s
+5n
+6ed
+6ing
+6s
+4catable
+7e
+8d
+8e
+9s
+8s
+7ing
+8on
+9ns
+7or
+9s
+5k
+6ed
+6ing
+6s
+4ok
+6ed
+6ing
+6s
+3ubricate
+9ted
+9tes
+9ting
+9tion
+9tions
+4cent
+5t
+6ance
+9es
+9ies
+9y
+8t
+9ly
+7te
+9d
+9s
+8ing
+9on
+9ons
+6ed
+6ing
+7vities
+9ty
+6s
+4me
+6d
+6s
+5ine
+8d
+8s
+7g
+7ing
+3y
+4ing
+2m
+3ade
+6s
+4il
+6ed
+6ing
+6s
+5n
+6der
+9ed
+9ing
+9man
+9men
+9s
+6ed
+6ing
+6s
+4ke
+6r
+7s
+6s
+5ing
+4n
+5d
+6ed
+6ing
+6ment
+9ts
+6s
+5ence
+9s
+8ies
+8y
+7t
+8s
+6t
+7s
+5ie
+7s
+5ned
+6ing
+5s
+5ufacture
+9tured
+9turer
+9turers
+9tures
+9turing
+4p
+5ped
+6ing
+5s
+4rk
+6abilities
+9lity
+8le
+9eness
+9es
+9y
+6ed
+7r
+8s
+7t
+8ed
+8ing
+8s
+6ing
+6s
+5que
+8d
+8s
+5riage
+9es
+7ed
+8s
+6y
+7ing
+4ster
+8ed
+8ing
+8s
+4tch
+7ed
+8s
+7ing
+5e
+6d
+6rialise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+6s
+5ing
+3blai
+7s
+5e
+6d
+6s
+5ing
+3ead
+6ed
+6ing
+6s
+5sure
+9d
+9ment
+9ments
+9s
+8ing
+4de
+6d
+6s
+5iabilities
+9lity
+8le
+9y
+7l
+8ly
+7t
+8e
+9d
+9s
+8ing
+9on
+9ons
+6ed
+7s
+6less
+9sly
+9sness
+6ng
+5y
+6ing
+4et
+6ing
+6s
+4id
+6ed
+6ing
+6s
+4lt
+6ed
+6ing
+6s
+4mber
+8ability
+9ble
+9bly
+8ed
+9r
+9rs
+8ing
+8s
+6rance
+9cer
+9cers
+9ces
+4n
+5d
+6ed
+6ing
+6s
+5s
+4rcied
+8s
+6y
+7ing
+5ge
+7d
+7s
+6ing
+4t
+4x
+3igate
+8d
+8s
+7ing
+8on
+9ns
+5es
+5ial
+5rate
+9d
+9s
+8ing
+9on
+9ons
+4litarise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+4nd
+6ed
+7r
+8s
+6ful
+6ing
+6s
+5eralise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+5isce
+9d
+9nce
+9nces
+9nt
+9ntial
+9ntly
+9nts
+9r
+9rs
+9s
+8ing
+5t
+6ed
+6ing
+6s
+4se
+6d
+6s
+5ing
+5s
+6ibilities
+9lity
+8le
+9eness
+9y
+7on
+9s
+7ve
+9ly
+6ly
+6ness
+9ses
+6ory
+4t
+5ment
+9s
+5s
+5table
+7l
+8s
+7nce
+9es
+6ed
+7e
+8s
+7nce
+9es
+9ies
+9y
+8t
+9ly
+7r
+8s
+6ing
+6or
+8s
+4x
+5ed
+6s
+5ing
+5t
+6ure
+9s
+3nant
+7al
+7s
+3obilisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+4del
+7ed
+8r
+9s
+7ing
+7led
+8ing
+7s
+5ified
+9s
+7y
+8ing
+4isten
+9ed
+9ing
+9s
+4lade
+8s
+5d
+6ed
+6ing
+6s
+4netisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5strance
+9nces
+9nt
+9ntly
+9nts
+9te
+9ted
+9tes
+9ting
+9tingly
+9tion
+9tions
+9tive
+9tively
+9tor
+9tors
+9tory
+5tant
+9s
+6oir
+9e
+9es
+9s
+4ra
+6lisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+6s
+5id
+5se
+7ful
+9lly
+9lness
+7less
+9ssly
+9ssness
+7s
+5tgage
+9ed
+9es
+9ing
+4te
+6ly
+6ness
+9ses
+6r
+6s
+7t
+5ion
+8s
+6vate
+9ed
+9es
+9ing
+9ion
+9ions
+4ud
+5lade
+9s
+6d
+7ed
+7ing
+7s
+5nt
+7ed
+7ing
+7s
+4vabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6l
+7ist
+9ts
+7s
+5e
+6able
+6d
+7ly
+7ness
+9sses
+6r
+7s
+6s
+5ing
+3s
+3uage
+7s
+4da
+6s
+4eur
+7s
+4nerability
+9le
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9ively
+9or
+9ors
+9ory
+4rmur
+8ed
+8ing
+8s
+3ythologise
+9gised
+9gises
+9gising
+9gize
+9gized
+9gizes
+9gizing
+2n
+3ague
+7d
+7s
+6ing
+4il
+6ed
+6ing
+6s
+5ssance
+9ces
+4l
+4me
+6d
+6s
+5ing
+4scence
+9es
+8t
+4tionalise
+9lised
+9lises
+9lising
+9lize
+9lized
+9lizes
+9lizing
+5uration
+9ions
+7e
+8d
+8s
+7ing
+4y
+5ed
+5ing
+5s
+3contre
+9s
+5unter
+9red
+9ring
+9rs
+3d
+4ed
+5r
+6able
+6ed
+7r
+8s
+6ing
+9s
+6s
+5zvous
+9sed
+9ses
+9sing
+4ible
+5ng
+5tion
+9ed
+9ing
+9s
+4s
+4zina
+8s
+3egade
+8d
+8s
+7ing
+7o
+8es
+8s
+6te
+8s
+7ion
+9ns
+5e
+6d
+6r
+7s
+6s
+5ing
+5otiable
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+5ue
+7d
+7r
+8s
+7s
+6ing
+4st
+6ed
+6ing
+6s
+4w
+5abilities
+9ity
+7le
+9s
+8y
+6l
+7s
+5ed
+7ly
+7ness
+9sses
+6r
+7s
+5ing
+8s
+5s
+4y
+5ed
+5ing
+5s
+3fierst
+4orce
+8d
+8s
+7ing
+6st
+3ga
+5s
+3ied
+5s
+4form
+4g
+5ged
+6ing
+5s
+4n
+5s
+4tence
+9s
+8ies
+8y
+7t
+3k
+4er
+5st
+3minbi
+8s
+3nase
+7s
+4e
+5d
+5s
+5t
+6s
+4in
+6g
+7s
+6s
+3ogram
+8s
+7phic
+9ies
+9y
+4minate
+9ed
+9es
+9ing
+9ion
+9ions
+4rmalisation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+4sterveld
+9elds
+4tified
+9s
+7y
+8ing
+4unce
+8able
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+4vascular
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+4wn
+6ed
+7r
+8s
+6ing
+6s
+3s
+4selaerite
+9rites
+3t
+4abilities
+9ty
+6le
+5l
+6ler
+9s
+6s
+4e
+5d
+5r
+6s
+5s
+4ier
+7s
+5ng
+7s
+4s
+3umber
+8ed
+8ing
+8s
+4nciate
+9es
+9ion
+9ions
+9ive
+9ory
+3verse
+8d
+8ment
+9ents
+8s
+7ing
+7t
+4oi
+6s
+5y
+6s
+3y
+4ing
+2o
+3bject
+8ed
+8ing
+8s
+4serve
+9d
+9s
+8ing
+4tain
+8ed
+8ing
+8s
+3ccupation
+9ions
+7ied
+9s
+7y
+8ing
+6r
+7red
+9nce
+9nces
+8ing
+7s
+3ffend
+8ed
+9r
+9rs
+8ing
+8s
+6r
+7ed
+7ing
+7s
+3il
+5ed
+5ing
+5s
+3pen
+6ed
+7r
+8s
+6ing
+9s
+6s
+5rate
+9d
+9s
+8ing
+9on
+9ons
+4pose
+8d
+8s
+7ing
+3rchestrate
+9rated
+9rates
+9rating
+9ration
+4dain
+8ed
+8ing
+8s
+5er
+7ed
+7ing
+7s
+5ination
+9ions
+4ganisation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+4ient
+8ate
+9ted
+9tes
+9ting
+9tion
+9tions
+8ed
+8ing
+8s
+3s
+3utfit
+8s
+8ted
+9ing
+3virus
+8es
+3xidation
+9ons
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+2p
+3acified
+9s
+7y
+8ing
+5k
+6age
+9d
+9r
+9rs
+9s
+8ing
+6ed
+6ing
+6s
+4ginate
+9ed
+9es
+9ing
+9ion
+9ions
+4id
+5nt
+7ed
+7ing
+9gs
+7s
+5r
+6abilities
+9lity
+8le
+6ed
+7r
+8s
+6ing
+6man
+7en
+6s
+4nd
+6ly
+5el
+7ed
+7ing
+7led
+8ing
+7s
+4per
+7ed
+7ing
+7s
+4rabilities
+9ity
+7le
+8y
+6tion
+9ns
+8ve
+7ory
+5k
+6ed
+6ing
+6s
+5tee
+8d
+8ing
+8s
+6ition
+9oned
+9oning
+9ons
+4ss
+6age
+9s
+6ed
+7s
+6ing
+5t
+6ed
+6ing
+6s
+6ure
+9s
+4tch
+7ed
+8s
+7ing
+5riate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+5tern
+9ed
+9ing
+9s
+4ve
+6d
+6s
+5ing
+4y
+5able
+5ing
+5ment
+9s
+5s
+3eal
+6able
+6ed
+7r
+8s
+6ing
+6s
+5t
+6abilities
+9lity
+8le
+6ed
+8ly
+7r
+8s
+6ing
+9s
+6s
+4chage
+9s
+4g
+5ged
+6ing
+5s
+4l
+5lance
+9es
+9ies
+9y
+8t
+9ly
+9s
+6ed
+7nce
+9es
+9ies
+9y
+8t
+9ly
+9s
+7r
+8s
+6ing
+9ly
+5s
+4nt
+6ance
+9es
+8t
+9ly
+9s
+6ed
+7r
+8s
+6ing
+9ly
+6s
+4ople
+8d
+8s
+7ing
+4rcuss
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+5epe
+8s
+5k
+6ed
+6ing
+6s
+5toire
+9es
+7rial
+9es
+8y
+5usal
+9s
+7e
+8d
+8s
+7ing
+4tend
+8s
+5iteur
+9rs
+9se
+9ses
+7ion
+9nal
+9nary
+9ns
+9us
+9usly
+9usness
+8ve
+9ely
+9eness
+3hotograph
+9aphed
+9aphing
+9aphs
+4rase
+8d
+8s
+7ing
+3igment
+9ed
+9ing
+9s
+4n
+5e
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+8s
+5ned
+6ing
+5s
+4que
+7d
+7s
+6ing
+3la
+5ce
+7ability
+9le
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+5n
+6ned
+7ing
+6s
+6t
+7ation
+9ions
+7ed
+7ing
+7s
+5ster
+9ed
+9ing
+9s
+5te
+7d
+7s
+6ing
+5y
+6ed
+6ing
+6s
+4ead
+7ed
+8r
+9s
+7ing
+7s
+5d
+6ge
+8d
+8s
+7ing
+5nish
+9able
+9ed
+9er
+9ers
+9es
+9ing
+9ment
+9ments
+5te
+7d
+7ly
+7ness
+9sses
+7s
+6ing
+7on
+9s
+5viable
+7ed
+8s
+7n
+8ed
+8ing
+8s
+7sable
+6y
+7ing
+4ica
+7bilities
+9lity
+8le
+7nt
+9s
+7s
+8e
+9s
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+6on
+8s
+5ed
+6r
+7s
+6s
+4ot
+6s
+6ted
+7ing
+5w
+6ed
+6ing
+6s
+4um
+6b
+7ed
+7ing
+7s
+5nge
+8d
+8s
+7ing
+4y
+5ing
+3o
+4int
+7ed
+7ing
+7s
+4larisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5ish
+8ed
+9s
+8ing
+5l
+6ed
+6ing
+6s
+4man
+5en
+4ne
+6d
+6s
+5ing
+4pularise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+4rt
+6able
+7ge
+9s
+6ed
+8ly
+7r
+8s
+6ing
+9ly
+9s
+6orial
+9ally
+6s
+4s
+5al
+7l
+8s
+7s
+5e
+6d
+7ly
+7ness
+9sses
+6ful
+9ly
+9ness
+9nesses
+6r
+7s
+6s
+5ing
+6t
+7ed
+7ing
+8on
+9ned
+9ning
+9ns
+7or
+9ies
+9s
+9y
+7s
+5sess
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+5t
+6ed
+6ing
+6s
+5ure
+8s
+4t
+5s
+5ted
+6ing
+9s
+4ur
+6ed
+6ing
+6s
+5ssage
+9es
+7e
+8s
+7oir
+9rs
+4wer
+7ed
+7ing
+7s
+3p
+4ed
+4ing
+7s
+4s
+3reeve
+8d
+8s
+7ing
+5hend
+9able
+9ed
+9er
+9ers
+9ing
+9s
+8sible
+9ibly
+9ion
+9ions
+9ive
+9ively
+9ory
+5sent
+9able
+9amen
+9amens
+9ant
+9ants
+9ation
+9ations
+9ative
+9atives
+9ed
+9ee
+9ees
+9er
+9ers
+9ing
+9ment
+9ments
+9or
+9ors
+9s
+6s
+7ed
+8r
+9s
+8s
+7ibility
+9le
+9ly
+8ng
+8on
+9nist
+9ns
+8ve
+9ely
+9eness
+7or
+9s
+7urise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+4ice
+7d
+7s
+6ing
+5efe
+8s
+6vable
+8l
+9s
+7e
+8d
+8r
+9s
+8s
+7ing
+5mand
+9ed
+9ing
+9s
+6e
+7d
+7s
+6ing
+5nt
+7ed
+8r
+9s
+7ing
+7s
+5sal
+8s
+6e
+7d
+7s
+6ing
+6tinate
+9ated
+9ates
+9ating
+9ation
+9ations
+5vatisation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+6e
+7d
+7s
+6ing
+5ze
+7d
+7s
+6ing
+4o
+5ach
+8able
+9bly
+8ed
+9r
+9rs
+9s
+8ful
+9ully
+9ulness
+8ing
+9ngly
+8less
+5bacies
+8y
+7nce
+9es
+7te
+9d
+9r
+9rs
+9s
+8ing
+9on
+9onary
+9ons
+9ve
+9vely
+8or
+9rs
+9ry
+6e
+7d
+7s
+6ing
+5cess
+9ed
+9es
+9ing
+9ings
+5duce
+9d
+9r
+9rs
+9s
+8ibility
+9ble
+9bles
+9bly
+9ng
+8tion
+9ions
+9ive
+9ively
+9ives
+9ivity
+5gram
+9ed
+9ing
+9mable
+9me
+9med
+9mes
+9ming
+9s
+8pher
+9hers
+9hic
+9hics
+9hies
+9hy
+5of
+7ed
+7ing
+7s
+5s
+5vable
+7l
+8s
+6e
+7d
+7r
+8s
+7s
+6ing
+9ly
+7sion
+9oned
+9oning
+9ons
+4yve
+7d
+7s
+6ing
+3s
+3tant
+5tion
+9s
+4ile
+7s
+6ia
+8n
+9ly
+9s
+7ferous
+7ous
+7um
+6oid
+3ublic
+8an
+9nise
+9nised
+9nises
+9nising
+9nism
+9nisms
+9nize
+9nized
+9nizes
+9nizing
+9ns
+9tion
+9tions
+8s
+7sh
+9ed
+9er
+9ers
+9es
+9ing
+4diable
+7te
+9d
+9s
+8ing
+9on
+9onist
+9onists
+9ons
+9ve
+8or
+9rs
+4gn
+6ance
+9es
+9ies
+9y
+8t
+9ly
+6ed
+6ing
+6s
+4lp
+6ed
+6ing
+6s
+5se
+7d
+7r
+8s
+7s
+6ing
+7on
+9s
+7ve
+9ly
+9ness
+9nesses
+4mp
+6ed
+6ing
+6s
+4nctuation
+9tions
+5it
+7s
+4rchase
+9ed
+9es
+9ing
+5e
+6d
+6s
+5ified
+9s
+7y
+8ing
+6ng
+5pose
+9d
+9s
+8ing
+5sue
+8d
+8s
+7ing
+4tabilities
+9ity
+7le
+8y
+6tion
+9nal
+9nless
+9ns
+8ve
+9ely
+5e
+6d
+7ly
+6less
+6s
+5ing
+8s
+2qualification
+9ed
+9es
+8y
+9ing
+4ere
+7d
+7s
+6ing
+5st
+7ed
+8r
+9s
+7ing
+7or
+9s
+7s
+4icken
+9ed
+9ing
+9s
+5em
+7s
+6scat
+9ts
+5ght
+8ed
+8ing
+8s
+5n
+6s
+5rable
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9s
+5site
+9ly
+9ness
+9nesses
+9s
+8ion
+9onary
+9oned
+9oning
+9onist
+9onists
+9ons
+8or
+9rs
+9ry
+5t
+6able
+7l
+8s
+6e
+7d
+7ful
+7less
+7ment
+9nts
+7r
+8s
+7s
+6ing
+6s
+6ted
+7ing
+4ote
+7d
+7s
+6ing
+5yle
+8d
+8s
+7ing
+2rack
+6ed
+6ing
+6s
+4diate
+9d
+9s
+8ing
+9on
+9ons
+4il
+6ed
+6ing
+9s
+6s
+5se
+7d
+7s
+6ing
+4n
+3ead
+6ing
+9s
+6s
+4brace
+9s
+4cord
+8ed
+8ing
+8s
+4dorter
+9rs
+6s
+7es
+7se
+9s
+4gister
+9red
+9ring
+9rs
+8ration
+9ations
+5ulate
+9ed
+9es
+9ing
+9ion
+9ions
+4lease
+9d
+9s
+8ing
+4mai
+7s
+5ice
+6nd
+8ed
+8ing
+8s
+5ouse
+4nt
+6ed
+6ing
+6s
+4peat
+8ed
+8ing
+8s
+4view
+8ed
+8ing
+8s
+6se
+8d
+8s
+7ing
+4ward
+8s
+3ig
+5ged
+6ing
+5s
+4se
+6n
+6s
+5ing
+3oll
+6ed
+7r
+8s
+6ing
+6s
+4of
+6ed
+6ing
+6s
+4se
+4ute
+7d
+7ing
+7s
+6ing
+3un
+5ning
+5s
+2s
+3addle
+8d
+8s
+7ing
+4id
+5l
+6ed
+6ing
+6s
+4lable
+5e
+6able
+6s
+5gar
+8s
+5ute
+8d
+8s
+7ing
+4mple
+8d
+8s
+7ing
+4t
+4w
+5ed
+5ing
+5n
+5s
+4y
+5ing
+5s
+3cale
+7d
+7s
+6ing
+4hedule
+9ed
+9es
+9ing
+9ings
+5ool
+8ed
+8ing
+8s
+4ind
+7able
+7ed
+8r
+9s
+7ing
+7ment
+9nts
+7s
+5ssible
+8on
+9ns
+7ory
+4ore
+7d
+7s
+6ing
+4reen
+8ed
+8ing
+8s
+5ipt
+8ed
+8ing
+8s
+4uable
+5e
+6d
+6r
+7s
+6s
+5ing
+5lpt
+8ed
+8ing
+8s
+3eal
+6able
+6ed
+6ing
+6s
+5rch
+8able
+8ed
+9r
+9rs
+9s
+8ful
+8ing
+9st
+9sts
+5son
+8ed
+8ing
+8s
+5t
+6ed
+6ing
+6s
+5u
+6s
+6x
+4ct
+6abilities
+9lity
+8le
+6ed
+6ing
+7on
+9al
+9s
+6s
+5ure
+8d
+8s
+7ing
+4da
+6s
+4e
+5d
+6ed
+6ing
+6s
+5ing
+5k
+6ing
+6s
+5n
+5s
+4gregate
+9ted
+9tes
+9ting
+9tion
+9tions
+4ize
+7d
+7s
+6ing
+6ure
+9s
+4lect
+8ed
+8ing
+9on
+9ons
+8s
+5l
+6er
+8s
+6ing
+6s
+4mblance
+9ces
+9t
+7e
+8d
+8r
+9s
+8s
+7ing
+4nd
+6ing
+6s
+5sitise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+5t
+6ed
+7nce
+9ed
+9es
+9ing
+7r
+8s
+6ful
+9ly
+9ness
+9nesses
+6ing
+9ly
+7ve
+6ment
+9ts
+6s
+4rpine
+9s
+5vable
+7tion
+9onist
+9onists
+9ons
+8ories
+9ry
+6e
+7d
+8ly
+8ness
+9esses
+7r
+8s
+7s
+6ice
+9d
+9s
+8ing
+7ng
+7st
+9s
+6oir
+9ed
+9ing
+9s
+4s
+4t
+5s
+5table
+6ed
+7r
+8s
+6ing
+6le
+8d
+8ment
+9ents
+8s
+7ing
+4w
+5ed
+5ing
+5n
+5s
+3h
+4ape
+7d
+7r
+8s
+7s
+6ing
+5rpen
+9ed
+9ing
+9s
+5ve
+7d
+7n
+7s
+6ing
+4es
+4ine
+7d
+7s
+6gle
+9d
+9s
+8ing
+6ing
+5p
+6ment
+9ts
+6ped
+8r
+9s
+7ing
+6s
+4od
+5e
+6d
+6ing
+6s
+5ne
+5ot
+7ing
+7s
+5t
+5w
+6ed
+7r
+8ed
+8ing
+8s
+6ing
+6n
+6s
+4uffle
+9d
+9s
+8ing
+3iance
+8s
+6t
+7s
+4d
+5e
+6d
+6nce
+9s
+8ies
+8y
+7t
+8er
+9rs
+8ial
+9ally
+9aries
+9ary
+8s
+9hip
+9hips
+6r
+7s
+6s
+5ing
+5s
+5ua
+7l
+8ly
+8s
+7ry
+6e
+7s
+6ous
+6um
+8s
+4ft
+6ed
+6ing
+6s
+4ght
+7ed
+7ing
+7s
+5n
+6ation
+9ons
+6ed
+8ly
+8ness
+9esses
+7r
+8s
+6ing
+6ment
+9ts
+6s
+4le
+6d
+6ment
+9ts
+6s
+5ience
+9es
+9ies
+9y
+8t
+9ly
+6n
+7g
+7s
+5ver
+8ed
+8ing
+8s
+4n
+5ata
+8s
+7e
+8d
+8s
+7ing
+5ed
+6r
+7s
+5iferous
+7ication
+9ations
+8ed
+9s
+7y
+8ing
+6ng
+6se
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5like
+5oid
+8s
+6ses
+7is
+6us
+8ly
+8ness
+9esses
+5s
+5y
+4piscence
+9nces
+9ncies
+9ncy
+9nt
+4st
+6ance
+9es
+8t
+9s
+6ed
+7nt
+9s
+7r
+8s
+6ibilities
+9lity
+8le
+9y
+7ng
+9ly
+7ve
+9ly
+9ness
+9nesses
+8ities
+9ty
+6less
+9sly
+9sness
+6or
+8s
+6s
+4t
+5e
+6d
+6s
+5ing
+5s
+5ting
+9s
+5uate
+9d
+9s
+8ing
+4ze
+6d
+6s
+5ing
+3ketch
+8ed
+9s
+8ing
+5w
+6ed
+6ing
+6s
+4ill
+7ed
+7ing
+9gs
+7s
+4ue
+6d
+6s
+5ing
+3late
+7d
+7s
+6ing
+3melt
+7ed
+7ing
+7s
+4ooth
+8ed
+8ing
+8s
+3natron
+9s
+3oak
+6ed
+6ing
+6s
+4cialisation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+4d
+5ded
+6ing
+5s
+4ften
+8ed
+8ing
+8s
+4jet
+7s
+4ld
+6er
+8ed
+8ing
+8s
+5e
+6d
+6s
+5idified
+9ies
+9y
+9ying
+6ng
+5ubilities
+9ity
+7le
+9ness
+9nesses
+6te
+8ly
+8ness
+9esses
+8r
+8s
+9t
+7ion
+9ner
+9ners
+9nist
+9nists
+9ns
+8ve
+5vabilities
+9lity
+8le
+9eness
+6e
+7d
+8ly
+8ness
+9esses
+7nt
+9s
+7r
+8s
+7s
+6ing
+4nance
+9s
+7t
+8ly
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+4rb
+6ed
+7nce
+9es
+8t
+6ing
+6s
+5cin
+8al
+8ol
+9ls
+8s
+5ption
+9ns
+8ve
+5t
+6ed
+7r
+8s
+6ing
+6s
+4ught
+5nd
+7ed
+7ing
+9gly
+7s
+5rce
+8d
+8ful
+9ully
+9ulness
+8less
+8s
+7ing
+4w
+5ed
+5ing
+5n
+5s
+3pace
+7d
+7s
+6ing
+5de
+7d
+7s
+6ing
+4eak
+7ing
+7s
+5cified
+9es
+8y
+9ing
+6t
+7abilise
+9ilised
+9ilises
+9ility
+9ilize
+9ilized
+9ilizes
+9le
+9leness
+9les
+9ly
+8nt
+7ed
+8r
+9s
+7ful
+9lly
+9lness
+7ing
+8ve
+9ely
+9eness
+7less
+7s
+5ll
+7ed
+7ing
+9gs
+7s
+6t
+4irabilities
+9lity
+8le
+7te
+9d
+8ing
+9on
+9onal
+9ons
+8or
+9rs
+9ry
+6e
+7d
+7s
+6ing
+7tualise
+9alised
+9alises
+9alize
+9alized
+9alizes
+6ometer
+9ters
+9tric
+9tries
+9try
+5te
+7d
+7less
+7s
+6ing
+4lend
+8ed
+9nce
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+8ing
+8s
+5ice
+8d
+8s
+7ing
+6t
+7s
+7ting
+4oke
+7n
+5nd
+7ed
+8nce
+9ces
+9cies
+9cy
+9t
+9tia
+9tias
+9ts
+8r
+9s
+7ing
+7s
+6sa
+7e
+8less
+8r
+9s
+8s
+7ibility
+9le
+9leness
+9ly
+8ons
+8ve
+9ely
+9eness
+7or
+9ial
+9ials
+9ies
+9s
+9y
+7um
+9s
+5ol
+7ed
+7ing
+7s
+5t
+6s
+6ted
+7ing
+4rang
+6y
+7ed
+7ing
+7s
+5ead
+8ing
+8s
+5ing
+8ing
+8s
+5out
+8ed
+8ing
+8s
+5ung
+3saldar
+9s
+4entiment
+9ents
+3t
+4abilise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+6le
+8d
+8s
+7ing
+5ck
+7ed
+7ing
+7s
+5ff
+7ed
+7ing
+7s
+5ge
+7d
+7s
+6ing
+5mp
+7ed
+7ing
+7s
+5rt
+7able
+7ed
+8r
+9s
+7ing
+7s
+5te
+7d
+7ment
+9nts
+7s
+6ing
+7on
+9ed
+9ing
+9s
+5urant
+9teur
+9teurs
+9ts
+8teur
+9eurs
+9ion
+9ions
+4ed
+5m
+6med
+7ing
+6s
+5r
+6s
+4ful
+7ler
+9st
+8y
+7ness
+9sses
+4harrow
+9ws
+4ier
+6st
+5ff
+6orm
+5mulate
+9ted
+9tes
+9ting
+9tion
+9tions
+5ng
+7s
+5tch
+8ed
+9s
+8ing
+6ute
+9d
+9s
+8ing
+9on
+9onism
+9onisms
+9onist
+9onists
+9ons
+9ve
+8or
+9rs
+9ry
+5ve
+7ly
+7ness
+9sses
+4less
+8ly
+8ness
+9esses
+4o
+5ck
+7ed
+7ing
+7s
+5ke
+7d
+7s
+6ing
+5rable
+9eness
+7l
+8s
+7tion
+9onism
+9onisms
+9onist
+9onists
+9ons
+9ve
+9vely
+9ves
+6e
+7d
+7r
+8s
+7s
+6ing
+5s
+4rain
+8able
+8ed
+9dly
+9dness
+9r
+9rs
+8ing
+9ngs
+8s
+8t
+9s
+5engthen
+9hened
+9hening
+9hens
+6ss
+8ed
+9s
+8ing
+6tch
+9ed
+9es
+9ing
+5icken
+7t
+8ed
+9dly
+9dness
+8ing
+9on
+9onism
+9onisms
+9onist
+9onists
+9ons
+9ve
+9vely
+9veness
+9ves
+8s
+6ke
+8s
+7ing
+6ng
+8e
+9d
+9ing
+9nt
+9nts
+9s
+8ing
+8s
+6ve
+8n
+8s
+7ing
+5oom
+8s
+6ve
+5uck
+7ture
+9red
+9res
+9ring
+9rings
+6ng
+4s
+4udied
+8s
+6y
+7ing
+5ff
+7ed
+7ing
+7s
+5mp
+7ed
+7ing
+7s
+4y
+5le
+7d
+7s
+6ing
+3ubject
+9ed
+9ing
+9s
+5mission
+9ions
+7t
+8s
+8ted
+9ing
+4lt
+6ant
+9ly
+9s
+7tive
+6ed
+6ful
+6ing
+6less
+9sness
+6s
+4mable
+5e
+6d
+6r
+7s
+6s
+5ing
+5mon
+8ed
+8ing
+8s
+5ption
+9ns
+8ve
+9ely
+4pinate
+9ion
+9ions
+7e
+5plied
+9s
+7y
+8ing
+4rface
+9d
+9r
+9rs
+9s
+8ing
+5ge
+7d
+7nce
+9es
+8t
+7s
+6ing
+5rect
+9ed
+9ing
+9ion
+9ional
+9ionary
+9ionise
+9ionism
+9ionist
+9ionize
+9ions
+9ive
+9or
+9ors
+9s
+5vey
+8ed
+8ing
+8s
+4scitable
+9nt
+9nts
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+5pend
+9ed
+9ing
+9s
+3veratrol
+9ols
+3wallow
+9ed
+9ing
+9s
+3ynchronise
+9nised
+9nises
+9nising
+9nize
+9nized
+9nizes
+9nizing
+5theses
+9is
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+4stematise
+9tised
+9tises
+9tising
+9tize
+9tized
+9tizes
+9tizing
+2t
+3able
+7s
+4ck
+6ed
+6ing
+6le
+8d
+8s
+7ing
+6s
+4g
+5ged
+6ing
+5s
+4il
+6ed
+7r
+8s
+6ing
+9s
+6ment
+9ts
+6or
+8ed
+8ing
+8s
+6s
+5n
+6able
+6ed
+7r
+8s
+9hip
+9hips
+6ing
+6ment
+9ts
+6s
+4ke
+6n
+6r
+7s
+6s
+5ing
+8s
+4liate
+9d
+9s
+8ing
+9on
+9onist
+9onists
+9ons
+9ve
+8or
+9rs
+9ry
+5lied
+8s
+6y
+7ing
+4ma
+6s
+4pe
+6d
+6s
+5ing
+4rget
+8ed
+8ing
+8s
+4ste
+7d
+7s
+6ing
+4ught
+4x
+5ed
+6s
+5ing
+3ch
+5ed
+6s
+5ing
+5less
+3e
+4ach
+7es
+7ing
+5m
+6ed
+6ing
+6s
+5r
+6ing
+6s
+4ll
+6er
+8s
+6ing
+9s
+6s
+4m
+5per
+8ed
+8ing
+8s
+5s
+4ne
+6s
+5tion
+9ist
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+9s
+8ities
+9ty
+4st
+6ed
+6ified
+9es
+8y
+9ing
+7ng
+6s
+4xture
+9d
+9s
+8ing
+3hink
+7er
+9s
+7ing
+7s
+4ought
+4read
+8ed
+8ing
+8s
+3ia
+5l
+5rii
+7us
+6y
+4cella
+9s
+6nce
+9s
+8ies
+8y
+7t
+8ly
+5le
+7s
+5ula
+8r
+9ly
+9y
+8te
+9ed
+9ely
+9es
+9ing
+9ion
+9ions
+7e
+8s
+7ocyte
+9ytes
+7um
+9s
+4e
+5d
+5ing
+5s
+4form
+4ghten
+9ed
+9ing
+9s
+4le
+6d
+6s
+5ing
+4me
+6d
+6s
+5ing
+4na
+6cula
+9ar
+9um
+6e
+6l
+7ite
+9es
+7s
+6s
+5e
+6ne
+8s
+6s
+5ispora
+9ras
+6te
+8s
+7ides
+8s
+9es
+5oblastoma
+9stomas
+6ic
+7d
+8s
+6l
+7s
+6pathies
+9hy
+6scope
+9pes
+9pic
+9pies
+9pist
+9pists
+9py
+7pora
+9ras
+6tectal
+5t
+6ed
+6ing
+6s
+5ue
+7d
+7s
+6la
+8e
+8r
+8s
+4racies
+7y
+6l
+7s
+6nt
+8s
+5e
+6d
+7ly
+7ness
+9sses
+6e
+7s
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+8ness
+9esses
+4tle
+7d
+7s
+6ing
+3old
+4ok
+5l
+6ed
+6ing
+6s
+4re
+5n
+5sion
+9s
+5t
+6ed
+7r
+8s
+6ing
+7on
+9s
+7ve
+6s
+4tal
+7ed
+7ing
+7led
+8ing
+7s
+4uch
+7able
+7ed
+8r
+9s
+8s
+7ing
+5r
+6ed
+6ing
+6s
+3race
+7able
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+6k
+7ed
+7ing
+7s
+6t
+7ability
+9le
+8tion
+9ions
+7ed
+7ibility
+9le
+8le
+9ities
+9ity
+8ng
+8on
+9ns
+8ve
+9ely
+7or
+9s
+7s
+5ict
+8s
+6n
+7able
+7ed
+8e
+9s
+7ing
+7s
+6t
+7e
+8s
+7s
+7t
+8s
+5l
+6ly
+5nsfer
+9rred
+9rring
+9rs
+8orm
+9rmed
+9rming
+9rms
+7late
+9ted
+9tes
+9ting
+9tion
+9tions
+7mission
+9ssions
+9t
+9ts
+9tted
+9tting
+5te
+7d
+7s
+6ing
+4ead
+7ed
+7ing
+7s
+6t
+7ant
+9ts
+7ed
+8r
+9s
+7ing
+7s
+5e
+6s
+5nch
+8able
+8ed
+9s
+8ing
+8ment
+9ents
+4ial
+7s
+5bute
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9vely
+8or
+9rs
+9ry
+5ed
+6s
+6vability
+9le
+9leness
+9ly
+8l
+9s
+7e
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ing
+9gs
+5m
+6med
+7ing
+6s
+4o
+5act
+8ed
+8ing
+9on
+9ons
+9ve
+9vely
+9veness
+9vities
+9vity
+8s
+5bulbar
+5cede
+9d
+9nce
+9nces
+9nt
+9s
+8ing
+7ssion
+9ions
+9ive
+6hoir
+9rs
+6ognition
+9itions
+5d
+6den
+6ict
+9ed
+9ing
+9ion
+9ions
+9ive
+9s
+5fire
+9d
+9s
+8ing
+7t
+8s
+8ted
+9ing
+9ings
+6lected
+9tion
+9tions
+8x
+9ed
+9es
+9ing
+9ion
+9ions
+5gradation
+9ations
+9e
+9ed
+9ely
+9es
+9ing
+7ess
+9sed
+9ses
+9sing
+9sion
+9sional
+9sions
+9sive
+9sively
+5ject
+9ed
+9ing
+9ion
+9ions
+9s
+5lental
+5mingencies
+9ency
+9ent
+9ents
+5nym
+8s
+5pack
+9s
+6eritoneal
+6hilia
+9iac
+9iacs
+9ias
+6ulsion
+9ions
+9ive
+5reflection
+9ective
+9ector
+9ectors
+6ocket
+9ets
+6se
+8ly
+5s
+6exual
+9als
+6pect
+9ted
+9ting
+9tion
+9tions
+9tive
+9tively
+9tives
+9ts
+5ussage
+9ges
+8e
+5verse
+9ion
+9ions
+8t
+9ed
+9ing
+9s
+6iral
+8us
+9ses
+4y
+5ing
+3s
+4ina
+7s
+3ted
+5ries
+6y
+4ing
+3und
+6ed
+6ing
+6s
+5e
+6d
+6s
+5ing
+4rf
+6ed
+6ing
+6s
+5n
+6abilities
+9lity
+8le
+9es
+6ed
+7e
+8s
+7r
+8s
+6ik
+8s
+7ng
+6less
+6s
+4se
+3wist
+7ed
+7ing
+7s
+3ying
+4pe
+6d
+6s
+5ing
+2unification
+9tions
+7ed
+8s
+6y
+7ing
+5on
+7ism
+9ms
+9t
+9tic
+9ts
+7s
+5table
+6e
+7d
+7r
+8s
+7s
+6ing
+3pholster
+9ered
+9ering
+9ers
+4take
+8s
+3rge
+6d
+6s
+5ing
+3sabilities
+9ty
+6le
+8s
+4e
+5d
+5s
+4ing
+3tilisation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+4ter
+7ed
+7ing
+7s
+2v
+3accinate
+9ted
+9tes
+9ting
+9tion
+9tions
+4lenta
+9s
+5idate
+9ed
+9es
+9ing
+9ion
+9ions
+5orisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5uate
+9d
+9s
+8ing
+9on
+9ons
+6e
+7d
+7s
+6ing
+4mp
+6ed
+7r
+8s
+6ing
+9s
+6s
+4nche
+8s
+7ism
+9ms
+9t
+9ts
+4rnish
+9ed
+9es
+9ing
+3eal
+6abilities
+9lity
+8le
+6ed
+7r
+8s
+6ing
+9ly
+9ness
+9nesses
+9s
+6ment
+9ts
+6s
+4getate
+9ed
+9es
+9ing
+9ion
+9ions
+4hent
+4ille
+8s
+4l
+5ation
+9nal
+9nist
+9nists
+9ns
+8ve
+7or
+9s
+9y
+5ed
+6r
+7s
+5ing
+5led
+7r
+8s
+6ing
+9s
+5ment
+9s
+5ries
+6ous
+6y
+5s
+4nant
+8s
+5dicate
+9ted
+9tes
+9ting
+9tion
+9tions
+5ge
+7d
+7ful
+9lly
+9lness
+7less
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9ly
+9s
+7ve
+5ual
+6e
+7d
+7r
+8s
+7s
+4rable
+5b
+6ed
+7rant
+9ntly
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tories
+9tors
+9tory
+6ing
+6s
+5e
+6d
+6nce
+9d
+9r
+9rs
+9s
+8ing
+7d
+8s
+7t
+8ial
+9ally
+8ly
+8ness
+9esses
+6r
+7s
+6s
+5ie
+7s
+6fied
+9s
+7y
+8ing
+6ng
+6st
+8s
+5s
+6al
+8s
+6e
+7d
+8ly
+7less
+8y
+7r
+8s
+7s
+6i
+7bilities
+9lity
+8le
+9es
+9y
+7ng
+9s
+7on
+9al
+9ally
+9aries
+9ary
+9er
+9ers
+9s
+7s
+8es
+6o
+7s
+5t
+6ant
+9s
+6ed
+7r
+8s
+6ible
+7ng
+7ve
+6s
+5y
+4st
+6ed
+6iaries
+9y
+7ng
+6ries
+7y
+6s
+4t
+5ment
+9s
+5s
+5ted
+6ing
+4ur
+6s
+5se
+7s
+3ibrate
+9d
+9s
+8ing
+4ctual
+9ed
+9ing
+9led
+9ling
+9s
+4e
+5d
+5s
+5w
+6able
+7l
+8s
+6ed
+7r
+8s
+6ing
+6s
+4le
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8ly
+8s
+4ndicate
+9ted
+9tes
+9ting
+9tion
+9tions
+4olate
+9d
+9s
+8ing
+4sable
+6l
+7s
+5e
+6d
+6r
+7s
+6s
+5ing
+6on
+8al
+9ry
+8ism
+9sms
+9st
+9sts
+8s
+6t
+7ant
+9ts
+8tion
+9ions
+7ed
+7ing
+7s
+5or
+7s
+7y
+5ualisation
+9zation
+4talisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+4vabilities
+9ity
+7le
+8y
+6l
+7ism
+9ms
+9t
+9tic
+9ts
+7s
+5e
+6d
+6ment
+9ts
+6r
+7s
+6s
+7cence
+9nces
+9ncies
+9ncy
+9nt
+5ification
+9ations
+8ed
+9s
+7y
+8ing
+6ng
+8ly
+8s
+6scence
+9nces
+9ncies
+9ncy
+9nt
+5or
+7s
+3ocabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6tion
+9ns
+7ory
+4ice
+7d
+7s
+6ing
+4kabilities
+9ity
+7le
+8y
+5e
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+4lt
+6ed
+7r
+8s
+6ing
+9ly
+6s
+5ute
+7ion
+9nal
+9naries
+9narily
+9nary
+9ner
+9ners
+9nise
+9nised
+9niser
+9nisers
+9nises
+9nising
+9nism
+9nisms
+9nist
+9nists
+9nize
+9nized
+9nizer
+9nizers
+9nizes
+9nizing
+9ns
+5vable
+9y
+6e
+7d
+7ncies
+9y
+7r
+8s
+7s
+6ing
+9ly
+9s
+4te
+6d
+6s
+5ing
+3s
+3ue
+5s
+4ist
+7s
+4lsed
+6ion
+9ary
+9s
+7ve
+9ly
+9s
+3ved
+4ing
+3ying
+2w
+3ake
+6d
+6n
+7ed
+7ing
+7s
+6s
+5ing
+4n
+4rd
+6able
+9eness
+6ed
+7r
+8s
+6ful
+6ing
+9ly
+6less
+6s
+5ewa
+8s
+5m
+6ed
+6ing
+6s
+4sh
+6ed
+7s
+6ing
+4ter
+7ed
+7ing
+7s
+4x
+5ed
+6s
+5ing
+3ear
+6ing
+6s
+5ve
+7d
+7s
+6ing
+4d
+5ded
+6ing
+5s
+4igh
+7ed
+7ing
+7s
+4ld
+6ed
+6ing
+6s
+4t
+5s
+5ted
+6ing
+3iden
+7ed
+7ing
+7s
+4lding
+9s
+4n
+5d
+6ed
+7r
+8s
+6ing
+6s
+5ning
+5s
+4rable
+5e
+6d
+6s
+5ing
+3oke
+6n
+4n
+4rd
+6ed
+6ing
+9s
+6s
+5e
+5k
+6ed
+6ing
+9s
+6s
+5n
+4und
+4ve
+6n
+3rap
+6ped
+7ing
+6s
+6t
+4ite
+7r
+8s
+7s
+6ing
+6ten
+4ote
+5ught
+3s
+3th
+5s
+2x
+3es
+3ine
+6s
+2ynard
+7s
+2z
+3ero
+6ed
+7s
+6ing
+6s
+3one
+6d
+6s
+5ing
+3zes
+1habdocoele
+9les
+6id
+8s
+6lith
+9hs
+6m
+7al
+8ncer
+9cers
+9cies
+9cy
+9tist
+9tists
+7e
+8re
+9es
+8s
+7s
+7yoma
+9mas
+9mata
+6sphere
+9eres
+6virus
+9uses
+5us
+7es
+3chial
+6des
+7ial
+6lla
+9s
+6s
+7es
+6tis
+9es
+3damanthine
+3gades
+6iform
+3mnaceous
+5ose
+8s
+5us
+7es
+4phoid
+7theca
+9ecae
+3nja
+6s
+3phae
+5e
+6s
+5ide
+8s
+6s
+4ontic
+9s
+4sode
+8s
+7ic
+9al
+9ally
+8es
+8se
+9ed
+9es
+9ing
+9t
+9tic
+9ts
+8ze
+9ed
+9es
+9ing
+7y
+3tanies
+6y
+2ea
+4s
+3bok
+6s
+3matic
+4e
+5s
+3nium
+7s
+3obase
+8s
+7ic
+4chord
+9s
+5ord
+8s
+4logic
+9al
+9ally
+8es
+8st
+9ts
+7y
+4meter
+9s
+7ric
+9cal
+9es
+8y
+5orphic
+9ism
+9isms
+4phil
+8e
+9s
+4receptor
+9tors
+4stat
+8ic
+8s
+4tactic
+6xes
+7is
+5ome
+8s
+5rope
+9s
+8ic
+9sm
+9sms
+3sus
+6es
+3tor
+6ic
+8al
+9lly
+8ian
+9ans
+8s
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6s
+3um
+5ateese
+9ses
+7ic
+9al
+9ally
+9ky
+9s
+8se
+9es
+9m
+9mal
+9ms
+8z
+9e
+9es
+7oid
+9dally
+8logical
+9ogies
+9ogist
+9ogists
+9ogy
+5ed
+5ic
+6er
+7st
+5s
+5y
+3xes
+4is
+6es
+2ies
+3golene
+9s
+3me
+5s
+3nal
+4e
+5ncephala
+9halic
+9halon
+9halons
+5s
+6tone
+9ed
+9es
+4itic
+7des
+7s
+8es
+4o
+5ceri
+9cal
+8os
+9ses
+9t
+9te
+9tes
+9tic
+5lalia
+9as
+6ith
+9s
+6ogical
+9es
+9st
+9sts
+8y
+5phyma
+9as
+6lastic
+9ties
+9ty
+5rrhagia
+9gias
+8oea
+9eal
+9eas
+5s
+6cleroma
+9romas
+9romata
+7ope
+9es
+9ic
+9ies
+9y
+5theca
+9ae
+5virus
+9ses
+3pidate
+6ion
+9s
+7um
+9s
+3zanthous
+4ic
+5ne
+7s
+4obia
+8l
+7um
+5carp
+9ic
+9ous
+9s
+7ul
+9s
+6ephalan
+9alans
+9alous
+6tonia
+9ias
+5genetic
+8ic
+8ous
+5id
+7al
+7s
+5ma
+7ta
+8ous
+6e
+7s
+6ic
+6orph
+9hous
+9hs
+5phagous
+7ilous
+7ore
+9es
+6i
+6lane
+9es
+6od
+8an
+9ns
+8ous
+8s
+6us
+8es
+5sphere
+9res
+5tomies
+8y
+2o
+3damin
+8e
+9s
+8s
+5nate
+9s
+6ic
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+4ic
+5e
+6s
+5nal
+8s
+5um
+7s
+4ochrosite
+9sites
+5daphne
+9nes
+6endra
+9ron
+9rons
+5lite
+9s
+5montade
+9aded
+9ades
+9ading
+5nite
+9s
+5phane
+9es
+6sin
+9s
+5ra
+7s
+5us
+4y
+3eadine
+9s
+3icissus
+9ses
+3mb
+5encephala
+9phalon
+7porphyr
+9rphyrs
+9rphyry
+5i
+6c
+7al
+5ohedra
+9ral
+9ron
+9rons
+6i
+7d
+8al
+8ei
+9s
+9us
+8s
+6s
+5porphyries
+9hyry
+5s
+5us
+7es
+3nchal
+6i
+7al
+6us
+4e
+5s
+3palic
+7sm
+9s
+6oceral
+9rous
+3s
+3tacise
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7ze
+9d
+9s
+8ing
+4ic
+6ities
+8y
+2ubarb
+7ed
+7ing
+9gs
+7s
+7y
+3mb
+5a
+6ed
+6ing
+6s
+6tron
+9ns
+5s
+3s
+4es
+2y
+3me
+5d
+5less
+5r
+6s
+5s
+6ter
+9s
+4ing
+5st
+7s
+3nchocoel
+9els
+7dont
+7phore
+9ores
+9orous
+4e
+5s
+3olite
+8s
+7ic
+3parographer
+9aphers
+9aphic
+9aphies
+9aphy
+3ta
+4hm
+6al
+6ed
+6i
+7c
+8al
+9lly
+8ities
+9ty
+8s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8t
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6less
+6ometer
+9ters
+7poeia
+9eias
+6s
+6us
+8es
+4idectomies
+9omy
+6ome
+9s
+5na
+7s
+4on
+6s
+1ia
+3d
+4s
+3l
+4s
+4to
+6s
+3ncies
+5y
+4t
+5ly
+3s
+3ta
+5s
+2b
+3a
+4ld
+6ly
+6ries
+7y
+6s
+4nd
+6s
+4s
+4ttuta
+9s
+4ud
+6red
+7ies
+7y
+6s
+4virin
+9s
+3band
+7s
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7s
+4on
+6ed
+6fish
+9hes
+6ing
+6like
+6ries
+7y
+6s
+6wood
+9ds
+6y
+4y
+3cage
+7s
+3es
+4ye
+6s
+3grass
+8es
+3ibe
+6s
+5le
+7s
+4er
+6s
+3less
+5t
+6s
+4ike
+3oflavin
+9ne
+9nes
+9ns
+4nuclease
+9ases
+9ic
+9oside
+9osides
+9otide
+9otides
+4se
+6s
+5omal
+7e
+8s
+4zymal
+7e
+8s
+3s
+4ton
+7e
+8s
+7s
+3work
+7s
+6t
+7s
+2ce
+4bird
+8s
+4d
+4r
+5car
+8e
+9s
+8i
+8s
+7ta
+9s
+5s
+4s
+4y
+3h
+4ed
+5n
+6ed
+6ing
+6s
+5r
+5s
+6se
+8s
+6t
+4ing
+4ly
+4ness
+8es
+4t
+5ed
+6r
+6st
+5ing
+5s
+4weed
+8s
+3ier
+5st
+4n
+5g
+5oleic
+5s
+5us
+7es
+3k
+4ed
+5r
+6s
+5t
+6ier
+8st
+7ly
+7ness
+9sses
+6s
+6tier
+9st
+7sia
+9ae
+9al
+9as
+7y
+6y
+5y
+6s
+4ing
+4le
+6s
+5y
+4rack
+8s
+4s
+5ha
+7s
+7w
+8s
+5tand
+9s
+6ick
+9s
+4yard
+8s
+3ochet
+8ed
+8ing
+8s
+8ted
+9ing
+4tta
+7s
+3rac
+6s
+3tal
+4us
+6es
+3y
+2d
+3abilities
+9y
+5le
+3dance
+8s
+4ed
+5n
+5r
+6s
+4ing
+4le
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+3e
+4able
+4nt
+4r
+5ed
+5less
+5s
+6hip
+9s
+4s
+3ge
+5back
+9s
+5d
+5l
+6ike
+7ne
+9s
+8g
+9s
+6s
+5pole
+9s
+5r
+6s
+5s
+5top
+8s
+6ree
+9s
+5way
+8s
+4ier
+6st
+5l
+6s
+5ng
+7s
+4ling
+8s
+4y
+3icule
+8d
+8r
+9s
+8s
+7ing
+7ous
+9sly
+9sness
+4ng
+6s
+3ley
+6s
+3otto
+7s
+3s
+2ebeckite
+9es
+3l
+4s
+3m
+4pie
+7s
+4s
+3sling
+8s
+3ve
+5r
+6s
+5s
+4ing
+2f
+3acimenti
+9to
+4mpicin
+9ns
+7n
+8s
+5ycin
+9s
+3e
+4ly
+4ness
+8es
+4r
+4st
+3f
+4age
+7s
+4ed
+4ing
+4le
+6d
+6r
+7s
+6s
+5ing
+4ola
+7s
+4raff
+8s
+4s
+3le
+5bird
+9s
+5d
+5man
+6en
+5r
+6ies
+6s
+6y
+5s
+4ing
+7s
+5p
+6s
+3s
+3t
+4e
+5d
+4ier
+6st
+5ng
+4less
+4s
+4y
+2g
+3adoon
+8s
+4marole
+9es
+4toni
+8s
+4udon
+8s
+3g
+4ald
+7s
+4ed
+5r
+6s
+4ing
+7s
+5sh
+4s
+3ht
+5able
+9ness
+9nesses
+8y
+5ed
+6n
+7ed
+7ing
+7s
+6ous
+9ly
+9ness
+9nesses
+6r
+7s
+6st
+5ful
+8ly
+8ness
+9esses
+5ies
+6ng
+8s
+6sh
+7m
+8s
+7t
+8s
+5less
+6y
+5most
+5ness
+9es
+5o
+5s
+6ize
+9d
+9s
+8ing
+5ward
+9ly
+9s
+5y
+3id
+5er
+6st
+5ification
+9ations
+8ed
+9s
+7y
+8ing
+6se
+8d
+8s
+7ing
+6ties
+7y
+6ze
+8d
+8s
+7ing
+5ly
+5ness
+9es
+5s
+3lin
+6g
+7s
+6s
+3marole
+9s
+3ol
+5l
+6s
+5s
+4r
+5ism
+8s
+7t
+8ic
+8s
+5ous
+8ly
+8ness
+9esses
+5s
+4ur
+6s
+5t
+6s
+3s
+4daler
+9s
+3widdie
+9s
+4oodie
+9s
+2jksdaaler
+9ers
+3stafel
+9s
+5tafel
+9ls
+2kisha
+7s
+6i
+3shaw
+7s
+2le
+4d
+4s
+4y
+3ier
+5st
+5vi
+6o
+4ng
+3l
+4e
+5d
+5s
+5t
+6s
+6tes
+4ing
+4mark
+8s
+4s
+2m
+3a
+4e
+4ye
+6s
+3e
+4d
+4less
+4r
+5s
+4s
+5ter
+8s
+3fire
+7s
+3ier
+5st
+4ness
+8es
+5g
+3land
+7s
+4ess
+3med
+5r
+6s
+3ose
+6ly
+5ities
+7y
+4us
+3ple
+6d
+6s
+5ing
+3rock
+7s
+3s
+4hot
+7s
+3u
+4s
+3y
+2n
+3d
+4ed
+5rpest
+9ts
+4ier
+6st
+5ng
+4less
+4s
+4y
+3e
+4s
+3forzando
+3g
+4bark
+8ed
+8ing
+8s
+5it
+7s
+5olt
+8s
+6ne
+8s
+4dove
+8s
+4ed
+5nt
+5r
+6s
+5tte
+8s
+4git
+7s
+4hals
+8es
+4ing
+7ly
+7s
+4leader
+9rs
+6ss
+6t
+7ed
+7s
+5ike
+4man
+6ster
+9rs
+5en
+4neck
+8s
+4s
+5ide
+8r
+9s
+8s
+5tand
+9s
+6er
+8s
+6raked
+4tail
+8s
+6w
+7s
+5one
+8s
+6ss
+8es
+4way
+7s
+5ise
+5omb
+8s
+6rk
+8s
+7m
+8s
+3k
+4ed
+4hals
+8es
+4ing
+4s
+3ning
+3s
+4abilities
+9ty
+6le
+4e
+5able
+5d
+5r
+6s
+5s
+4ibilities
+9ty
+6le
+5ng
+7s
+3thereout
+9uts
+2oja
+5s
+3t
+4ed
+5r
+6s
+4ing
+7s
+5se
+7s
+5ze
+7s
+4ous
+7ly
+7ness
+9sses
+4ries
+5y
+4s
+2p
+3arial
+7n
+8s
+3cord
+7s
+3e
+4ck
+6s
+4d
+4ly
+4n
+5ed
+6r
+7s
+6ss
+8es
+5ing
+5s
+4r
+5s
+4s
+5t
+3idolite
+9es
+4eni
+7st
+9s
+6o
+7s
+4ng
+3off
+6s
+4st
+6e
+7d
+7s
+6ing
+6s
+3p
+4able
+4ed
+5r
+6s
+4ier
+7s
+5ng
+7ly
+7s
+4le
+6d
+6r
+7s
+6s
+6t
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5y
+4s
+3rap
+6ped
+7ing
+6s
+3s
+4aw
+6ed
+6ing
+6n
+6s
+4norter
+9rs
+8ing
+9ngly
+4top
+7s
+3t
+4ide
+7s
+2roriro
+8s
+2saldar
+8s
+3e
+4n
+4r
+5s
+4s
+3hi
+5s
+3ibilities
+9y
+5le
+7s
+6y
+4ng
+6s
+3k
+4ed
+5r
+6s
+4ful
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4less
+4s
+4y
+3oluto
+4rgimento
+9ntos
+5ii
+6us
+4tto
+7s
+3p
+4ed
+5tti
+7o
+4ing
+7s
+4s
+3que
+6s
+3sole
+7s
+3tra
+6s
+3us
+5es
+2t
+3ard
+6ando
+9os
+6s
+3e
+4less
+4nuto
+8s
+4s
+3onavir
+9s
+4rnel
+8l
+9e
+9es
+9i
+9o
+9os
+9s
+8s
+4urnelle
+9les
+3s
+3t
+4ed
+5r
+6s
+4ing
+4s
+3ual
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ically
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+6s
+4ximab
+9s
+3z
+4es
+4ier
+6st
+5ly
+5ness
+9es
+4y
+2va
+4ge
+6s
+4l
+5ed
+6ss
+8es
+5ing
+6se
+8d
+8s
+7ing
+6ties
+7y
+6ze
+8d
+8s
+7ing
+5led
+7ss
+6ing
+5ries
+6ous
+6y
+5s
+6hip
+9s
+4s
+3e
+4d
+4l
+5led
+6ing
+5s
+4n
+4r
+5ain
+8s
+5bank
+9s
+6ed
+8s
+6oat
+9s
+5craft
+9ts
+5ed
+6t
+7s
+5front
+9ts
+5head
+9s
+5ine
+5less
+6ike
+5man
+6en
+5s
+6cape
+9es
+6ide
+9s
+5ward
+9s
+7y
+8s
+6eed
+9s
+6orthiness
+9hy
+5y
+4s
+4t
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5s
+5ted
+6ing
+3iera
+7s
+6e
+7s
+4ng
+3lin
+6s
+3o
+3ulet
+7s
+5ose
+2yal
+5s
+2z
+3a
+4rd
+6s
+4s
+3zar
+6ed
+6ing
+6s
+6t
+7s
+4er
+6ed
+6ing
+6s
+4or
+6ed
+6ing
+6s
+1oach
+5ed
+6s
+5ing
+3d
+4abilities
+9ty
+4bed
+7s
+5lock
+9ed
+9ing
+9s
+4craft
+9s
+4eo
+6s
+4header
+9rs
+5olding
+9ngs
+6use
+9s
+4ie
+6s
+5ng
+7s
+4kill
+8s
+4less
+4man
+5en
+4roller
+9rs
+5unner
+9rs
+4s
+5how
+8s
+5ide
+8s
+5man
+6en
+5tead
+9s
+7r
+8s
+4way
+7s
+5ork
+8s
+7thies
+9iness
+9y
+3m
+4ed
+5r
+6s
+4ing
+7s
+4s
+3n
+4pipe
+8s
+4s
+3r
+4ed
+5r
+6s
+4ie
+6r
+6st
+5ng
+7ly
+7s
+4ming
+4s
+4y
+3st
+5ed
+6r
+7s
+5ing
+8s
+5s
+3te
+5d
+5s
+4ing
+2b
+3alo
+6s
+4nd
+6s
+3bed
+5r
+6ies
+6s
+6y
+4in
+6g
+6s
+3e
+4d
+4rdsman
+8en
+5tsman
+8en
+4s
+3in
+5g
+6s
+5ia
+7s
+5s
+3le
+5s
+3orant
+8s
+6ting
+4t
+5ic
+7ally
+7s
+6sation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ries
+6y
+5s
+3s
+3urite
+8s
+4st
+6a
+7s
+6er
+7st
+6ious
+9sly
+9sness
+6ly
+6ness
+9ses
+2c
+3aille
+8s
+4mbole
+9s
+3h
+4es
+5t
+6s
+3k
+4abies
+7llies
+9y
+6le
+6y
+7e
+8s
+5way
+8s
+4bound
+4ed
+5r
+6ies
+6s
+6y
+5t
+6ed
+7er
+9s
+7r
+8s
+6ing
+6ries
+7y
+6s
+4fall
+8s
+5ish
+8es
+4hopper
+9rs
+6und
+9ing
+9ings
+9s
+4ier
+7s
+6st
+5ly
+5ness
+9es
+6g
+7ly
+7s
+4lay
+7s
+5ess
+5ike
+6ng
+8s
+4oon
+7s
+4rose
+8s
+4s
+5haft
+9s
+5lide
+9s
+5teadies
+9y
+4water
+9s
+5eed
+8s
+5ork
+8s
+4y
+3oco
+6s
+3quet
+7s
+3s
+2d
+3ded
+4ing
+7s
+3e
+4d
+4nt
+6icide
+9des
+6s
+4o
+5ed
+5ing
+5s
+4s
+4way
+7s
+3fisher
+9s
+7ing
+9gs
+3gersia
+9s
+3ing
+6s
+3less
+4ike
+3man
+4en
+3omontade
+9ded
+9der
+9ders
+9des
+9ding
+3s
+4man
+5en
+4ter
+7s
+2e
+3buck
+7s
+3d
+3mer
+6s
+3ntgen
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8ogram
+9grams
+9graph
+9graphs
+9graphy
+9logic
+9logies
+9logist
+9logy
+9paque
+9scope
+9scopes
+9scopic
+9scopy
+8s
+3s
+4ti
+6s
+5one
+8s
+2gallo
+7s
+4tion
+8s
+5ory
+3er
+5ed
+5ing
+8s
+5s
+3non
+6s
+3ue
+5d
+5ing
+5r
+6ies
+6s
+6y
+5s
+6hip
+9s
+4ing
+5sh
+7ly
+7ness
+9sses
+4y
+2il
+4ed
+4ier
+6st
+5ng
+4s
+4y
+3n
+4ed
+4ing
+5sh
+4s
+3st
+5ed
+6r
+7ed
+8r
+9s
+7ing
+9gs
+7ous
+9sly
+7s
+5ing
+5s
+2jak
+5s
+3i
+4s
+2k
+3e
+4d
+4lay
+7s
+4r
+5s
+4s
+3ier
+5st
+4ng
+3kaku
+3s
+3y
+2lag
+5s
+4mite
+8s
+3e
+4s
+3f
+4ed
+5r
+6s
+4ing
+7s
+4s
+3l
+4able
+5way
+8s
+4back
+8s
+6r
+7s
+4collar
+9rs
+4ed
+5r
+6ball
+9ls
+7lade
+9ded
+9der
+9ders
+9des
+9ding
+9dings
+6coaster
+9stered
+9sters
+6s
+4ick
+7ed
+7ing
+9gs
+7s
+7y
+5ng
+7s
+4mop
+7s
+4neck
+8s
+4ock
+7ing
+9gs
+7s
+5ut
+7s
+5ver
+8s
+4s
+4top
+4way
+7s
+2m
+3a
+4ge
+6s
+4ika
+7s
+5ne
+7s
+4ji
+6s
+4l
+5s
+4n
+5ce
+7d
+7r
+8s
+7s
+6ical
+7ng
+9s
+5esco
+9s
+5icite
+9es
+6sation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5o
+6s
+5s
+5tic
+8al
+9lities
+9lity
+9lly
+8isation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+5za
+7s
+4unt
+7s
+3com
+6s
+3eldale
+9s
+4o
+5s
+3neya
+7s
+3p
+4ed
+5r
+6s
+4ing
+7ly
+5sh
+7ly
+7ness
+9sses
+4s
+3s
+2ncador
+8s
+3dache
+8s
+5vel
+8s
+4e
+5au
+7x
+5l
+6et
+8s
+6le
+8s
+6s
+5s
+4ino
+7s
+4o
+5letto
+9os
+5s
+4ure
+7s
+3e
+4o
+5ed
+5ing
+5s
+4pipe
+8s
+4s
+3g
+4geng
+8s
+3in
+5s
+4on
+6s
+3ne
+5l
+6s
+4ie
+6s
+5ng
+3t
+4e
+5s
+4gen
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ogram
+9rams
+9raph
+9raphs
+9raphy
+8logical
+9ogies
+9ogist
+9ogists
+9ogy
+8paque
+8scope
+9copes
+9copic
+9copies
+9copy
+8therapy
+7s
+4s
+3yon
+6s
+3z
+4er
+6s
+2o
+3d
+4s
+3f
+4ed
+5r
+6s
+4ie
+6r
+6s
+7t
+5ng
+7s
+4less
+8ness
+9esses
+5ike
+6ne
+8s
+4s
+5cape
+9s
+4top
+7s
+5ree
+8s
+4y
+3ibos
+4kat
+7s
+4nek
+7s
+3k
+4ed
+5ries
+6y
+4ie
+6r
+6s
+7t
+5ng
+5sh
+4s
+4y
+3m
+4ed
+5r
+6s
+5tte
+8s
+4ful
+7s
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+4mate
+8s
+4s
+5ome
+4y
+3n
+4s
+3p
+4ed
+4ier
+6st
+5ng
+5t
+4s
+4y
+3rbach
+8s
+7k
+8s
+3s
+4a
+5s
+4e
+5d
+5r
+6s
+5s
+4ing
+4t
+5ed
+6r
+7s
+5ing
+5s
+3t
+4age
+7s
+4bound
+4cap
+7s
+4ed
+6ly
+6ness
+9ses
+5r
+6s
+4hold
+8s
+4ier
+6s
+7t
+5ness
+9es
+6g
+7s
+4kit
+7s
+4le
+6d
+6s
+7s
+8ness
+9esses
+6t
+7s
+5ike
+6ng
+4s
+5erver
+9rs
+5ier
+7st
+6ness
+9ses
+5talk
+9s
+6ock
+9s
+5y
+4worm
+8s
+4y
+2pable
+3e
+4able
+4d
+5ancer
+9rs
+8ing
+9ngs
+4like
+4r
+5ies
+5s
+5y
+4s
+4walk
+8er
+9rs
+8s
+6y
+7s
+5ork
+8s
+4y
+3ier
+5st
+4ly
+4ness
+8es
+5g
+6s
+3y
+2que
+5laure
+9es
+5s
+5t
+6ed
+6ing
+6s
+6te
+8s
+2ral
+3e
+4s
+3ic
+4d
+4e
+5r
+5st
+3qual
+7s
+3t
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7s
+4s
+4y
+3y
+2sace
+6a
+7s
+6ous
+6s
+4ker
+7s
+4lia
+7s
+4nilin
+9e
+9es
+9s
+4ria
+7n
+8s
+6es
+6um
+8s
+5y
+3bif
+6s
+3cid
+4oe
+6s
+3e
+4al
+5te
+7ly
+4bay
+7s
+5owl
+8s
+5ud
+7s
+6sh
+8es
+4d
+4finch
+9es
+6sh
+8es
+4hip
+7s
+4less
+5ike
+5la
+7s
+6e
+7s
+4maling
+9gs
+6ries
+7y
+4ola
+7r
+7s
+4ries
+5oot
+8s
+5y
+4s
+5lug
+8s
+4t
+5ed
+5ing
+5s
+5te
+7d
+7s
+6ing
+9s
+6y
+5y
+4water
+9s
+5ood
+8s
+3hi
+5s
+3ied
+5r
+6e
+7s
+6s
+5s
+6t
+4ly
+4n
+5ate
+8s
+5ed
+6r
+7s
+6ss
+8es
+5g
+5ing
+5ol
+7s
+6us
+5s
+5weed
+9s
+5y
+4t
+5ed
+5ing
+5s
+3marine
+9s
+3oglio
+8s
+4lio
+7s
+3ser
+6s
+3t
+4ed
+5lla
+8r
+8te
+7um
+9s
+5r
+6ed
+6ing
+9s
+6s
+4i
+5ng
+5s
+4ra
+6l
+7ly
+6te
+8d
+5ocarinate
+9inates
+5um
+7s
+4s
+3ula
+6s
+6te
+3y
+4ing
+2t
+3a
+4chute
+9s
+4l
+4meter
+9s
+4n
+5s
+4plane
+9s
+4ries
+5y
+4s
+4table
+5e
+6d
+6s
+5ing
+6on
+8al
+8s
+6ve
+8ly
+5or
+7es
+7s
+7y
+4vate
+8d
+8s
+7ing
+7or
+9s
+5irus
+9es
+3ch
+5e
+6s
+5ie
+7s
+3e
+4d
+4none
+8s
+4s
+3grass
+8es
+4ut
+6s
+3her
+6s
+3i
+4fer
+7al
+8n
+9s
+7ous
+7s
+5orm
+4ng
+4s
+5serie
+9es
+3l
+4s
+3o
+4graph
+9ed
+9ing
+9s
+7vure
+9res
+4lo
+6s
+4n
+5s
+4r
+5craft
+9ts
+5s
+4s
+5cope
+9d
+9s
+8ing
+4till
+8ed
+9r
+9rs
+8ing
+8s
+4vate
+8d
+8s
+7ing
+7or
+9s
+3s
+3tan
+6s
+4e
+5d
+5n
+6er
+7st
+6ly
+6ness
+9ses
+6s
+7tone
+9ned
+9nes
+9ning
+5r
+6s
+5s
+4ing
+4weiler
+9rs
+3ula
+6e
+6s
+4nd
+6a
+7s
+7te
+6ed
+7r
+7st
+6ing
+7ties
+8y
+6ly
+6ness
+9ses
+6s
+4rier
+8s
+2uble
+6s
+3che
+6s
+4ou
+6s
+3e
+4n
+5s
+4s
+3ge
+5d
+5s
+4h
+5age
+8s
+5back
+9s
+5cast
+9ed
+9er
+9ers
+9ing
+9s
+5dried
+9s
+7y
+8ing
+5ed
+6n
+7ed
+7ing
+7s
+6r
+7s
+6st
+5hew
+8ed
+8ing
+8n
+8s
+6ouse
+9ed
+9es
+9ing
+5ie
+7s
+6ng
+6sh
+5leg
+8s
+6y
+5neck
+9ed
+9ing
+9s
+7ss
+9es
+5rider
+9rs
+5s
+6hod
+5t
+5y
+4ing
+3ille
+7s
+3l
+4ade
+7s
+4e
+5au
+7s
+7x
+5s
+5tte
+8d
+8s
+7ing
+4s
+3m
+4ing
+7s
+4s
+3nce
+6s
+6val
+9s
+5ies
+5y
+4d
+5about
+9tation
+9ted
+9tedly
+9tility
+9ting
+9tly
+9tness
+9ts
+6rch
+9ed
+5ball
+9s
+5ed
+7ly
+7ness
+9sses
+6l
+7ay
+9s
+7s
+6r
+7s
+6st
+5hand
+9s
+6eaded
+9edness
+7el
+9s
+6ouse
+9es
+5ing
+8s
+6sh
+5le
+7s
+7t
+8s
+6y
+5ness
+9es
+5s
+6man
+7en
+5table
+9es
+6rip
+9ping
+9pings
+9s
+5up
+7s
+6re
+8s
+5wood
+9s
+7rm
+9s
+3p
+4ed
+5t
+4ier
+6st
+5ly
+5ng
+5t
+4s
+4y
+3sant
+4e
+5about
+9ts
+5d
+6ness
+9ses
+5ment
+9s
+5r
+6s
+5s
+4ing
+7ly
+4seau
+8s
+6tte
+9s
+4t
+5about
+9ts
+5ed
+6r
+7s
+5ing
+5s
+3t
+4e
+5d
+5ing
+5man
+7rch
+9hed
+9hes
+9hing
+6en
+5r
+6s
+5s
+5way
+8s
+4h
+5ie
+7r
+7st
+5s
+4ine
+7er
+9s
+7ly
+7s
+6g
+7s
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+4ous
+7ly
+4s
+3x
+2ve
+4d
+4n
+4r
+5s
+4s
+3ing
+6ly
+6s
+2w
+3able
+4n
+5berries
+9y
+5s
+3boat
+7s
+3dedow
+8s
+4ier
+6s
+7t
+5ly
+5ness
+9es
+4y
+5dow
+8s
+5ish
+7m
+8s
+3ed
+4l
+5ed
+5ing
+5led
+6ing
+5s
+4n
+5s
+4r
+5s
+3ing
+6s
+3lock
+7s
+3me
+5s
+3nd
+5ed
+6ll
+8s
+5ing
+5s
+3over
+7s
+3s
+3t
+4ed
+4h
+5s
+4ing
+4s
+2yal
+5et
+7s
+5ise
+8d
+8s
+7ing
+7m
+8s
+7t
+8ic
+8s
+6ze
+8d
+8s
+7ing
+5ler
+7st
+6y
+5mast
+9s
+5s
+5ties
+6y
+3ne
+5d
+5s
+4ing
+5sh
+3st
+5ed
+6r
+7ed
+8r
+9s
+7ing
+7ous
+7s
+5ing
+5s
+2zelle
+7s
+4t
+5ed
+5ing
+5s
+3it
+5ed
+5ing
+5s
+3zer
+6s
+1uana
+5s
+2b
+3aboo
+7s
+4ce
+6s
+4i
+5yat
+4sse
+7s
+4ti
+5o
+6s
+3baboo
+8s
+4ed
+5r
+6ed
+6ier
+8st
+7ng
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6like
+6neck
+9ked
+9ker
+9kers
+9king
+9ks
+6s
+6wear
+9rs
+6y
+5t
+4idies
+6y
+5es
+5ng
+7s
+5sh
+7ed
+8s
+7ing
+7ly
+7y
+5t
+6ies
+6y
+4le
+6d
+6s
+6work
+9ks
+5ier
+7st
+6ng
+5y
+4oard
+8s
+4y
+3down
+7s
+3e
+4facient
+9nts
+7tion
+9ons
+5ied
+7s
+5y
+6ing
+4l
+5la
+7n
+8s
+7s
+6ite
+9s
+5s
+4ola
+7r
+7s
+4s
+5cence
+9es
+8t
+3iaceous
+4celle
+9s
+5on
+7ed
+7ing
+7s
+5und
+8ities
+9ty
+4dic
+6um
+8s
+4ed
+5r
+5s
+6t
+4fied
+7s
+5y
+6ing
+4ginose
+8us
+5o
+6s
+4n
+5e
+6ous
+6s
+5s
+4ous
+3le
+5s
+3off
+6s
+4ut
+6s
+3ric
+6al
+8ly
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6ian
+9s
+6s
+3s
+4tone
+8s
+3us
+3y
+4ing
+4like
+4throat
+9ts
+2c
+3he
+5d
+5s
+4ing
+7s
+3k
+4ed
+4ing
+4le
+6d
+6s
+5ing
+4man
+5en
+4s
+5ack
+8s
+5eat
+8s
+4us
+6es
+3ola
+6s
+3s
+3tation
+9s
+4ion
+7s
+6us
+2d
+3aceous
+4s
+5es
+3beckia
+9s
+3d
+4ed
+5r
+6head
+9ds
+6less
+6post
+9ts
+6s
+7tock
+9cks
+4ied
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+4le
+6d
+6man
+7en
+6s
+5ing
+4ock
+7s
+4s
+4y
+5ing
+3e
+4ly
+4ness
+8es
+4r
+5al
+7s
+5ies
+5y
+4s
+5bies
+6y
+5t
+3ie
+5s
+4ment
+8al
+9lly
+9rily
+9riness
+9ry
+8s
+4sh
+3s
+2e
+3d
+4a
+5s
+3ful
+6ly
+6ness
+9ses
+3ing
+6s
+3lle
+6s
+5ia
+7s
+3r
+4s
+3s
+2fescence
+9es
+8t
+3f
+4e
+5d
+5s
+4ian
+7ed
+7ing
+8sh
+9m
+9ms
+7ly
+7s
+5n
+6g
+6s
+4le
+6d
+6r
+7s
+6s
+5ier
+7st
+6ke
+6ng
+8s
+5y
+4s
+3iyaa
+7s
+3ous
+2g
+3a
+4e
+4l
+5ach
+4te
+3bies
+4y
+3elach
+3ged
+6er
+7st
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+6ness
+9ses
+5lach
+5r
+6s
+4ier
+6st
+5ng
+7s
+4y
+3like
+3ola
+6s
+4sa
+6s
+5e
+6ly
+5ities
+7y
+4us
+3s
+3ulose
+2in
+4able
+5te
+7d
+7s
+6ing
+7on
+9s
+4ed
+5r
+6s
+4g
+5s
+4ing
+7s
+4ous
+7ly
+7ness
+9sses
+4s
+2kh
+4s
+2lable
+3e
+4d
+4less
+4r
+5ed
+5ing
+5s
+6hip
+9s
+4s
+5se
+3ier
+5st
+4ng
+6s
+3lion
+7s
+4ock
+7s
+3y
+2m
+3aki
+6s
+4l
+5s
+3ba
+5ed
+5ing
+5s
+4elow
+8s
+4le
+6d
+7ethump
+9humps
+6gumption
+9ptions
+6r
+7s
+6s
+5ier
+7st
+6ng
+8ly
+8s
+5y
+4o
+5s
+4ullion
+9ns
+5stical
+8ous
+9usly
+9usness
+3e
+4lgumption
+9tions
+4n
+5s
+4s
+3fustian
+9ns
+3gumption
+9ons
+3ina
+6l
+6nt
+8ly
+8s
+6te
+8d
+8s
+7ing
+9gly
+8on
+9ns
+8ve
+9ely
+7or
+9s
+3kin
+6s
+3legumption
+9tions
+4y
+3mage
+7d
+7r
+8s
+7s
+6ing
+4elgumption
+9ptions
+5r
+6s
+5st
+4ier
+6s
+7t
+5ly
+5ness
+9es
+5sh
+4legumption
+9ptions
+4y
+3ness
+7es
+3or
+5ed
+5ing
+5monger
+9ering
+9erings
+9ers
+5ous
+5s
+4ur
+6ed
+7r
+8s
+6ing
+6s
+3p
+4ed
+4ies
+5ng
+4le
+6d
+6s
+7s
+5ier
+7st
+6ng
+5y
+4o
+5s
+4s
+4us
+6es
+4y
+3runner
+9s
+3s
+2n
+3about
+8s
+4gate
+8s
+4nga
+7s
+4round
+9s
+4way
+7s
+3back
+7s
+3ch
+5es
+4ible
+5nate
+3d
+4ale
+7s
+4le
+6d
+6s
+6t
+7s
+4own
+7s
+4s
+3e
+4craft
+9s
+4d
+4like
+4s
+3flat
+7s
+3g
+4less
+4s
+3ic
+3kle
+6d
+6s
+5ing
+3less
+5t
+6s
+3nable
+4el
+6s
+5r
+6s
+5t
+6s
+4ier
+6st
+5ness
+9es
+6g
+7ly
+7s
+5on
+7s
+4y
+3off
+6s
+4ut
+6s
+4ver
+7s
+3rig
+6s
+4ound
+8s
+3s
+3t
+4ed
+4ier
+6st
+5ness
+9es
+5sh
+7ly
+4s
+4y
+3way
+6s
+2pee
+5s
+4strian
+3ia
+5h
+6s
+5s
+4coline
+7ous
+3turable
+6e
+7d
+7s
+7wort
+9rts
+6ing
+2ral
+5isation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8s
+7t
+8s
+6te
+8s
+7ies
+7y
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ly
+5ness
+9es
+5s
+3ban
+3idecanal
+3p
+4s
+3u
+4s
+2sa
+4lka
+7s
+4s
+3cus
+6es
+3e
+4s
+3h
+4ed
+5e
+6s
+5n
+5r
+6s
+5s
+4ier
+6st
+5ness
+9es
+6g
+7s
+4light
+9s
+6ke
+4y
+3ine
+3k
+4s
+3ma
+5s
+3se
+5l
+6s
+5t
+6ed
+6ing
+9s
+6s
+6ting
+9gs
+6y
+4ia
+6s
+5fied
+8s
+6y
+7ing
+4ula
+7e
+7s
+3t
+4able
+4bucket
+4ed
+4ic
+6al
+8ly
+8s
+7na
+7te
+9d
+9s
+8ing
+9ngs
+9on
+9ons
+8or
+9rs
+6ial
+7se
+9d
+9s
+8ing
+8m
+9s
+7ties
+8y
+7ze
+9d
+9s
+8ing
+6ly
+6s
+6work
+9ks
+5er
+6st
+5ly
+5ness
+9es
+6g
+7s
+4le
+6d
+6r
+7s
+6s
+7s
+5ing
+8ly
+8s
+4proof
+9ed
+9ing
+9ings
+9s
+4re
+6d
+6s
+4s
+4y
+2t
+3abaga
+8s
+4ceous
+3h
+4enic
+7ous
+7um
+9s
+5rford
+9dium
+9diums
+9ds
+4ful
+7ly
+7ness
+9sses
+4less
+8ly
+8ness
+9esses
+4s
+3ilant
+6ted
+5e
+6s
+4n
+5s
+3s
+3ted
+5r
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+5sh
+7ly
+7ness
+9sses
+4y
+1ya
+3l
+4s
+3s
+2bat
+5s
+4udrye
+9s
+2e
+3bread
+8s
+3flour
+8s
+3grass
+8es
+3peck
+7s
+3s
+2fe
+2ke
+4d
+4s
+3ing
+2mme
+5d
+5s
+4ing
+2nd
+4s
+2okan
+6s
+3t
+4s
+4wari
+8s
+2pe
+4ck
+6s
+4r
+0saag
+4s
+2b
+3adilla
+9s
+4l
+5s
+4ton
+7s
+4yon
+7s
+3bat
+6arian
+6h
+7s
+6ic
+8al
+9ls
+8s
+7ne
+7se
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+6s
+4ed
+4ing
+7s
+3e
+4d
+4ing
+4lla
+7s
+4r
+5ed
+5ing
+5like
+5metrician
+9icians
+9ics
+5s
+4s
+3ha
+5s
+3in
+5e
+6s
+5s
+4r
+5s
+3kha
+6h
+7s
+6s
+6t
+7s
+3le
+5d
+5fish
+9es
+5s
+4ing
+3ot
+5age
+8d
+8s
+7ing
+5eur
+8s
+5ier
+8s
+5s
+3ra
+5s
+4e
+5d
+5s
+5tache
+9es
+5ur
+7s
+5wing
+9s
+4ing
+3s
+3uline
+5ose
+7ities
+9y
+6us
+4rra
+7l
+7s
+7tion
+9ons
+2c
+3ahuista
+9as
+9e
+9es
+4ton
+7s
+3but
+6s
+3cade
+7s
+6ic
+8ally
+5te
+4harase
+9es
+8te
+9ed
+9es
+7ic
+8de
+9es
+8ferous
+9ied
+9ies
+9y
+9ying
+8meter
+9eters
+9etries
+9etry
+8n
+9e
+9ely
+9es
+9ities
+9ity
+9s
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7oid
+9dal
+9ds
+8meter
+9eters
+9yces
+9ycetes
+8se
+9es
+7um
+9s
+4iform
+4oi
+5s
+6es
+4ular
+7te
+9d
+8ion
+9ons
+6e
+7s
+6i
+7form
+6us
+3ella
+6um
+4rdotal
+9lise
+9lised
+9lises
+9lising
+9lism
+9lisms
+9list
+9lists
+9lize
+9lized
+9lizes
+9lizing
+9lly
+3hem
+6dom
+9s
+6ic
+6s
+7hip
+9ps
+5t
+6ed
+6s
+3k
+4able
+5ge
+7s
+4but
+7s
+4cloth
+9s
+4ed
+5r
+6s
+4ful
+7s
+4ing
+7s
+4less
+5ike
+4s
+5ful
+3less
+4ike
+3que
+6s
+3ra
+5l
+6gia
+9s
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+5ment
+9al
+9alism
+9alisms
+9alist
+9alists
+9ality
+9ally
+9alness
+9als
+9arian
+9arians
+9aries
+9ary
+9ed
+9ing
+9s
+5ria
+8l
+7um
+4ed
+6ly
+6ness
+9ses
+4ifice
+9able
+9d
+9r
+9rs
+9s
+8ial
+9ally
+9ng
+7de
+7ed
+8s
+6y
+7ing
+5lege
+9s
+8ious
+9ously
+9st
+9sts
+5ng
+7s
+5st
+7an
+9s
+7ies
+7s
+7y
+4ococcygeal
+7stal
+9als
+5iliac
+9cs
+8itis
+9tises
+5sanct
+9tities
+9tity
+9tness
+4um
+6s
+3s
+2d
+3ded
+5n
+6ed
+6ing
+6s
+5r
+5st
+4hu
+6s
+4ie
+6s
+5ng
+5sh
+4le
+6back
+9ked
+9ks
+8g
+9s
+7ill
+9ls
+7ow
+9s
+7red
+9ds
+6cloth
+9ths
+6d
+6less
+6r
+7ies
+7oom
+9ms
+7s
+7y
+6s
+6tree
+9es
+5ing
+4o
+5es
+5s
+3e
+4s
+3hana
+7s
+4e
+5s
+4u
+5s
+3i
+4ron
+7s
+4s
+3ly
+3ness
+7es
+3o
+4masochism
+9hisms
+9hist
+9histic
+9hists
+4s
+3s
+3za
+5s
+2e
+3culum
+8s
+3ter
+6s
+2fari
+6ed
+6ing
+6s
+7t
+8s
+3e
+4cracker
+9ers
+9ing
+9ings
+4d
+4guard
+9ed
+9ing
+9s
+4keeping
+9ngs
+4light
+9s
+5y
+4ness
+8es
+4r
+4s
+5t
+4tied
+7s
+5y
+6ing
+6man
+7en
+3fian
+7s
+4lower
+9s
+4ron
+7ed
+7s
+7y
+3ing
+3ranin
+8e
+9s
+8s
+4ol
+6e
+7s
+6s
+5nal
+8s
+3t
+4er
+5st
+2g
+3a
+4cious
+9ly
+9ness
+9nesses
+6ties
+7y
+4man
+5en
+5ore
+8s
+4nash
+8es
+4penum
+9s
+4s
+4thies
+6y
+3but
+6s
+3e
+4brush
+9es
+4ly
+4ne
+6s
+7s
+8es
+5ite
+8s
+7ic
+4r
+4s
+5t
+3gar
+6d
+7s
+6ed
+6ing
+6s
+4ed
+5r
+6ed
+6ing
+6s
+4ier
+6st
+5ng
+7s
+4y
+3ier
+5st
+4nate
+8d
+8s
+7ing
+8on
+9ns
+4tta
+7l
+8ly
+7ries
+8y
+7s
+7te
+6iform
+3o
+4in
+6s
+4s
+4uin
+7s
+3rada
+3s
+3uaro
+7s
+4in
+6s
+4m
+3y
+2heb
+5s
+3ib
+5a
+6h
+7s
+6s
+5s
+4wal
+7s
+3uaro
+7s
+2i
+3bling
+8s
+3c
+4e
+5s
+4k
+5s
+4s
+3d
+4est
+4s
+5t
+3ga
+5s
+3kei
+6s
+4less
+3l
+4able
+4board
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+7t
+8er
+9rs
+8ing
+9ngs
+8s
+4cloth
+9s
+4ed
+5r
+6s
+4fish
+8es
+4ing
+7s
+4less
+4maker
+9s
+7ing
+9gs
+4or
+6ing
+9s
+6less
+7ike
+7y
+6s
+4plane
+9d
+9r
+9rs
+9s
+8ing
+4room
+8s
+4s
+3m
+4in
+6s
+5ri
+7s
+4s
+3n
+4e
+5d
+4foin
+8s
+4ing
+4s
+4t
+5dom
+8s
+5ed
+6ss
+8es
+5foin
+9s
+5hood
+9s
+5ing
+6sh
+7m
+8s
+5less
+6ier
+8st
+7ke
+7ly
+7ness
+9sses
+8g
+9s
+6y
+5paulia
+9ias
+5s
+6hip
+9s
+3que
+6s
+3r
+4ed
+5r
+5st
+4ing
+4s
+3s
+4t
+3th
+5e
+6s
+5s
+3yid
+6s
+2jou
+5s
+2kai
+5s
+3e
+4r
+5et
+7s
+5s
+4s
+3i
+4a
+5s
+4eh
+6s
+4s
+4yeh
+7s
+3koi
+5s
+6es
+3saul
+7s
+2l
+3aam
+6ed
+6ing
+6s
+4bilities
+9y
+5le
+7ness
+9sses
+6y
+4cious
+9ly
+9ness
+9nesses
+6ties
+7y
+4d
+5ang
+8s
+5e
+6s
+5ing
+8s
+5s
+4l
+5s
+4mander
+9rs
+8rian
+9ine
+9oid
+9oids
+5i
+6s
+5on
+7s
+4ngane
+9s
+4riat
+8s
+6ed
+7s
+5y
+6ing
+6man
+7en
+3band
+7s
+4utamol
+9ls
+3chow
+7s
+3e
+4abilities
+9ty
+6le
+8ness
+9esses
+7y
+4p
+5s
+4ratus
+9es
+5ing
+8s
+5oom
+8s
+4s
+5clerk
+9ks
+5girl
+9s
+5ladies
+8y
+5man
+8ship
+9hips
+6en
+5people
+7rson
+9ons
+5room
+9s
+5woman
+8en
+4t
+5s
+4wd
+4yard
+8s
+3fern
+7s
+3iaunce
+9s
+4c
+5aceous
+5es
+6t
+7a
+7s
+7um
+9s
+5in
+7e
+8s
+7s
+6onal
+9ls
+5ornia
+9as
+5ylamide
+9ides
+8te
+9ed
+9es
+9ing
+7ic
+8sm
+9ms
+4ence
+8s
+7ies
+7y
+6t
+7ian
+9ns
+7ly
+7s
+4ferous
+5iable
+6cation
+9ions
+6ed
+7s
+5y
+6ing
+4got
+7s
+4meter
+9s
+7ric
+9es
+8y
+4na
+6s
+5e
+6s
+5isation
+9ions
+7e
+8d
+8s
+7ing
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ometer
+9ers
+9ric
+9ries
+9ry
+4va
+6l
+6ry
+6s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+4x
+3l
+4ad
+6s
+5l
+6s
+4e
+5e
+6s
+5nders
+5s
+5t
+6s
+4ied
+6r
+7s
+6s
+4ow
+6ed
+7r
+7st
+6ing
+7sh
+6ly
+6ness
+9ses
+6s
+6y
+4y
+5ing
+5port
+9s
+3magundi
+9ies
+9is
+9y
+5naser
+9rs
+7zar
+9rs
+4i
+5s
+4on
+6berries
+9ry
+6ella
+9ae
+9as
+9oses
+9osis
+7t
+8s
+6id
+8s
+6oid
+9s
+6s
+6y
+3ol
+5s
+4meter
+9s
+4n
+5s
+4on
+6s
+5p
+6s
+4p
+5ettes
+5ian
+5s
+3p
+4a
+5e
+5s
+4ian
+7s
+5con
+8s
+5d
+6s
+5form
+5glosses
+9sis
+9sises
+5ngectomies
+9tomy
+8s
+7ian
+8tes
+9ic
+9ides
+9is
+9ises
+6x
+7es
+4s
+3s
+4a
+5ed
+5ing
+5s
+4e
+5s
+4ifies
+6y
+5lla
+8s
+4olaceous
+4uginous
+3t
+4ando
+6t
+7s
+5relli
+9o
+9os
+5te
+7d
+7s
+6ing
+7on
+9ism
+9isms
+9ist
+9ists
+9s
+6o
+7rial
+9ous
+8y
+4box
+7es
+5ush
+8es
+4cat
+7s
+5ellar
+9rs
+5huck
+9er
+9ers
+9s
+4ed
+5r
+6n
+7s
+6s
+5st
+4fish
+8es
+4ie
+6r
+7s
+6s
+7t
+5grade
+9es
+5ly
+5mbanco
+9cos
+7occa
+9cas
+5ne
+7s
+8s
+9es
+6g
+7s
+5re
+7s
+7wise
+5sh
+7ly
+7ness
+9sses
+4less
+5ike
+5y
+4ness
+8es
+4o
+5ed
+5ing
+5s
+4pan
+7s
+5eter
+9s
+7re
+9man
+9men
+9s
+4s
+5haker
+9rs
+4us
+6es
+4water
+5ork
+8s
+7t
+8s
+4y
+3ubrious
+9sly
+9sness
+7ties
+8y
+4e
+5d
+5s
+4ing
+4ki
+6s
+4retic
+9s
+4tarily
+8ness
+9esses
+7y
+6tion
+9nal
+9ns
+7orian
+9ians
+9ies
+9ily
+9y
+5e
+6d
+6r
+7s
+6s
+5iferous
+6ng
+3vabilities
+9ty
+6le
+8ness
+9esses
+7y
+5ge
+7ability
+9le
+7d
+7e
+8s
+7r
+8s
+7s
+6ing
+5rsan
+9s
+5tion
+9al
+9ism
+9isms
+9ist
+9ists
+9s
+6ories
+8y
+4e
+5d
+5r
+6form
+6s
+5s
+5te
+7s
+4ia
+6s
+5fic
+8al
+9lly
+5ng
+7s
+6iaceous
+4o
+5ed
+6s
+5ing
+5r
+6s
+5s
+3war
+6s
+2m
+3a
+4an
+6s
+4dhi
+7s
+4n
+5s
+4ra
+6s
+5iform
+6tan
+9s
+6um
+8s
+5skite
+9es
+4s
+3ba
+5ed
+5ing
+5l
+6s
+5r
+6s
+5s
+4har
+7s
+5ur
+7s
+4o
+5s
+4uca
+7s
+5ke
+7s
+5r
+6s
+3e
+4ch
+6s
+4k
+5h
+6s
+5s
+4l
+5y
+4n
+5ess
+8es
+4s
+4y
+5ness
+9es
+3foo
+6s
+4u
+5s
+3iel
+6s
+5r
+5st
+4sen
+7s
+4te
+6s
+5hi
+7s
+5i
+6s
+4zdat
+8s
+3let
+6s
+4or
+6s
+3med
+4ies
+5ng
+4y
+3nitis
+8es
+3osa
+6s
+4var
+7s
+4yed
+7s
+3p
+4an
+6s
+4hire
+8s
+4i
+5re
+7s
+5s
+4le
+6d
+6r
+7ies
+7s
+7y
+6s
+5ing
+8s
+4s
+3s
+4ara
+7s
+6ic
+4hoo
+7s
+5u
+6s
+3urai
+7s
+2n
+3ative
+5oria
+8um
+9ms
+7y
+3benito
+9s
+3cai
+6s
+4ho
+6s
+4ta
+5ifiable
+8cation
+9ations
+8ed
+9dly
+9r
+9rs
+9s
+7y
+8ing
+9ngly
+9ngs
+6monies
+9ious
+9iously
+9y
+6on
+8able
+8ed
+9er
+9ers
+9r
+9rs
+8ing
+8less
+8s
+6ties
+7ude
+9es
+7y
+5uaries
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+8y
+6m
+7s
+3d
+4able
+5l
+6ed
+6ing
+6led
+7ing
+6s
+6wood
+9ds
+5rac
+8h
+9s
+8s
+4bag
+7ged
+9r
+9rs
+8ing
+7s
+6nk
+8s
+6r
+7s
+5last
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+5ox
+7es
+6y
+7s
+5ur
+7r
+8s
+7s
+4castle
+9es
+5rack
+9s
+4dab
+7s
+4ed
+5k
+6s
+5r
+6ling
+9gs
+6s
+7es
+7wood
+9ods
+4fish
+8es
+5lies
+6y
+4glass
+9es
+5roper
+9rs
+7use
+9es
+4heap
+8s
+5i
+6ll
+8s
+6s
+5og
+7s
+4ier
+6st
+5ness
+9es
+6g
+7s
+5ver
+8s
+4less
+5ike
+6ng
+8s
+5ot
+7s
+7ter
+9rs
+4man
+5en
+4painting
+9ings
+6per
+9ed
+9ing
+9s
+9y
+5eep
+8s
+5ile
+8s
+6per
+9s
+6t
+7s
+5ump
+8s
+4s
+5hoe
+8s
+5oap
+8s
+5pout
+9s
+6ur
+8s
+5tone
+9s
+7rm
+9s
+5ucker
+9rs
+4wich
+8ed
+9s
+8ing
+5orm
+8s
+7t
+8s
+4y
+5ish
+3e
+4d
+4ly
+4ness
+8es
+4r
+4s
+5t
+3g
+4a
+5r
+6ee
+8s
+6s
+5s
+4eet
+7s
+5r
+6s
+4froid
+9s
+4h
+5a
+6s
+6t
+7s
+5s
+4lier
+8s
+4o
+5ma
+7s
+5s
+4ria
+7s
+4s
+4uiferous
+7ication
+9ations
+8ed
+9s
+7y
+8ing
+6naria
+9ias
+9ily
+9iness
+9y
+7e
+8d
+8ly
+8ness
+9esses
+8ous
+9usness
+8s
+7ing
+8ties
+9y
+8vorous
+7olencies
+9ency
+9ent
+6vorous
+3icle
+7s
+4dine
+8s
+4es
+4fied
+7s
+5y
+6ing
+4ng
+4ous
+4taria
+9n
+9nism
+9nisms
+9ns
+8es
+8ly
+8ness
+9esses
+8st
+9ts
+8um
+9ms
+7y
+6te
+8d
+8s
+7ing
+8on
+9nist
+9nists
+9ns
+5ies
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5oria
+8um
+9ms
+5y
+3jak
+6s
+3k
+4o
+5s
+3nie
+6s
+4op
+6s
+4up
+6s
+4yasi
+8n
+9s
+8s
+3pan
+6s
+4ro
+6s
+3s
+4a
+5r
+6s
+5s
+4culotte
+9terie
+9teries
+9tes
+9tic
+9tides
+9tish
+9tism
+9tisms
+9tist
+9tists
+4ei
+6s
+5rif
+8s
+5vieria
+9ias
+3t
+4al
+6aceous
+6ic
+7n
+8s
+6ol
+8s
+6s
+4era
+7s
+6ia
+8s
+6o
+7s
+4imi
+6s
+6u
+5r
+6s
+4o
+5l
+6ina
+9s
+6s
+5n
+6ica
+9s
+7n
+8s
+6s
+5or
+7s
+5s
+5ur
+7s
+4s
+4ur
+6s
+3yasi
+7s
+2ola
+5s
+3uari
+7s
+2p
+3ajou
+7s
+4n
+5s
+5wood
+9s
+3ego
+6es
+4le
+6s
+3ful
+3head
+7ed
+7s
+5na
+7e
+7s
+6ous
+3id
+5ities
+7y
+5less
+5ness
+9es
+4ence
+8s
+7ies
+7y
+6s
+6t
+7ial
+9lly
+7ly
+7s
+4ndaceous
+3less
+7ness
+9sses
+4ing
+7s
+3odilla
+9s
+4genin
+9s
+4naceous
+9usness
+6ria
+9s
+6ted
+5ifiable
+8cation
+9ations
+8ed
+9r
+9rs
+9s
+7y
+8ing
+6n
+7e
+8s
+7s
+6te
+8s
+4r
+5ific
+5ous
+5s
+4ta
+6ceous
+6s
+5e
+6s
+4ur
+6s
+3pan
+6s
+6wood
+9ds
+4ed
+5r
+6ment
+6s
+4hic
+7s
+6re
+8d
+8s
+7ine
+9es
+6sm
+8s
+7t
+8s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4le
+6d
+6s
+5ing
+4y
+3raemia
+9s
+8c
+4emia
+8s
+7c
+4obe
+7s
+6ial
+7c
+7ont
+9ts
+8tic
+5genic
+9cities
+9city
+8ous
+5legnia
+9ias
+6ite
+9s
+8ic
+5pel
+8ic
+9te
+9tes
+8s
+6hagous
+7yte
+9es
+9ic
+9ically
+9ism
+9isms
+5troph
+9hic
+9hs
+5zoic
+3s
+4ago
+7s
+4ucker
+9s
+3ucaia
+8s
+3wood
+7s
+2r
+3aband
+8e
+9s
+8s
+4fan
+7s
+4n
+5gi
+7s
+5s
+4pe
+6s
+3bacane
+9s
+3casm
+7s
+6tic
+9ally
+4enchymatous
+9me
+9mes
+6et
+8s
+4ina
+7e
+7s
+4ocarp
+9s
+6olla
+9as
+6ystis
+9ises
+5de
+7s
+6ic
+5id
+7oses
+9is
+7s
+5lemma
+9al
+9as
+9ata
+6ogies
+8y
+5ma
+7s
+7ta
+8oid
+9ses
+9sis
+9us
+6ere
+9s
+5net
+8s
+5phagal
+9i
+9ous
+9us
+9uses
+6lasm
+9mic
+9ms
+6tic
+5somal
+8e
+9s
+5us
+3d
+4ana
+7s
+5r
+6s
+4el
+6le
+8s
+6s
+4ine
+7d
+7s
+6ing
+5us
+7es
+4onian
+7c
+8al
+9lly
+8ism
+9sms
+6yx
+8es
+4s
+3ed
+4e
+5s
+3gasso
+8s
+7um
+9s
+4e
+5s
+4o
+5s
+6es
+4us
+6es
+3i
+4n
+5g
+5s
+4s
+3k
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4s
+4y
+3ment
+7a
+8ceous
+7ose
+8us
+7s
+7um
+4ie
+6s
+3ney
+6s
+4ie
+6s
+3od
+5e
+6s
+5ist
+8s
+5s
+4ng
+6s
+5ic
+4s
+5es
+3panch
+8es
+3racenia
+9aceous
+9as
+5sin
+8s
+5zin
+8s
+4usophone
+9ones
+3s
+4aparilla
+9llas
+5r
+6s
+4den
+7s
+4en
+6et
+8s
+6s
+4net
+7s
+3tor
+6ial
+9ly
+8n
+7i
+7us
+9es
+6s
+3us
+5es
+2sarara
+8s
+3er
+5s
+3h
+4ay
+6ed
+6ing
+6s
+4ed
+5s
+4imi
+7s
+5ng
+4less
+3in
+5e
+6s
+5s
+3katoon
+9s
+3quatch
+9es
+3s
+4abies
+6y
+5fras
+9es
+5rara
+9s
+4e
+5d
+5s
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+4olin
+8s
+7te
+9s
+4wood
+8s
+4y
+5wood
+9s
+3tra
+6s
+5uga
+7i
+2t
+3ai
+5s
+4ng
+6s
+5ic
+7al
+9ly
+9ness
+9nesses
+6sm
+8s
+7t
+8s
+6ties
+7y
+5ologies
+9y
+6phanies
+9ny
+8obia
+9bias
+4ra
+6s
+4y
+5s
+3chel
+7ed
+7ful
+9ls
+7led
+7s
+8ful
+3e
+4d
+5ness
+9es
+4en
+6s
+4less
+5les
+6ite
+9d
+9s
+8ic
+9ng
+9se
+9sed
+9ses
+9sing
+9um
+9ums
+9ze
+9zed
+9zes
+9zing
+4m
+4s
+3i
+4abilities
+9ty
+6le
+7y
+5te
+7d
+7s
+6ing
+7on
+9s
+4eties
+6y
+4n
+5ed
+6t
+7s
+7ta
+9s
+8e
+9s
+5flower
+9ers
+5g
+5ing
+5pod
+8s
+5s
+5wood
+9s
+5y
+4re
+6s
+5ic
+7al
+9ly
+9ness
+9nesses
+6sable
+8tion
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7t
+8s
+6zable
+8tion
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+4s
+5faction
+9ions
+9orily
+9ory
+6iable
+7ce
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+7ed
+8r
+9s
+8s
+6y
+7ing
+9gly
+4ve
+3ori
+6s
+3rap
+6al
+6ies
+6s
+6y
+3suma
+7s
+3urabilities
+9ity
+7le
+6nt
+8s
+6te
+8d
+8r
+9s
+8s
+7ing
+8on
+9ns
+7or
+9s
+5nalia
+9an
+9anly
+9as
+6ic
+7id
+9s
+7ne
+9ly
+8ities
+9ty
+7sm
+9s
+8t
+9s
+3yagraha
+9as
+9i
+9is
+4r
+5a
+6l
+7s
+6s
+5esque
+7s
+8es
+5iases
+8is
+6c
+7al
+6d
+7s
+6sk
+8s
+5like
+5s
+2u
+3ba
+5s
+3ce
+5boat
+9s
+7x
+8es
+5d
+5less
+5pan
+8s
+6ot
+8s
+5r
+6ful
+9s
+6less
+7ike
+6s
+5s
+4h
+5s
+4ier
+7s
+6st
+5ly
+5ness
+9es
+6g
+5sse
+8s
+7on
+9s
+4y
+3erbraten
+9ens
+5kraut
+9ts
+3fgard
+8s
+3ger
+6s
+4h
+5s
+5y
+3l
+4ge
+6s
+4ie
+6s
+4s
+4t
+5s
+3na
+5ed
+5ing
+5s
+4t
+5ed
+6r
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7s
+5ing
+5s
+3rel
+6s
+4ian
+7s
+5es
+5schian
+9ans
+4ognathous
+5id
+5pod
+8ous
+8s
+6sidan
+9ans
+6terygian
+4y
+3sage
+7s
+4surite
+9es
+9ic
+3t
+4e
+5d
+5ed
+6ing
+5ing
+5rne
+8s
+5s
+4ing
+4oir
+7e
+8s
+7s
+4s
+2v
+3able
+7ness
+9sses
+4ge
+6d
+7om
+9s
+6ly
+6ness
+9ses
+6r
+7ies
+7y
+6s
+7t
+5ing
+6sm
+8s
+4nna
+7h
+8s
+7s
+5t
+6e
+7s
+6s
+4rin
+7s
+4te
+6s
+3e
+4able
+8ness
+9esses
+4d
+4gard
+8ed
+8ing
+8s
+4loy
+7s
+4r
+5s
+4s
+4y
+5ed
+5ing
+5s
+3in
+5e
+6s
+5g
+6ly
+6ness
+9ses
+6s
+5s
+4or
+6s
+5ur
+7s
+3or
+5ed
+6r
+7s
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5less
+5ous
+5s
+5y
+4ur
+6ed
+7r
+8s
+6ier
+8s
+9t
+7ly
+7ness
+9sses
+8g
+6less
+7y
+6s
+6y
+4y
+5ard
+8s
+5s
+3s
+3vey
+6ed
+6ing
+6s
+4ied
+6r
+6s
+7t
+5ly
+5ness
+9es
+4y
+5ing
+2w
+3ah
+5s
+3bill
+7s
+4lade
+8s
+4ones
+8es
+4uck
+7s
+3der
+6ed
+6ing
+6s
+4ust
+7ed
+7ing
+7s
+7y
+3ed
+4r
+5s
+3fish
+7es
+4lies
+5y
+3grass
+8es
+3horse
+8s
+3ing
+6s
+3like
+4og
+6s
+3mill
+7s
+3n
+4ey
+6s
+3pit
+6s
+3s
+4hark
+8s
+3teeth
+4imber
+9s
+4ooth
+3yer
+6s
+2x
+3atile
+4ul
+6s
+3e
+4s
+3horn
+7s
+3icavous
+5ole
+7ine
+7ous
+4fragaceous
+8e
+9s
+4toxin
+9s
+3onies
+6te
+8s
+5y
+4phone
+9s
+8ic
+9st
+9sts
+3tuba
+7s
+2y
+3able
+3ed
+5s
+4r
+5s
+4st
+3id
+5s
+4ng
+6s
+3ne
+3on
+5ara
+8s
+5s
+3s
+4t
+3yid
+6s
+2z
+3erac
+7s
+4s
+3hen
+6s
+3zes
+1birri
+5o
+1cab
+4bard
+8ed
+8ing
+8less
+8s
+5ed
+7ness
+9sses
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5le
+7d
+7s
+6ing
+5y
+4erulous
+4ies
+6tic
+5osa
+8s
+6us
+8es
+4land
+8s
+5ike
+4rid
+7ities
+9y
+5ous
+8ly
+8ness
+9esses
+4s
+3d
+4s
+3ff
+5ie
+7s
+5olage
+9es
+7d
+8age
+9ges
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+5s
+3g
+4ged
+5ing
+4lia
+7s
+6ola
+9s
+4s
+3il
+5ed
+5ing
+5s
+4th
+6ed
+6ing
+6less
+6s
+3la
+5bilities
+9ty
+6le
+8ness
+9esses
+7y
+5de
+7s
+6o
+7s
+5e
+5ge
+7s
+5r
+6e
+7s
+6iform
+9rmly
+6s
+5tion
+9s
+5wag
+8s
+4d
+5berries
+9y
+5ed
+6r
+7s
+5fish
+9es
+5head
+9s
+5ic
+6ng
+8s
+7i
+7o
+5s
+6hip
+9s
+4e
+5able
+8y
+5board
+9ds
+5d
+5less
+6ike
+5ne
+6i
+6ohedra
+9dron
+9drons
+6us
+5pan
+8s
+5r
+6s
+5s
+5tail
+9s
+5up
+7s
+5work
+9s
+4ier
+6st
+5ness
+9es
+6g
+7s
+4l
+5awag
+9s
+5ed
+5ies
+6on
+8s
+5op
+7ed
+8r
+9s
+7ing
+9gs
+9i
+9is
+7s
+5s
+5y
+6wag
+9s
+4ogram
+9s
+5ppine
+9es
+9i
+4p
+5ed
+6l
+7lic
+9form
+7s
+6r
+7s
+5ing
+8s
+7s
+5less
+5riform
+6um
+8s
+5s
+4y
+3m
+4baiting
+9ngs
+5le
+7d
+7r
+8s
+7s
+6ing
+9ly
+9s
+4el
+6s
+4med
+6r
+7s
+5ing
+5oniate
+8es
+7y
+4p
+5ed
+6r
+7ed
+8r
+9s
+7ing
+7s
+5i
+6es
+6ng
+8s
+6s
+7h
+8ly
+8ness
+9esses
+5s
+4s
+5ter
+8s
+4to
+6s
+3n
+4d
+5al
+7ed
+7ing
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7led
+8ing
+7monger
+9ngers
+7ous
+9sly
+9sness
+7s
+5ent
+5ia
+7s
+6c
+6um
+8s
+4nable
+5ed
+6r
+7s
+5ing
+8s
+4s
+5ion
+8s
+5orial
+4t
+5ed
+6r
+6st
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+7g
+6ties
+7y
+5le
+7d
+7s
+6ing
+9s
+6y
+5ness
+9es
+5s
+5y
+3pa
+5ed
+5ing
+5s
+4e
+5d
+5gallows
+9owses
+6oat
+9ed
+9ing
+9ings
+9ism
+9isms
+9s
+6race
+9es
+5less
+5ment
+9s
+5s
+5wheel
+9ls
+4hocephali
+9halic
+9halics
+9halies
+9halism
+9halous
+9halus
+9haly
+6id
+8s
+6pod
+9s
+4i
+5gerous
+5ng
+4olite
+9s
+5se
+4ple
+7d
+7s
+6ing
+4ula
+7e
+7r
+8ies
+8s
+8y
+7s
+7ted
+6imancies
+9ncy
+9ntic
+6omancies
+9ncy
+9ntic
+5s
+3r
+4ab
+6aean
+9ns
+8i
+9d
+9ds
+9st
+9sts
+8oid
+9ids
+8us
+9ses
+6ee
+8s
+6oid
+9s
+6s
+5mouch
+9he
+9hes
+4ce
+6ly
+6ment
+9ts
+6ness
+9ses
+6r
+6st
+5ities
+7y
+4e
+5crow
+9s
+5d
+6er
+7st
+5head
+9s
+5monger
+9ering
+9erings
+9ers
+5r
+6s
+5s
+5y
+4f
+5ed
+6r
+7s
+5ing
+8s
+6sh
+8es
+5pin
+8s
+5s
+6kin
+9s
+5wise
+4ier
+6st
+5fication
+9tions
+9tor
+9tors
+7ed
+8r
+9s
+8s
+6y
+7ing
+9gly
+5ly
+5ness
+9es
+6g
+5ose
+6us
+4latina
+9al
+9as
+5ess
+6t
+7ed
+7ing
+7s
+4moge
+8s
+4p
+5a
+6ed
+6ing
+6s
+5ed
+6r
+7ed
+7ing
+7s
+6tti
+8o
+5h
+6ed
+6ing
+6s
+5ines
+7g
+8s
+5s
+4re
+6d
+6s
+5ier
+7st
+6ng
+8s
+5y
+4s
+4t
+5ed
+5h
+6s
+5ing
+5s
+4ves
+4y
+3tback
+8s
+4ch
+6es
+4h
+5e
+6d
+6ful
+9ness
+9nesses
+6less
+6s
+5ing
+8ly
+5s
+4ole
+7s
+6ogic
+9cal
+9es
+9st
+9sts
+8y
+5phagies
+9ous
+9y
+4s
+4t
+5ed
+6r
+7able
+8tion
+9ions
+7brain
+9ained
+9ains
+7ed
+9ly
+8r
+9s
+7good
+9ods
+8ram
+9ams
+8un
+9ns
+7ing
+9gly
+9gs
+7ling
+9ngs
+7mouch
+9uches
+7ometer
+9eters
+7s
+8hot
+7y
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5s
+5y
+4urient
+3ud
+5ed
+5ing
+5s
+4p
+5ed
+6r
+7s
+5ing
+5s
+4r
+5ed
+5ies
+6ng
+5s
+5y
+3vage
+7r
+8s
+7s
+4enge
+8d
+8r
+9ed
+9ies
+9ing
+9ings
+9s
+9y
+8s
+7ing
+9gs
+3w
+4s
+4tite
+8s
+3zon
+6s
+6tes
+7ic
+9s
+2eat
+5t
+6as
+3dule
+7d
+7s
+6ing
+3lerat
+8e
+9s
+8s
+3na
+5ries
+7o
+8s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8t
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6y
+5s
+4d
+5ed
+5ing
+5s
+4e
+5d
+5man
+6en
+5ries
+6y
+5s
+6hifter
+9ters
+6ter
+9s
+4ic
+6al
+8ly
+6s
+5ng
+4ographer
+9hers
+9hic
+9hical
+9hies
+9hy
+4t
+5ed
+5ful
+5ing
+8s
+5less
+9ness
+9nesses
+5s
+3psis
+7es
+4ter
+7ed
+7ing
+7less
+7s
+5ic
+7al
+9ly
+7ism
+9ms
+7s
+5ral
+6e
+7d
+7less
+7s
+6ing
+6y
+3rne
+6d
+6s
+5ing
+3uophylacia
+9acium
+9ax
+9axes
+2hadenfreude
+9eudes
+4lstein
+9ns
+4nse
+7s
+5tze
+8s
+5ze
+7s
+4ppe
+7d
+7ing
+7s
+5ska
+8s
+4tchen
+9s
+4v
+5s
+3echita
+9h
+9hs
+9s
+5klaton
+9ons
+4dular
+7e
+8d
+8r
+9s
+8s
+7ing
+4elite
+9s
+4fflera
+9as
+4llies
+6um
+8s
+6y
+5m
+6s
+4ma
+6s
+6ta
+7ic
+9al
+9ally
+9s
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5e
+6d
+6r
+7s
+6s
+5ie
+7s
+6ng
+8ly
+8s
+5ozzle
+9ed
+9es
+9ing
+4rzandi
+9o
+9os
+6i
+6o
+7s
+3iavone
+9s
+4edam
+8s
+4ller
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+6ing
+9s
+4mmel
+8s
+4ndyleses
+9sis
+9tic
+4pperke
+9es
+4sm
+6a
+7s
+7tic
+9cal
+9cally
+9cals
+9cs
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+6s
+5t
+6ose
+8ities
+9ty
+8omal
+9me
+9mes
+9miases
+9miasis
+7us
+6s
+4zaeaceous
+6nthus
+9uses
+5ier
+7st
+5o
+6carp
+9pic
+9pous
+9ps
+6geneses
+9esis
+9etic
+9ic
+7nathous
+7onic
+9ies
+9ous
+9y
+6id
+8al
+8s
+6mycete
+9etes
+9etic
+9etous
+6nt
+8s
+6phrene
+9enes
+9enetic
+9enia
+9enias
+9enic
+9enics
+8yceous
+9te
+9tes
+9tic
+7od
+9al
+9ous
+9s
+6s
+6thymia
+9mias
+9mic
+5y
+5zier
+8st
+6y
+3lager
+8s
+4emiel
+9s
+7hl
+9s
+5p
+6p
+7ed
+8r
+9s
+7ier
+9st
+8ng
+7s
+7y
+6s
+4ich
+7s
+5ere
+8n
+7ic
+5mazel
+9ls
+4ock
+7er
+9s
+7ier
+9st
+7meister
+9isters
+7s
+7y
+5ss
+7es
+4ub
+6s
+5mbergera
+9geras
+6p
+7ed
+7ier
+9st
+8ng
+7s
+7y
+3maltz
+8es
+8ier
+9est
+8y
+6z
+7es
+7ier
+9st
+7y
+5tte
+8s
+4ear
+7ed
+7ing
+7s
+5ck
+7s
+5er
+7ed
+7ing
+7s
+5lz
+7e
+8s
+4ick
+7er
+8st
+4o
+5ck
+7s
+5e
+6s
+5os
+7e
+8d
+8s
+7ing
+6z
+7e
+8d
+8r
+9s
+8s
+7ier
+9st
+8ng
+7y
+5s
+4uck
+7s
+5tter
+9s
+3napper
+9s
+7s
+8es
+6s
+7es
+5uzer
+9s
+4ecke
+8n
+5ll
+4itzel
+9s
+4ook
+7s
+5rkel
+9ed
+9ing
+9led
+9ling
+9s
+6r
+7ed
+8r
+9s
+7ing
+7s
+5z
+6es
+6z
+7es
+7le
+9s
+3olar
+7ch
+9s
+7lier
+9est
+9ness
+9nesses
+8y
+7s
+8hip
+9ips
+6stic
+9cal
+9cally
+9cate
+9cates
+9cism
+9cisms
+9cs
+5ia
+7st
+9ic
+9s
+6on
+6um
+8s
+4ol
+6bag
+9s
+7ook
+9ks
+8y
+9ish
+9s
+6child
+9ldren
+7raft
+9fts
+6day
+9s
+6e
+7d
+7ries
+8y
+7s
+6fellow
+9lows
+6girl
+9lish
+9ls
+7oing
+9ngs
+6house
+9ses
+6ie
+8s
+7ng
+9s
+6kid
+9s
+6maid
+9ds
+8n
+8rm
+9mish
+9ms
+8ster
+9tered
+9tering
+9terish
+9terly
+9ters
+8te
+9es
+7en
+7istress
+9tressy
+6room
+9ms
+6s
+6teacher
+9chers
+9ching
+9chings
+7ide
+9es
+8me
+9es
+6ward
+9ds
+7ork
+9ks
+5ner
+8s
+4rl
+6aceous
+6omite
+9tes
+6s
+4ttische
+9hes
+4ut
+6s
+3recklich
+4ik
+6s
+4od
+6s
+3tick
+7s
+5k
+6s
+4ook
+7s
+6m
+4uck
+7s
+5m
+3uit
+6s
+4l
+5n
+5s
+4ss
+6boomer
+9mers
+6ed
+7r
+8s
+7s
+6ing
+4yt
+6s
+3vartze
+9s
+3wa
+5rmerei
+9eis
+9isch
+6tze
+9s
+6zlot
+9ts
+5s
+2iaenid
+8s
+6oid
+9s
+4machies
+8y
+4rid
+7s
+4tic
+7a
+8l
+8s
+7s
+3ence
+7d
+7s
+5t
+6er
+6ial
+7fic
+9cal
+9cally
+9cities
+9city
+7se
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7ze
+9d
+9s
+8ing
+3licet
+4la
+6s
+3metar
+8s
+4itar
+8s
+6er
+8s
+3ncoid
+8ian
+9ans
+8s
+4dapsus
+9ses
+4tigram
+9ms
+9phic
+9phies
+9phy
+6lla
+9e
+9nt
+9ntly
+9s
+9scope
+9scopes
+9te
+9ted
+9tes
+9ting
+9tingly
+9tion
+9tions
+9tor
+9tors
+8iscan
+9scans
+8ometer
+9meters
+9n
+9ns
+9scope
+9scopes
+6scan
+9nner
+9nners
+9ns
+3olism
+8s
+7t
+8ic
+8s
+5ous
+5to
+4machies
+8y
+6ncer
+9rs
+8ies
+8y
+7tic
+4n
+5s
+4phyte
+9s
+8ic
+4sophies
+8y
+3roc
+6co
+8s
+6s
+4rhi
+6oid
+7sities
+9ty
+7us
+6us
+8es
+3ssel
+7s
+5il
+7e
+7s
+6on
+8s
+6parities
+9ity
+5or
+7ed
+8r
+9s
+7s
+7tail
+9ils
+7wise
+5ure
+8s
+3tamineous
+3urid
+7s
+6ne
+8s
+5oid
+2laff
+6ed
+7r
+8s
+6ing
+6s
+4te
+6s
+4under
+9s
+4ve
+6s
+3era
+6e
+6l
+6s
+5e
+6id
+8e
+9s
+8s
+6ma
+8s
+6nchyma
+9ymas
+9ymata
+6s
+5iases
+8is
+6te
+8s
+7ic
+8s
+9es
+5ocaulies
+9lous
+9ly
+6derm
+9ma
+9mas
+9mata
+9matous
+9mia
+9mias
+9mic
+9mite
+9mites
+9mous
+9ms
+6id
+6ma
+8lacia
+9acias
+8s
+8ta
+7eter
+9ers
+9ric
+6phyll
+9llies
+9llous
+9lls
+9lly
+7rotein
+9teins
+6sal
+7e
+8d
+8s
+7ing
+8s
+6tal
+9s
+7ia
+9l
+8c
+9s
+8n
+9s
+8oid
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8tis
+9ises
+8um
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7omies
+9y
+6us
+3iff
+6s
+4m
+5med
+6ing
+5s
+2odier
+6st
+4y
+3ff
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5law
+8s
+5s
+3g
+4ged
+5ing
+4s
+3inson
+8s
+3ld
+5able
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5s
+4eces
+6id
+8s
+7form
+7te
+9s
+6oid
+5x
+4ia
+5ces
+5oma
+8s
+6n
+6ses
+7is
+6tic
+4lop
+7ed
+7ing
+7s
+4opaceous
+6endra
+9ras
+9rid
+9rids
+9riform
+9rine
+9rium
+9riums
+4ytid
+8s
+6oid
+9s
+3mbrid
+8s
+6oid
+9s
+4fish
+8ed
+9s
+8ing
+3nce
+6d
+6s
+5heon
+9s
+5ing
+4e
+5s
+4tion
+8s
+3obies
+5y
+4ch
+6ed
+7s
+6ing
+4g
+5ed
+5ing
+5s
+4p
+5able
+5ed
+6r
+7s
+5ful
+8s
+5ing
+8s
+5s
+6ful
+4sh
+6ed
+7s
+6ing
+4t
+5ch
+7ed
+8s
+7ing
+5ed
+6r
+7ist
+9ts
+7s
+5ing
+5s
+3p
+4a
+5e
+5te
+4e
+5d
+5lid
+8s
+6oid
+9s
+5s
+4ing
+4olamine
+9nes
+6ine
+9s
+5philia
+9iac
+9iacs
+9ias
+9ic
+7obia
+9ias
+4s
+4tophilia
+9lias
+8obia
+9bias
+4ula
+7e
+7s
+7te
+3rbutic
+9ally
+4ch
+6ed
+7r
+8s
+7s
+6ing
+9ly
+9ness
+9nesses
+9s
+4dato
+7ura
+9as
+4e
+5board
+9ds
+5card
+9s
+5d
+5keeper
+9ers
+5less
+6ine
+9s
+5pad
+8s
+5r
+6s
+5s
+6heet
+9ts
+4ia
+6c
+7eous
+6e
+5fication
+9tions
+7ed
+8r
+9s
+8s
+6y
+7ing
+5ng
+7s
+5ous
+4n
+5ed
+6r
+7s
+5ful
+8ly
+8ness
+9esses
+5ing
+8s
+5s
+4odite
+9s
+4paenid
+9ds
+8oid
+9ids
+5er
+7s
+5ioid
+9s
+7n
+8ic
+8s
+4rendo
+4se
+6d
+6r
+7s
+6s
+5ing
+4zonera
+9as
+3t
+4ch
+6ed
+7s
+6ing
+4er
+6s
+4ia
+6s
+4odinia
+9as
+5ma
+7s
+7ta
+8ous
+6eter
+9rs
+6ia
+8s
+7es
+6y
+5phil
+6ia
+8s
+7c
+4s
+4tie
+7s
+3ug
+5ed
+5ing
+5s
+4ndrel
+9ly
+9s
+4p
+5ed
+5ing
+5s
+4r
+5ed
+6r
+7s
+5ge
+7d
+7r
+8s
+7s
+6ing
+5ie
+7s
+6ng
+8s
+5s
+6e
+7d
+7s
+6ing
+4se
+6r
+7s
+6s
+4t
+5craft
+9ts
+5ed
+6r
+7s
+5h
+6er
+8ed
+8ing
+9ngs
+8s
+8y
+6s
+5ing
+8s
+5master
+9ers
+5s
+3w
+4der
+7ed
+7ing
+9gs
+7s
+4ed
+4ing
+4l
+5ed
+6r
+7s
+5ing
+8ly
+5s
+4p
+5ed
+5ing
+5s
+4rer
+7s
+5ie
+7s
+4s
+4th
+6er
+8ed
+8ing
+8s
+6s
+3zza
+6s
+2rab
+5bed
+6ing
+6le
+8d
+8r
+9s
+8s
+7ier
+9st
+8ng
+7y
+5s
+4e
+5s
+4g
+5ged
+8ness
+9esses
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6lier
+9st
+8ng
+7y
+6y
+5s
+4ich
+7ed
+7ing
+7s
+5gh
+7ed
+7ing
+7s
+4m
+5b
+6ed
+6ing
+6le
+8d
+8r
+9s
+8s
+7ing
+9gly
+9gs
+6s
+5jet
+8s
+5med
+6ing
+5s
+4n
+5ch
+7ed
+8s
+7ing
+5nel
+8s
+6ier
+8st
+6y
+5s
+4p
+5able
+5book
+9ed
+9ing
+9ings
+9s
+5e
+6d
+6good
+9ds
+7ut
+9s
+6pennies
+9ny
+6r
+7board
+9ards
+7s
+6s
+5heap
+9s
+5ie
+7s
+6ng
+8s
+5page
+9s
+6ed
+7r
+8s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6le
+8s
+6y
+5s
+5yard
+9s
+4t
+5ch
+7back
+9cks
+8oard
+9ards
+8uild
+9ilder
+9ilders
+9ilding
+9ilds
+9ilt
+7card
+9rds
+7ed
+8r
+9s
+8s
+7ie
+9r
+9s
+9st
+8ly
+8ness
+9esses
+9g
+9gly
+9gs
+7less
+7plate
+9ates
+7y
+5s
+5ted
+6ing
+6le
+8d
+8s
+7ing
+4uch
+7ed
+7ing
+7s
+5gh
+7ed
+7ing
+7s
+4w
+5l
+6ed
+7r
+8s
+6ier
+8st
+7ng
+9ly
+9s
+6s
+6y
+5m
+6ed
+6ing
+6s
+5nier
+8st
+7ly
+7ness
+9sses
+6y
+5p
+6ed
+6ing
+6s
+5s
+4y
+5e
+6s
+5s
+3eak
+6ed
+6ier
+8st
+7ng
+6s
+6y
+5m
+6ed
+7r
+8s
+6ing
+9ly
+6o
+7s
+6s
+4e
+5ch
+7ed
+8r
+9s
+8s
+7ier
+9st
+8ng
+7y
+5d
+6ed
+7r
+8s
+6ing
+9s
+6s
+5n
+6able
+7ger
+9rs
+6craft
+9fts
+6ed
+7r
+8s
+6ful
+9s
+6ie
+8s
+7ng
+9s
+6land
+9ds
+7ike
+6play
+9ys
+6s
+7aver
+9ers
+7hot
+9ts
+6writer
+9ters
+5s
+5t
+6ed
+6ing
+6s
+5ve
+7d
+7r
+8s
+7s
+6ing
+9s
+4ich
+7ed
+7ing
+7s
+5gh
+7ed
+7ing
+7s
+4w
+5able
+5ball
+9s
+6ean
+9s
+5driver
+9ers
+5ed
+6r
+7s
+5ier
+7st
+6ness
+9ses
+7gs
+5like
+5s
+5top
+8s
+5up
+7s
+5worm
+9s
+5y
+3ibable
+6cious
+9usness
+6l
+5ble
+8d
+8ment
+9ents
+8r
+9s
+8s
+7ier
+9st
+8ng
+9gly
+9gs
+7y
+5e
+6d
+6r
+7s
+6s
+5ing
+8s
+6sm
+8s
+4ech
+7ed
+7ing
+7s
+5d
+5ne
+7s
+5s
+5ve
+7board
+9ards
+7d
+7s
+6ing
+4ggle
+8d
+8s
+7ier
+9st
+8ng
+7y
+4ke
+6d
+6s
+5ing
+4m
+5mage
+9d
+9r
+9rs
+9s
+8ing
+5p
+6ed
+7r
+8s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+7t
+6ly
+6ness
+9ses
+6s
+6y
+5s
+6hander
+9dered
+9dering
+9ders
+9died
+9dies
+9dy
+9dying
+9k
+9ked
+9king
+9ks
+8w
+9ed
+9ing
+9s
+7oner
+9ers
+5ure
+8s
+4ne
+6s
+4p
+5ophile
+9les
+9lies
+9list
+9lists
+9ly
+5page
+9s
+5s
+5t
+6ed
+7r
+8s
+6ing
+6oria
+9al
+9um
+9ums
+8y
+6s
+6ural
+9lism
+9lisms
+9list
+9lists
+9lly
+8e
+9s
+8ism
+9sms
+9st
+9sts
+6writer
+9ters
+9ting
+9tings
+4tch
+7ed
+8s
+7ing
+4ve
+6board
+9rds
+6d
+6ner
+9s
+9ship
+9ships
+7ing
+9gs
+6s
+5ing
+3obble
+8d
+8s
+7ing
+5e
+6s
+5icular
+9ate
+9ated
+9e
+9es
+4d
+5dled
+5s
+4fula
+8s
+7ous
+9sly
+9sness
+4g
+5gie
+8r
+8st
+7n
+8s
+6y
+5s
+4ll
+6able
+6ed
+7r
+8s
+6ing
+9s
+6s
+6wise
+7ork
+9ks
+4me
+6d
+6s
+5ing
+4och
+7ed
+8s
+7ing
+5ge
+7d
+7s
+6ing
+5p
+6ed
+6ing
+6s
+5tch
+8ed
+9s
+8ing
+4phularia
+9rias
+4rp
+6s
+4ta
+6l
+5es
+4uge
+7d
+7r
+8s
+7s
+6ing
+5nge
+8d
+8r
+9s
+8s
+7ier
+9st
+8ng
+9gs
+7y
+4w
+5dge
+8d
+8s
+7ing
+5l
+6e
+7d
+7s
+6ing
+6s
+5s
+4yle
+7s
+3ub
+5bable
+6ed
+7r
+8s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9s
+6y
+5land
+9s
+5s
+5woman
+8en
+4ff
+6ier
+8st
+7ly
+7ness
+9sses
+6s
+6y
+4m
+5down
+9s
+5mage
+9d
+9r
+9rs
+9s
+8ing
+6ed
+6ie
+8r
+8s
+9t
+7ng
+6y
+5p
+6ed
+6ies
+7ng
+6le
+8d
+8s
+7ing
+6ox
+8es
+6s
+6tious
+9usly
+9usness
+6y
+5s
+4nch
+7ed
+8on
+9ns
+8s
+7ie
+9r
+9s
+9st
+8ng
+8on
+9ns
+7y
+5t
+6ier
+8st
+6s
+6y
+4ple
+7d
+7less
+7r
+8s
+7s
+6ing
+5ulosities
+9ity
+8us
+9sly
+9sness
+4tabilities
+9ity
+7le
+6tor
+9s
+5ineer
+9rs
+7ies
+8se
+9ed
+9er
+9ers
+9es
+9ing
+9ingly
+8ze
+9ed
+9er
+9ers
+9es
+9ing
+9ingly
+7ous
+9sly
+7y
+5o
+6ire
+9s
+6s
+4ze
+6d
+6s
+5ing
+3y
+4de
+4er
+6s
+4ing
+7s
+4ne
+6s
+2uba
+5ed
+5ing
+5s
+3chin
+7s
+3d
+4daler
+9s
+5ed
+6r
+7s
+5ing
+5le
+7d
+7s
+6ing
+4i
+4ler
+7s
+4o
+4s
+3ff
+5ed
+6r
+7s
+5ing
+5le
+7d
+7r
+8s
+7s
+6ing
+5s
+4t
+5s
+3g
+4ged
+5ing
+4s
+3l
+4ch
+6es
+4dudderies
+9ry
+8ries
+9y
+6ggeries
+9ry
+4k
+5ed
+6r
+7s
+5ing
+5s
+4l
+5e
+6d
+6r
+7ies
+7s
+7y
+6s
+5ing
+8s
+6on
+8s
+5s
+4p
+5ed
+5in
+7g
+7s
+5s
+6it
+5t
+6ed
+6ing
+6or
+8s
+6ress
+9ses
+6s
+6ural
+9lly
+8e
+9d
+9s
+9sque
+9squely
+8ing
+9ngs
+4s
+4tch
+7es
+3m
+4bag
+7s
+5er
+7ed
+7ing
+7s
+5le
+7d
+7s
+6ing
+9s
+4fish
+8ed
+9s
+8ing
+4less
+5ike
+4med
+6r
+7s
+5ier
+7st
+6ly
+6ng
+8s
+5y
+4s
+3ncheon
+9s
+4dered
+4ge
+6d
+6s
+5ier
+7st
+6lli
+9s
+6ng
+5y
+4ner
+7ed
+7ing
+7s
+3p
+4paug
+8s
+5er
+7ed
+7ing
+7nong
+9ngs
+7s
+4s
+3r
+4f
+5ier
+7st
+6ness
+9ses
+5s
+5y
+4red
+5ied
+7r
+8s
+7s
+6l
+7e
+7ities
+9y
+7ous
+9sly
+9sness
+6ng
+6our
+9s
+5y
+6ing
+4s
+4vier
+7s
+8t
+6ly
+6ness
+9ses
+5y
+3se
+5d
+5s
+4ing
+3t
+4a
+5ge
+7s
+5l
+5te
+6ion
+9s
+4ch
+6ed
+7on
+9less
+9s
+7r
+8s
+7s
+6ing
+9s
+4e
+5lla
+8r
+8te
+9ed
+9ion
+9ions
+7um
+5s
+4iform
+5ger
+8s
+4s
+4ter
+7ed
+7ing
+7s
+5le
+7butt
+9tts
+7d
+7ful
+9ls
+7r
+8s
+7s
+6ing
+4um
+4work
+8s
+3zz
+5bag
+8s
+7ll
+9s
+5es
+5ier
+7st
+5y
+2ybala
+6ous
+6um
+3e
+4s
+3phate
+5i
+6form
+6stoma
+9mae
+9mas
+5ozoan
+9ns
+5us
+3tale
+7s
+4he
+6d
+6like
+6man
+7en
+6r
+7s
+6s
+5ing
+1daine
+6d
+6s
+5ing
+3yn
+5ed
+5ing
+5s
+2eign
+6e
+7d
+7s
+6full
+9ly
+6ing
+6s
+4n
+5ed
+5ing
+5s
+2rucciola
+1ea
+3bag
+6s
+5nk
+7s
+4each
+8es
+5d
+6s
+4ird
+7s
+4lite
+8s
+4oard
+8s
+5ot
+7s
+5rgium
+9ms
+6ne
+5ttle
+9s
+3coast
+8s
+5ck
+7s
+4raft
+8s
+4unnies
+7y
+3dog
+6s
+4rome
+8s
+3farer
+8s
+6ing
+9s
+4loor
+8s
+4olk
+7s
+5od
+7s
+5wl
+7s
+4ront
+8s
+3girt
+4oing
+4ull
+7s
+3hawk
+7s
+4og
+6s
+5rse
+8s
+5und
+8s
+3kale
+7s
+3l
+4able
+5nt
+7s
+4ch
+6s
+4ed
+5r
+6ies
+6s
+6y
+4gh
+6s
+4ift
+7ed
+7ing
+7s
+5ne
+7s
+6g
+7s
+4like
+4point
+9s
+4s
+5kin
+8s
+4wax
+7es
+4yham
+8s
+3m
+4aid
+7s
+5n
+6like
+7y
+6ship
+9ps
+5rk
+7s
+4e
+5d
+5n
+5r
+6s
+5s
+4free
+4ier
+6st
+5ness
+9es
+6g
+7s
+4less
+8ly
+8ness
+9esses
+5ike
+4ount
+8s
+4s
+5et
+7s
+5ter
+8s
+6ress
+9ses
+9sies
+9sy
+4y
+3n
+4ce
+6s
+4ed
+4ing
+4nachie
+9es
+8y
+4s
+3piece
+8s
+4lane
+8s
+4ort
+7s
+3quake
+8s
+6ria
+8um
+9ms
+3r
+4at
+6s
+4ce
+6d
+6s
+5h
+6able
+6ed
+7r
+8s
+7s
+6ing
+9ly
+9ness
+9nesses
+6less
+7ight
+9hts
+5ing
+4e
+5d
+6ness
+9ses
+5r
+5st
+4ing
+7ly
+7s
+4ness
+8es
+4obin
+8s
+4s
+3s
+4cape
+8s
+5out
+8s
+4e
+5d
+5s
+4hell
+8s
+5ore
+8s
+4ick
+7er
+8st
+7ness
+9sses
+5de
+7s
+5ng
+4on
+6abilities
+9lity
+8le
+9eness
+9y
+7l
+8ities
+9ty
+8ly
+8ness
+9esses
+8s
+6ed
+7r
+8s
+6ing
+9s
+6less
+6s
+4peak
+8s
+4trand
+9s
+4ure
+7s
+3t
+4back
+8s
+5elt
+8s
+4ed
+5r
+6s
+4ing
+7s
+4less
+4mate
+8s
+4rain
+8s
+5out
+8s
+4s
+4work
+8s
+3wall
+7s
+5n
+6s
+6t
+7s
+5rd
+7ly
+7s
+6e
+7s
+5ter
+8s
+5y
+6s
+4eed
+7s
+4ife
+5ves
+4oman
+6en
+5rm
+7s
+6thier
+9est
+9ness
+9nesses
+8y
+3ze
+5d
+5s
+4ing
+2baceous
+5ic
+4sic
+4te
+6s
+3esten
+8s
+3iferous
+5ic
+3orrhea
+9l
+9s
+8ic
+7oea
+9al
+9as
+9ic
+3um
+5s
+4ndies
+6y
+2c
+3alose
+8s
+4nt
+6ly
+6s
+4teur
+8s
+3co
+5s
+3ede
+6d
+6r
+7s
+6s
+5ing
+4rn
+6ed
+7nt
+9s
+6ing
+6ment
+9ts
+6s
+4sh
+6er
+8s
+7s
+5sion
+9al
+9ism
+9isms
+9ist
+9ists
+9s
+3h
+4s
+3kel
+6s
+4le
+6s
+3lude
+7d
+8ly
+8ness
+9esses
+7s
+6ing
+5sion
+9ist
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+3o
+4barbital
+9tals
+4dont
+8s
+4nal
+7s
+5d
+6aries
+9ly
+9ness
+9nesses
+8y
+6e
+7d
+7e
+8s
+7r
+8s
+7s
+6hand
+6i
+7ng
+6ly
+6ment
+9ts
+6o
+6s
+3par
+6s
+3recies
+6y
+5t
+6a
+7ge
+9s
+8ogic
+9gue
+9gues
+7ire
+9es
+7rial
+9at
+9ate
+9ates
+9ats
+9es
+8y
+9ship
+9ships
+6e
+7d
+7r
+7s
+8t
+6in
+8g
+8s
+7on
+9al
+9ary
+9s
+7ve
+9ly
+9ness
+9nesses
+6ly
+6ness
+9ses
+6or
+8ies
+8s
+8y
+6s
+3s
+3t
+4arial
+8n
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ize
+9ized
+9izes
+9izing
+9s
+7es
+6y
+5tor
+8s
+4ile
+6ities
+8y
+5on
+7al
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+9ly
+9s
+7ed
+7ing
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7s
+4or
+6al
+6ed
+6ial
+9s
+7ng
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+4s
+3ular
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7ly
+7s
+5um
+7s
+4nd
+6ine
+9s
+6ly
+6ogeniture
+6um
+4rable
+6nce
+9s
+5e
+6d
+6ly
+6ment
+9ts
+6ness
+9ses
+6r
+7s
+6s
+7t
+5iform
+6ng
+6tan
+9s
+7ies
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7y
+5ocrat
+9ts
+2d
+3an
+5s
+4rim
+4te
+6d
+6ly
+6ness
+9ses
+6r
+6s
+7t
+5ing
+6on
+8s
+6ve
+8s
+3ent
+6arily
+9ness
+9nesses
+8y
+4r
+5s
+5unt
+8s
+4s
+3ge
+5d
+5land
+9s
+5s
+4ier
+6st
+4y
+3igitated
+4le
+5ia
+6um
+4ment
+8able
+9rily
+9ry
+9tion
+9tions
+8ed
+8ing
+8ologic
+9logies
+9logist
+9logy
+9us
+8s
+4tion
+8aries
+9ry
+8s
+7us
+9ly
+9ness
+9nesses
+3uce
+6able
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ible
+6ng
+8ly
+8s
+6ve
+5tion
+9s
+7ve
+9ly
+9ness
+9nesses
+6or
+8s
+6ress
+9ses
+4lities
+7y
+5ous
+8ly
+8ness
+9esses
+4m
+5s
+2e
+3able
+3catch
+8ie
+3d
+4bed
+7s
+5ox
+7es
+4cake
+8s
+6se
+8s
+4eater
+9s
+5d
+5r
+6s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4less
+5ike
+6ng
+8s
+6p
+7s
+4man
+5en
+4ness
+8es
+4pod
+7s
+4s
+5man
+6en
+5tock
+9s
+4time
+8s
+4y
+3ing
+6s
+3k
+4er
+6s
+4ing
+4s
+3l
+4d
+4ed
+4ie
+6r
+6st
+5ng
+7s
+4s
+4y
+3m
+4ed
+5lesse
+5r
+6s
+4ing
+7ly
+7ness
+9sses
+7s
+4less
+5ier
+7st
+6head
+9ds
+8d
+9s
+6ness
+9ses
+5y
+6hed
+9s
+4s
+3n
+3p
+4age
+7s
+4ed
+4ier
+6st
+5ng
+4s
+4y
+3r
+4ess
+7es
+4s
+5ucker
+9rs
+3s
+4aw
+6ed
+6ing
+6s
+3the
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+3wing
+2fer
+2g
+3ar
+5s
+3etal
+3gar
+6s
+3hol
+6ate
+9s
+6s
+3ment
+7al
+9ly
+8ry
+8te
+9ion
+9ions
+7ed
+7ing
+7s
+3ni
+4o
+5s
+3o
+4l
+5ate
+8s
+5s
+4s
+3reant
+5gable
+7nt
+9s
+7te
+9d
+9s
+8ing
+9on
+9onal
+9onist
+9onists
+9ons
+9ve
+8or
+9rs
+3s
+3ue
+5d
+5ing
+5s
+4idilla
+9as
+2hri
+5s
+2i
+3cento
+8s
+4he
+6s
+3del
+6s
+3f
+4s
+3gneur
+8ial
+9e
+9es
+8s
+8y
+5ior
+8age
+9ges
+9lties
+9lty
+8ial
+9es
+8s
+9hip
+9hips
+8y
+5orage
+9es
+8l
+7ial
+8es
+7y
+3k
+4er
+5st
+3l
+4ed
+4ing
+4s
+3ne
+5d
+5r
+6s
+5s
+4ing
+7s
+3r
+4s
+3s
+4able
+4e
+5d
+5r
+6s
+5s
+4in
+6g
+7s
+6s
+4m
+5al
+5ic
+7al
+9ly
+7ities
+9y
+6sm
+8s
+5ogram
+9ms
+9ph
+9pher
+9phers
+9phic
+9phical
+9phies
+9phs
+9phy
+6logic
+9ical
+9ically
+9ies
+9ist
+9ists
+9y
+6meter
+9ers
+9ric
+9rical
+9ries
+9ry
+6nastic
+9ties
+9ty
+6scope
+9pes
+9pic
+5s
+4or
+6s
+4ure
+7s
+3tan
+6s
+4en
+6s
+4ies
+4y
+3zable
+4e
+5d
+5r
+6s
+5s
+4in
+6g
+7s
+6s
+4or
+6s
+4ure
+7s
+2jant
+3eant
+2kos
+5es
+3t
+4s
+2l
+3achian
+9s
+4dang
+8s
+4ginella
+9las
+4h
+5s
+4mlik
+8s
+3couth
+3d
+4om
+6ly
+6ness
+9ses
+4seen
+5hown
+3e
+4ct
+6a
+7ble
+7s
+6ed
+7e
+8s
+6ing
+7on
+9ist
+9ists
+9s
+7ve
+9ly
+9ness
+9nesses
+8ities
+9ty
+6ly
+6man
+7en
+6ness
+9ses
+6or
+8ate
+9tes
+8ial
+8s
+6s
+4giline
+9es
+4nate
+8s
+5ian
+6c
+6de
+8s
+6ferous
+6ous
+6te
+8s
+7ic
+6um
+8s
+5ocentric
+6dont
+9ts
+6graph
+9pher
+9phers
+9phic
+9phical
+9phies
+9phist
+9phists
+9phs
+9phy
+6logical
+9ies
+9ist
+9ists
+9y
+6ses
+7is
+6us
+4s
+3f
+4dom
+7s
+4ed
+4heal
+8s
+5ood
+8s
+4ing
+7s
+5sh
+7ly
+7ness
+9sses
+6m
+7s
+6t
+7s
+4less
+8ly
+8ness
+9esses
+4ness
+8es
+4s
+5ame
+8ness
+9esses
+4ward
+8s
+3ictar
+8s
+3kie
+6s
+3l
+4a
+5ble
+5e
+5s
+4e
+5r
+6s
+5s
+4ing
+7s
+4off
+7s
+5tape
+9d
+9s
+8ing
+5ut
+7s
+4s
+3s
+4yn
+6s
+3tzer
+7s
+5ogene
+9es
+3va
+5ge
+7d
+7e
+8s
+7s
+6ing
+5s
+4edge
+8d
+8s
+7ing
+5s
+2mainier
+9s
+4nteme
+9s
+6ic
+8al
+9lly
+8ist
+9sts
+8s
+7de
+9s
+6ra
+7on
+4phore
+9d
+9s
+8ic
+9cal
+9cally
+9ng
+4siological
+9gies
+9gist
+9gists
+9gy
+4tic
+5ologies
+9y
+3blable
+9s
+8y
+6nce
+9s
+7t
+8s
+6tive
+5e
+6d
+6s
+5ing
+3e
+4e
+5d
+4ia
+5ologic
+9ical
+9ies
+9ist
+9ists
+9y
+6n
+6tic
+9ally
+9ian
+9ians
+9s
+4lparities
+9ty
+8ous
+4me
+6s
+5ic
+4s
+5ter
+8s
+6ral
+7ial
+3i
+4abstract
+9action
+5ngle
+9s
+6nual
+9lly
+5quatic
+5rboreal
+6id
+8ities
+9ty
+5utomatic
+9atics
+8nomous
+4bald
+5old
+8s
+5reve
+9s
+5ull
+8s
+4carbazide
+9zides
+9zone
+9zones
+5entennial
+9nnials
+5horus
+9ses
+5ircle
+9ed
+9es
+8ular
+9larly
+7que
+9es
+6vilised
+9ized
+5lassic
+9ical
+9ics
+5olon
+9ial
+9ialism
+9ies
+9s
+9y
+6ma
+8s
+8tose
+7mercial
+6nducting
+9ction
+9ctions
+9ctor
+9ctors
+7scious
+9iously
+5rystallic
+9alline
+5ured
+5ylinder
+9ders
+9drical
+4darkness
+9esses
+5eaf
+6ified
+9es
+8y
+9ing
+6ponent
+9ents
+6sert
+9ts
+6tached
+5iameter
+9ters
+6urnal
+6vine
+5ocumentary
+6me
+8d
+8s
+7inant
+5ry
+7ing
+5warf
+9s
+8ves
+4e
+5lliptical
+5mpirical
+5rect
+5s
+5vergreen
+4feudal
+5inal
+9ist
+9ists
+9s
+7ished
+6t
+7ted
+5lexible
+6uid
+9ic
+9ities
+9ity
+9s
+5ormal
+5reddi
+9o
+9os
+4gala
+5lobular
+7ss
+9es
+5roup
+9s
+4hard
+5igh
+5obo
+8es
+8s
+4legendary
+6thal
+9ls
+5iquid
+9ds
+6terate
+9ates
+5lon
+8s
+5og
+7arithmic
+5ucent
+6nar
+8te
+7e
+8s
+6strous
+4manufacture
+6t
+7t
+8e
+5enstrual
+6tal
+9lic
+9s
+5icro
+6ld
+5oist
+6nastic
+7thlies
+9ly
+5ute
+5ystical
+4na
+6l
+7ities
+9y
+7ly
+6r
+7ial
+9n
+9ns
+8es
+8st
+9ts
+7s
+7y
+6te
+8d
+8s
+7ing
+8on
+9ns
+7ural
+5iferous
+5oma
+8d
+9ic
+9s
+8s
+8ta
+4ochemical
+9icals
+5fficial
+9ially
+5logic
+9cal
+9cally
+9es
+9st
+9sts
+8y
+5paque
+6en
+5ses
+6is
+5tic
+8ally
+8ian
+9ans
+9st
+9sts
+8s
+5val
+6iparous
+4palmate
+9ted
+9tion
+9tions
+6rasite
+9ites
+9itic
+9itism
+9itisms
+5ed
+7s
+6llucid
+6rimeter
+9eters
+7manent
+8eable
+5ious
+5lume
+9s
+5olar
+7itical
+6pular
+6rcelain
+9lains
+6stal
+9ls
+5recious
+6ivate
+6o
+7s
+5ublic
+4quaver
+9rs
+4raw
+5eligious
+6tired
+9ement
+9ements
+5igid
+5ound
+9s
+5ural
+4s
+5acred
+5ecret
+6dentary
+6s
+5hrubby
+5killed
+5oft
+6lid
+9s
+7us
+9es
+5tiff
+5ubmersible
+5weet
+5ynthetic
+4tar
+7s
+6ur
+8s
+5erete
+7restrial
+5ist
+8s
+5onal
+9ly
+7e
+8s
+7ic
+9ally
+5railer
+9ers
+7nslucent
+9parent
+6opic
+9cal
+9cs
+6uck
+9s
+4urban
+4vitreous
+5ocal
+9ic
+6wel
+9s
+4water
+5eeklies
+9y
+5ild
+5orks
+4yearly
+3mit
+6s
+3olina
+8s
+3per
+6vivum
+9ums
+4iternal
+9ally
+9ities
+9ity
+9um
+9ums
+4le
+6r
+6st
+5ice
+4re
+4ster
+8ing
+9ngs
+8s
+6ress
+9ses
+9sing
+9sings
+3sem
+6s
+3uncia
+8e
+8l
+8s
+2n
+3a
+4ries
+6i
+6us
+5montite
+9ites
+5y
+4s
+4te
+6s
+5or
+7ial
+9lly
+9n
+7s
+8hip
+9ips
+3d
+4able
+5l
+6s
+4ed
+5r
+6s
+4ing
+7s
+4off
+7s
+4s
+4up
+6s
+3e
+4ca
+6s
+5io
+7s
+5titude
+9des
+4ga
+6s
+4s
+5cence
+9es
+8t
+6hal
+9s
+9ship
+9ships
+3gi
+4reen
+8s
+3hor
+6a
+7s
+6es
+6ita
+9s
+6s
+3ile
+6ly
+6s
+5ities
+7y
+4or
+6ities
+8y
+6s
+4ti
+3na
+5chie
+9s
+5s
+4et
+6s
+4ight
+8s
+5t
+6s
+3opia
+7s
+4r
+5a
+6s
+5es
+5ita
+8s
+5s
+3ryu
+3s
+4a
+5te
+7d
+7ly
+7s
+6ing
+7on
+9al
+9alise
+9alised
+9alises
+9alism
+9alisms
+9alist
+9alists
+9alize
+9alized
+9alizes
+9ally
+9ism
+9isms
+9ist
+9ists
+9less
+9s
+4e
+5d
+5ful
+5i
+6s
+5less
+9ly
+9ness
+9nesses
+5s
+4i
+5bilia
+9ties
+9ty
+6le
+8ness
+9esses
+8r
+8s
+9t
+7y
+5le
+6la
+8e
+7um
+5ng
+7s
+5s
+6m
+7s
+6t
+7s
+5tisation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7ve
+9ly
+9ness
+9nesses
+9s
+8ities
+9ty
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ometer
+9ters
+9tric
+9tries
+9try
+4omotor
+5r
+6ia
+8l
+9ly
+7ly
+7motor
+7neural
+7um
+9s
+6s
+6y
+4ual
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7ness
+9sses
+5m
+5osities
+9y
+6us
+8ly
+8ness
+9esses
+3t
+4e
+5d
+5nce
+8d
+8r
+9s
+8s
+7ing
+6tia
+9e
+9l
+9lly
+8ous
+9usly
+9usness
+4i
+5ence
+9s
+8ies
+8y
+7t
+8ly
+8s
+5ment
+9al
+9alise
+9alised
+9alises
+9alism
+9alisms
+9alist
+9alists
+9ality
+9alize
+9alized
+9alizes
+9ally
+9s
+6o
+7s
+5nel
+8ed
+8ing
+8led
+9ing
+8s
+6g
+4ries
+5y
+4s
+3vies
+4y
+3za
+2pad
+5ded
+6ing
+5s
+4l
+5ed
+5ine
+5led
+5odies
+7y
+6id
+6us
+5s
+4rabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6ta
+7e
+8d
+8ly
+8ness
+9esses
+8s
+7ing
+8on
+9nism
+9nisms
+9nist
+9nists
+9ns
+8sm
+9ms
+9t
+9tic
+9ts
+8ve
+9ely
+9eness
+7or
+9ies
+9s
+9y
+7rices
+9x
+7um
+9s
+3hen
+6s
+3ia
+5s
+4c
+4ment
+8s
+4olite
+9s
+5st
+7aire
+9res
+7s
+4um
+6s
+3mag
+3oy
+5s
+3puku
+7s
+3s
+4es
+4is
+3t
+4a
+5ge
+7s
+5l
+5ria
+8n
+7um
+5te
+6ion
+9s
+5valent
+4emfid
+6vir
+9ate
+9ates
+9i
+9s
+5naries
+9i
+9us
+8y
+6decillion
+6nate
+9es
+7ia
+9l
+9lly
+8um
+9ms
+6trial
+9on
+9onal
+9onally
+9ones
+9ons
+5t
+6s
+6te
+8s
+4ic
+6aemia
+9ias
+9ic
+7l
+8ly
+6emia
+9as
+9c
+6idal
+9lly
+7ties
+8y
+6s
+5ferous
+6orm
+6ragal
+5lateral
+6lion
+9ns
+9nth
+9nths
+5mal
+6e
+7s
+6ole
+9s
+5valent
+4leva
+8s
+4s
+4uagenarian
+9arians
+9aries
+9ary
+5m
+6s
+5or
+7s
+5ple
+8d
+8s
+8t
+9s
+7icate
+9ates
+8ng
+3ulcher
+9ed
+9ing
+9s
+7ral
+9lly
+8e
+9d
+9s
+8ing
+8ous
+5tural
+8e
+9d
+9s
+8ing
+2quacious
+9sly
+9sness
+7ties
+8y
+4el
+6a
+7e
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6s
+5nce
+8d
+8r
+9s
+8s
+7ies
+8ng
+9gs
+7y
+6t
+7ial
+9lities
+9lity
+9lly
+7ly
+7s
+5ster
+9ed
+9ing
+9s
+7ra
+9ble
+9l
+9nt
+9nts
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tor
+9tors
+8um
+9ms
+4in
+6ed
+6ing
+6ned
+6s
+5tur
+8s
+4oia
+7s
+2r
+3a
+4c
+5s
+4file
+8s
+6n
+7s
+4glio
+8s
+4i
+5l
+6s
+5s
+4l
+4ng
+6s
+4pe
+6s
+5h
+6ic
+8al
+9lly
+7m
+8s
+7n
+8e
+9s
+8s
+6s
+4skier
+9ate
+9ates
+9s
+3dab
+6s
+3e
+4d
+4in
+6s
+4nade
+8d
+8r
+9s
+8s
+7ing
+6ta
+8s
+7e
+8s
+5dipities
+9tist
+9tists
+9tous
+9tously
+9ty
+5e
+6d
+6ly
+6ness
+9ses
+6r
+6s
+7t
+5ing
+6ties
+7y
+4r
+4s
+5t
+3f
+4age
+7s
+4dom
+7s
+4hood
+8s
+4ish
+4like
+4s
+5hip
+8s
+3ge
+5ancies
+8y
+7t
+8ies
+8s
+9hip
+9hips
+8y
+5d
+5r
+6s
+5s
+4ing
+7s
+3ial
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+6s
+5te
+7d
+7ly
+7s
+6im
+7ng
+7on
+9s
+4c
+5eous
+5iculture
+9tures
+9turist
+6n
+7s
+6te
+8s
+7ic
+8sation
+9ations
+8zation
+9ations
+5on
+7s
+5teria
+9um
+5ultural
+9re
+9res
+9rist
+9rists
+4ema
+7s
+5s
+4f
+5ed
+5fed
+5s
+4graph
+9er
+9ers
+9ic
+9ies
+9s
+9y
+4n
+5e
+6s
+6tte
+9s
+5g
+6a
+7s
+5s
+4ocomic
+9cal
+9cally
+5us
+7ly
+7ness
+9sses
+4ph
+6s
+3jeancies
+8y
+7t
+8ies
+8ries
+9y
+8s
+9hip
+9hips
+8y
+3k
+4ali
+7s
+4s
+3mon
+6ed
+7er
+9s
+7r
+8s
+7t
+8s
+8te
+9es
+6ic
+8al
+7ng
+9s
+7se
+9d
+9r
+9rs
+9s
+8ing
+7ze
+9d
+9r
+9rs
+9s
+8ing
+6s
+3oconversion
+9rsions
+9rt
+9rted
+9rting
+9rts
+4diagnoses
+9osis
+9ostic
+4group
+9s
+4logic
+9al
+9ally
+8es
+8st
+9ts
+7y
+4n
+5egative
+9ivity
+5s
+4on
+6s
+4positive
+9ivity
+5urulent
+6s
+7es
+4sa
+6e
+6l
+6s
+5ities
+7y
+4taxonomies
+9omy
+5herapies
+9py
+5inal
+7e
+8s
+7ies
+7ous
+7y
+5onergic
+7in
+9ergic
+9s
+5ype
+8d
+8s
+7ic
+8ng
+9gs
+4us
+6ness
+9ses
+4var
+7s
+4w
+5s
+3pent
+7iform
+8ne
+9ed
+9ely
+9es
+9ic
+9ing
+9ingly
+9ings
+9ise
+9ised
+9ises
+9ising
+9ite
+9ites
+9ize
+9ized
+9izes
+9izing
+9ous
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7like
+7ries
+8y
+7s
+4igines
+8ous
+9usly
+6o
+7es
+7s
+4ulid
+8s
+7te
+9s
+3r
+4a
+5della
+9as
+6illa
+9as
+5e
+5n
+6id
+8s
+6o
+7id
+9s
+7s
+6s
+5s
+6almo
+9os
+5te
+7d
+7s
+6i
+7ng
+7on
+9s
+7rostral
+6ulate
+7re
+9s
+7s
+8es
+4e
+5d
+5file
+9s
+5s
+4icorn
+5ed
+7ly
+7ness
+9sses
+6s
+5form
+5ng
+4s
+4ulate
+9d
+8ion
+9ons
+4y
+5ing
+3s
+3tularian
+9ans
+3uewe
+7d
+7s
+6ing
+4m
+5al
+5s
+3vable
+5l
+6s
+5nt
+7ed
+7hood
+9ods
+7ing
+7less
+7ries
+8y
+7s
+8hip
+9ips
+4e
+5able
+5d
+5r
+6ies
+6s
+6y
+5s
+5we
+7d
+7s
+6ing
+4ice
+7ability
+9le
+9leness
+9ly
+7berries
+9rry
+7d
+7less
+7man
+8en
+7r
+8s
+7s
+7woman
+9men
+6ing
+5ent
+6tte
+9s
+5le
+7ly
+7ness
+9sses
+7s
+6ism
+9s
+7ties
+8y
+5ng
+7s
+5tor
+8ial
+8s
+9hip
+9hips
+6ress
+9ses
+6ude
+9s
+4let
+7s
+4o
+5control
+9rols
+5mechanical
+9anism
+9anisms
+6otor
+9rs
+5s
+4qual
+8s
+2same
+6s
+5oid
+8s
+3e
+4li
+6s
+4y
+3h
+4es
+3quialter
+9era
+9eras
+6carbonate
+7entenary
+6oxide
+9des
+6pedal
+9alian
+9ality
+7licate
+6sulphide
+9phides
+6terpene
+9penes
+9tia
+9tias
+3s
+4a
+4es
+4ile
+6ities
+8y
+5on
+7al
+9ly
+7s
+4pool
+8s
+3terce
+8s
+6tia
+8i
+8um
+9s
+5t
+6s
+6t
+7e
+8s
+7o
+8s
+7s
+4ina
+7s
+6e
+7s
+4on
+6s
+2t
+3a
+4ceous
+9ly
+4e
+4l
+3back
+7s
+3enant
+8s
+3iferous
+5orm
+4gerous
+3line
+7s
+3ness
+7es
+3off
+6s
+4n
+5s
+4se
+4us
+5t
+6s
+3s
+4crew
+8s
+3t
+4ee
+6s
+5r
+6ed
+6ing
+6s
+6wort
+9ts
+4ing
+7s
+4le
+6able
+6d
+7ness
+9sses
+6ment
+9ts
+6r
+7s
+6s
+5ing
+8s
+5or
+7s
+4s
+3uale
+7s
+4le
+6s
+5ose
+6us
+4p
+5s
+3wall
+7s
+2ven
+5fold
+5pence
+9es
+8nies
+9y
+5s
+5teen
+9s
+9th
+9thly
+9ths
+6h
+7ly
+7s
+6ies
+8th
+9hs
+6y
+4r
+5abilities
+9ity
+7le
+6l
+7fold
+7ly
+7s
+7ties
+8y
+6nce
+9s
+5e
+6d
+6ly
+6ness
+9ses
+6r
+6st
+5ies
+6ng
+6ties
+7y
+5s
+5y
+3iche
+7s
+3ruga
+7s
+2w
+3abilities
+9y
+5le
+4ge
+6s
+4n
+5s
+4r
+5s
+3ed
+4l
+5lel
+8s
+5s
+4n
+5s
+4r
+5age
+8s
+5ed
+5ing
+8s
+5less
+6ike
+5s
+3in
+5g
+6s
+5s
+3n
+3s
+2xagenarian
+9ians
+9ies
+9y
+6simal
+9ally
+9als
+4holic
+9s
+4ngular
+9rly
+4valent
+3centenaries
+9ary
+3decillion
+9ions
+3ed
+4nnial
+9ly
+9s
+4r
+5cise
+9s
+5s
+4s
+3fid
+4oil
+7s
+3ier
+5st
+4ly
+4ness
+8es
+5g
+6s
+4sm
+6s
+5t
+6s
+4valent
+3less
+7ly
+7ness
+9sses
+4inked
+4ocular
+3ologic
+9al
+8es
+8st
+9ts
+7y
+3partite
+4ert
+7s
+4loitation
+9tions
+4ot
+6s
+3t
+4ain
+7s
+5n
+6s
+7es
+6t
+7al
+7s
+5rii
+7us
+4et
+6s
+6t
+7e
+8s
+7s
+4ile
+7s
+6lion
+9ns
+9nth
+9nths
+4o
+5decimo
+9mos
+5let
+8s
+5n
+6ess
+9es
+6s
+7hip
+9ps
+5s
+4s
+4uor
+7s
+5ple
+8d
+8s
+8t
+9s
+7icate
+9ated
+9ates
+9ating
+8ng
+7y
+3ual
+6isation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+3valent
+2y
+3en
+5s
+3s
+4ure
+7s
+2z
+1ferics
+2orzandi
+8o
+9s
+6ti
+7o
+8s
+2umato
+7s
+1graffiti
+8o
+1h
+2a
+3bash
+4batot
+5ier
+7st
+6ly
+6ness
+9ses
+5le
+7s
+5y
+4rack
+8s
+7que
+9es
+3ck
+5ed
+5ing
+5le
+7bone
+9nes
+7d
+7r
+8s
+7s
+6ing
+5o
+6es
+6s
+5s
+3d
+4berries
+8y
+5low
+8s
+5ush
+8es
+4chan
+8im
+8s
+4dock
+8s
+4e
+5d
+5less
+5r
+6s
+5s
+4flies
+6y
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4khan
+8im
+8s
+4oof
+7s
+5w
+6box
+9ed
+9es
+9ing
+6cast
+9ting
+9tings
+9ts
+6ed
+7r
+8s
+6graph
+9phies
+9phs
+9phy
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9s
+6less
+7ike
+6s
+6y
+4rach
+8s
+4s
+4uf
+6s
+4y
+3ft
+5ed
+6r
+7s
+5ing
+8s
+5less
+5s
+3gbark
+8s
+4gers
+5ier
+7st
+6ly
+6ness
+9ses
+5y
+6mane
+9es
+4pile
+4reen
+8ed
+8s
+5oon
+8s
+4s
+4tastic
+3h
+4ada
+7s
+4dom
+7s
+4eed
+7s
+4id
+6s
+4s
+4toosh
+9es
+3ikh
+6s
+4rd
+6s
+5n
+6s
+4tan
+7s
+3kable
+4e
+5able
+5d
+6own
+9s
+5n
+5out
+8s
+5r
+6s
+5s
+5up
+7s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4o
+5es
+5s
+4t
+4udo
+7s
+5hachi
+9is
+4y
+3le
+5d
+5like
+5s
+5y
+4ier
+6st
+5ng
+4l
+5i
+6s
+5on
+7s
+6on
+8s
+6p
+7s
+6t
+7s
+6w
+7ed
+8r
+8st
+7ing
+9gs
+7ly
+7ness
+9sses
+7s
+4m
+5s
+4om
+6s
+5t
+6s
+4t
+4war
+7s
+4y
+3m
+4a
+5ble
+7y
+5l
+6s
+5n
+6ic
+7sm
+9s
+8t
+9ic
+9s
+6s
+5s
+5teur
+9ism
+9isms
+9s
+4ba
+6s
+5le
+7d
+7s
+6ier
+8st
+7ng
+9s
+6y
+5olic
+4e
+5able
+8y
+5d
+5faced
+9dly
+9dness
+7st
+9ness
+9nesses
+6ul
+8ly
+8ness
+9esses
+5less
+9ly
+9ness
+9nesses
+5r
+6s
+5s
+5worthy
+4iana
+8h
+9s
+8s
+5na
+7s
+6g
+5sen
+8s
+5yanah
+9hs
+4mas
+7h
+8im
+7im
+5ed
+6r
+7s
+6s
+5ied
+7s
+6ng
+5os
+7im
+5y
+6ing
+4ois
+5s
+6im
+5y
+6ed
+6ing
+6s
+4poo
+7ed
+8r
+9s
+7ing
+7s
+4rock
+8s
+4s
+4us
+6es
+3n
+4achie
+9s
+4d
+5ies
+5ries
+6y
+7dan
+9ns
+5s
+5y
+6gaff
+9fs
+4ghai
+8ed
+9r
+9rs
+8ing
+8s
+4k
+5bone
+9s
+5ed
+5ing
+5piece
+9es
+5s
+4nies
+5y
+4s
+4tey
+7s
+5i
+6es
+6h
+7s
+6s
+5ung
+8s
+5y
+6man
+7en
+6town
+9ns
+3pable
+4e
+5able
+5d
+5less
+9ly
+9ness
+9nesses
+6ier
+8st
+7ness
+9sses
+6y
+5n
+5r
+6s
+5s
+5up
+7s
+5wear
+4ing
+7s
+4s
+3rable
+5wadgi
+9is
+7ggi
+9is
+4d
+5ed
+5ing
+5s
+4e
+5abilities
+9ity
+7le
+5crop
+9ped
+9per
+9pers
+9ping
+9s
+5d
+5farmer
+9ers
+5holder
+9ers
+9ing
+9ings
+5man
+6en
+6ilker
+9ers
+5r
+6s
+5s
+6man
+7en
+5ware
+9s
+4ia
+6h
+7s
+6s
+6t
+7s
+5f
+6ian
+6s
+5ng
+7s
+4k
+5ed
+6r
+7s
+5ing
+8s
+5like
+5s
+6kin
+9s
+6ucker
+9ers
+4n
+5ier
+7st
+5s
+5y
+4on
+4p
+5bender
+9ers
+5ed
+6n
+7ed
+8r
+9s
+7ing
+7s
+6r
+7s
+6st
+5ie
+7s
+6ng
+8s
+6sh
+5ly
+5ness
+9es
+5s
+6hooter
+9ters
+9ting
+9tings
+5y
+4row
+7ed
+7s
+4t
+5ed
+6r
+5ing
+5s
+3sh
+5ed
+6s
+5ing
+5lick
+9s
+7k
+8s
+4lik
+7s
+4ter
+7s
+5ra
+7s
+3t
+4oosh
+8es
+4ter
+7ed
+8r
+9s
+7ing
+9gly
+7proof
+7s
+7y
+3uchle
+8d
+8s
+7ier
+9st
+8ng
+7y
+4gh
+6s
+4l
+5ed
+5ing
+5s
+3vable
+4e
+5able
+5d
+5ling
+9s
+5n
+5r
+6s
+5s
+5tail
+9s
+4ie
+6s
+5ng
+7s
+3w
+4ed
+4ing
+4l
+5ed
+6y
+7s
+5ie
+7s
+6ng
+8s
+5less
+5s
+4m
+5s
+4n
+4s
+3y
+4a
+5s
+4s
+3zam
+2chi
+5s
+2e
+3a
+4ding
+8s
+4f
+5ed
+5ier
+7st
+6ng
+5like
+5s
+5y
+4l
+5ed
+5ing
+8s
+5s
+4r
+5ed
+6r
+7s
+5ing
+8s
+5leg
+8s
+6ing
+9s
+5man
+6en
+5s
+5water
+9rs
+4s
+4tfish
+9es
+5h
+6bill
+9ls
+6e
+7d
+7r
+8s
+7s
+6fish
+9hes
+6ier
+8st
+7ng
+9s
+6less
+6s
+6y
+4ve
+6d
+6s
+5ing
+3bang
+7s
+4ean
+7s
+5en
+7ed
+8r
+9s
+7ing
+9gs
+7s
+3chita
+8h
+9s
+8s
+4klaton
+9ns
+3d
+4able
+4dable
+5ed
+6r
+7s
+5ing
+8s
+4ful
+7s
+4hand
+8s
+4like
+5oad
+8s
+4s
+3el
+5ed
+5ing
+5s
+4n
+5ed
+6y
+7s
+5ful
+5ie
+7r
+7s
+8t
+6ng
+5s
+5y
+4p
+5berries
+9y
+5cot
+8e
+9s
+8s
+5dog
+8s
+5fold
+9s
+5head
+9s
+7rder
+9ers
+9ing
+9ings
+5ier
+7st
+6sh
+8ly
+8ness
+9esses
+5le
+6ike
+5man
+6en
+5o
+6s
+5shank
+9ks
+7ead
+9ds
+9rer
+9rers
+9ring
+9rings
+6kin
+9s
+5track
+9ks
+5walk
+9s
+5y
+4r
+5ed
+6r
+6st
+5ing
+5leg
+8s
+6y
+5ness
+9es
+5s
+4sh
+6a
+7s
+4t
+5ed
+6r
+7s
+5fed
+5ier
+7st
+6ng
+8s
+5less
+6ike
+5rock
+9ed
+9ing
+9s
+5s
+5y
+4ve
+6s
+3getz
+3hita
+7h
+8s
+7s
+3ik
+5dom
+8s
+5h
+6a
+7s
+6dom
+9s
+6s
+5s
+4la
+6s
+5ing
+8s
+4tan
+7s
+3kalim
+4el
+6im
+6s
+3ldduck
+9s
+5rake
+9s
+5uck
+8s
+4f
+5ed
+5ful
+8s
+5ier
+7st
+6ng
+5like
+5room
+9s
+5s
+5talker
+9ers
+5y
+4l
+5ac
+7k
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+7s
+5back
+9s
+7rk
+9s
+6ound
+5cracker
+9kers
+5drake
+9es
+6uck
+9s
+5ed
+6r
+7s
+5fire
+9s
+7sh
+9eries
+9ery
+9es
+6ul
+8s
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5proof
+5s
+6hock
+9ked
+9ks
+5work
+9s
+5y
+6coat
+9ts
+4ta
+6s
+5er
+7belt
+9lts
+7ed
+8r
+9s
+7ing
+9gs
+7less
+7s
+7y
+5ie
+7s
+5y
+4ve
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5y
+3mozzle
+9d
+9s
+8ing
+3nanigan
+9ns
+4d
+5ing
+5s
+4t
+3ol
+5s
+3pherd
+8ed
+9ss
+9sses
+8ing
+8less
+9ing
+9ings
+8s
+3qalim
+4el
+6s
+3rang
+7s
+5rdisation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+4bert
+8s
+6t
+7s
+4d
+5s
+4e
+5ef
+7ian
+7s
+4gottite
+9tes
+4ia
+6s
+6t
+7s
+5f
+6f
+7alties
+9ty
+7dom
+9ms
+7s
+8hip
+9ips
+6ian
+6s
+4lock
+8s
+4oot
+7s
+4pa
+6s
+4ries
+6s
+7es
+5y
+4wani
+8s
+3s
+3t
+4land
+8s
+4s
+4ting
+3uch
+6ed
+6ing
+6s
+4gh
+6ed
+6ing
+6s
+3va
+5s
+3w
+4bread
+9s
+4ed
+5l
+6s
+5r
+6s
+4ing
+4n
+4s
+2h
+2iai
+5s
+4tsu
+7s
+5zu
+7s
+3bah
+6s
+4boleth
+9hs
+4uichi
+9s
+3cker
+7ed
+7s
+5sa
+7s
+3dder
+7s
+5uch
+8im
+3ed
+4l
+5d
+6ed
+7r
+8s
+6ing
+9s
+6less
+7ike
+8ng
+9gs
+6rake
+9es
+6s
+6wall
+9ls
+5ed
+5ing
+8s
+5s
+4r
+5s
+4s
+5t
+3ft
+5able
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5less
+9ly
+9ness
+9nesses
+5s
+5work
+9s
+5y
+3gella
+8e
+8s
+7oses
+9is
+3itake
+8s
+3kar
+6ee
+8s
+6i
+7s
+6red
+7ing
+6s
+4ker
+7s
+4sa
+6s
+5e
+6h
+7s
+6s
+3lingi
+4l
+5aber
+9s
+6la
+8h
+9s
+8s
+5ed
+6lagh
+9hs
+8h
+9s
+5ing
+8less
+8s
+9worth
+9worths
+5s
+5yshallied
+9llier
+9lliers
+9llies
+9lly
+9llying
+4pit
+4y
+3m
+4aal
+7s
+4med
+6r
+7ed
+7ier
+9st
+8ng
+9gly
+9gs
+7s
+7y
+6y
+7s
+5ied
+7s
+6ng
+5y
+6ing
+4ozzle
+9s
+4s
+3n
+4bone
+8s
+4dies
+6g
+7s
+5y
+6s
+4e
+5d
+5less
+5r
+6s
+5s
+6s
+7es
+4gle
+7d
+7r
+8s
+7s
+6ier
+8st
+7ng
+9s
+6y
+5uard
+9s
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+7ly
+7ness
+9sses
+4ju
+6s
+4kin
+7s
+4leaf
+8s
+7ves
+4ne
+6d
+6ries
+7y
+6s
+6y
+7ed
+7ing
+7s
+5ied
+7s
+6ng
+5y
+6ing
+4plaster
+9ers
+4s
+5plints
+4tied
+7s
+5y
+6ing
+4y
+3p
+4board
+9s
+6rne
+5roker
+9rs
+5uilder
+9ers
+9ing
+9ings
+4fitter
+9rs
+5ul
+7s
+4lap
+7ped
+8ing
+7s
+5ess
+5oad
+8s
+4man
+6ster
+9rs
+6te
+8s
+5en
+7t
+8s
+4owner
+9s
+4pable
+5ed
+6n
+7s
+6r
+7s
+5ie
+7s
+6ng
+8s
+5o
+6n
+7s
+6s
+6und
+9s
+4s
+5hape
+5ide
+8s
+4way
+7s
+5orm
+8s
+5reck
+9ed
+9ing
+9s
+6ight
+9ts
+4yard
+8s
+3r
+4alee
+8s
+4e
+5d
+5man
+6en
+5s
+4ing
+4k
+5ed
+6r
+7s
+5ing
+5s
+4r
+5a
+6lee
+9s
+6s
+5ed
+5ing
+8s
+5s
+4s
+4t
+5band
+9s
+5dress
+9ses
+5ed
+5front
+9ts
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5less
+6ifter
+9ers
+5maker
+9rs
+5s
+6leeve
+9ved
+9ves
+5tail
+9ed
+9ing
+9s
+5waist
+9ter
+9ters
+9ts
+5y
+3sh
+5a
+6s
+4o
+5s
+4t
+5s
+3take
+7s
+4tah
+7s
+5im
+7s
+7wood
+9ods
+4zu
+6s
+3ur
+5im
+3v
+4a
+5h
+6s
+5ree
+8d
+8ing
+8s
+5s
+4e
+5r
+6ed
+7r
+8s
+6ier
+8st
+7ng
+9ly
+9s
+6s
+6y
+5s
+4iti
+7s
+4oo
+6s
+4s
+4ved
+5ing
+2kotzim
+2lemiehl
+9s
+7l
+8s
+5ozzle
+9ed
+9es
+9ing
+4p
+5p
+6ed
+7r
+8s
+6ing
+6s
+5s
+3imazel
+9s
+3ock
+6ier
+8st
+6s
+6y
+4shim
+8s
+3ub
+5s
+4mp
+6ed
+6ing
+6s
+6y
+2maltz
+7es
+7ier
+9st
+7y
+4tte
+7s
+3ear
+6s
+4k
+5s
+3o
+4ck
+6s
+4es
+4ose
+7d
+7s
+6ing
+5ze
+7d
+7r
+8s
+7s
+6ier
+8st
+7ng
+6y
+3uck
+6s
+2napps
+5s
+3ook
+6s
+4rrer
+8s
+2oal
+5ed
+6r
+6st
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5ness
+9es
+5s
+5wise
+5y
+4t
+5s
+3chet
+7im
+7s
+4k
+5abilities
+9ity
+7le
+5ed
+6r
+7s
+5headed
+5ing
+8ly
+8ness
+9esses
+5proof
+5s
+6tall
+9ls
+5umentaries
+9tary
+3d
+4den
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+5y
+4er
+6s
+3e
+4bill
+8s
+5lack
+9s
+5ox
+7es
+4d
+4horn
+8ed
+8ing
+8s
+4ing
+7s
+4lace
+8s
+5ess
+4maker
+9s
+7ing
+9gs
+4pac
+7k
+8s
+7s
+4r
+5s
+4s
+5hine
+9s
+5tring
+9gs
+4tree
+8s
+3far
+6s
+4roth
+3g
+4ged
+5ing
+5le
+7d
+7s
+6ier
+8st
+7ng
+6y
+4i
+5s
+4s
+4un
+6al
+7te
+9s
+6s
+3ji
+5s
+3la
+5s
+4om
+6s
+3ne
+5en
+7s
+4gololo
+9os
+4kier
+7st
+5y
+3o
+4ed
+4flies
+6y
+4gie
+7d
+7ing
+7s
+5le
+7d
+7s
+6ier
+8st
+7ng
+6y
+4ing
+4k
+5s
+4l
+5e
+6d
+6s
+5ing
+5s
+4n
+4ra
+6s
+4s
+4t
+5able
+6round
+9nds
+5down
+9s
+5er
+7s
+5ing
+8s
+6st
+8s
+5out
+8s
+5s
+3p
+4aholic
+9cs
+9sm
+9sms
+4board
+9s
+6t
+7s
+6y
+7s
+5reaker
+9ers
+9ing
+9ings
+4e
+4fitter
+9rs
+5ront
+9s
+5ul
+7s
+4girl
+8s
+4har
+7s
+5roth
+4keeper
+9rs
+8ing
+9ngs
+4lift
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+4man
+5en
+4pe
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5y
+4s
+5oiled
+4talk
+8s
+4walker
+9rs
+5indow
+9ws
+5oman
+7en
+6rn
+3ran
+6s
+4e
+5bird
+9s
+5d
+5front
+9ts
+5less
+6ine
+9s
+5man
+6en
+5r
+6s
+5s
+6ide
+9s
+6man
+7en
+5ward
+9s
+6eed
+9s
+4ing
+7s
+4l
+5s
+4n
+4t
+5age
+8s
+6rm
+5board
+9ds
+6read
+9ds
+5cake
+9s
+6hange
+9ged
+9ger
+9gers
+9ges
+9ging
+6oming
+9ngs
+6rust
+6ut
+8s
+8ting
+5ed
+6n
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6r
+6st
+5fall
+9s
+5gown
+9s
+5hair
+9ed
+9s
+7nd
+9ed
+9s
+6ead
+9s
+6old
+7rn
+9s
+5ia
+7s
+6e
+7s
+6ng
+6sh
+5list
+9ed
+9ing
+9s
+6y
+5ness
+9es
+5s
+6ighted
+9tedly
+6top
+9s
+6word
+9ds
+5wave
+9d
+9s
+8ing
+5y
+3t
+4e
+5s
+4firer
+9s
+4gun
+7ned
+9r
+9rs
+8ing
+7s
+4hole
+8s
+4maker
+9s
+7ing
+9gs
+4proof
+4s
+4t
+5e
+6d
+6n
+6s
+5ing
+5le
+7s
+5s
+3ugh
+6s
+4ld
+6er
+8ed
+8ing
+9ngs
+8s
+7st
+6st
+4se
+6s
+4t
+5ed
+6r
+7s
+5her
+8ed
+8ing
+8s
+5ier
+7st
+6ng
+8ly
+8s
+5line
+9s
+5s
+5y
+3ve
+5d
+5l
+6board
+9rds
+6ed
+7r
+8s
+6ful
+9s
+6head
+9ds
+6ing
+6led
+8r
+9s
+7ing
+6nose
+9es
+6s
+7ful
+5r
+6s
+5s
+4ing
+7s
+3w
+4able
+4biz
+7zes
+8y
+5oat
+8ed
+9r
+9rs
+8ing
+8s
+6x
+7es
+5read
+9s
+4case
+8d
+8s
+7ing
+4d
+5ed
+5ing
+5own
+8s
+5s
+4ed
+5r
+6ed
+7r
+8s
+6ful
+6head
+9ds
+6ier
+8st
+7ness
+9sses
+8g
+9s
+6less
+6proof
+9ofed
+9ofing
+9ofings
+9ofs
+6s
+6y
+4ghe
+7s
+5irl
+8s
+5round
+9ds
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4jump
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+4man
+7ly
+7ship
+9ips
+5en
+4n
+4off
+7s
+4piece
+9s
+5lace
+9s
+4ring
+8s
+5oom
+8s
+4s
+5topper
+9ers
+9ing
+4time
+8s
+4y
+5ard
+8s
+3yu
+5s
+2raddha
+8s
+4nk
+4pnel
+8s
+3ed
+5ded
+7r
+8s
+6ier
+8st
+7ng
+9s
+6y
+5less
+5s
+4ek
+6ed
+6ing
+6s
+4ik
+6ed
+6ing
+6s
+4w
+5d
+6er
+7st
+6ie
+8s
+6ly
+6ness
+9ses
+5ed
+5ing
+6sh
+8ly
+8ness
+9esses
+5like
+5mice
+6ouse
+5s
+3i
+4ech
+7ed
+8s
+7ing
+5k
+6ed
+7r
+8s
+6ier
+8st
+7ng
+9ly
+9s
+6s
+6y
+5val
+8ties
+9y
+6e
+7d
+7s
+6ing
+4ft
+6s
+4ght
+7s
+4ke
+6d
+6s
+5ing
+4ll
+6ed
+7r
+7st
+6ier
+8st
+7ng
+9s
+6ness
+9ses
+6s
+6y
+4mp
+6ed
+7r
+8s
+6ier
+8st
+7ngs
+6like
+6s
+6y
+4nal
+5e
+6d
+6like
+6s
+5ing
+5k
+6able
+7ge
+9s
+6er
+8s
+6ing
+9ly
+6pack
+9ks
+6s
+4s
+4tch
+7ed
+8s
+7ing
+4ve
+6d
+6l
+7ed
+7ing
+7led
+8ing
+7s
+6n
+6r
+7s
+6s
+5ing
+8s
+3off
+6age
+9s
+6ed
+6ing
+6s
+4om
+6ed
+7r
+8s
+6ing
+6s
+4ud
+6ed
+6ier
+8st
+7ng
+9s
+6less
+6s
+6y
+4ve
+6d
+6s
+5ing
+4w
+5d
+5ed
+5ing
+5s
+3ub
+5bed
+7ried
+9es
+8y
+6ier
+8st
+7ness
+9sses
+8g
+6y
+5land
+9s
+6ess
+6ike
+5s
+4g
+5ged
+6ing
+5s
+4nk
+6en
+2tchi
+6s
+3etel
+7ach
+7s
+5l
+6ach
+6s
+3ick
+6ier
+8st
+6s
+6y
+4k
+5s
+3ook
+6s
+5m
+3uck
+6s
+4m
+5m
+4p
+5ped
+6ing
+5s
+2ubunkin
+9s
+3ck
+5ed
+6r
+7s
+5ing
+8s
+5s
+3dder
+7ed
+7ing
+9gly
+9gs
+7s
+8ome
+7y
+3ffle
+7board
+9ards
+7d
+7r
+8s
+7s
+6ing
+9ly
+9s
+4ti
+6es
+6s
+5y
+3ggies
+5y
+3l
+4e
+5d
+5s
+4ing
+4n
+4s
+3n
+4amitism
+9sms
+4less
+4nable
+5ed
+6r
+7s
+5ing
+4pike
+8d
+8r
+9s
+8s
+7ing
+9gs
+4s
+4t
+5ed
+6r
+7s
+5ing
+8s
+5s
+3ra
+5s
+4iken
+8s
+3sh
+5ed
+6r
+7s
+6s
+5ing
+3t
+4down
+8s
+4e
+5d
+5s
+5ye
+7s
+4ing
+4off
+7s
+5ut
+7s
+4s
+4ter
+7bug
+9gs
+7ed
+7ing
+9gs
+7less
+7s
+5ing
+5le
+7cock
+9cked
+9cking
+9cks
+7d
+7less
+7r
+8s
+7s
+7wise
+6ing
+2vartze
+8s
+2wa
+4npan
+8s
+4s
+3eshwe
+8s
+2y
+3er
+5s
+4st
+3ing
+4sh
+3lock
+7ed
+7ing
+7s
+4y
+3ness
+7es
+3poo
+6s
+3ster
+7s
+1i
+2al
+4agogic
+8ue
+9es
+4ic
+5d
+6an
+8s
+6s
+4ogogic
+8ue
+9es
+6ram
+9s
+8phies
+9hy
+5id
+5lith
+9s
+5n
+6s
+5rrhoea
+9eas
+4s
+3mang
+7s
+4ese
+7d
+7s
+6ing
+5ze
+7d
+7s
+6ing
+2b
+3b
+4s
+3ilance
+9s
+8ies
+8y
+7t
+8ly
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+9y
+5ous
+3ling
+7s
+3s
+4hip
+7s
+3yl
+5ic
+5lic
+7ne
+5s
+2c
+3can
+5r
+5tive
+9s
+4ed
+4ing
+5ties
+6y
+3e
+4s
+3h
+4t
+5ed
+5ing
+5s
+3iliana
+8e
+8o
+9s
+6enne
+9es
+3k
+4bay
+7s
+5ed
+7s
+4ed
+5e
+6s
+5n
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+5r
+6ly
+6ness
+9ses
+5st
+4ie
+6s
+5ng
+5sh
+7ly
+7ness
+9sses
+4le
+6bill
+9ls
+6d
+6man
+7en
+7ia
+9s
+8c
+6s
+5ied
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5y
+6ing
+4ness
+8es
+5urse
+9s
+8ing
+9ngs
+4o
+5s
+5ut
+7s
+4room
+8s
+4s
+3like
+3s
+2da
+4lcea
+8s
+4s
+3dha
+6s
+5i
+6s
+5uism
+9s
+4ur
+6im
+6s
+3e
+4arm
+7s
+4band
+8s
+6r
+7s
+5oard
+9s
+6nes
+5urned
+8s
+4car
+7s
+5heck
+9s
+4d
+5ness
+9es
+5ress
+9es
+4hill
+8s
+4kick
+8s
+4levers
+5ight
+9s
+6ne
+8d
+8r
+9s
+8s
+7g
+7ing
+5ock
+8s
+6ng
+4man
+5en
+4note
+8s
+4path
+8s
+5iece
+9s
+4r
+5al
+6te
+8d
+8s
+7ing
+8on
+9ns
+5eal
+8ly
+5ite
+8s
+7ic
+5oad
+8s
+6lite
+9es
+6penia
+9ias
+7hile
+9les
+9lic
+9lin
+9lins
+6ses
+7is
+7tat
+9tic
+9ts
+6tic
+5s
+4s
+5addle
+9es
+5hoot
+9s
+7w
+8s
+5lip
+8ped
+9ing
+8s
+5man
+6en
+5pin
+8s
+6litting
+9tingly
+5tep
+8ped
+9er
+9ers
+9ing
+8s
+6ream
+7oke
+9es
+5wipe
+9d
+9r
+9rs
+9s
+8ing
+4track
+9ed
+9ing
+9s
+4walk
+8s
+7l
+8s
+6rd
+8s
+6y
+7s
+5heel
+9er
+9ers
+9s
+5inder
+9rs
+6se
+3h
+4a
+5s
+4e
+3ing
+6s
+3le
+5d
+5r
+6s
+5s
+4ing
+7ly
+2ecle
+6s
+3ge
+5craft
+9ts
+5d
+5r
+6s
+5s
+5works
+4ing
+3ld
+3mens
+3n
+4ite
+7s
+4na
+6s
+4s
+4t
+5s
+3rozem
+8s
+4ra
+6n
+6s
+3s
+4ta
+6s
+3th
+5s
+3ur
+5s
+3ve
+5d
+5like
+5rt
+7s
+5s
+4ing
+2f
+3aka
+6s
+3fle
+6d
+6s
+6ur
+8s
+7se
+9s
+5ing
+3rei
+3t
+4ed
+5r
+6s
+4ing
+7ly
+7s
+4s
+2ganid
+7s
+3h
+4ed
+5r
+6s
+4ful
+4ing
+7ly
+4less
+5ike
+4s
+4t
+5able
+5ed
+6r
+7s
+5ing
+8s
+5less
+9ly
+9ness
+9nesses
+6ier
+8st
+7ne
+9s
+9ss
+9sses
+6y
+5s
+6aw
+6creen
+9ens
+6ee
+8ing
+9ngs
+8n
+8r
+9s
+8s
+6man
+7en
+5worthy
+3il
+5larian
+9ans
+9d
+9ds
+8y
+7te
+8ion
+9ons
+5s
+4sbei
+7o
+3la
+5s
+4oi
+5s
+4um
+3ma
+5s
+5te
+7d
+7s
+6ic
+7ng
+7on
+9s
+7sm
+9s
+6ron
+9s
+4oid
+7al
+9ly
+7ectomies
+9tomy
+7oscope
+9copes
+9copic
+9copies
+9copy
+7s
+3n
+4a
+5ble
+5ge
+7s
+5l
+6ed
+7r
+8s
+6ing
+9s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6led
+8r
+9s
+7ing
+9gs
+7y
+6man
+7en
+9t
+9ts
+6s
+5ries
+6y
+5tories
+8y
+6ure
+9s
+4board
+9s
+4ed
+5e
+6s
+5r
+6s
+5t
+6ed
+6ing
+6s
+5ur
+7ie
+9s
+4ieur
+8s
+5fiable
+7cance
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9nts
+9te
+9tes
+9tion
+9tions
+9tive
+9tively
+9tor
+9tors
+9tory
+8s
+7ed
+9s
+8r
+9s
+8s
+6y
+7ing
+9gs
+5ng
+7s
+5or
+7i
+8es
+7s
+7y
+4less
+4or
+6a
+7s
+6e
+7s
+6i
+7a
+8l
+8s
+7es
+7na
+9s
+8e
+8i
+8o
+6s
+6y
+4post
+8ed
+8ing
+8s
+4s
+2jo
+4s
+2k
+3a
+4s
+3e
+4r
+4s
+3orskies
+7y
+2lage
+6d
+6ing
+6s
+5ing
+4ne
+6s
+4stic
+8s
+3d
+4s
+3e
+4d
+4n
+5ce
+7d
+7r
+8s
+7s
+6ing
+5e
+6s
+5i
+5s
+5t
+6er
+7st
+6iaries
+9y
+6ly
+6ness
+9ses
+6s
+5us
+4r
+5s
+4s
+5ia
+7s
+4x
+5es
+3houette
+9ed
+9es
+9ing
+9ist
+9ists
+3ica
+6s
+6te
+8d
+8s
+7ing
+5eous
+5ic
+7olous
+6de
+8s
+6ferous
+7ication
+9ations
+8ed
+9s
+7y
+8ing
+6ous
+6um
+8s
+5le
+7s
+5on
+7e
+8s
+7ised
+8zed
+7s
+6ses
+7is
+6tic
+9s
+5ula
+8e
+8s
+7e
+8s
+7ose
+4ng
+4qua
+7ceous
+7e
+7s
+6e
+7s
+6ose
+7us
+3k
+4alene
+9s
+6ine
+9s
+4ed
+5n
+6ed
+6ing
+6s
+4grower
+9rs
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+4like
+4oline
+9s
+4s
+5creen
+9ns
+4tail
+8s
+4weed
+8s
+5orm
+8s
+4y
+3l
+4abub
+8s
+5dar
+8s
+4er
+6s
+4ibub
+8s
+5er
+6s
+7t
+5ly
+5manite
+9tes
+5ness
+9es
+4ock
+7s
+4s
+4y
+3o
+4ed
+4ing
+4s
+4xane
+8s
+3phia
+6um
+8s
+3t
+4ation
+9s
+4ed
+4ier
+6st
+5ng
+4s
+5tone
+9s
+4y
+3urian
+6d
+7s
+6st
+8s
+5oid
+8s
+3va
+5e
+5n
+6s
+5s
+5tic
+4er
+6back
+9ks
+7erries
+9ry
+7ill
+9ls
+6ed
+7r
+8s
+7ye
+9s
+6fish
+9hes
+6horn
+9ns
+6ier
+8st
+7ness
+9sses
+8g
+9s
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6ling
+9gs
+7y
+6n
+6point
+9nts
+6s
+7ide
+9es
+9eses
+7kin
+9ns
+7mith
+9thing
+9things
+9ths
+6tail
+9ls
+6ware
+9es
+7eed
+9ds
+6y
+5strian
+5x
+6es
+4ical
+6s
+6ultural
+9urally
+9ure
+9ures
+9urist
+9urists
+3ymarin
+9s
+2m
+3a
+4r
+5ouba
+9ceous
+9s
+5re
+7s
+5s
+5uba
+8ceous
+8s
+4s
+4tic
+4zine
+8s
+3ba
+5s
+3i
+4al
+5n
+6s
+4lar
+7ities
+9y
+7ly
+6tive
+5e
+6s
+5ise
+8d
+8s
+7ing
+6tude
+9es
+6ze
+8d
+8s
+7ing
+5limum
+9ms
+5or
+7s
+4oid
+5us
+4s
+4tar
+7s
+3kin
+6s
+3lin
+6s
+3mer
+6ed
+6ing
+6s
+3nel
+6s
+3oleon
+8s
+4niac
+8al
+9lly
+8s
+6es
+6ous
+6se
+8d
+8s
+7ing
+7t
+8s
+6ze
+8d
+8s
+7ing
+5y
+4om
+6s
+5n
+6s
+4rg
+6s
+3p
+4ai
+6s
+5tico
+4er
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+4kin
+7s
+4le
+6d
+6minded
+9dedly
+6ness
+9ses
+6r
+7s
+6s
+7se
+9s
+7t
+6ton
+9s
+6x
+7es
+5ices
+7ia
+9l
+9lly
+8dentate
+8ter
+9ies
+9y
+6fication
+9ations
+9ative
+9ator
+9ators
+8ed
+9r
+9rs
+9s
+7y
+8ing
+6ng
+8s
+6sm
+8s
+7t
+8e
+8ic
+9cally
+8s
+5y
+4s
+3s
+3ul
+5acra
+8e
+9s
+8um
+9ms
+6nt
+8s
+6r
+7s
+6te
+8d
+8s
+7ing
+8on
+9ns
+8ve
+9ely
+7or
+9s
+9y
+5cast
+9ed
+9ing
+9s
+5ium
+8s
+5s
+5taneities
+9ity
+9ous
+9ouses
+9ously
+4rg
+6h
+7s
+6s
+2n
+3anthropus
+9puses
+4pism
+8s
+4rchism
+9ms
+9t
+9ts
+5quism
+9ms
+9t
+9ts
+3ce
+5re
+7ly
+7ness
+9sses
+7r
+7st
+6ities
+8y
+4ipita
+9l
+6ut
+8s
+3d
+4ed
+4ing
+7s
+4on
+6ologies
+9gist
+9gists
+9gy
+7phanies
+9any
+6s
+4s
+3e
+4cure
+8s
+7ism
+9ms
+9t
+9ts
+4d
+4s
+4w
+5ed
+5ier
+7st
+6ness
+9ses
+7g
+5less
+5s
+5y
+3fonia
+8s
+7e
+8tta
+9tas
+4ul
+6ly
+6ness
+9ses
+3g
+4able
+8ness
+9esses
+5long
+9s
+4e
+5d
+5ing
+5r
+6s
+5s
+4ing
+7ly
+7s
+4le
+6d
+7om
+9s
+6hood
+9ds
+6ness
+9ses
+6s
+7tick
+9cks
+6t
+7on
+9s
+7rack
+9cks
+8ee
+9es
+7s
+5ing
+8s
+5y
+4s
+5ong
+8ed
+8ing
+8s
+8y
+5piel
+9s
+4ular
+8isation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8ness
+9esses
+8s
+8y
+6t
+7s
+7us
+9es
+3h
+4s
+3ical
+5ise
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+4ng
+4ster
+8ities
+9ty
+8ly
+8ness
+9esses
+8wise
+6ral
+9ities
+9ity
+9ly
+9s
+7odextral
+8rsal
+9sally
+9se
+9sely
+8us
+9sly
+3k
+4able
+5ge
+7s
+4er
+6s
+4hole
+8s
+4ier
+6st
+5ng
+7s
+4s
+4y
+3less
+7ly
+7ness
+9sses
+3ned
+5r
+6ed
+6ing
+6s
+5t
+6s
+4ing
+7ia
+9s
+3oatrial
+4logical
+8es
+8st
+9ts
+7ue
+9s
+7y
+4pia
+7s
+6e
+6s
+7es
+6te
+8s
+3s
+4emilla
+9as
+4yne
+3ter
+6abilities
+9lity
+6ed
+6ing
+6s
+6y
+3uate
+7d
+7ly
+7s
+6ing
+7on
+9s
+4itis
+8es
+4ose
+6ities
+8y
+5us
+7ly
+7ness
+9sses
+4pallial
+9ate
+4s
+5es
+5itis
+9es
+5like
+5oid
+8al
+9lly
+8s
+2p
+3e
+4d
+4s
+3hon
+6age
+9s
+7l
+7te
+6ed
+7t
+8s
+6ic
+7ng
+6ogam
+9mies
+9ms
+9my
+7phore
+9ores
+9orous
+7stele
+9eles
+9elic
+6s
+4uncle
+9s
+3ing
+3ped
+5r
+6s
+5t
+6s
+4ing
+4le
+6d
+6s
+5ing
+4y
+3s
+3unculid
+9ds
+8oid
+9ids
+2r
+3car
+6s
+3dar
+6s
+3e
+4d
+4e
+5s
+4n
+5ian
+8s
+6c
+6se
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5s
+4s
+3gang
+7s
+3i
+4ases
+6is
+4h
+5s
+4ng
+6s
+4s
+3kar
+6s
+3loin
+7s
+3name
+7d
+7s
+6ing
+3oc
+5co
+7s
+5s
+4nise
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+4set
+3ra
+5h
+6s
+5s
+4ed
+5e
+6s
+4ing
+3s
+3tuin
+7s
+3up
+5ed
+5ier
+7st
+6ng
+5s
+5y
+3vente
+8s
+2s
+3al
+5s
+3eraries
+7y
+4s
+3kin
+6s
+3s
+4es
+4ier
+6s
+7t
+5fied
+5ness
+9es
+4oo
+6s
+4y
+5ish
+5ness
+9es
+3t
+4ed
+5r
+6ed
+6hood
+9ds
+6ing
+6less
+7ike
+8ness
+9esses
+7y
+6s
+4ing
+4ra
+5oid
+5um
+7s
+4s
+2t
+3ar
+5ist
+8s
+5s
+4tunga
+9s
+3com
+6s
+3e
+4d
+4lla
+7s
+4s
+3fast
+7s
+3h
+4e
+5d
+5e
+5n
+6ce
+6s
+5s
+4ing
+3ing
+4ologies
+8y
+5phobia
+9ias
+3ka
+5mer
+8s
+3ologies
+7y
+4phobia
+9as
+4sterol
+9ls
+3rep
+6s
+3s
+3tar
+6s
+4ella
+8s
+5n
+5r
+6s
+4ine
+6g
+7s
+3uate
+7d
+7s
+6ing
+7on
+9al
+9ally
+9ism
+9isms
+9s
+4la
+6e
+4p
+5s
+4s
+5es
+4tunga
+9s
+3z
+4krieg
+9s
+4mark
+8s
+2ver
+5s
+2wash
+6ed
+7s
+6ing
+2x
+3ain
+6e
+7s
+6s
+3er
+5s
+4s
+3fold
+3mo
+5s
+3pence
+8s
+6nies
+7y
+3score
+8s
+3te
+5en
+7er
+9s
+7mo
+9s
+7s
+7th
+9ly
+9s
+5s
+4h
+5ly
+5s
+4ies
+6th
+8s
+4y
+5ish
+2zable
+7ness
+9sses
+6y
+4r
+5s
+6hip
+9s
+3e
+4able
+8ness
+9esses
+7y
+4d
+4ism
+7s
+6t
+7s
+4l
+5s
+4r
+5s
+4s
+3ier
+5st
+4ness
+8es
+5g
+6s
+4sm
+6s
+5t
+6s
+3y
+3zle
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+1jambok
+7ed
+7ing
+7ked
+8ing
+7s
+2oe
+1ka
+3g
+4s
+3il
+5ed
+5ing
+5s
+4th
+6ed
+6ing
+6less
+6s
+3ld
+5ic
+5s
+6hip
+9s
+3nger
+7s
+4ked
+6r
+7s
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5s
+5y
+3rt
+5h
+6s
+5s
+3s
+3t
+4e
+5board
+9ded
+9der
+9ders
+9ding
+9dings
+9ds
+5d
+5park
+9s
+5r
+6s
+5s
+4ing
+7s
+4ol
+6e
+7s
+6s
+4s
+4t
+5s
+3w
+4s
+2ean
+5e
+6s
+5s
+4r
+5ed
+5ier
+7st
+6ng
+5s
+5y
+3daddle
+9d
+9r
+9rs
+9s
+8ing
+3e
+4chan
+8s
+4d
+4f
+4ing
+4lier
+7st
+5y
+4n
+5s
+4r
+5ed
+5ier
+7st
+6ng
+5s
+5y
+4s
+5icks
+4ted
+6r
+7s
+5s
+3g
+4g
+5er
+7s
+5s
+4s
+3igh
+6er
+7st
+4n
+5ed
+5ing
+5s
+3lder
+7ed
+7ing
+7s
+4etal
+8ly
+6ogenous
+7n
+8ic
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8s
+4f
+5s
+4l
+5ie
+7d
+7r
+7s
+8t
+5och
+8ed
+8ing
+8s
+5s
+5um
+7s
+5y
+6ing
+4m
+5s
+4p
+5ed
+5ing
+8s
+6t
+5s
+4ter
+7ed
+7ing
+7s
+4um
+6s
+3n
+4e
+5s
+4ned
+5ing
+4s
+3o
+4s
+3p
+4ful
+7s
+4ped
+5ing
+4s
+5is
+7es
+4tic
+7al
+9ly
+9ness
+9nesses
+7ism
+9ms
+7s
+3r
+4red
+5ick
+8s
+6es
+6ng
+5y
+4s
+3t
+4ch
+6abilities
+9lity
+8le
+6book
+9ks
+6ed
+7r
+8s
+7s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6pad
+9s
+6y
+4s
+4ted
+5ing
+3uomorph
+9hic
+9hism
+9hisms
+9hs
+3w
+4back
+8ed
+8s
+6ld
+8s
+4ed
+5r
+6ed
+6ing
+6s
+5st
+4ing
+4ness
+8es
+4s
+4whiff
+2i
+3able
+4gram
+8s
+7ph
+9s
+4machies
+8y
+4scope
+9s
+8ies
+8y
+4tron
+8s
+3bob
+6bed
+8r
+9s
+7ing
+9gs
+6s
+3d
+4ded
+6r
+7s
+5ier
+7st
+6ng
+5oo
+7ed
+7ing
+7s
+5y
+4lid
+7s
+4oo
+6ed
+6ing
+6s
+4pan
+7s
+5roof
+4s
+4way
+7s
+3ed
+4r
+5s
+4s
+4y
+5er
+6st
+3ff
+5ed
+5ing
+5le
+7d
+7s
+8s
+6ing
+5s
+3ing
+6s
+3jorer
+8s
+6ing
+9s
+3kjoring
+9gs
+3lful
+7ly
+7ness
+9sses
+4l
+5centre
+9res
+5ed
+6ss
+8ness
+9esses
+6t
+7s
+5ful
+8ly
+8ness
+9esses
+5ier
+7s
+8t
+6galee
+9ees
+7olee
+9ees
+6ng
+8s
+6on
+8s
+5s
+5y
+3m
+4board
+9ed
+9er
+9ers
+9ing
+9s
+4med
+6r
+7s
+5ia
+7s
+6ng
+8ly
+8s
+8ton
+9ons
+4o
+5bile
+9d
+9s
+8ing
+5s
+4p
+5ed
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+5s
+5y
+4s
+3n
+4care
+8s
+4flick
+9s
+7nt
+9s
+9y
+5ood
+8s
+5ul
+7s
+4head
+8s
+4k
+5ed
+6r
+7s
+5ing
+5s
+4less
+5ike
+4ned
+6r
+7s
+5ier
+7s
+8t
+6ness
+9ses
+7g
+5y
+4s
+4t
+5er
+6st
+5ight
+9s
+3o
+4ring
+8s
+4s
+3p
+4jack
+8s
+4lane
+8s
+4pable
+5ed
+6r
+7ed
+7ing
+9gs
+7s
+6t
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5y
+4s
+3rl
+5ed
+5ing
+8s
+5s
+4mish
+8ed
+9r
+9rs
+9s
+8ing
+9ngs
+4r
+5ed
+6t
+7s
+5ing
+5s
+4t
+5ed
+6r
+7s
+5ing
+8s
+5less
+6ike
+5s
+3s
+3t
+4ch
+6ed
+7s
+6ing
+4e
+5d
+5s
+4ing
+4s
+4ter
+7ed
+7ier
+9st
+8ng
+7s
+7y
+5ish
+8ly
+8ness
+9esses
+5le
+7d
+7s
+6ing
+3ve
+5d
+5r
+6ed
+6ing
+6s
+5s
+4ie
+6r
+6st
+5ng
+7s
+4vied
+7s
+5y
+6ing
+4y
+3wear
+2late
+6d
+6s
+5ing
+3ent
+6ed
+6ing
+6s
+3iff
+6s
+4m
+5med
+6ing
+5s
+2oal
+5ed
+5ing
+5s
+3ff
+5ed
+5ing
+5s
+3kiaan
+8s
+3l
+4ia
+5on
+4led
+5ie
+7s
+6ng
+5y
+4s
+3okum
+4l
+5s
+4sh
+6ed
+7s
+6ing
+3rt
+5s
+3sh
+5es
+2ran
+5s
+3eegh
+7ed
+7ing
+7s
+5n
+6s
+4igh
+7ed
+7ing
+7s
+3iech
+7ed
+7ing
+7s
+5d
+5gh
+7ed
+7ing
+7s
+5s
+4k
+5e
+6d
+6s
+5ing
+5s
+4mmage
+9d
+9s
+8ing
+5p
+6ed
+6ing
+6s
+5shank
+9ked
+9ker
+9kers
+9king
+9ks
+3onk
+6s
+3ump
+6ed
+6ing
+6s
+3y
+4er
+6s
+4ing
+2ua
+4s
+3dler
+7s
+3g
+4ged
+5ing
+4s
+3ldudderies
+9ry
+6ggeries
+9ry
+4k
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5s
+4l
+5cap
+8s
+5duggeries
+9ery
+5ed
+5ing
+5s
+4pin
+7s
+3mmer
+7ed
+7ing
+7s
+3nk
+5bird
+9s
+5ed
+5ier
+7st
+6ng
+5s
+5weed
+9s
+5y
+3rried
+7s
+5y
+6ing
+3tterudite
+9ites
+5le
+7d
+7s
+6ing
+2y
+3board
+8s
+5rn
+7e
+5x
+6es
+4ridge
+9s
+3cap
+6s
+4lad
+3dive
+7d
+7r
+8s
+7s
+6ing
+9s
+4ove
+3ed
+4r
+5s
+4y
+3f
+4ed
+4ing
+4s
+3home
+7s
+5ok
+7s
+3ier
+5st
+4ng
+4sh
+3jack
+7ed
+8r
+9s
+7ing
+9gs
+7s
+3lab
+6s
+5rk
+7ed
+8r
+9s
+7ing
+9gs
+7s
+4ess
+4ight
+8ed
+8s
+5ke
+5ne
+7s
+5t
+3man
+4en
+3phoi
+6s
+3r
+4e
+5d
+5s
+4ing
+4mion
+8s
+4ocket
+9ed
+9ing
+9s
+4s
+3sail
+7s
+4cape
+8s
+5raper
+9rs
+4urf
+7ed
+8r
+9s
+7ing
+9gs
+7s
+3te
+5d
+5s
+4ing
+3walk
+7s
+5rd
+7s
+5y
+6s
+4rite
+8r
+9s
+8s
+7ing
+9gs
+7ten
+5ote
+1lab
+4bed
+6r
+7ed
+8r
+9s
+7ier
+9st
+8ng
+7s
+7y
+5ier
+7st
+6ness
+9ses
+7g
+5y
+4like
+4s
+5tone
+9s
+3ck
+5ed
+6n
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6r
+7s
+6st
+5ing
+5ly
+5ness
+9es
+5s
+5tivism
+9sms
+9st
+9sts
+4tivism
+9ms
+9t
+9ts
+3dang
+7s
+4e
+5s
+3e
+4s
+3g
+4ged
+5ier
+7st
+6ng
+8s
+5y
+4s
+3id
+4n
+5te
+4rg
+6ed
+6ing
+6s
+4ster
+8ed
+8ies
+9ng
+8s
+8y
+3kable
+4e
+5able
+5d
+5less
+5r
+6s
+5s
+4ing
+3lom
+6ed
+7r
+8s
+6ing
+7st
+9s
+6s
+3m
+4dance
+9d
+9s
+8ing
+4makin
+9s
+5ed
+6r
+7kin
+9ns
+7s
+5ing
+8s
+4s
+3nder
+7ed
+8r
+9s
+7ing
+7ous
+9sly
+9sness
+7s
+4e
+5s
+4g
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+8s
+6sh
+5s
+5uage
+9s
+6lar
+5y
+4k
+4t
+5ed
+6ndicular
+6r
+7s
+5ier
+7st
+6ndicular
+7g
+8ly
+8ways
+5ly
+5s
+5ways
+6ise
+5y
+3p
+4dash
+8ed
+9s
+8ing
+4happier
+9est
+8y
+5ead
+8s
+4jack
+8s
+4ped
+6r
+7s
+5ing
+8s
+4s
+5hot
+8s
+5tick
+9s
+3rt
+5ed
+5ing
+5s
+3sh
+5ed
+6r
+7s
+6s
+5fest
+9s
+5ing
+8ly
+8s
+3t
+4ch
+6es
+4e
+5d
+5like
+5r
+6s
+5s
+5y
+4her
+7ed
+7ing
+7s
+4ier
+6st
+5ness
+9es
+6g
+7s
+4s
+4ted
+6r
+7ed
+7ing
+7n
+8liness
+9y
+8s
+7s
+7y
+5ing
+8s
+4y
+3ughter
+9able
+9ed
+9er
+9ers
+9house
+9houses
+9ies
+9ing
+9man
+9men
+9ous
+9ously
+9s
+9y
+3ve
+5d
+5holder
+9ers
+9ing
+9ings
+5r
+6ed
+7r
+8s
+6ies
+7ng
+9ly
+9s
+6s
+6y
+5s
+5y
+6s
+4ing
+5sh
+7ly
+7ness
+9sses
+4ocracies
+9y
+8t
+9s
+5phil
+9e
+9es
+9s
+3w
+4s
+3y
+4able
+4ed
+5r
+6s
+4ing
+7s
+4s
+2eave
+6d
+6s
+5ing
+4ze
+6bag
+9s
+8ll
+9ls
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+5o
+6id
+8s
+5y
+3b
+4s
+3d
+4ded
+6r
+7s
+5ing
+8s
+4ed
+4ge
+6d
+6hammer
+9mered
+9mering
+9mers
+6r
+7s
+6s
+5ing
+8s
+4s
+3e
+4ch
+6es
+6ier
+8st
+6y
+4k
+5ed
+6n
+7ed
+7ing
+7s
+6r
+7s
+6st
+5ier
+7st
+6ng
+8s
+6t
+5ly
+5ness
+9es
+5s
+6tone
+9es
+5y
+4p
+5away
+5er
+7s
+7y
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5less
+9ly
+9ness
+9nesses
+6ike
+5out
+8s
+6ver
+9s
+5ry
+5s
+6uit
+9s
+5walk
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+6ear
+5y
+6head
+9ded
+9ds
+4r
+4st
+4t
+5ed
+5ier
+7st
+6ness
+9ses
+7g
+5s
+5y
+4ve
+6d
+6en
+8s
+6hand
+9ds
+6less
+8t
+9s
+7ike
+6r
+7s
+6s
+5ing
+8s
+4zier
+7st
+5y
+3ided
+4gh
+6ed
+7r
+8s
+6ing
+9s
+6s
+6t
+7s
+3nder
+7er
+8st
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7ly
+7ness
+9sses
+4ter
+7s
+3pt
+3uth
+6ed
+6hound
+9nds
+6ing
+6s
+3w
+4ed
+4ing
+4s
+3y
+4s
+2ice
+5able
+5d
+5r
+6s
+5s
+4ing
+7s
+4k
+5ed
+6n
+7ed
+8r
+9s
+7ing
+7s
+8ide
+9ded
+9des
+6r
+7ed
+7s
+6st
+5ing
+8s
+5ly
+5ness
+9es
+5rock
+9s
+5s
+6ter
+9s
+7one
+9es
+3d
+4able
+4den
+6r
+7ed
+7ing
+7s
+7y
+4e
+5d
+5r
+6s
+5s
+5way
+8s
+4ing
+7ly
+7s
+3er
+4st
+4ve
+6s
+3ght
+6ed
+7r
+8s
+7st
+6ing
+9ly
+7sh
+6ly
+6ness
+9ses
+6s
+3ly
+3m
+4down
+8s
+4e
+5ball
+9s
+5d
+5s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4line
+5y
+4med
+6r
+7s
+6st
+5ing
+8s
+6sh
+4nastics
+5ess
+8es
+4psier
+8st
+6y
+4s
+5ier
+7st
+5y
+4y
+3ng
+5back
+9s
+5er
+7s
+5ing
+5s
+6hot
+9s
+6tone
+9es
+4k
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5s
+6kin
+9s
+5weed
+9s
+5y
+4ter
+7s
+3otar
+7s
+3p
+4case
+8d
+8s
+5over
+9ed
+9ing
+9s
+4dress
+9es
+4e
+5d
+5s
+4form
+8ed
+8ing
+8s
+4ing
+4knot
+8s
+4less
+4noose
+9s
+4out
+7s
+5ver
+8s
+4page
+8s
+5ed
+6r
+7ed
+7ier
+9st
+8ly
+8ness
+9esses
+9g
+7s
+7wort
+9rts
+7y
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5y
+4rail
+8s
+4s
+5heet
+9ed
+9ing
+9s
+6od
+8diness
+8ness
+9esses
+5lop
+8py
+8s
+5ole
+8s
+5tream
+9med
+9ming
+9ms
+4t
+4up
+6s
+4ware
+8s
+6y
+7s
+3sh
+5es
+3t
+4her
+7ed
+7ier
+9st
+8ng
+7s
+7y
+4less
+5ike
+4s
+4ted
+6r
+7s
+5ier
+7st
+6ng
+5y
+3ve
+5d
+5n
+5r
+6ed
+7r
+8s
+6ing
+6s
+5s
+4ing
+4ovic
+8a
+9s
+8es
+7tz
+9es
+5witz
+9es
+2oan
+5s
+3b
+4ber
+7ed
+8r
+9s
+7ier
+9st
+8ng
+7s
+7y
+5ier
+7st
+6sh
+8ness
+9esses
+5y
+4land
+8s
+4s
+3ckdolager
+9gers
+8iger
+9gers
+8oger
+9gers
+5en
+7ed
+7ing
+7s
+3e
+4bush
+8es
+4s
+4thorn
+9s
+5ree
+8s
+3g
+4an
+6eer
+9ed
+9ing
+9ings
+9s
+6ise
+9d
+9s
+8ing
+9ngs
+7ze
+9d
+9s
+8ing
+9ngs
+6s
+4ged
+6r
+7s
+5ing
+4s
+3id
+5s
+3jd
+5s
+3ken
+6ed
+6ing
+6s
+3mmock
+8ed
+8ing
+8s
+3om
+5ed
+5ier
+7st
+6ng
+5s
+5y
+4p
+5s
+4sh
+6ed
+7s
+6ing
+4t
+5s
+3p
+4e
+5d
+5r
+6s
+5s
+5wise
+4ier
+6st
+5ng
+7ly
+7ness
+9sses
+4ped
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5y
+4s
+4work
+8er
+9rs
+8s
+4y
+3rm
+5ed
+5ing
+5s
+3sh
+5ed
+6s
+5ier
+7st
+6ng
+8s
+5y
+3t
+4back
+8s
+4h
+5ed
+5ful
+8ly
+8ness
+9esses
+5ing
+5s
+4s
+4ted
+6r
+7s
+5ing
+3uch
+6ed
+7r
+8s
+7s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9ly
+6y
+4gh
+6ed
+6i
+7er
+8st
+7ng
+7s
+6s
+6y
+3ve
+5n
+6lier
+9st
+8ke
+8ness
+9esses
+7y
+6ries
+7y
+6s
+3w
+4back
+8s
+4coach
+9es
+4down
+8s
+4ed
+5r
+5st
+4ing
+7s
+5sh
+4ly
+4ness
+8es
+4poke
+8s
+4s
+4worm
+8s
+3yd
+5s
+2ub
+4b
+5ed
+6r
+7ed
+7ing
+9gly
+9gs
+7s
+5ier
+7st
+6ng
+8s
+5s
+5y
+4s
+3dge
+6d
+6s
+5ier
+7st
+6ng
+5y
+3e
+4d
+4ing
+4s
+3ff
+5ed
+5ing
+5s
+3g
+4abed
+8s
+4fest
+8s
+4gabed
+9s
+6rd
+8ise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+8liness
+9y
+8ness
+9esses
+8s
+5ed
+6r
+7s
+5ing
+6sh
+8ly
+8ness
+9esses
+4horn
+8e
+9s
+8s
+4s
+3ice
+6d
+6gate
+9es
+6like
+6s
+6way
+9s
+5ier
+7st
+6ng
+5y
+4ng
+4t
+5s
+3m
+4ber
+7ed
+8r
+9s
+7ful
+7ing
+9gly
+9gs
+7land
+9nds
+8ess
+7ous
+9sly
+9sness
+7s
+8ome
+7y
+5rous
+9ly
+6y
+4gullion
+9ons
+6m
+7s
+4ism
+7s
+4lord
+8s
+4med
+6r
+7s
+5ier
+7st
+6ng
+8s
+5ock
+8ed
+8ing
+8s
+5y
+4p
+5ed
+5flation
+9ionary
+9ions
+5ier
+7st
+6ng
+5s
+5y
+4s
+3ng
+5shot
+9s
+4k
+3r
+4b
+5an
+5s
+4p
+5ed
+6r
+7s
+5ier
+7st
+6ng
+5s
+5y
+4red
+5ied
+7s
+6ng
+5y
+6ing
+4s
+3se
+5s
+4h
+5ed
+6s
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5y
+3tch
+6es
+6ier
+8st
+6y
+2y
+3boots
+3er
+4st
+3ish
+3ly
+3ness
+7es
+3pe
+5s
+1ma
+3ak
+5ed
+5ing
+5s
+3ck
+5down
+9s
+5ed
+6r
+7s
+5head
+9s
+5ing
+8s
+5s
+3ik
+5s
+3ll
+5age
+8s
+5boy
+8s
+5clothes
+5ed
+6r
+6st
+5holder
+9ers
+9ing
+9ings
+5ing
+6sh
+5mouth
+9hs
+5ness
+9es
+5pox
+8es
+5s
+6at
+8s
+6word
+9ds
+5time
+4m
+5ed
+5ily
+6ness
+9ses
+7g
+5s
+5y
+4t
+5i
+6ne
+8s
+6te
+8s
+5o
+6s
+5s
+3ragd
+7e
+8s
+7ine
+8te
+9es
+7s
+4m
+5ed
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5s
+5y
+4t
+5asses
+5ed
+6n
+7ed
+7ing
+7s
+6r
+6st
+5ie
+7s
+6ng
+8ly
+6sh
+5ly
+5mouth
+9hs
+5ness
+9es
+5phone
+9es
+5s
+5weed
+9s
+5y
+6pants
+3sh
+5able
+5ed
+6r
+7oo
+9s
+7s
+6s
+5ing
+8ly
+8s
+5up
+7s
+3tch
+6ed
+7s
+6ing
+4ter
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7s
+3ze
+5s
+2ear
+5case
+9s
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5s
+5y
+4th
+6s
+3ctic
+6te
+8s
+7ic
+3ddum
+7s
+3e
+4ch
+6ed
+7s
+6ing
+4k
+5ed
+5ing
+5s
+4s
+4th
+6s
+3gmas
+3ik
+5ed
+5ing
+5s
+3ke
+5d
+5s
+4ing
+3ll
+5able
+5ed
+6r
+7s
+5ier
+7s
+8t
+6ness
+9ses
+7g
+8s
+5s
+5y
+4t
+5ed
+6r
+7ies
+7s
+7y
+5ing
+8s
+5s
+3rk
+5ed
+5ing
+5s
+3use
+6s
+3w
+4s
+2icker
+7ed
+7ing
+9gs
+7s
+6t
+7s
+5ly
+3ddied
+7s
+5y
+6ing
+4ge
+6n
+7s
+6on
+8s
+6s
+5in
+7s
+3ercase
+9s
+3fligate
+9ed
+9es
+9ing
+3ght
+6ing
+6s
+3lacaceous
+5x
+6es
+4e
+5d
+5ful
+5less
+5r
+6s
+5s
+5t
+6s
+5y
+6s
+4ier
+6st
+5ng
+7ly
+7ness
+9sses
+7s
+4odon
+8s
+3r
+4ch
+6ed
+7r
+8s
+7s
+6ing
+4k
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ng
+8ly
+5s
+5y
+4r
+5ed
+5ier
+7st
+6ng
+5s
+5y
+4s
+4ting
+8s
+3t
+4e
+5r
+6s
+5s
+4h
+5craft
+9ts
+5ed
+6reen
+9ned
+9ning
+9ns
+7ies
+7s
+7y
+5ied
+7s
+6ng
+5s
+6onite
+9tes
+5y
+6ing
+4ing
+4s
+4ted
+6n
+5ing
+5le
+2ock
+5ed
+5ing
+8s
+5like
+5s
+3g
+4gier
+7st
+5y
+4less
+4s
+3ile
+6d
+6s
+5ing
+3kable
+4e
+5able
+5board
+9ds
+7x
+8es
+5d
+5ho
+7od
+9s
+7s
+7use
+9es
+5jack
+9s
+5less
+9ly
+9ness
+9nesses
+6ike
+5pot
+8s
+6roof
+5r
+6s
+5s
+6creen
+9ens
+6tack
+9ks
+5tight
+5y
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+4o
+5s
+4y
+3lder
+7ed
+7ing
+7s
+4t
+5s
+3och
+6ed
+7r
+8s
+7s
+6ier
+8st
+7ng
+6y
+4dge
+7d
+7s
+6ing
+4ge
+6d
+6s
+5ing
+4r
+5ed
+5ing
+5s
+4sh
+6ed
+7s
+6ing
+4t
+5ed
+5h
+6able
+6bore
+9ed
+9es
+6ed
+7n
+8ed
+8ing
+8s
+7r
+8s
+7s
+8t
+6ie
+8s
+7ng
+9s
+7sh
+6ly
+6ness
+9ses
+6pate
+9es
+6s
+6y
+5ing
+5s
+3rbrod
+8s
+4e
+5d
+5s
+4gasbord
+9rds
+4ing
+4rebrod
+9ds
+4zando
+6to
+3te
+4her
+7ed
+8r
+9s
+7iness
+9esses
+9g
+9gly
+9gs
+7s
+7y
+3uch
+6ed
+7s
+6ing
+4lder
+8ed
+8ing
+9ngly
+9ngs
+8s
+6ry
+4se
+6d
+6r
+7s
+6s
+5ing
+4t
+5ed
+5ing
+5s
+3wt
+5s
+3yle
+6d
+6s
+5ing
+2riti
+6s
+2udge
+6d
+7ly
+6less
+6r
+7s
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5y
+3g
+4ged
+6r
+7ies
+7y
+6st
+5ing
+5le
+7d
+7r
+8s
+7s
+6ing
+9s
+4ly
+4ness
+8es
+4s
+3r
+4fing
+8s
+4red
+5ier
+7st
+6ng
+5y
+4s
+3sh
+5ed
+6s
+5ing
+3tch
+6ed
+7s
+6ier
+8st
+7ng
+6y
+4s
+4ted
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5y
+2ytrie
+7s
+1nab
+4ble
+7d
+7s
+6ing
+4s
+3ck
+5ed
+6r
+7s
+6tte
+9s
+5ing
+5s
+3ffle
+7d
+7s
+6ing
+4u
+5ed
+5ing
+5s
+3g
+4ged
+5ier
+7st
+6ng
+5leteeth
+8ooth
+9othed
+5y
+4like
+4s
+3il
+5ed
+6ries
+7y
+5fish
+9es
+5ier
+7st
+6ng
+5like
+5s
+5y
+3ke
+5bird
+9s
+7t
+8e
+9s
+8ten
+5d
+5fish
+9es
+5head
+9s
+5like
+5mouth
+9hs
+5pit
+8s
+5root
+9s
+5s
+6kin
+9s
+6tone
+9es
+5weed
+9s
+6ise
+6ood
+9s
+5y
+4ier
+6st
+5ly
+5ness
+9es
+6g
+5sh
+7ness
+9sses
+4y
+3p
+4back
+8s
+4dragon
+9ns
+4hance
+9s
+6unce
+9es
+9h
+9hes
+4less
+5ink
+8s
+4pable
+5ed
+6r
+7ed
+7ing
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+8s
+6sh
+8ly
+8ness
+9esses
+5y
+4s
+5hooter
+9ers
+9ing
+9ings
+7t
+8s
+8ted
+9ing
+4tin
+7s
+4weed
+8s
+3r
+4e
+5d
+5less
+5r
+6s
+5s
+4f
+5ed
+5ing
+5s
+4ier
+6st
+5ng
+7s
+4k
+5ier
+7st
+6ly
+5s
+5y
+4l
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5s
+5y
+4red
+5ing
+4s
+4y
+3sh
+5ed
+6s
+5ing
+4te
+6s
+3tched
+7r
+8s
+7s
+6ier
+8st
+7ly
+7ng
+9ly
+9s
+6y
+4h
+5e
+6s
+5s
+3w
+4ed
+4ing
+4s
+3zzier
+7st
+6ly
+6ness
+9ses
+5y
+2ead
+5s
+4k
+5ed
+6r
+7ed
+7s
+6up
+8s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+8ness
+9esses
+6sh
+8ly
+8ness
+9esses
+5s
+6bies
+7y
+5y
+4p
+5ed
+5ing
+5s
+4th
+6s
+3b
+4be
+6d
+6s
+5ing
+4s
+3ck
+5ed
+5ing
+5s
+3d
+4ded
+5ing
+4s
+3e
+4d
+4ing
+4r
+5ed
+6r
+7s
+5ful
+5ier
+7st
+6ng
+8ly
+8s
+5s
+5y
+4s
+5h
+6an
+8s
+6es
+6in
+8g
+9s
+8s
+4ze
+6d
+6less
+6r
+7s
+6s
+6weed
+9ds
+7ood
+9ds
+8rt
+9ts
+5ier
+7st
+6ng
+8s
+5y
+3ll
+5ed
+6r
+6st
+5ing
+5s
+5y
+2ib
+4bed
+5ing
+4s
+3ck
+5ed
+6r
+7ed
+8r
+9s
+7ing
+7s
+8nee
+9eed
+9eeing
+9ees
+7y
+6t
+7s
+5ing
+5s
+3de
+5d
+5ly
+5ness
+9es
+5r
+5s
+6t
+5y
+4ier
+6st
+5ng
+3es
+3ff
+5able
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+8s
+6sh
+8ly
+8ness
+9esses
+5le
+7d
+7r
+8s
+7s
+6ier
+8st
+7ng
+6y
+5s
+5y
+4t
+5ed
+6r
+7ed
+7ing
+7s
+5ier
+7st
+6ng
+5s
+5y
+3g
+4ged
+6r
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7s
+5ing
+5le
+7d
+7r
+8s
+7s
+6ing
+9s
+4let
+7s
+4s
+3p
+4e
+5d
+5fish
+9es
+5like
+5r
+6s
+7cope
+9pes
+5s
+4ier
+6st
+5ng
+7s
+4ped
+6r
+7s
+8napper
+9appers
+6t
+7ier
+9st
+8ness
+9esses
+7s
+7y
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5y
+4s
+4y
+3rt
+5le
+7d
+7s
+6ing
+5s
+3t
+4ch
+6ed
+7r
+8s
+7s
+6ier
+8st
+7ng
+6y
+4s
+3vel
+6ed
+7r
+8s
+6ing
+6led
+8r
+9s
+7ing
+9gs
+7y
+6s
+2ob
+4beries
+7y
+5ier
+7st
+6ly
+6sh
+8ly
+8ness
+9esses
+7m
+8s
+5ocracies
+9cy
+5y
+4ling
+8s
+4ocracies
+9y
+5grapher
+9hers
+9hies
+9hy
+4s
+3d
+4ded
+6r
+6st
+5ing
+6t
+4s
+3ek
+5s
+4p
+3g
+4ged
+5ing
+4s
+3ke
+5d
+5s
+4ing
+3llygoster
+9ters
+3od
+5ed
+5ing
+5s
+4k
+5ed
+6r
+7ed
+7ing
+7s
+5ing
+5s
+4l
+5ed
+5ing
+5s
+4p
+5ed
+6r
+7s
+8cope
+9opes
+5ier
+7st
+6ly
+6ng
+5s
+5y
+4t
+5ed
+5ful
+8s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5s
+5y
+4ze
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+5le
+7d
+7s
+6ing
+5y
+3re
+5d
+5r
+6s
+5s
+4ing
+7s
+4kel
+7ed
+8r
+9s
+7ing
+7led
+8ing
+9ngs
+7s
+4t
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5s
+5y
+3t
+4rag
+7s
+4s
+4ted
+6r
+7ed
+7ies
+8ng
+7s
+7y
+5ie
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5y
+3ut
+5ed
+5ier
+7st
+6ng
+6sh
+5less
+6ike
+5s
+5y
+3w
+4ball
+8ed
+8s
+6nk
+8s
+5ell
+8s
+7t
+8s
+6rries
+8y
+5ird
+8s
+5lader
+9rs
+9s
+8ing
+9ngs
+6ink
+9s
+6ower
+9rs
+5oard
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+6ot
+8s
+6und
+5rush
+9es
+5ush
+8es
+4cap
+7ped
+7s
+6t
+7s
+5lone
+9s
+4dome
+8s
+5rift
+9s
+6op
+8s
+4ed
+4fall
+8s
+5ield
+9s
+5lake
+9s
+6eck
+9s
+6ick
+9s
+4globe
+9s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+5sh
+4k
+5ed
+5ing
+5s
+4land
+8s
+5ess
+5ike
+6ne
+8s
+4maker
+9s
+7ing
+6n
+5elt
+8s
+6n
+5obile
+9er
+9ers
+9es
+9ing
+9ings
+9ist
+9ists
+6ld
+8s
+4pack
+8s
+5lough
+9hed
+9hing
+9hs
+7w
+8ed
+8ing
+8s
+4s
+5cape
+9s
+5hed
+8s
+6oe
+8d
+8ing
+8r
+9s
+8s
+5lide
+9s
+7p
+8s
+5torm
+9s
+5uit
+8s
+6rfing
+9ngs
+4tubing
+9gs
+4y
+2ub
+4be
+6d
+6r
+7s
+6s
+5ier
+7st
+6ness
+9ses
+7g
+8ly
+8s
+6sh
+5y
+4fin
+4ness
+8es
+4s
+3ck
+3dge
+6d
+6s
+5ing
+3ff
+5box
+8es
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5le
+7d
+7r
+8s
+7s
+6ier
+8st
+7ng
+9s
+6y
+5s
+5y
+3g
+4ged
+6r
+7ie
+9s
+7y
+6st
+5ies
+6ng
+5le
+7d
+7s
+6ing
+4ly
+4ness
+8es
+4s
+3sh
+5ed
+6s
+5ing
+3zzle
+7d
+7s
+6ing
+2y
+3e
+4s
+1o
+2ak
+4age
+7s
+5way
+8s
+4ed
+5n
+5r
+6s
+4ing
+7ly
+7s
+4s
+3p
+4bark
+8s
+5erries
+8y
+5ox
+7ed
+8s
+7ing
+4ed
+5r
+6s
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+4land
+8s
+5ess
+5ike
+4olallie
+9ies
+4root
+8s
+4s
+5tone
+9s
+5uds
+8y
+4wort
+8s
+4y
+3r
+4away
+4e
+5d
+5r
+6s
+5s
+4ing
+7ly
+7s
+4s
+3ve
+5s
+2b
+3a
+4s
+3bed
+5r
+6s
+4ing
+7ly
+7s
+3eit
+4r
+5ed
+6r
+6st
+5ing
+8ly
+6se
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5ly
+5ness
+9es
+5s
+6ided
+9dness
+9s
+3ful
+3ole
+6s
+5iferous
+3rieties
+7y
+5quet
+9s
+3s
+2c
+3a
+4ge
+6r
+7s
+6s
+4s
+3cage
+7s
+4er
+6s
+3dolager
+9rs
+6iger
+9rs
+6oger
+9rs
+3iabilities
+9ty
+6le
+8ness
+9esses
+8s
+7y
+5l
+6isable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ically
+9s
+7te
+9s
+8ies
+8y
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ly
+6ness
+9ses
+6s
+5te
+7s
+6ion
+9s
+7ve
+4etal
+8ly
+6ies
+6y
+4obiological
+9ogies
+9ogist
+9ogists
+9ogy
+5cultural
+9urally
+5economic
+5gram
+9s
+5historical
+5lect
+9s
+6inguist
+9uistic
+9uists
+6ogese
+9ses
+8ic
+9cal
+9cally
+9es
+9sm
+9sms
+9st
+9stic
+9sts
+8y
+5metric
+9ies
+9ist
+9ists
+9y
+5path
+9ic
+9ies
+9s
+9y
+6olitical
+5religious
+5sexual
+3k
+4dolager
+9ers
+7iger
+9ers
+7oger
+9ers
+4ed
+5t
+6ed
+6ing
+6s
+6te
+8s
+5ye
+7s
+4ing
+4less
+4man
+5en
+4o
+4s
+3le
+5s
+3man
+4en
+3s
+2d
+3a
+4ic
+5n
+6e
+4less
+5ist
+8s
+6te
+8s
+7ies
+7y
+4mide
+8s
+4s
+3buster
+9s
+3ded
+5n
+6ed
+6ing
+6ly
+6ness
+9ses
+6s
+4ier
+6s
+7t
+5ng
+4y
+3ger
+6ed
+6ing
+6s
+3ic
+5ities
+7y
+4um
+6s
+3om
+5ies
+6se
+8d
+8s
+7ing
+7t
+8s
+6te
+8s
+7ic
+9al
+9ally
+5s
+3s
+2ever
+2fa
+4bed
+7s
+4r
+5s
+4s
+3fioni
+5t
+6s
+3t
+4a
+5s
+4back
+8s
+6ll
+8er
+9rs
+8s
+5ound
+9s
+4core
+6ver
+9s
+4ed
+5n
+6ed
+7r
+8s
+6ing
+9s
+6s
+5r
+5st
+4goods
+4head
+8ed
+9dly
+9dness
+8s
+7rted
+9edly
+9edness
+4ie
+6s
+5ng
+5sh
+4ling
+8s
+5y
+4ness
+8es
+4s
+5hell
+9s
+4ware
+8s
+5ood
+8s
+4y
+2g
+3dolager
+9rs
+6iger
+9rs
+6oger
+9rs
+3er
+5s
+3ged
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4y
+3s
+2h
+3o
+3s
+3ur
+5s
+2igne
+6e
+3l
+4age
+7s
+4borne
+4ed
+4ier
+6st
+5ness
+9es
+6g
+7s
+4less
+4s
+4ure
+7s
+4y
+3ree
+6s
+2ja
+4s
+3ourn
+7ed
+8r
+9s
+7ing
+9gs
+7ment
+9nts
+7s
+2kah
+5s
+4iya
+3e
+4man
+7ries
+8y
+5en
+4n
+5s
+4s
+3ol
+5s
+2l
+3a
+4ce
+6d
+6ment
+9ts
+6r
+7s
+6s
+5ing
+6ous
+4h
+5s
+4n
+5aceous
+5d
+6er
+8s
+6s
+5in
+7e
+8s
+7s
+5o
+6s
+5s
+5um
+7s
+4r
+5ia
+6meter
+9ers
+6sation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8s
+7t
+8s
+6um
+8s
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5s
+4s
+4te
+6d
+6s
+5ia
+6ng
+6on
+8s
+6um
+3d
+4ado
+7s
+5n
+6s
+5tesque
+4e
+5r
+6abilities
+9lity
+8le
+6ed
+7r
+8s
+6ing
+9s
+6s
+5s
+4i
+5er
+7ed
+7ies
+8ng
+9gs
+7like
+9ness
+9nesses
+8y
+7s
+8hip
+9ips
+7y
+4o
+4s
+3e
+4cise
+8d
+8s
+7ing
+7m
+8s
+7t
+8ic
+9cal
+9cally
+8s
+6ze
+8d
+8s
+7ing
+4d
+4i
+5n
+4less
+5y
+4mn
+6er
+7ss
+9es
+8t
+6ification
+9ed
+9es
+8y
+9ing
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ly
+6ness
+9ses
+4ness
+8es
+6tte
+9s
+5odon
+9s
+6id
+8al
+9lly
+8s
+4plate
+9s
+5rint
+9s
+4r
+5a
+6s
+5et
+7s
+5s
+4s
+4us
+6es
+3fatara
+9s
+8ic
+4ege
+7s
+6gi
+8o
+9s
+5rino
+9s
+3gel
+3i
+4cit
+7ant
+9ts
+8tion
+9ions
+7ed
+7ies
+8ng
+9gs
+7or
+9s
+9ship
+9ships
+8us
+9sly
+9sness
+7s
+7ude
+9es
+7y
+4d
+5ago
+8s
+6re
+8s
+7ism
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+7y
+6te
+8d
+8s
+7ing
+5er
+6st
+5i
+6fiable
+8cation
+9ations
+8ed
+9r
+9rs
+9s
+7y
+8ing
+6sh
+7m
+8s
+7t
+8s
+6ties
+7y
+5ly
+5ness
+9es
+5s
+5um
+7s
+6ngulate
+9lous
+6s
+4fidian
+9nism
+9nisms
+9ns
+5luction
+9ions
+7xion
+9ons
+4loquies
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8y
+4ng
+4on
+6s
+4ped
+7ous
+7s
+5sism
+9s
+8t
+9ic
+9ically
+9s
+4quid
+8s
+4taire
+9s
+6rian
+9ns
+8es
+8ly
+8ness
+9esses
+7y
+5o
+6n
+7s
+5ude
+8s
+7inarian
+9arians
+9ous
+4vagant
+9ts
+5e
+6s
+3lar
+6s
+4er
+6et
+8s
+6s
+4icker
+9s
+3misation
+9ons
+5zation
+9ons
+3o
+4ed
+4ing
+5st
+7ic
+7s
+4n
+5chak
+9s
+5ets
+8es
+7z
+8es
+8ic
+5isation
+9ions
+6zation
+9ions
+5s
+4s
+3pugid
+8s
+3s
+4tice
+8s
+6tial
+9lly
+3ubilisation
+9ations
+9e
+9ed
+9es
+9ing
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+5le
+7ness
+9sses
+7s
+6y
+4m
+5s
+4nar
+4s
+4tal
+5e
+6s
+5ion
+8al
+8ed
+8ing
+9st
+9sts
+8s
+6ve
+3vabilities
+9ty
+6le
+8ness
+9esses
+5te
+7d
+7s
+6ing
+7on
+9s
+4e
+5d
+5ncies
+7y
+6t
+7less
+8y
+7s
+5r
+6s
+5s
+4ing
+4olyses
+8is
+7tic
+2m
+3a
+4esthesia
+9sias
+9sis
+9sises
+9tic
+4n
+5s
+4s
+5cope
+9s
+4ta
+5ic
+7ally
+6sm
+8s
+7t
+8s
+5ogenic
+6logic
+9ical
+9ically
+9ies
+9ist
+9ists
+9y
+6medin
+9ins
+6plasm
+9sms
+9stic
+8eural
+9ure
+9ures
+9uric
+6sensory
+7tatin
+9tins
+6tensic
+7onia
+9ias
+9ic
+7rophic
+9phin
+9phins
+9pic
+9pin
+9pins
+7ype
+9ed
+9es
+9ing
+3ber
+6ed
+7r
+7st
+6ing
+6ly
+6ness
+9ses
+6s
+4re
+6d
+6ly
+6ness
+9ses
+6r
+7ite
+9es
+7o
+8s
+6s
+7t
+5ing
+5ous
+3e
+4bodies
+7y
+4day
+5eal
+6le
+4gate
+4how
+4one
+7s
+4place
+9s
+4rsault
+9ted
+9ting
+9ts
+6et
+8ed
+8ing
+8s
+8ted
+9ing
+4sthesia
+9ias
+9is
+9ises
+8tic
+4thing
+9s
+5ime
+8s
+4way
+7s
+5hat
+8s
+6en
+8ce
+7re
+9s
+6ile
+9s
+7ther
+6y
+5ise
+3ital
+5e
+6s
+5ic
+3melier
+9s
+3nambulance
+9ances
+9ant
+9ants
+9ar
+9ary
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ator
+9ators
+9e
+9es
+9ic
+9ism
+9isms
+9ist
+9istic
+9ists
+4ial
+6te
+8d
+8s
+7ing
+8ve
+7ory
+5facient
+9ents
+6erous
+9usly
+6ic
+5loquence
+9ences
+9ies
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+9ous
+9y
+4olence
+9es
+9ies
+9y
+8t
+9ly
+7scent
+3oni
+3s
+3y
+2n
+3ance
+7s
+6ies
+6y
+5t
+6al
+6ic
+6s
+4r
+5man
+6en
+5s
+4ta
+6s
+5ina
+8s
+7e
+3ce
+5s
+3dage
+7s
+4e
+5li
+7s
+5r
+6s
+5s
+3e
+4ri
+6s
+4s
+3g
+4bird
+8s
+5ook
+8s
+4craft
+9s
+4fest
+8s
+5ul
+7ly
+7ness
+9sses
+4kok
+7s
+4less
+8ly
+5ike
+4man
+5en
+4ololo
+9s
+4s
+5mith
+9s
+5ter
+8s
+6ress
+9ses
+4writer
+9rs
+8ing
+9ngs
+3hood
+7s
+3ic
+5ally
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5s
+4ferous
+3less
+4ike
+4y
+3ne
+5s
+5t
+6ary
+6ed
+7er
+9ing
+9ings
+9s
+6ing
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6s
+6ted
+7ing
+4ies
+4y
+3obuoy
+8s
+4gram
+8s
+7ph
+9er
+9ers
+9ies
+9s
+9y
+4meter
+9s
+4rant
+8s
+5ities
+7y
+5ous
+8ly
+8ness
+9esses
+4vox
+7es
+3s
+4e
+5s
+4hip
+7s
+4ie
+6r
+6st
+4y
+3tag
+6s
+4ies
+2ochong
+8s
+3ey
+3gee
+6d
+6ing
+6s
+4ie
+6d
+6ing
+6s
+3jey
+6s
+3k
+4ed
+4ing
+4s
+3l
+4e
+5d
+5s
+4ing
+4s
+3m
+4ed
+4ing
+4s
+3n
+4er
+6s
+5st
+3p
+4ed
+4ing
+7s
+4s
+5take
+3t
+4e
+5d
+5rkin
+9s
+5s
+4flake
+9s
+4h
+5e
+6d
+6r
+7ed
+7ing
+7s
+6s
+7t
+5fast
+9ly
+9ness
+9nesses
+6ul
+5ing
+8ly
+8ness
+9esses
+8s
+5lich
+6y
+5s
+6aid
+7y
+8er
+9rs
+8ing
+9ngs
+8s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4less
+4s
+4y
+2p
+3aipilla
+9as
+4pilla
+9s
+3h
+4eric
+7m
+4ies
+5sm
+7s
+6t
+7er
+9s
+7ic
+9al
+9ally
+9ate
+9ated
+9atedly
+9ates
+9ating
+9ation
+9ations
+9ator
+9ators
+7ries
+8y
+7s
+4omore
+9s
+8ic
+9cal
+4s
+4y
+3ite
+6d
+6s
+5ing
+3or
+5iferous
+9ously
+7ic
+9ally
+9s
+5ose
+6us
+5s
+3ped
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4y
+3ra
+5ni
+7ni
+8o
+9s
+7st
+9s
+6o
+7s
+3s
+2ra
+4ge
+6s
+4l
+4s
+3b
+4abilities
+9ty
+6le
+5ria
+8s
+5te
+7s
+4ed
+5facient
+9ents
+5nt
+7s
+5t
+6s
+4ic
+5ng
+5te
+7s
+6ic
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ol
+8s
+4o
+5se
+7s
+4s
+4us
+6es
+3cerer
+8s
+7ss
+9es
+6ies
+6ous
+6y
+3d
+4a
+5mente
+4es
+4id
+6er
+7st
+6ly
+6ness
+9ses
+5ne
+7s
+6i
+6o
+4o
+5r
+6s
+4s
+3e
+4d
+5ia
+7l
+7te
+6um
+4e
+5s
+4head
+8ed
+9dly
+9dness
+8s
+5on
+7s
+4l
+5l
+6s
+5s
+5y
+4ness
+8es
+4r
+4s
+5t
+4x
+5es
+3gho
+6s
+5um
+7s
+4o
+5s
+3i
+4cident
+6ne
+5oid
+4ng
+6s
+4tes
+5ic
+7al
+3n
+4ed
+5r
+6s
+4ing
+7s
+4s
+3oban
+7s
+4che
+7s
+4ral
+7ly
+6te
+8s
+5ial
+8ly
+6cidal
+9e
+9es
+6se
+8d
+8s
+7ing
+6ties
+7y
+6ze
+8d
+8s
+7ing
+4ses
+5is
+7es
+3ption
+8s
+6ve
+3ra
+5s
+4el
+6s
+4ier
+6st
+5ly
+5ness
+9es
+4ow
+6ed
+7r
+8s
+6ful
+9ly
+9ness
+9nesses
+6ing
+9s
+6less
+6s
+4y
+5ish
+3t
+4a
+5ble
+7y
+5l
+6s
+5nce
+8s
+5tion
+9s
+4ed
+5r
+6s
+5s
+4ie
+6d
+6ing
+6s
+5lege
+9r
+9rs
+9s
+8ies
+8y
+5ng
+7s
+5tion
+9s
+4ment
+8s
+4s
+3us
+2s
+3atie
+7s
+3s
+4ed
+5s
+4ing
+7s
+3tenuti
+8o
+9s
+2t
+3erial
+6ologic
+9gical
+9gies
+9gy
+3h
+4s
+3ol
+5s
+3s
+3ted
+6ly
+4ing
+7s
+5sh
+7ly
+7ness
+9sses
+6ier
+9s
+2u
+3ari
+6s
+3bise
+7s
+4rette
+9s
+8ish
+5iquet
+9ts
+3car
+6s
+4e
+5d
+5s
+4hong
+8s
+4ing
+4t
+3dan
+6s
+3ffle
+7d
+7ed
+7s
+3gh
+5ed
+5ing
+5s
+5t
+3k
+4ed
+4ing
+4ous
+7es
+4s
+3l
+4dan
+7s
+5ier
+8ed
+8ing
+8s
+4ed
+4ful
+7ly
+7ness
+9sses
+4less
+8ly
+8ness
+9esses
+5ike
+4mate
+8s
+4s
+3m
+4ed
+4ing
+7s
+4s
+3nd
+5able
+6like
+9es
+5bite
+9s
+6oard
+9ds
+7x
+8es
+5card
+9s
+5ed
+6r
+7s
+6st
+5ing
+8ly
+8s
+5less
+9ly
+9ness
+9nesses
+6y
+5man
+6en
+5ness
+9es
+5post
+9s
+6roof
+9fed
+9fing
+9fings
+9fs
+5s
+6cape
+9es
+6tage
+9es
+5track
+9ked
+9king
+9ks
+3p
+4con
+7s
+4ed
+5r
+6s
+4fin
+7s
+4ier
+6st
+5ng
+4le
+6d
+6s
+7s
+5ike
+6ng
+4s
+5poon
+9s
+4y
+3r
+4ball
+8s
+4ce
+6book
+9ks
+6d
+6ful
+6less
+6s
+5ing
+8s
+4deline
+9es
+5ine
+8s
+5ough
+9s
+4ed
+5r
+5st
+4ing
+7s
+5sh
+7ly
+4ly
+4ness
+8es
+4ock
+7s
+4puss
+8es
+4s
+5e
+6s
+5op
+7s
+4veld
+8s
+4wood
+8s
+3s
+4aphone
+9es
+9ist
+9ists
+4e
+5d
+5s
+4ing
+7s
+4lik
+7s
+3t
+4ache
+8s
+5ne
+7s
+5r
+6s
+4eneur
+9s
+5r
+6ly
+6rain
+9ns
+6s
+4h
+5bound
+5east
+9er
+9erlies
+9erly
+9ern
+9ers
+9s
+9ward
+9wards
+6d
+6r
+7ed
+7ing
+7lies
+9ness
+9nesses
+8y
+7most
+7n
+8er
+9rs
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+8ly
+8most
+8ness
+9esses
+8s
+8wood
+9oods
+7s
+5ing
+8s
+5land
+9er
+9ers
+9s
+5most
+5paw
+8s
+5ron
+8s
+5s
+6aid
+7y
+8ing
+8s
+5ward
+9ly
+9s
+6est
+9er
+9erlies
+9erly
+9ern
+9ers
+9s
+9ward
+9wardly
+9wards
+4ie
+6s
+4piel
+8s
+4s
+3venir
+8ed
+8ing
+8s
+4laki
+8a
+9s
+8s
+2v
+3enance
+9s
+4reign
+9ly
+9s
+9ties
+9tist
+9tists
+9ty
+3iet
+6ic
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ological
+9gist
+9gists
+6s
+3khoz
+7es
+7y
+3ran
+6ly
+6s
+6ties
+7y
+3s
+2w
+3able
+4ns
+4r
+5ree
+8s
+6ies
+6y
+5s
+3back
+7s
+4ellies
+7y
+4read
+8s
+3car
+6s
+4e
+5d
+5s
+4ing
+3der
+6s
+3ed
+4ns
+4r
+5s
+3f
+4ed
+4f
+5ed
+5ing
+5s
+4ing
+4s
+3ing
+6s
+3l
+4e
+5d
+5s
+4ing
+4s
+3m
+4ed
+4ing
+4s
+3n
+4d
+5ed
+5ing
+5s
+4e
+5s
+3p
+4s
+3s
+4e
+5d
+5s
+4ing
+4se
+6d
+6s
+5ing
+3ter
+6s
+4h
+5ed
+5ing
+5s
+2x
+2y
+3a
+4s
+3bean
+7s
+3le
+5s
+3milk
+7s
+3s
+3uz
+5es
+2z
+3in
+5e
+6s
+5s
+3zle
+6d
+6s
+5ier
+7st
+6ng
+5y
+1pa
+3ce
+5band
+9s
+6orne
+5craft
+9ts
+5d
+5faring
+9ngs
+6light
+9hts
+5lab
+8s
+6ess
+5man
+6en
+5plane
+9es
+6ort
+9s
+5r
+6s
+5s
+6hip
+9s
+6uit
+9s
+5walk
+9ed
+9er
+9ers
+9ing
+9s
+7rd
+6oman
+8en
+5y
+4ial
+7ly
+5er
+6st
+5ness
+9es
+6g
+7s
+5ous
+8ly
+8ness
+9esses
+4kle
+7d
+7s
+6ing
+4y
+3dassin
+9s
+4e
+5d
+5fish
+9es
+6ul
+8s
+5like
+5man
+6en
+5r
+6s
+5s
+6man
+7en
+5work
+9s
+4ger
+7s
+4iceous
+7s
+6ifloral
+5lle
+8s
+7io
+9s
+7o
+8s
+5ng
+5x
+6es
+4o
+5es
+5nes
+5s
+4roon
+8s
+3e
+4d
+4ing
+7s
+4man
+5en
+4r
+5s
+4s
+4tzle
+8s
+4wife
+6ves
+3g
+4eric
+4ged
+5ing
+4hetti
+9like
+9ni
+9nis
+9s
+4iric
+4s
+4yric
+8al
+9lly
+8s
+7st
+9s
+3hee
+6s
+4i
+5s
+3il
+5s
+4n
+5ed
+5g
+6s
+5ing
+5s
+4rge
+7d
+7s
+6ing
+4t
+5s
+3ke
+3ld
+5een
+8s
+5s
+4e
+5s
+4l
+5able
+6tion
+9ns
+5e
+6d
+6r
+7s
+6s
+5ing
+8s
+5s
+4peen
+8s
+4t
+5ed
+5ing
+5s
+3m
+4bot
+7s
+4med
+6r
+7s
+5ie
+7r
+7s
+8t
+6ng
+8s
+5y
+4s
+3n
+4aemia
+9s
+8c
+5kopita
+9tas
+4cel
+7ed
+7ing
+7led
+8ing
+7s
+4dex
+7es
+5rel
+8s
+6il
+8s
+4e
+5d
+5s
+4g
+5ed
+5hew
+8ed
+8ing
+8s
+5ing
+5le
+7d
+7r
+8s
+7s
+7t
+8s
+6ier
+8st
+7ng
+9s
+6y
+5s
+4iel
+7led
+8ing
+7s
+5ng
+5olate
+9ed
+9es
+9ing
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+4k
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5s
+4less
+4ned
+6r
+7s
+5ing
+4okopita
+9tas
+4s
+5pek
+8s
+5ule
+8s
+4worm
+8s
+3r
+4able
+8s
+5gmatic
+6rass
+9ses
+5xis
+8es
+4d
+4e
+5able
+5d
+5less
+6y
+5ness
+9es
+5r
+6ib
+8s
+6s
+5s
+6t
+4ganium
+9ms
+5e
+6d
+6r
+7s
+6s
+5ing
+4id
+6s
+5ng
+7ly
+7ness
+9sses
+4k
+5e
+6d
+6r
+7s
+6s
+5ie
+7r
+7s
+8t
+6ly
+6ng
+6sh
+8ly
+5le
+7d
+7r
+8s
+7s
+8s
+9ly
+7t
+8s
+6ier
+8s
+9t
+7ng
+9ly
+9s
+6y
+5plug
+9ged
+9ging
+9s
+5s
+5y
+4like
+6ng
+8s
+4oid
+7s
+4re
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5ow
+7fart
+9rts
+7grass
+9asses
+7hawk
+9wks
+7like
+7s
+5y
+4s
+5e
+6dly
+6ly
+6ness
+9ses
+6r
+6st
+5ities
+7y
+4t
+5an
+7s
+5eine
+9s
+6rie
+9s
+5h
+6e
+7s
+6s
+5icle
+9s
+6na
+8s
+5s
+3s
+4m
+5atic
+9al
+5ed
+5ic
+6ng
+5odic
+9al
+9ally
+8st
+9ts
+6lytic
+9ics
+5s
+3t
+4angoid
+9ds
+4chcock
+9ked
+9king
+9ks
+4e
+5s
+4fall
+8s
+4haceous
+6l
+5e
+6d
+6s
+5ic
+6phyllum
+9llums
+5ose
+5ulate
+4ial
+7ities
+9y
+7ly
+5otemporal
+4lese
+8n
+8s
+4s
+4ted
+6e
+7s
+6r
+7dash
+9shes
+8ock
+9cks
+7ed
+7ing
+7s
+7work
+9rks
+5ing
+4ula
+7r
+7s
+7te
+6e
+7s
+4zle
+7s
+3ul
+5d
+6s
+5s
+3vie
+6s
+6t
+5n
+6ed
+6s
+3w
+4l
+5ed
+5ing
+5s
+4n
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8s
+5s
+5y
+4s
+3y
+4ad
+6s
+4d
+5s
+4ed
+4ing
+4s
+2eak
+5able
+5easies
+8y
+6r
+7ine
+9es
+7phone
+9ones
+7s
+8hip
+9ips
+5ing
+8ly
+8s
+5out
+8s
+5s
+4l
+5s
+4n
+5ed
+5ing
+5s
+4r
+5ed
+6r
+7s
+5fish
+9ed
+9es
+9ing
+5gun
+8s
+5head
+9ed
+9ing
+9s
+5ier
+7st
+6ng
+5like
+5man
+6en
+6int
+9s
+5s
+5wort
+9s
+5y
+4t
+5s
+3c
+4ced
+5ies
+6ng
+5y
+4ial
+7er
+8st
+7isation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7led
+8ing
+8y
+7ness
+9sses
+7ogue
+9ues
+7s
+7ties
+8y
+6te
+8d
+8s
+7ing
+8on
+9nal
+9ns
+5e
+6s
+7ism
+9ms
+9t
+9ts
+5fiable
+7c
+8al
+9lly
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+8ities
+9ty
+8s
+7ed
+8r
+9s
+8s
+6y
+7ing
+5men
+8s
+5ocide
+9es
+6sities
+9y
+6us
+8ly
+8ness
+9esses
+4k
+5ed
+5ier
+7st
+6ng
+5le
+7d
+8ness
+9esses
+7s
+8s
+6ing
+5s
+6ioneer
+9eers
+5tioneer
+9eers
+5y
+4s
+4tacle
+9d
+9s
+7ular
+9arity
+9arly
+9ars
+6te
+8d
+8s
+7ing
+7or
+9ial
+9s
+9ship
+9ships
+7ress
+9sses
+8ices
+9x
+9xes
+5er
+7s
+5inomycin
+9ycins
+5ra
+7l
+8ities
+9ty
+8ly
+8ness
+9esses
+6e
+7s
+6in
+8s
+6ogram
+9ams
+9aph
+9aphic
+9aphies
+9aphs
+9aphy
+7logical
+9gies
+9gy
+7meter
+9ters
+9tric
+9tries
+9try
+7scope
+9opes
+9opic
+9opical
+9opies
+9opist
+9opists
+9opy
+6um
+8s
+4ula
+7r
+8ities
+9ty
+8ly
+7te
+9d
+9s
+8ing
+9on
+9ons
+9st
+9sts
+9ve
+9vely
+9veness
+8or
+9rs
+9ry
+8rices
+9ix
+9ixes
+6um
+8s
+3d
+3ech
+6craft
+9fts
+6ed
+7s
+6ful
+9ness
+9nesses
+6ification
+9ed
+9er
+9ers
+9es
+8y
+9ing
+7ng
+6less
+9sly
+9sness
+6maker
+9ers
+9ing
+9ings
+6writer
+9ters
+4d
+5ball
+9ed
+9ing
+9ings
+9s
+6oat
+9ing
+9ings
+9s
+5ed
+6r
+7s
+5freak
+9ks
+6ul
+8ly
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5less
+5o
+6meter
+9ers
+6s
+5read
+9ing
+9s
+5s
+6kating
+9ings
+6ter
+9s
+5up
+7s
+5way
+8s
+6ell
+9s
+5y
+4l
+5ed
+6r
+7s
+5ing
+5s
+4r
+5ed
+5ing
+8s
+5s
+3il
+5ed
+5ing
+5s
+4r
+5ed
+5ing
+8s
+5s
+4se
+6s
+5s
+6es
+3k
+4boom
+8s
+4s
+3laean
+6ological
+9gies
+9gist
+9gists
+9gy
+7them
+9ems
+4d
+5ed
+6r
+7ed
+7ing
+7s
+5in
+7g
+8s
+7s
+5rin
+8g
+9s
+8s
+5s
+4ean
+5ological
+9ies
+9ist
+9ists
+9y
+6them
+9ms
+9rapies
+9rapy
+4k
+5s
+4l
+5able
+5bind
+9er
+9ers
+9ing
+9ingly
+9s
+6ound
+5check
+9ker
+9kers
+9ks
+5down
+9s
+5ed
+6r
+7s
+5ful
+5ican
+9s
+6ng
+8ly
+8s
+5s
+6topt
+4t
+5er
+7s
+5s
+5z
+6es
+4unk
+7ed
+8r
+9s
+7ing
+9gs
+7s
+3nce
+6r
+7s
+6s
+4d
+5able
+6ll
+8s
+5er
+7s
+5ier
+7st
+6ng
+8s
+5s
+5thrift
+9fts
+5y
+4se
+6s
+4t
+3os
+5es
+3rling
+8s
+4m
+5aceti
+9is
+6duct
+9ts
+6gonia
+9ium
+6phyte
+9tes
+9tic
+6ria
+8es
+8um
+7y
+6theca
+9cae
+9cal
+9cas
+7ia
+9l
+8c
+9al
+9ally
+9s
+8d
+9s
+8um
+7oblast
+9lastic
+9lasts
+8cele
+9eles
+9idal
+9ide
+9ides
+9yte
+9ytes
+8geneses
+9enesis
+9enetic
+9enic
+9enies
+9enous
+9eny
+9onia
+9onial
+9onium
+8phoral
+9hore
+9hores
+9hyte
+9hytes
+9hytic
+8rrhea
+9rheas
+9rhoea
+9rhoeas
+8theca
+9hecae
+8zoa
+9oal
+9oan
+9oans
+9oic
+9oid
+9oids
+9oon
+5ic
+7idal
+9e
+9es
+6duct
+9ts
+6ne
+8s
+6ogeneses
+9nesis
+9netic
+5ogone
+9es
+9ia
+9ium
+6phile
+9les
+8yte
+9tes
+9tic
+6us
+5s
+4re
+6d
+6s
+5ing
+5ylite
+9es
+4se
+6d
+6s
+5ing
+5t
+4the
+7s
+3ssartine
+9nes
+9te
+9tes
+3t
+4ch
+6es
+4s
+5naz
+8es
+4ting
+4znaz
+8es
+3ug
+5s
+3w
+4ed
+5r
+6s
+4ier
+6st
+5ness
+9es
+6g
+4s
+4y
+2hacelate
+9ed
+9es
+9ing
+9ion
+9ions
+7us
+9es
+4er
+6e
+7s
+6idia
+9um
+7te
+9s
+6ocrystal
+9ystals
+7siderite
+6s
+4gnicolous
+6ologies
+9gist
+9gists
+9gy
+7us
+6um
+8s
+4iree
+8s
+6istike
+9ikes
+4lerite
+9es
+3ear
+6e
+7s
+6s
+4ndone
+9s
+5e
+6s
+5ic
+5odon
+9s
+9t
+6gram
+9ms
+6id
+8al
+8s
+6psid
+9ds
+4ral
+5e
+6d
+6less
+7ike
+6s
+5ic
+7al
+9ities
+9ity
+9ly
+9ness
+9nesses
+7ities
+9y
+7s
+6er
+7st
+6ng
+6sterion
+9rions
+5ocyte
+9es
+9oses
+9osis
+6id
+8al
+9lly
+8ically
+9cities
+9city
+9sation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+6meter
+9ers
+6plast
+9sts
+5ular
+7e
+8s
+7ite
+9es
+9ic
+5y
+3incter
+9al
+9ial
+9ic
+9s
+5ges
+6id
+8s
+6omyelin
+9elins
+7sine
+9nes
+5x
+6es
+6like
+3ragistic
+9ics
+3ygmic
+6ogram
+9ams
+9aph
+9aphic
+9aphies
+9aphs
+9aphy
+7id
+7logies
+9gy
+7meter
+9ters
+7phone
+9ones
+7scope
+9opes
+6us
+8es
+4nx
+6es
+2ial
+5s
+3ca
+5e
+5s
+5te
+7d
+4cato
+8s
+4e
+5berries
+9y
+6ush
+9es
+5d
+5less
+5r
+6ies
+6s
+6y
+5s
+5y
+4ier
+6st
+5lege
+9s
+6y
+5ness
+9es
+6g
+4k
+5er
+6st
+5nel
+8s
+5s
+4s
+4ula
+7e
+7r
+7te
+8ion
+9ons
+6e
+7s
+6um
+4y
+3de
+5r
+6ier
+8st
+7sh
+6like
+6man
+7en
+6s
+6web
+9s
+7ood
+9ds
+8rk
+9ks
+9t
+9ts
+6y
+5s
+3e
+4d
+4gel
+7eisen
+9sens
+7s
+4l
+5ed
+6r
+7s
+5ing
+5s
+4r
+5ed
+5ing
+5s
+4s
+3f
+4f
+5ed
+5ied
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5licate
+9ted
+9tes
+9ting
+9tion
+9tions
+5s
+5y
+6ing
+4licate
+9ed
+9es
+9ing
+9ion
+9ions
+4s
+3ght
+6ed
+6ing
+6s
+4nel
+7s
+4ot
+6s
+3k
+4e
+5d
+5fish
+9es
+5let
+8s
+6ike
+5nard
+9s
+5r
+6ies
+6s
+6y
+5s
+5y
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4s
+4y
+3le
+5d
+5s
+4ikin
+8s
+5ng
+7s
+5te
+7s
+6ic
+4l
+5able
+6ge
+8s
+5ed
+6r
+7s
+5ikin
+9s
+6ng
+8s
+5over
+9s
+5s
+5way
+8s
+4osite
+9s
+4t
+5h
+6s
+3m
+4s
+3n
+4a
+5cene
+9s
+7ous
+6h
+7es
+7like
+7y
+5e
+5ge
+7s
+5l
+6ly
+6s
+5r
+6s
+5s
+5te
+4dle
+7d
+7legs
+7r
+8s
+7s
+8hanks
+6ier
+8st
+7ng
+9s
+6y
+5rift
+9s
+4e
+5d
+5l
+6ess
+9ly
+9ness
+9nesses
+6ike
+6le
+8s
+6s
+5s
+6cence
+9ces
+9t
+5t
+6s
+6te
+8s
+4ier
+6st
+5ferous
+7x
+8es
+6orm
+5gerous
+6rade
+5ness
+9es
+4k
+5s
+4less
+4meister
+9ers
+4naker
+9s
+5er
+7et
+9s
+9te
+9tes
+7ies
+7s
+7ule
+9es
+7y
+6t
+7s
+6y
+7s
+5ies
+6ng
+8s
+5y
+4ode
+7s
+5ff
+7s
+5ne
+6i
+5r
+6s
+5se
+7ly
+6ities
+8y
+5us
+6t
+7s
+4s
+5ter
+8dom
+9oms
+8hood
+9oods
+8ial
+9an
+9sh
+8ly
+8s
+9hip
+9hips
+6ress
+9ses
+4text
+8s
+5hariscope
+9scopes
+5o
+6s
+4ula
+7e
+7te
+6e
+7s
+8cent
+6iferous
+6ose
+7us
+4y
+3racle
+8s
+6ula
+9r
+9te
+8um
+5ea
+7s
+5l
+6ed
+6iform
+7ng
+7sm
+9s
+8t
+9s
+7ties
+8y
+6led
+7ing
+7y
+6s
+5nt
+7s
+5ster
+9s
+5ted
+6ion
+9s
+4e
+5a
+6s
+5d
+5less
+7t
+8s
+5m
+6e
+7s
+6s
+5s
+5wise
+4ic
+6s
+5er
+6st
+5ferous
+5lla
+8r
+7oses
+9is
+7um
+5ng
+5t
+6ed
+8ly
+8ness
+9esses
+6ful
+6ing
+9s
+7sm
+9s
+8t
+9ic
+9s
+6less
+9sly
+9sness
+6oso
+7us
+9ness
+9nesses
+6s
+6ual
+9ise
+9ised
+9iser
+9isers
+9ises
+9ising
+9ism
+9isms
+9ist
+9istic
+9ists
+9ities
+9ity
+9ize
+9ized
+9izer
+9izers
+9izes
+9izing
+9ly
+9ness
+9nesses
+9s
+9ties
+9ty
+7el
+9le
+7osities
+9ity
+8us
+9sness
+7s
+8es
+6y
+4ketting
+9ngs
+4ling
+8s
+4ochaetaemia
+9te
+9tes
+9toses
+9tosis
+7etal
+9e
+9es
+9oses
+9osis
+5gram
+9s
+8ph
+9hic
+9hies
+9hs
+9hy
+6yra
+9s
+5id
+5meter
+9rs
+8ric
+9ies
+9y
+5nolactone
+9ctones
+5phore
+9es
+4t
+5ed
+5ing
+5le
+7s
+5s
+4ula
+7e
+7s
+6ina
+9e
+9s
+4y
+3ssitude
+9es
+3t
+4al
+6s
+4ball
+8s
+4chcock
+9ked
+9king
+9ks
+6er
+4e
+5d
+5ful
+8ler
+9est
+9y
+8ness
+9esses
+5s
+4fire
+8s
+4ing
+4s
+5ticker
+9ers
+4ted
+6n
+6r
+7s
+5ing
+8s
+5le
+7bug
+9gs
+7s
+5oon
+8s
+4z
+5es
+3v
+4s
+4veries
+7y
+5ier
+7st
+6sh
+5y
+2lake
+6s
+4nchnic
+8ocele
+9celes
+9logies
+9logy
+4sh
+6back
+9ks
+7oard
+9rds
+6down
+9ns
+6ed
+7r
+8s
+7s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9s
+6proof
+6y
+4t
+5ch
+7ed
+8s
+7ing
+5s
+5ted
+7r
+8ed
+8ing
+8punk
+9unks
+8s
+6ing
+9s
+4y
+5ed
+5feet
+6oot
+9ed
+9edly
+5ing
+5s
+3een
+6ful
+9ly
+6ier
+8st
+7sh
+6less
+6s
+7tone
+9nes
+6wort
+9ts
+6y
+4native
+5dent
+6id
+8er
+9st
+8ious
+8ly
+8ness
+9esses
+8ous
+7ferous
+9rously
+6or
+8ous
+8s
+7ur
+9s
+6rous
+5ectomies
+9mise
+9mised
+9mises
+9mising
+9mize
+9mized
+9mizes
+9mizing
+9my
+6tic
+9al
+9ally
+9s
+5ia
+7l
+6c
+6i
+6sation
+9ions
+6tis
+9es
+6um
+8s
+7s
+8es
+6zation
+9ions
+5omegalies
+9aly
+5t
+6s
+4uchan
+9s
+3ice
+6d
+6r
+7s
+6s
+5ing
+8s
+4ff
+6s
+4ne
+6d
+6s
+5ing
+5t
+6ed
+7r
+8ed
+8ier
+9est
+9ng
+8s
+8y
+6ing
+6like
+6s
+6wood
+9ds
+4sh
+6ed
+7s
+6ing
+4t
+5s
+5ted
+7r
+8s
+6ing
+9s
+7sm
+9s
+8t
+9s
+3odge
+7d
+7s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6y
+4g
+5s
+4osh
+7ed
+8s
+7ing
+4re
+6s
+4sh
+6ed
+7s
+6ing
+4tch
+7ed
+8s
+7ier
+9st
+8ly
+8ness
+9esses
+9g
+7y
+3urge
+7d
+7r
+8s
+7s
+6ier
+8st
+7ng
+6y
+4tter
+8ed
+9r
+9rs
+8ing
+9ngly
+9ngs
+8s
+8y
+2od
+4dier
+7st
+5y
+4e
+5s
+4ium
+7s
+4ogram
+9s
+5mancies
+9y
+8tic
+5sol
+8s
+4s
+4umene
+9s
+3ffish
+5y
+3il
+5able
+6ge
+8s
+5ed
+6r
+7s
+5five
+9s
+6ul
+5ing
+5s
+6man
+7en
+6port
+9ts
+5t
+3ke
+5d
+5n
+5s
+6have
+9es
+6man
+9ship
+9ships
+7en
+6people
+8rson
+9sons
+6woman
+9en
+5wise
+4ing
+3liate
+8d
+8s
+7ing
+8on
+9ns
+8ve
+7or
+9s
+9y
+3ndaic
+8al
+8s
+5ee
+7s
+5oolicks
+5ulicks
+8x
+5yl
+7ites
+9ic
+9ics
+9ides
+9is
+9ises
+7olyses
+9ysis
+8ses
+9is
+9ises
+8us
+7s
+4ge
+6able
+6bag
+9s
+6d
+6like
+6ous
+6r
+7s
+6s
+6ware
+9es
+7ood
+9ds
+5icolous
+6er
+7st
+6form
+6ly
+6n
+7ess
+9ses
+7g
+7s
+6oblast
+9astic
+9asts
+7se
+7us
+5oid
+6logies
+9ist
+9ists
+9y
+5y
+4sal
+7ia
+5ible
+6ng
+8s
+6on
+8al
+8s
+5on
+7s
+6r
+7ed
+7ial
+8ng
+7s
+8hip
+9ips
+4taneities
+9ty
+8ous
+9usly
+9usness
+5oon
+8s
+3of
+5ed
+6r
+7ies
+7s
+7y
+5ier
+7st
+6ng
+8s
+5s
+5y
+4k
+5ed
+6ries
+7y
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+6sh
+5s
+5y
+4l
+5ed
+6r
+7s
+5ing
+8s
+5s
+4m
+5ed
+5ing
+5s
+4n
+5bait
+9s
+6ill
+9s
+5drift
+9ts
+5ed
+6rism
+9ms
+6y
+7s
+5fed
+6ul
+8s
+5hook
+9s
+5ier
+7s
+8t
+6ly
+6ng
+5s
+6ful
+5ways
+6ise
+6orm
+9s
+5y
+4r
+5ed
+6r
+7s
+5ing
+5s
+4t
+5s
+3radic
+8al
+9lly
+9lness
+5l
+5ngia
+9l
+8ola
+9le
+9les
+9lum
+9phore
+9phores
+9spore
+9spores
+8um
+4e
+5d
+5s
+4icidal
+8e
+9s
+5desm
+9s
+6ia
+8l
+7um
+5ng
+4k
+5s
+4ocarp
+9s
+6yst
+9ic
+9s
+7te
+9s
+5geneses
+9sis
+8ic
+9es
+8ous
+8y
+6onia
+9al
+9c
+9es
+9um
+8y
+5id
+5phore
+9es
+9ic
+9ous
+7yl
+9l
+9ls
+9s
+8te
+9es
+9ic
+6ollenin
+9enins
+5trichoses
+9hosis
+5zoa
+8l
+8n
+9s
+7ic
+8te
+9es
+7on
+4ran
+7s
+4t
+5abilities
+9ity
+7le
+6nce
+9s
+5caster
+9ers
+5ed
+6r
+7s
+5fisherman
+9ermen
+9ing
+9ings
+6ul
+8ly
+8ness
+9esses
+5ier
+7s
+8t
+6f
+6ly
+6ness
+9ses
+7g
+8ly
+6ve
+8ly
+8ness
+9esses
+5less
+5s
+6cast
+9ter
+9ters
+9ting
+9tings
+9ts
+6man
+9like
+9ly
+9ship
+9ships
+7en
+6people
+8rson
+9sons
+6wear
+9rs
+7oman
+9en
+7riter
+9ters
+9ting
+9tings
+5y
+4ular
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+6e
+7s
+3sh
+5es
+5ier
+7st
+5y
+3t
+4less
+8ly
+8ness
+9esses
+5ight
+9ed
+9ing
+9s
+6t
+4s
+4table
+5ed
+7ness
+9sses
+6r
+7s
+5ie
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+8s
+5y
+3usage
+8s
+6l
+7ly
+7s
+5e
+6d
+6less
+6s
+5ing
+4t
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8s
+5less
+5s
+5y
+3ylefull
+2rachgefuhl
+9uhls
+5k
+6le
+8d
+8s
+7ing
+4d
+5dle
+8d
+8s
+7ing
+4g
+5ged
+6ing
+5s
+4id
+5n
+6ed
+6ing
+6s
+6t
+7s
+4ng
+6le
+8d
+8s
+7ing
+6s
+4t
+5s
+5tle
+8d
+8s
+7ing
+4uchle
+9d
+9s
+8ing
+5ncier
+9st
+7y
+4wl
+6ed
+7r
+8s
+6ier
+8st
+7ng
+6s
+6y
+4y
+5ed
+6r
+7s
+6y
+5ier
+7st
+6ng
+8s
+5s
+3ead
+6abilities
+9lity
+8le
+6er
+8s
+6ing
+9ly
+9s
+6s
+7heet
+9ets
+5gh
+7eries
+9y
+7s
+5the
+8d
+8s
+7ing
+5ze
+7d
+7s
+6ing
+4cheries
+8y
+6gesang
+9angs
+6stimme
+9mmes
+5kled
+4d
+5d
+6e
+7n
+7s
+6ing
+6s
+5s
+4e
+5d
+5ing
+5s
+5the
+8d
+8s
+7ing
+5ze
+7d
+7s
+6ing
+4kelia
+9s
+4nt
+4w
+5s
+3ier
+5st
+4g
+5ged
+7r
+8s
+6ier
+8st
+7ng
+6y
+5ht
+7ed
+7ful
+9lly
+9lness
+7ing
+7less
+8ier
+9est
+9ness
+9nesses
+8y
+7s
+5s
+5tail
+9s
+4ng
+6al
+8d
+9s
+8s
+6board
+9rds
+8k
+9s
+7uck
+9ks
+6e
+7d
+7ing
+7r
+8s
+7s
+6haas
+8lt
+9ts
+8se
+7ead
+9ds
+7ouse
+9ses
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9s
+6keeper
+9pers
+6le
+8s
+9s
+8t
+9s
+7ike
+6s
+6tail
+9ls
+7ide
+9es
+8me
+9es
+6water
+9ers
+7ood
+9ds
+8rt
+9ts
+6y
+5kle
+8d
+8r
+9ed
+9ing
+9s
+8s
+7ing
+9gs
+5t
+6ed
+7r
+8s
+6ing
+9s
+6s
+4t
+5e
+6ful
+6lier
+9st
+7y
+6s
+5s
+6ail
+9s
+5z
+6ed
+7r
+8s
+7s
+6ig
+8s
+7ng
+3ocket
+8s
+4d
+5s
+4g
+5s
+4ng
+4ut
+6ed
+6ing
+9s
+6s
+3uce
+6d
+6ly
+6ness
+9ses
+6r
+6s
+7t
+5ier
+7st
+6ng
+5y
+4e
+5s
+4g
+5s
+4ik
+6ed
+7r
+8s
+6ing
+6s
+5t
+6s
+4ng
+4sh
+6ed
+7s
+6ing
+3y
+4er
+5st
+4ly
+4ness
+8es
+2ud
+4ded
+6r
+7s
+5ier
+7st
+6ng
+8s
+5le
+7s
+5y
+4s
+3e
+4d
+4ing
+4r
+5s
+4s
+3g
+4gies
+5y
+4s
+3ilzie
+8d
+8ing
+8s
+4ng
+3le
+5blade
+9es
+5s
+4ye
+6d
+6ing
+6s
+5ie
+7d
+7ing
+7s
+4zie
+7d
+7ing
+7s
+3mante
+8s
+4e
+5d
+5s
+6cence
+9ces
+9t
+4ier
+6st
+5ng
+4one
+7s
+6i
+7s
+5us
+4y
+3n
+4bonded
+4ge
+6s
+4ked
+5ie
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5s
+5y
+4yarn
+8s
+3r
+4gall
+8ed
+8ing
+8s
+5e
+6s
+4iae
+5osities
+9y
+6us
+8ly
+8ness
+9esses
+4less
+5ing
+8s
+4n
+5e
+6d
+6r
+7s
+6s
+5ing
+8s
+5s
+4red
+6r
+7s
+6y
+7s
+5ier
+8s
+7s
+8t
+6ng
+8s
+5y
+4s
+4t
+5ed
+6r
+7s
+5ing
+5le
+7s
+5s
+4way
+7s
+3ta
+4nik
+7s
+4ter
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7s
+7y
+4um
+2y
+3al
+5s
+3cam
+6s
+3glass
+8es
+3hole
+7s
+3ing
+6s
+3master
+9s
+3plane
+8s
+3re
+5s
+3ware
+7s
+1quab
+5ash
+8ed
+9r
+9rs
+9s
+8ing
+5bed
+7r
+7st
+6ier
+8st
+7ng
+7sh
+6le
+8d
+8r
+9s
+8s
+7ing
+6y
+5s
+4cco
+7s
+4d
+5ded
+6ie
+8s
+7ng
+6y
+5ron
+8al
+8e
+9d
+9s
+8ing
+8s
+5s
+4il
+6ed
+7r
+8s
+6ing
+9s
+6s
+4lene
+8s
+5id
+7er
+8st
+7ities
+9y
+7ly
+7ness
+9sses
+5l
+6ed
+7r
+8s
+6ier
+8st
+7ng
+9s
+7sh
+6s
+6y
+5oid
+6r
+7s
+4ma
+6e
+6te
+8s
+7ion
+9ns
+5e
+6lla
+9s
+6s
+5iform
+5osal
+9s
+7e
+8ly
+8ness
+9esses
+7ities
+9y
+6us
+8ly
+8ness
+9esses
+5ula
+8s
+7e
+8s
+7ose
+4nder
+8ed
+9r
+9rs
+8ing
+9ngly
+9ngs
+8mania
+9anias
+8s
+4re
+6d
+6head
+9ds
+6ly
+6ness
+9ses
+6r
+7s
+6s
+7t
+6wise
+5ial
+8s
+6ng
+8s
+6sh
+8ly
+8ness
+9esses
+5k
+6s
+5rose
+5son
+8age
+9ges
+8s
+4sh
+6able
+6ed
+7r
+8s
+7s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6y
+4t
+5ly
+5ness
+9es
+5s
+5ted
+7r
+8ed
+8ing
+8s
+7st
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6le
+8d
+8s
+7ing
+6ocracies
+9acy
+6y
+4w
+5bush
+9es
+5fish
+9es
+5k
+6ed
+7r
+8s
+6ier
+8st
+7ng
+9s
+6s
+6y
+5man
+6en
+5root
+9s
+5s
+3eak
+6ed
+7r
+8ies
+8s
+8y
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9ly
+9s
+6s
+6y
+5l
+6ed
+7r
+8s
+6ing
+9s
+6s
+5mish
+9ly
+9ness
+9nesses
+4egee
+8d
+8ing
+8s
+5zabilities
+9lity
+8le
+6e
+7d
+7r
+8s
+7s
+6ier
+8st
+7ng
+9s
+6y
+4g
+5ged
+7r
+8s
+6ing
+9s
+5s
+4lch
+7ed
+8r
+9s
+8s
+7ier
+9st
+8ng
+9gs
+7y
+4teague
+9es
+3ib
+5bed
+6ing
+9s
+5s
+4d
+5ded
+6ing
+5ge
+7d
+7s
+6ier
+8st
+7ng
+6y
+5s
+4er
+6s
+4ff
+6ed
+7r
+8s
+6ier
+8st
+6y
+4ggle
+8d
+8r
+9s
+8s
+7ier
+9st
+8ng
+7y
+4lgee
+8d
+8ing
+8s
+5l
+6a
+7e
+7s
+6ion
+9s
+6s
+4nancies
+8y
+5ch
+7ed
+8s
+7ing
+5ied
+7s
+5nied
+8r
+8s
+9t
+6y
+7ing
+5t
+6ed
+7r
+8s
+7st
+6ier
+8st
+7ng
+9ly
+9s
+6s
+6y
+5y
+6ing
+4rage
+8s
+6lities
+9y
+7ties
+8y
+6rch
+9al
+9ical
+9ies
+9s
+9y
+5e
+6age
+9s
+7rch
+9hal
+9hical
+9hies
+9hs
+9hy
+6d
+7om
+9s
+6en
+8s
+6hood
+9ds
+6like
+8ng
+9gs
+7y
+6s
+7hip
+9ps
+7s
+8es
+5ing
+6sh
+5m
+6ed
+7r
+8s
+6ier
+8st
+7ng
+9ly
+6s
+6y
+5r
+6ed
+7l
+8ed
+8fish
+9ishes
+8ing
+8led
+9ing
+9y
+8s
+8y
+6ing
+6s
+5t
+6ed
+7r
+8s
+6ing
+9s
+6s
+4sh
+6ed
+7s
+6ier
+8st
+7ness
+9sses
+8g
+6y
+4t
+5ch
+7es
+5s
+5ters
+4z
+5zes
+3oosh
+7ed
+8s
+7ier
+9st
+8ng
+7y
+3ush
+6ed
+7s
+6ing
+1raddha
+7s
+4ha
+6s
+2i
+3s
+1t
+2ab
+4bed
+6r
+7s
+5ing
+8ly
+8s
+4ilate
+9s
+6e
+7s
+6isation
+9tions
+9tor
+9tors
+8e
+9d
+9r
+9rs
+9s
+8ing
+7ties
+8y
+7zation
+9tions
+9tor
+9tors
+8e
+9d
+9r
+9rs
+9s
+8ing
+4le
+6boy
+9s
+6d
+6man
+8te
+9es
+7en
+6ness
+9ses
+6r
+7s
+6s
+7t
+5ing
+8s
+6sh
+8ed
+9s
+8ing
+8ment
+9ents
+5y
+4s
+3cation
+9s
+4cati
+8ssimo
+7o
+8s
+4hys
+7es
+4k
+5able
+5ed
+6r
+7s
+6t
+7s
+5ing
+8s
+5less
+5room
+9s
+5s
+5up
+7s
+5yard
+9s
+4te
+6s
+5ometer
+9ers
+3dda
+6s
+5le
+7s
+8tone
+9ones
+4e
+5s
+4holder
+9rate
+9rates
+9rs
+9rship
+9rships
+4ia
+6l
+7s
+6s
+5ometer
+9ers
+5um
+7s
+4tholder
+9erate
+9erates
+9ers
+9ership
+3ff
+5age
+8s
+5ed
+6r
+7s
+5ing
+5man
+6en
+5rider
+9rs
+6oom
+9s
+5s
+3g
+4e
+5able
+5coach
+9hes
+9hing
+9hings
+9hman
+9hmen
+6raft
+9ts
+5d
+5ful
+8s
+5hand
+9s
+5like
+5r
+6ies
+6s
+6y
+5s
+6truck
+5tte
+8s
+5y
+4flation
+9onary
+9ons
+4gard
+8s
+7t
+8s
+5ed
+6r
+7bush
+9shes
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7s
+7y
+5ie
+7r
+7s
+8t
+6ng
+5y
+4horn
+8s
+6und
+9s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4nance
+9s
+8ies
+8y
+7t
+8ly
+6te
+8d
+8s
+7ing
+8on
+9ns
+4s
+4y
+3id
+5er
+6st
+5ly
+5ness
+9es
+4g
+5s
+4n
+5abilities
+9ity
+7le
+5ed
+6r
+7s
+5ing
+8s
+5less
+9es
+9ly
+9ness
+9nesses
+5proof
+5s
+4r
+5case
+9d
+9s
+8ing
+9ngs
+5ed
+5foot
+9s
+5head
+9s
+5less
+6ift
+9s
+7ke
+5s
+6tep
+9ped
+9ping
+9s
+5way
+8s
+6ell
+9s
+6ise
+6ork
+9s
+4th
+6e
+7s
+6s
+3ke
+5d
+5holder
+9ers
+5out
+8s
+5s
+4hanovism
+9isms
+9ite
+9ites
+4ing
+4tometer
+9ers
+3lactic
+9al
+8form
+8tal
+9e
+9ed
+9es
+9ic
+9ical
+9ically
+9iform
+9ious
+5g
+6ma
+8s
+7ite
+9es
+9ic
+9ical
+9ically
+7ometer
+9eters
+9etries
+9etry
+6s
+4e
+5d
+5ly
+5mate
+9d
+9s
+8ing
+5ness
+9es
+5r
+5s
+6t
+4ing
+4k
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5less
+6ike
+5o
+6es
+5s
+5y
+4l
+5age
+8s
+5ed
+6nger
+9rs
+5holder
+9ers
+5ing
+8er
+9rs
+8s
+6on
+8s
+5man
+7ster
+9ers
+6en
+5s
+4wart
+8ly
+8ness
+9esses
+8s
+5orth
+9s
+3men
+6ed
+6s
+4ina
+7l
+7s
+7te
+6eal
+7ous
+6iferous
+6ode
+9s
+8ia
+9es
+9um
+8y
+7id
+4mel
+7s
+6r
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7s
+4noi
+6s
+4p
+5ed
+7e
+8d
+8r
+9s
+8s
+7ing
+7o
+8ed
+8ing
+8s
+6r
+7s
+5ing
+8s
+5less
+5s
+3nce
+6s
+5h
+6able
+6ed
+7l
+8led
+9ing
+8s
+7r
+8ed
+8ing
+8s
+7s
+8t
+6ing
+9s
+7on
+9ed
+9ing
+9s
+6less
+7y
+6ness
+9ses
+5k
+4d
+5ard
+8bred
+9reds
+8isation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8less
+9y
+8s
+6way
+5by
+7s
+5down
+9s
+5ee
+7s
+6n
+6r
+7s
+5fast
+9s
+6irst
+9ts
+5gale
+9s
+5ing
+8s
+6sh
+8es
+5off
+8ish
+9shly
+9shness
+8s
+6ut
+8s
+6ver
+9s
+5pat
+8ter
+9ers
+9ism
+9isms
+6ipe
+9s
+6oint
+9ts
+5s
+6till
+9ls
+5up
+7s
+4e
+5d
+5s
+4g
+5ed
+5ing
+5s
+4hope
+8s
+4iel
+7s
+5ne
+7s
+6g
+4k
+5ed
+5ing
+5s
+4naries
+7y
+6te
+8s
+7or
+9s
+5el
+7s
+5ic
+6ferous
+6te
+8s
+5otype
+9es
+6us
+5um
+7s
+4ol
+6s
+4yel
+7s
+4za
+6ed
+6ic
+6s
+5e
+6s
+5o
+6es
+6s
+3p
+4edectomies
+9omy
+7s
+6ial
+7i
+7us
+9es
+5lia
+8s
+5s
+4h
+5s
+5yline
+9id
+9ids
+8tis
+9ises
+7ococcal
+9occi
+9occic
+9occus
+8ma
+9as
+9ata
+8plastic
+9lasty
+8rrhaphy
+4le
+6d
+6r
+7s
+6s
+5ing
+8s
+4ped
+5ing
+5le
+7s
+4s
+3r
+4agen
+8s
+4board
+9ed
+9ing
+9s
+5urst
+9s
+4ch
+6ed
+8ly
+8ness
+9esses
+7r
+8s
+7s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6like
+6y
+4dom
+7s
+5rift
+9s
+5ust
+8s
+4e
+5d
+5r
+6s
+5s
+5ts
+7es
+6z
+7es
+4fish
+8ed
+9s
+5lower
+9rs
+5ruit
+9s
+4gaze
+8d
+8r
+9s
+8s
+8y
+7ing
+9gs
+4ing
+7ly
+7s
+4k
+5ed
+6n
+7ed
+7ing
+7s
+6r
+7s
+6st
+5ing
+5ly
+5ness
+9es
+5s
+4less
+6t
+7s
+5ight
+9ed
+9s
+6ke
+6ng
+8s
+6t
+4monger
+9rs
+4n
+5ed
+5ie
+7s
+6ng
+5ose
+8s
+5s
+4osta
+8s
+7ies
+7y
+4r
+5ed
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5s
+5y
+4s
+5hine
+9s
+7p
+8s
+5pot
+8s
+5tone
+9s
+6ruck
+4t
+5ed
+6r
+7s
+5ful
+5ing
+8ly
+8s
+6sh
+5le
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ing
+9ly
+9s
+7sh
+6y
+5s
+6y
+5up
+7s
+4vation
+9ns
+5e
+6d
+6ling
+9gs
+6r
+7s
+6s
+5ing
+8s
+4wort
+8s
+3ses
+4h
+5ed
+6s
+5ie
+7s
+6ng
+4idion
+9s
+5ma
+6on
+7rphies
+9hy
+5s
+3t
+4able
+5l
+5nt
+4e
+5able
+5craft
+9ts
+5d
+6ly
+5hood
+9s
+7use
+9es
+5less
+9ness
+9nesses
+7t
+8s
+6ier
+8st
+7ly
+7ness
+9sses
+6y
+5ment
+9ed
+9ing
+9ings
+9s
+5r
+6oom
+9s
+6s
+5s
+6ide
+6man
+9like
+9ly
+9ship
+9ships
+7en
+6person
+9sons
+6woman
+9en
+5wide
+4ic
+6al
+8ly
+6e
+7s
+6ky
+6s
+5m
+5n
+6g
+6s
+5on
+7al
+8ries
+9ily
+9iness
+9y
+7ed
+8r
+9ies
+9s
+9y
+7ing
+7master
+9sters
+7s
+5sm
+7s
+6t
+7ic
+9al
+9ally
+9ian
+9ians
+9s
+7s
+5ve
+7s
+4oblast
+9ts
+5cyst
+9s
+5latries
+9y
+6ith
+9ic
+9s
+5r
+6s
+5scope
+9es
+4s
+4to
+6s
+4ua
+6ries
+7y
+6s
+5e
+6d
+6s
+7que
+9ely
+9eness
+6tte
+9s
+5re
+7d
+7s
+5s
+6es
+6y
+5table
+9y
+6e
+7s
+6orily
+8y
+3umrel
+8s
+4n
+5ch
+7able
+7ed
+8r
+9s
+8s
+9t
+7ing
+9gs
+7less
+8y
+7ness
+9sses
+5ing
+5s
+4rolite
+9es
+9ic
+6scope
+9pes
+9pic
+3ve
+5d
+5s
+6acre
+9es
+4ing
+4udine
+9s
+3w
+4ed
+4ing
+4s
+3y
+4away
+8s
+4cation
+9ns
+4ed
+5r
+6s
+4ing
+4less
+4maker
+9s
+4ne
+6d
+6s
+5ing
+4re
+6s
+4s
+5ail
+8s
+2ead
+5ed
+5fast
+9ly
+9ness
+9nesses
+5ied
+7r
+8s
+7s
+8t
+6ly
+6ness
+9ses
+7g
+8s
+5s
+5y
+6ing
+4k
+5house
+9es
+5s
+4l
+5able
+6ge
+8s
+5e
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+5s
+5t
+6h
+7ed
+7ful
+7ier
+9st
+8ly
+8ness
+9esses
+9g
+9gs
+7s
+7y
+4m
+5boat
+9s
+5ed
+6r
+7ed
+7ing
+7s
+5fitter
+9ers
+5ie
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+8s
+5roll
+9ed
+9er
+9ered
+9ering
+9ers
+9ing
+9s
+5s
+6hip
+9s
+5tight
+9tness
+5y
+4n
+5e
+6d
+6s
+5ing
+8s
+5s
+4psin
+8s
+4r
+5age
+8s
+6te
+8s
+5d
+5e
+6d
+6s
+5ic
+6n
+7e
+8s
+7g
+7s
+5optene
+9nes
+5s
+6man
+8te
+9es
+7en
+4tite
+8s
+7ic
+5ocele
+9es
+6lyses
+9is
+6ma
+8s
+8tous
+6pyga
+9as
+9ia
+9ias
+9ic
+9ous
+6rrhea
+9eas
+9oea
+9oeas
+6ses
+7is
+3d
+4d
+5e
+6d
+6s
+5ied
+7s
+6ng
+5s
+5y
+6ing
+4e
+5d
+5s
+4fast
+8ly
+8ness
+9esses
+4ing
+4s
+3ed
+5ed
+5ied
+7s
+6ng
+5like
+5s
+5y
+6ing
+4k
+5ed
+5ing
+6t
+5s
+4l
+5bow
+8s
+5d
+5ed
+5head
+9s
+5ie
+7r
+7s
+8t
+6ness
+9ses
+7g
+8s
+5maker
+9rs
+8ing
+9ngs
+7n
+6en
+5s
+5ware
+9s
+6ork
+9er
+9ers
+9ing
+9ings
+9s
+5y
+6ard
+9s
+4m
+5ed
+5ing
+5s
+4n
+5bok
+8s
+6ras
+9es
+6uck
+9s
+5ed
+5ing
+8s
+5kirk
+9s
+5s
+4p
+5downe
+5ed
+7owne
+6n
+7ed
+7ing
+7s
+6r
+7s
+6st
+6up
+5ier
+7st
+6ness
+9ses
+7g
+6sh
+5le
+7bush
+9shes
+7chase
+9ased
+9aser
+9asers
+9ases
+9asing
+9asings
+7d
+7jack
+9cks
+7s
+6ing
+6y
+5ness
+9es
+5s
+5up
+5y
+4r
+5able
+6ge
+8s
+8way
+9ays
+5ed
+6r
+7s
+5ies
+6ng
+8s
+5ling
+9s
+5s
+6man
+8te
+9es
+7en
+5y
+4ve
+6d
+6ly
+6r
+6s
+7t
+5ing
+8s
+3ganogram
+9ams
+9aph
+9apher
+9aphers
+9aphic
+9aphies
+9aphist
+9aphs
+9aphy
+7pod
+9dous
+9ds
+4noses
+7is
+6tic
+4ocarpous
+6ephalian
+9alians
+9alous
+5don
+8s
+8t
+9s
+5myia
+9s
+5philist
+9ists
+5saur
+9ian
+9s
+9us
+9uses
+3il
+5s
+4n
+5bock
+9s
+7k
+8s
+5ed
+5ing
+8s
+5kirk
+9s
+5s
+3la
+5e
+5i
+5r
+4e
+5ne
+5s
+4ic
+4l
+5a
+6r
+7ator
+9ors
+6s
+6te
+8d
+8ly
+5ed
+6rid
+9an
+9ans
+9s
+5iferous
+7ied
+9s
+7orm
+7y
+8ing
+9ngs
+6ng
+6o
+7n
+8ate
+9tes
+8s
+6te
+8s
+5s
+5ular
+9ly
+8te
+3m
+4bok
+7s
+5uck
+8s
+4e
+5d
+5s
+4head
+8s
+4ing
+4less
+6t
+7s
+5ike
+4ma
+6s
+6ta
+7ic
+7ous
+5e
+6d
+6r
+7ies
+7s
+7y
+6s
+5ier
+7st
+6ng
+8s
+5y
+4pel
+7s
+5le
+7s
+4s
+5on
+7s
+4ware
+8s
+5inder
+9rs
+3n
+4ch
+6ed
+7s
+6ful
+6ier
+8st
+7ng
+6y
+5il
+7ed
+8r
+9s
+7ing
+7led
+9r
+9rs
+8ing
+9ngs
+7s
+4d
+5ed
+5ing
+5s
+4gah
+7s
+4lock
+8s
+4ned
+5ing
+4o
+5bath
+9ic
+9s
+5cardia
+9ias
+6hrome
+9mes
+9mies
+9my
+5graph
+9hed
+9her
+9hers
+9hic
+9hical
+9hies
+9hing
+9hist
+9hists
+9hs
+9hy
+5haline
+5kies
+6ous
+6y
+5paeic
+7ic
+6etalous
+6hagous
+7yllous
+5s
+6ed
+7s
+6is
+5therm
+9mal
+9ms
+6ic
+6opic
+6ropic
+6ype
+9d
+9r
+9rs
+9s
+8ic
+9es
+9ng
+9st
+9sts
+8y
+4s
+4t
+5ed
+5ing
+5master
+9ers
+5or
+7ian
+7s
+6ur
+8s
+5s
+3p
+4bairn
+9s
+5rother
+9ers
+4child
+9ren
+4dame
+8s
+6ncer
+9rs
+8ing
+9ngs
+6ughter
+9ters
+4families
+9y
+6ther
+9rs
+4hane
+8s
+7ite
+9es
+7otis
+9ises
+4ladder
+9rs
+5ike
+4mother
+9rly
+9rs
+4ney
+7s
+4over
+8s
+4parent
+9ting
+9tings
+9ts
+5e
+6d
+6r
+7s
+6s
+5ing
+4s
+5ister
+9rs
+5on
+7s
+5tool
+9s
+4t
+4wise
+3radian
+9s
+4coraceous
+8l
+8nism
+9isms
+9ist
+9ists
+8rious
+9y
+8te
+9ed
+9es
+9ing
+7icolous
+5ulia
+9ceous
+9s
+4e
+5o
+6acuities
+9ity
+6bate
+9es
+9ic
+7lind
+6card
+9ds
+7hemical
+9mistry
+8rome
+9omed
+9omes
+9omies
+9oming
+9omy
+6ed
+6gnoses
+9sis
+7ram
+9ms
+9ph
+9phed
+9phic
+9phical
+9phies
+9phing
+9phs
+9phy
+6ing
+7somer
+9meric
+9merism
+9mers
+9metric
+6logical
+9ically
+9ies
+9y
+6me
+8s
+8ter
+9ers
+9ric
+9rical
+9ries
+9ry
+6phonic
+9nies
+9ny
+7ses
+8ides
+9s
+7ticon
+9cons
+9cs
+6regular
+6s
+7cope
+9pes
+9pic
+9pical
+9pies
+9pist
+9pists
+9py
+7onic
+7pecific
+6tactic
+9tical
+8xes
+9ia
+9ias
+9ic
+9ically
+9is
+7omies
+9y
+7ropic
+9pism
+9pisms
+7ype
+9ed
+9er
+9ers
+9es
+9ic
+9ical
+9ically
+9ies
+9ing
+9ings
+9ist
+9ists
+9y
+6vision
+9ions
+5s
+4ic
+6al
+8ly
+5gma
+8s
+8ta
+5lant
+9s
+6e
+7ly
+6isable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7ties
+8y
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+4let
+7s
+5ing
+8ly
+8ness
+9esses
+8s
+4n
+5a
+6ge
+8s
+6l
+7gia
+9as
+9c
+5board
+9ds
+5ebra
+9e
+6d
+6r
+6st
+5fast
+9s
+6oremost
+5ing
+6te
+8s
+7ic
+5ly
+5most
+5ness
+9es
+5ocostal
+6tribe
+5port
+9s
+7st
+9s
+5s
+6heet
+9ts
+6on
+8s
+5um
+7s
+6tation
+9ions
+9ive
+9ives
+9or
+9ories
+9ors
+9ory
+5ward
+9s
+7y
+8s
+6orks
+4oid
+7al
+7ogeneses
+9enesis
+9enic
+7s
+5l
+6s
+4tor
+7ous
+9sly
+9sness
+7s
+4ve
+6d
+6s
+5ing
+3t
+4hoscope
+9pes
+9pic
+9pies
+9pist
+9pists
+9py
+4s
+5on
+7s
+4ted
+5ing
+3vedore
+9d
+9s
+8ing
+5n
+6graph
+9phs
+6s
+4ia
+3w
+4able
+5rd
+7ed
+8ss
+9ses
+7ing
+7ries
+8y
+7s
+8hip
+9ips
+6tries
+8y
+4bum
+7s
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7s
+4pan
+7s
+5ond
+8s
+6t
+7s
+4s
+4y
+3y
+4er
+5st
+2henia
+7s
+6c
+2iacciato
+9os
+3bble
+7r
+8s
+7s
+4ial
+7ism
+9ms
+5ne
+7s
+5um
+7s
+4nite
+8s
+3ccado
+8es
+8s
+6to
+8es
+8s
+4h
+5aria
+8on
+9ns
+5era
+7on
+5ic
+7ally
+6dia
+8um
+5oi
+6logies
+9y
+6metric
+9rical
+9ries
+9ry
+7ythia
+9hias
+9hic
+9hies
+9hy
+6s
+5s
+4k
+5abilities
+9ity
+7le
+5ball
+9s
+5ed
+6r
+7ed
+7ing
+7s
+5ful
+8s
+5handle
+9led
+9ler
+9lers
+9les
+9ling
+9lings
+5ied
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+8s
+6t
+5jaw
+8s
+5le
+7ader
+9ers
+7back
+9cks
+7d
+7r
+8s
+7s
+6ike
+7ng
+5man
+6en
+5out
+8s
+5pin
+8s
+5s
+6eed
+9s
+5tight
+9ts
+5um
+7s
+6p
+7s
+5weed
+9s
+6ork
+9s
+5y
+6beak
+9ked
+9king
+9ks
+6ing
+4tion
+8s
+3ddie
+7d
+7ing
+7s
+3e
+4d
+4s
+4ve
+6ly
+6r
+6st
+3ff
+5ed
+6n
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6r
+6st
+5ie
+7s
+6ng
+6sh
+5ly
+5ness
+9es
+5s
+5ware
+9s
+5y
+4le
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+3gma
+6l
+6rian
+9ns
+6s
+7terol
+9rols
+6ta
+7ic
+9al
+9ally
+9s
+8ferous
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9ts
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7ophilia
+9hilias
+9hilist
+8se
+5e
+6s
+3lb
+5ene
+8s
+6strol
+9ols
+5ite
+8s
+5oestrol
+9rols
+5s
+4e
+5d
+5s
+5t
+6s
+6to
+8ed
+9s
+8ing
+8s
+4ing
+4l
+5age
+8s
+6tories
+9y
+5birth
+9hs
+6orn
+9s
+5ed
+6r
+7s
+6st
+5house
+9es
+5icide
+9es
+6er
+7st
+6form
+6ng
+8s
+6on
+8s
+5man
+6en
+5ness
+9es
+5room
+9s
+5s
+5y
+4pnosiderite
+4t
+5bird
+9s
+5ed
+7ly
+7ness
+9sses
+6r
+7s
+5ier
+7st
+6ness
+9ses
+7g
+8s
+6sh
+5s
+5y
+3m
+4e
+5d
+5s
+4ie
+6d
+6s
+5ng
+4pmeter
+9rs
+4s
+4ulable
+7ncies
+9y
+8t
+9s
+7te
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+9on
+9ons
+9ve
+9ves
+8or
+9rs
+9ry
+6i
+6us
+4y
+5ing
+3ng
+5aree
+9s
+5bull
+9s
+5ed
+6r
+7s
+5fish
+9es
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+7g
+8ly
+8ness
+9esses
+8s
+5less
+5o
+6s
+5ray
+8s
+5s
+5y
+4k
+5ard
+8s
+5bird
+9s
+6ug
+8s
+5er
+7oo
+9s
+7s
+5horn
+9s
+5ier
+7st
+6ng
+8ly
+8ness
+9esses
+5o
+5pot
+8s
+5s
+6tone
+9es
+5weed
+9s
+6ood
+9s
+5y
+4t
+5ed
+7ly
+7ness
+9sses
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5less
+5s
+5y
+3pa
+5s
+4e
+5d
+5l
+6late
+6s
+5nd
+7iaries
+9ry
+9te
+9ted
+9tes
+9ting
+7s
+5s
+4iform
+5tate
+6es
+6iform
+4ple
+7d
+7r
+8s
+7s
+6ing
+9s
+4ulable
+7ceous
+7r
+8y
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+9ry
+6e
+7d
+7s
+3r
+4about
+9s
+4e
+5d
+5s
+4ing
+4k
+5s
+4less
+4p
+5es
+5iculture
+9tures
+5s
+4ra
+6ble
+6h
+7s
+6s
+5e
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+5up
+7s
+4s
+3shie
+7s
+3tch
+6craft
+9fts
+6ed
+7r
+8ies
+8s
+8y
+7s
+6ing
+9s
+6work
+9ks
+9t
+9ts
+4hied
+7s
+5y
+6ing
+3ve
+5d
+5r
+6s
+5s
+4ier
+6st
+5ng
+4y
+2oa
+4e
+4i
+4s
+4t
+5s
+3b
+4bed
+5ing
+4ie
+4s
+3ccado
+8s
+6ta
+8s
+4hastic
+9cally
+4ious
+4k
+5ade
+8d
+8s
+7ing
+6ge
+8s
+5breeder
+9ders
+9ding
+9dings
+7oker
+9erage
+9erages
+9ers
+9ing
+9ings
+5car
+8s
+5ed
+6r
+7s
+5fish
+9es
+5holder
+9ers
+9ing
+9ings
+7rse
+9es
+5ier
+7st
+6ly
+6ness
+9ses
+8t
+9s
+9te
+9tes
+7g
+8ed
+9r
+9rs
+8less
+8s
+6sh
+8ly
+8ness
+9esses
+7t
+8s
+5jobber
+9eries
+9ers
+9ery
+9ing
+9ings
+5keeper
+9ers
+5less
+6ist
+9s
+6ock
+9s
+5man
+6en
+5pile
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+6ot
+8s
+6unisht
+5room
+9s
+7ute
+9es
+5s
+5take
+9n
+9s
+8ing
+9ngs
+6ook
+5work
+9s
+5y
+6ard
+9s
+3dge
+6d
+6r
+7s
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5y
+3echiological
+9ogies
+9ogy
+8metric
+9etries
+9etry
+4p
+5s
+3gey
+6s
+4ie
+6s
+4y
+3ic
+5al
+7ly
+7ness
+9sses
+5heiologies
+9logy
+9metric
+9metry
+6iological
+9ogies
+9ogy
+8metric
+9etries
+9etry
+5ism
+8s
+5s
+4t
+5ed
+6r
+7ed
+7ing
+7s
+5ing
+5s
+3ke
+5d
+5hold
+9s
+8e
+9s
+5r
+6s
+5s
+6ia
+8s
+4ing
+4vel
+7s
+3le
+5d
+5n
+6wise
+5s
+4id
+6er
+7st
+6ities
+8y
+6ly
+6ness
+9ses
+4len
+7s
+4n
+4on
+6ate
+6ic
+7ferous
+6s
+4port
+8s
+3ma
+5ch
+7ache
+9hes
+8l
+7ed
+8r
+9s
+7ful
+9lness
+9ls
+7ic
+9al
+9s
+8ng
+7less
+7ous
+7s
+7y
+6k
+7s
+5l
+5s
+5ta
+7l
+6e
+7s
+6ic
+7tic
+9des
+9s
+9ses
+6odaea
+9eum
+7gastric
+7logical
+9gies
+9gy
+7plasties
+9asty
+8od
+9ds
+7us
+4ia
+5um
+7s
+4odaea
+9l
+8um
+9ms
+6ea
+8l
+7um
+9s
+4p
+5ed
+6r
+7s
+5ie
+7s
+6ng
+5s
+3nable
+4d
+5s
+4e
+5able
+5boat
+9s
+7rer
+9rs
+6rash
+9hes
+7eak
+9ks
+5cast
+9s
+6hat
+9s
+6rop
+9s
+6utter
+9ers
+9ing
+9ings
+5d
+5fish
+9es
+6lies
+7y
+5ground
+5hand
+9s
+6orse
+9es
+5less
+9ness
+9nesses
+6ike
+5mason
+9nries
+9nry
+9ns
+5n
+5r
+6ag
+8s
+7w
+8s
+6n
+6s
+5s
+6hot
+9s
+5wall
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+7re
+9s
+7sh
+9ed
+9es
+9ing
+6ork
+9er
+9ers
+9s
+8t
+9s
+5y
+4g
+4ied
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+5sh
+7ed
+8s
+7ing
+4k
+5ed
+6r
+7ed
+7ing
+7s
+5ing
+5s
+4n
+5e
+6d
+6s
+5ing
+5s
+4y
+5hearted
+5ing
+3od
+5en
+4ge
+6d
+6s
+5ing
+4k
+5ed
+6r
+7s
+5ie
+7s
+6ng
+5s
+4l
+5ball
+9s
+5ed
+5ie
+7s
+6ng
+5s
+4p
+5ball
+9s
+5e
+6d
+6r
+7s
+6s
+5ing
+8ly
+5s
+4r
+5s
+4shie
+8s
+4ze
+6d
+6r
+7s
+6s
+5ing
+8s
+3p
+4bank
+8s
+4cock
+8s
+4e
+5d
+5r
+6s
+5s
+4gap
+7s
+4ing
+7s
+4less
+5ight
+9s
+4off
+7s
+5ver
+8s
+4pable
+6ge
+8s
+5ed
+6r
+7ed
+7ing
+7s
+5ing
+8s
+5le
+7d
+7s
+6ing
+4s
+4t
+4watch
+9es
+5ord
+8s
+3rable
+8s
+5ge
+7s
+5x
+6es
+4e
+5d
+5front
+9ts
+5house
+9es
+5keeper
+9ers
+9ing
+9ings
+5man
+6en
+5r
+6oom
+9s
+6s
+5s
+6hip
+9s
+5wide
+5y
+6ed
+6s
+4ge
+6s
+4iated
+5ed
+6s
+6tte
+9s
+5ng
+5ologies
+9ist
+9ists
+9y
+4k
+5s
+6bill
+9ls
+4m
+5bird
+9s
+6ound
+5cock
+9s
+5ed
+6r
+7s
+5ful
+8ly
+8ness
+9esses
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5less
+6ike
+5proof
+5s
+6tayed
+5y
+4nelli
+8o
+4y
+5board
+9ded
+9ding
+9ds
+7ok
+9s
+5ette
+9s
+5ing
+8s
+5line
+9s
+5teller
+9ers
+9ing
+9ings
+3ss
+5es
+3t
+4in
+6ka
+7i
+6ov
+6s
+5ous
+4s
+4t
+5ed
+6r
+7ed
+7ing
+7s
+5ie
+7s
+6ng
+5s
+5y
+3un
+5d
+6ed
+6ing
+6s
+5ing
+5s
+4p
+5s
+4r
+5e
+6s
+5ie
+7r
+7st
+5s
+5y
+4sh
+6ed
+7s
+6ie
+8s
+7ng
+4t
+5en
+7ed
+7ing
+7s
+6r
+6st
+5h
+6earted
+9tedly
+7rie
+9es
+6rief
+9fs
+6s
+5ish
+5ly
+5ness
+9es
+5s
+3vaine
+8s
+4e
+5d
+5pipe
+9s
+5r
+6s
+5s
+5top
+8s
+4ies
+5ng
+7s
+3w
+4able
+5ge
+7s
+5way
+8s
+4down
+8s
+4ed
+5r
+6s
+4ing
+7s
+4lins
+4n
+5d
+6ed
+6ing
+6s
+5lins
+4p
+5s
+4re
+6s
+4s
+2rabism
+8al
+8ic
+9cal
+8ometer
+9meters
+8s
+8us
+9ses
+5ometer
+9ers
+6tomies
+9y
+4cchini
+9o
+5k
+4d
+5dle
+8back
+8d
+8r
+9s
+8s
+7ing
+5iot
+8s
+5s
+4e
+5s
+4fe
+6d
+6r
+7s
+6s
+5f
+6ed
+6ing
+6s
+5ing
+4g
+5gle
+8d
+8r
+9s
+8s
+7ier
+9st
+8ng
+9gly
+9gs
+7y
+5s
+4icht
+8er
+9st
+5ght
+8away
+9ways
+8bred
+9reds
+8ed
+9dge
+9dged
+9dges
+9n
+9ned
+9ner
+9ners
+9ning
+9ns
+9r
+9st
+8forth
+9orward
+8ing
+9sh
+8jacket
+9ackets
+8laced
+9y
+8ness
+9esses
+8s
+8way
+9ays
+5k
+6ed
+6ing
+6s
+5n
+6ed
+8ly
+7r
+8s
+6ing
+9s
+6s
+6t
+7s
+5t
+6ed
+7n
+8ed
+8ing
+8s
+7r
+7st
+6ing
+6jacket
+9keted
+9keting
+9kets
+6laced
+9edly
+9edness
+7y
+6ness
+9ses
+6s
+6waistcoat
+4k
+5e
+6d
+6s
+4macon
+9s
+6sh
+8ed
+9s
+8ing
+6zon
+9s
+5ineous
+5mel
+8s
+5onies
+8um
+9ms
+7y
+5p
+6ed
+6ing
+6s
+4nd
+6ed
+8ness
+9esses
+7r
+8s
+6flat
+9ts
+6ing
+6line
+9es
+6s
+6wolf
+9ves
+5g
+6e
+7ly
+7ness
+9sses
+7r
+8ed
+8ing
+8s
+7s
+8t
+6le
+8d
+8hold
+9olds
+8ment
+9ents
+8r
+9s
+8s
+7ing
+6ulate
+9ted
+9tes
+9ting
+9tion
+9tions
+7ries
+8y
+4p
+5hang
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+6ung
+5less
+9es
+6ine
+9s
+5ontin
+9ns
+5pados
+6ed
+7r
+8s
+6ier
+8st
+7ng
+9s
+6y
+5s
+5wort
+9s
+4ss
+6es
+4ta
+6gem
+9s
+6l
+6s
+5egetic
+9ical
+7ic
+9al
+9ally
+9s
+8es
+8se
+9ed
+9es
+9ing
+9t
+9ts
+8ze
+9ed
+9es
+9ing
+7y
+5h
+6s
+7pey
+9ys
+5i
+6culate
+9ation
+9ations
+6fication
+9ations
+8ed
+9s
+7orm
+7y
+8ing
+6grapher
+9phers
+9phic
+9phical
+9phies
+9phist
+9phists
+9phy
+5ocracies
+9cy
+9t
+9tic
+9ts
+7umuli
+9ulus
+6nic
+6pause
+9ses
+6se
+7phere
+9eres
+9eric
+9erical
+6tanker
+9kers
+6us
+6volcano
+9canoes
+9canos
+5um
+7s
+6s
+4ucht
+8ed
+9r
+9st
+8ing
+8s
+5ght
+8ed
+9r
+9st
+8ing
+8s
+5nge
+4vage
+8d
+8s
+7ing
+6ig
+8ed
+9r
+9rs
+8ing
+8s
+4w
+5berries
+9y
+6oard
+9ds
+5ed
+6n
+5flower
+9ers
+5hat
+5ier
+7st
+6ng
+5less
+6ike
+5n
+5s
+5weight
+9hts
+6orm
+9s
+5y
+4y
+5ed
+6r
+7s
+5ing
+8s
+5ling
+9s
+5s
+5ve
+7d
+7s
+6ing
+3eak
+6ed
+7r
+8s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9s
+6like
+6s
+6y
+5m
+6bed
+9s
+6ed
+7r
+8ed
+8s
+6ier
+8st
+7ness
+9sses
+8g
+9ly
+9s
+6less
+8t
+9s
+7ike
+8ne
+9ed
+9er
+9ers
+9es
+9g
+9gs
+9ing
+6s
+7ide
+9es
+6y
+4ek
+6ed
+7r
+8s
+6ing
+6s
+5l
+6ed
+6ing
+6s
+5t
+6age
+9s
+6boy
+9s
+6car
+9s
+6ed
+6ful
+9s
+6ier
+8st
+7ng
+6keeper
+9pers
+6lamp
+9ps
+7ight
+9hts
+6room
+9ms
+6s
+7cape
+9pes
+7mart
+6walker
+9kers
+9king
+9kings
+8rd
+9ds
+7ear
+9rs
+7ise
+6y
+4ight
+8s
+6ne
+8d
+8s
+7ing
+4litz
+8es
+8i
+9a
+9as
+4ne
+6s
+5gth
+8en
+9ned
+9ner
+9ners
+9ning
+9nings
+9ns
+8ful
+8less
+8s
+5uities
+8y
+6osities
+9ty
+7us
+9ly
+9ness
+9nesses
+4p
+5ent
+6rous
+5hosymbolia
+5itant
+8tion
+9ions
+7oso
+8us
+5s
+6ipterous
+5tobacilli
+9cillus
+7carpus
+9rpuses
+8occal
+9cci
+9ccic
+9ccus
+7kinase
+9nases
+7lysin
+9sins
+7myces
+9cete
+9cetes
+9cin
+9cins
+7solen
+9lens
+7thricin
+9ricins
+4ss
+6buster
+9ters
+9ting
+6ed
+7s
+6ful
+9ly
+9ness
+9nesses
+6ing
+6less
+9sness
+6or
+8s
+4tch
+7ability
+9le
+7ed
+8r
+9ed
+9ing
+9s
+8s
+7ier
+9st
+8ness
+9esses
+9g
+9gs
+7less
+7marks
+7y
+5ta
+7s
+6e
+6i
+6o
+7s
+4usel
+8s
+4w
+5age
+8s
+5ed
+6r
+7s
+5ing
+8s
+5ment
+9s
+5n
+5s
+5th
+3ia
+5e
+5ta
+6e
+7d
+7s
+6ing
+7on
+9s
+6um
+8s
+7re
+9s
+4ch
+6es
+5k
+6en
+8ly
+6le
+8d
+8s
+7ing
+6s
+5t
+6er
+7st
+6ion
+9s
+7sh
+6ly
+6ness
+9ses
+6ure
+9d
+9s
+4dden
+6le
+8d
+8s
+7ing
+5e
+6legged
+9s
+6nce
+9s
+8ies
+8y
+7t
+8ly
+6r
+7s
+6s
+6ways
+5ing
+5ling
+5or
+7s
+5ulance
+9ces
+9t
+9tly
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+9ory
+7ous
+9sly
+9sness
+4fe
+6ful
+6less
+6s
+5t
+6s
+4g
+5a
+6e
+6te
+5ged
+6ing
+5iform
+6l
+7s
+6ne
+5ose
+5s
+4ke
+6bound
+7reaker
+9akers
+9aking
+9akings
+6less
+6out
+9s
+7ver
+9rs
+6r
+7s
+6s
+5ing
+8ly
+8ness
+9esses
+8s
+4m
+5med
+6ing
+5s
+4ng
+6board
+9rds
+6course
+9rses
+6ed
+7ncies
+9y
+8do
+8t
+9ly
+9ness
+9nesses
+7r
+8s
+6halt
+9ted
+9ts
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9s
+6less
+7ike
+6piece
+9ces
+6s
+6y
+7bark
+9rks
+5kle
+8d
+8s
+7ing
+9gs
+4p
+5e
+6d
+6less
+6r
+7s
+6s
+6y
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5ling
+9s
+5ogram
+9ms
+5pable
+6ed
+7r
+8gram
+9rams
+8s
+6ing
+9s
+5s
+5t
+6ease
+9er
+9ers
+9es
+5y
+4ve
+6d
+6n
+6r
+7s
+6s
+5ing
+8ly
+8s
+3oam
+6ed
+6ing
+6s
+4be
+6d
+6s
+5ic
+6l
+7a
+8ceous
+8e
+8r
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+7e
+8s
+7i
+8form
+8ne
+8sation
+9ations
+8zation
+9ations
+7oid
+7s
+7us
+9es
+6ng
+8s
+5oscope
+9pes
+9pic
+9pical
+6tron
+9ns
+4ddle
+8d
+8s
+7ing
+5e
+5le
+7d
+7s
+6ing
+4ganoff
+9fs
+4kable
+5e
+6d
+6n
+6play
+6r
+7s
+6s
+5ing
+8s
+4ll
+6ed
+7r
+8s
+6ing
+9s
+6s
+4ma
+6l
+6ta
+7ic
+7olite
+9ites
+9itic
+8us
+5b
+6s
+6uliferous
+9form
+7s
+8es
+4nd
+6s
+5g
+6arm
+9ed
+9ing
+9s
+6box
+9es
+6er
+7st
+6hold
+9ds
+6ish
+6ly
+6man
+7en
+6ness
+9ses
+6point
+9nts
+6room
+9ms
+6yl
+8e
+9s
+8oid
+9idoses
+9idosis
+9ids
+9ses
+9sis
+8s
+5tia
+8n
+9ite
+9ites
+9s
+8s
+7c
+7um
+9s
+4ok
+6e
+7n
+7s
+4p
+5hanthin
+9hins
+9hus
+9huses
+6e
+7s
+6ic
+8al
+7olate
+9ated
+9e
+9es
+6oid
+9s
+6uli
+8us
+5ped
+7r
+8s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6y
+5s
+4ssers
+4ud
+6ing
+9s
+6s
+5p
+6ach
+9s
+7n
+8s
+6s
+5t
+6ed
+6ing
+6s
+4ve
+4w
+5ed
+6r
+7s
+5ing
+8s
+5n
+5s
+4y
+5ed
+6r
+7s
+5ing
+5s
+3uck
+6en
+5tural
+9lise
+9lised
+9lises
+9lising
+9lism
+9lisms
+9list
+9lists
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9tion
+9tions
+8e
+9d
+9less
+9s
+8ing
+4del
+7s
+4ggle
+8d
+8r
+9s
+8s
+7ing
+9gly
+9gs
+4m
+5a
+6e
+6s
+6tic
+5itis
+9es
+5med
+7l
+8s
+7r
+8s
+6ing
+5ose
+6us
+5pet
+8ed
+8ing
+8s
+5s
+4ng
+5t
+6ed
+6ing
+6s
+4t
+5hioid
+9ds
+8us
+5s
+5ted
+7r
+8s
+6ing
+9ly
+9s
+3ychnia
+9s
+8c
+8ne
+9ed
+9es
+9ing
+9ism
+9isms
+8sm
+9ms
+2ub
+4bed
+5ie
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5le
+7d
+7s
+6ier
+8st
+6y
+5orn
+8ed
+9r
+9st
+8ing
+8ly
+8ness
+9esses
+8s
+5y
+4s
+3cco
+6ed
+7r
+8s
+7s
+6ing
+6s
+6work
+9ks
+4k
+5s
+3d
+4book
+8s
+4ded
+6n
+5ie
+7s
+6ng
+8s
+9ail
+9ails
+5le
+7s
+4e
+5nt
+7ries
+8y
+7s
+8hip
+9ips
+7y
+4farm
+8s
+5ish
+8es
+4horse
+9s
+4ied
+7ly
+7ness
+9sses
+6r
+7s
+6s
+5o
+6s
+6us
+8ly
+8ness
+9esses
+4lier
+7st
+5y
+4s
+4work
+8s
+4y
+5ing
+3ff
+5ed
+6r
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5less
+5s
+5y
+3ggier
+7st
+5y
+3iver
+7s
+3kkend
+3ll
+5s
+4m
+5s
+4tification
+9ations
+8ed
+9r
+9rs
+9s
+7y
+8ing
+3m
+4ble
+7bum
+9ms
+7d
+7r
+8s
+7s
+6ier
+8st
+7ng
+9ly
+6y
+4er
+6s
+4m
+5ed
+6l
+7s
+5ing
+4p
+5age
+8s
+5ed
+6r
+7s
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+7g
+8s
+5s
+5work
+9s
+5y
+4s
+3n
+4g
+4k
+5ard
+4ned
+6r
+7s
+5ing
+8ly
+8s
+4s
+5ail
+8s
+4t
+5ed
+7ness
+9sses
+5ing
+5man
+6en
+5s
+5woman
+8en
+3pa
+5s
+4e
+5d
+5facient
+9ents
+8tion
+9ions
+9ive
+6ied
+8r
+9s
+8s
+6y
+7ing
+9gly
+5ndious
+7ous
+9sly
+9sness
+6t
+5s
+4id
+6er
+7st
+6ities
+8y
+6ly
+6ness
+9ses
+6s
+5ng
+4or
+6ous
+6s
+4rate
+8d
+8s
+7ing
+8on
+9ns
+3rdied
+7r
+7s
+8t
+6ly
+6ness
+9ses
+5y
+4e
+4geon
+8s
+4mer
+7s
+4nine
+5oid
+5us
+7es
+4t
+5ed
+5ing
+5s
+3shie
+7s
+3tter
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7s
+2y
+3e
+4d
+4s
+3gian
+3ing
+3lar
+5te
+4e
+5book
+9s
+5d
+5e
+6s
+5less
+9ness
+9nesses
+5r
+6s
+5s
+5t
+6s
+4i
+5e
+6r
+6st
+5ferous
+6orm
+5ng
+7s
+5sation
+9ons
+6e
+7d
+7r
+8s
+7s
+6h
+7ly
+7ness
+9sses
+6ing
+6t
+7ic
+9ally
+9s
+7s
+5te
+7s
+6ic
+7sm
+9s
+5zation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+4o
+5bate
+9s
+5graph
+9hic
+9hical
+9hies
+9hs
+9hy
+5id
+7s
+5lite
+9s
+8ic
+5metries
+9y
+5pes
+6hone
+9es
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6odia
+9um
+6s
+5s
+6tixes
+9is
+4us
+6es
+3me
+5d
+5s
+4ie
+6d
+6ing
+6s
+5ng
+4y
+5ing
+3psis
+7es
+4tic
+7al
+7ities
+9y
+7s
+3racaceous
+5x
+6es
+4e
+5d
+5ne
+7s
+5s
+4ing
+4ofoam
+9s
+3te
+5d
+5s
+4ing
+1uabilities
+8y
+4le
+5y
+3sible
+5on
+7s
+5ve
+7ly
+7ness
+9sses
+4ory
+3ve
+5ly
+5ness
+9es
+5olent
+5r
+5st
+4ities
+6y
+2b
+3a
+4bbot
+8s
+5dominal
+4cetate
+9es
+5id
+7ities
+9y
+7ly
+7ness
+9sses
+5rid
+5t
+6ed
+6ing
+7on
+9s
+6s
+5ute
+8ly
+4dar
+7s
+5olescent
+9cents
+5ult
+8s
+4erial
+9ly
+4ffluent
+4gencies
+8y
+7t
+8s
+5gregate
+9ates
+9ation
+9ations
+4h
+5dar
+8ies
+8s
+8y
+5s
+6hip
+9s
+4lar
+5liance
+9ces
+6ocation
+9tions
+5pine
+5tern
+9ant
+9ants
+9ate
+9ates
+9ation
+9ations
+9ities
+9ity
+9s
+4ngular
+5tarctic
+4pical
+5ostolic
+5pearance
+9ances
+4qua
+7tic
+6eous
+4rachnoid
+9oidal
+5boreal
+9scent
+5ctic
+9s
+6uate
+9ion
+9ions
+5ea
+7s
+5id
+5ration
+9ons
+6hation
+9ions
+5ticle
+9es
+4s
+5semble
+9led
+9les
+9lies
+9ling
+9ly
+6ociation
+9ations
+5tral
+4tmospheric
+5om
+7ic
+9s
+7s
+4udible
+7o
+7tion
+9ons
+5ral
+6icular
+4verage
+4xial
+6llary
+3basal
+6e
+7ment
+9nts
+7s
+6in
+8s
+6s
+7es
+4ed
+4ie
+6s
+5ng
+7s
+5tuminous
+4lock
+8s
+4ranch
+9es
+5eed
+8s
+4ureau
+9s
+9x
+4y
+3cabinet
+9ts
+5liber
+8re
+5ntor
+9s
+5psular
+5rdinal
+9als
+6rier
+9rs
+5ste
+8s
+5tegories
+9rise
+9rised
+9rises
+9rising
+9rize
+9rized
+9rizes
+9rizing
+9ry
+5udal
+6se
+8s
+5vities
+8y
+4eiling
+9gs
+5lestial
+9ials
+6l
+7ar
+9s
+7s
+7ular
+5nter
+9s
+7ral
+9lly
+5ption
+9ns
+4hanter
+9rs
+6pter
+9rs
+6rter
+9rs
+6ser
+9s
+5elate
+5ief
+8s
+5loride
+9des
+5ord
+8s
+4ircuit
+9ts
+5vilisation
+9sed
+9zation
+9zed
+4laim
+8s
+6n
+7s
+6ss
+8ed
+9s
+8ified
+9fies
+9fy
+9fying
+9ng
+6use
+9s
+6vian
+9ns
+8cular
+5erk
+8s
+5imactic
+8x
+9es
+6nical
+9ally
+5uster
+9red
+9ring
+9rs
+4ode
+7s
+5llection
+9tions
+8ge
+9es
+9iate
+6onies
+8y
+5mmission
+9sioned
+9sioner
+9sions
+8ttee
+9tees
+7unities
+9ity
+6pact
+9ts
+7onent
+9ents
+5nscious
+9ouses
+9ously
+7ul
+9s
+6tiguous
+8nent
+9ental
+9ents
+9uous
+7ract
+9cted
+9cting
+9ctings
+9ctor
+9ctors
+9cts
+9octave
+9ries
+9riety
+9ry
+5ol
+7ed
+7ing
+7s
+5rdate
+6iaceous
+6tex
+9es
+7ical
+9es
+5sta
+8e
+8l
+9s
+5unties
+8y
+4ranial
+5itical
+5ust
+8al
+8s
+4ult
+7s
+7ural
+9ally
+9e
+9ed
+9es
+9ing
+5rative
+9ves
+5taneous
+9ously
+6es
+6is
+8es
+3deacon
+9ate
+9ates
+9ries
+9ry
+9s
+9ship
+9ships
+6ler
+9s
+6n
+7eries
+9y
+7s
+5b
+6s
+6utante
+9ntes
+5canal
+6ision
+9ons
+5liria
+9ous
+9um
+9ums
+5partment
+9ments
+6ot
+8s
+6uties
+8y
+5rmal
+9ly
+5velopment
+9pments
+5w
+6ed
+6ing
+6s
+4iaconal
+9ate
+9ates
+6lect
+9ts
+5rector
+9ors
+5scipline
+9lines
+6trict
+9cted
+9cting
+9cts
+5vidable
+8e
+9d
+9r
+9rs
+9s
+8ing
+7sible
+9on
+9onal
+9ons
+9ve
+4olous
+5minant
+9nts
+5rsal
+4uable
+8y
+6l
+7s
+5ce
+7d
+7s
+6ing
+6t
+7ed
+7ing
+8on
+9ns
+7s
+5e
+6d
+7ly
+7ness
+9sses
+6ment
+9ts
+6r
+7s
+6s
+5ing
+5ple
+7icate
+5ral
+4warf
+8s
+3echo
+7es
+5onomic
+9ies
+9y
+4dar
+7s
+5it
+7ed
+7ing
+7or
+9ial
+9s
+9ship
+9ships
+7s
+4mployed
+9ment
+9ments
+4ntire
+6ries
+7y
+4pidermal
+5och
+8s
+4qual
+7torial
+4r
+5ate
+8s
+5ect
+6ous
+5ic
+6n
+7s
+6sation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ose
+6us
+5s
+3factorial
+9ials
+5milies
+8y
+4ertile
+9ities
+9ity
+5u
+6dation
+9ions
+9ory
+6ed
+6ing
+6s
+4ield
+8s
+5le
+7s
+5x
+6es
+4loor
+8s
+5uid
+4ossil
+9s
+4rame
+8s
+5eezing
+4usc
+7ous
+7s
+6k
+7s
+3genera
+9tion
+9tions
+8ic
+9cally
+6re
+8s
+6us
+8es
+4lacial
+9lly
+5obose
+7ular
+4oal
+7s
+5vernment
+9ments
+4rade
+8s
+6ph
+8s
+5oup
+8ed
+8ing
+8s
+4um
+6s
+3ha
+5rmonic
+9ics
+5s
+6tation
+9ions
+4ead
+7ing
+9gs
+7s
+5dral
+4uman
+8s
+6id
+3idea
+7s
+4maginal
+9es
+7o
+8es
+8s
+4ncise
+9d
+9s
+8ing
+9on
+9ons
+5dex
+8es
+6icate
+9ted
+9tes
+9ting
+9tion
+9tions
+9tive
+8es
+6ustries
+9ry
+5feud
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9atory
+9ed
+9ing
+9s
+5hibitory
+5sinuation
+9ations
+6pector
+9tors
+5tellection
+9igence
+9igitur
+7rval
+9als
+6rant
+7oduce
+9uced
+9uces
+9ucing
+5volution
+9tions
+4rrigate
+9ted
+9tes
+9ting
+9tion
+9tions
+4taneous
+5em
+7s
+5ise
+8d
+8s
+7ing
+6ze
+8d
+8s
+7ing
+5o
+3jacencies
+9y
+8t
+9ly
+4ect
+7ability
+9le
+7ed
+7ified
+9ies
+9y
+9ying
+8ng
+8on
+9ns
+8ve
+9ely
+9eness
+9es
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9istic
+9ists
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+7less
+7s
+8hip
+9ips
+4oin
+7der
+9rs
+7ed
+7ing
+7s
+4ugable
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+5nction
+9ons
+9ve
+9vely
+9ves
+3kingdom
+9ms
+3lanceolate
+6guage
+9ges
+5psarian
+9ianism
+9ians
+5te
+7d
+7s
+6ing
+7on
+9s
+4ease
+8d
+8s
+7ing
+5ssee
+9s
+7or
+9s
+5t
+6hal
+9ly
+6s
+6ter
+9s
+7ing
+9gs
+5vel
+8s
+4ibrarian
+9ians
+5cense
+9ed
+9es
+9ing
+5eutenancy
+9nant
+9nants
+5mable
+7te
+9d
+9s
+8ing
+9on
+9ons
+6e
+7d
+7ly
+7ness
+9sses
+7r
+8s
+7s
+8t
+6inal
+9lly
+9ls
+8g
+9s
+7se
+9d
+9s
+8ing
+7t
+8ies
+8s
+8y
+7ze
+9d
+9s
+8ing
+5ne
+7ar
+8tion
+9ions
+7s
+6gual
+5teracies
+9cy
+9ry
+9te
+9tes
+9ture
+9tures
+6toral
+9als
+4ot
+6s
+4unar
+8y
+7te
+5xate
+9d
+9s
+8ing
+9on
+9ons
+3man
+6ager
+9rs
+6dibular
+9ulars
+5rginal
+9ally
+6ine
+9d
+9r
+9rs
+9s
+8ing
+6ket
+9s
+5trices
+8x
+9es
+5xillaries
+9ary
+7mal
+4ediant
+9ts
+5n
+6ta
+8l
+7um
+6u
+7s
+5rge
+8d
+8ment
+9ents
+8nce
+9ces
+8s
+7ibility
+9le
+9les
+8ng
+6se
+8d
+8s
+7ibility
+9le
+9les
+8ng
+8on
+9ns
+5tacentric
+9ntrics
+4icrogram
+8n
+9s
+8scopic
+5llimeter
+5niature
+9ures
+9urise
+9urised
+9urises
+9urize
+9urized
+9urizes
+7mal
+7ster
+9ers
+5ss
+7ible
+8on
+9ns
+8ve
+9ely
+9eness
+7ly
+7ness
+9sses
+5t
+6s
+6table
+8l
+9s
+7ed
+8r
+9s
+7ing
+9gs
+4olecule
+9les
+5ntane
+9ely
+4ucosa
+9e
+9l
+9s
+7us
+5ltiple
+9les
+5nition
+9ons
+3nasal
+6cent
+5tional
+6ural
+4et
+6s
+6work
+9ked
+9king
+9ks
+5ural
+4iche
+8s
+5veal
+8n
+4odal
+5rmal
+9ities
+9ity
+9ly
+9s
+4uclear
+8i
+8us
+9ses
+3occipital
+5ean
+8ic
+5tave
+9s
+6uple
+5ular
+4ffice
+9r
+9rs
+9s
+4percula
+9lar
+9lum
+5tic
+7mal
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8um
+4ral
+5bicular
+7tal
+5der
+8s
+6inal
+9ries
+9ry
+9te
+9ted
+9tely
+9teness
+9tes
+9ting
+9tion
+9tions
+9tive
+9tor
+9tors
+5ganisation
+9zation
+5n
+6ation
+9ons
+9ve
+6ed
+7r
+8s
+6ing
+6s
+4scine
+9s
+4val
+6te
+4xide
+8s
+3panation
+9ons
+6el
+8s
+5r
+6agraph
+9aphs
+7llel
+6t
+7s
+4ena
+7ed
+7ing
+7s
+5riod
+9s
+4hase
+8s
+5renic
+5yla
+8r
+7um
+4lot
+7s
+4oena
+8ed
+8ing
+8s
+5lar
+5pulation
+9tions
+5tencies
+9y
+8t
+4refect
+9ts
+9ture
+9tures
+5imate
+9es
+7e
+8s
+6ncipal
+9pals
+6or
+8ess
+9sses
+8s
+5oblem
+9ms
+6cess
+9ses
+6duct
+9ts
+6fessional
+6gram
+9ms
+6ject
+9ts
+6letariat
+9ariats
+4ubic
+3race
+7s
+5tional
+4eference
+9nces
+5gion
+9al
+9s
+5nt
+7s
+5ption
+9ns
+8tious
+9iously
+8ve
+4ing
+7s
+4ogate
+9d
+9s
+8ing
+9on
+9ons
+5utine
+9es
+4ule
+7s
+3s
+4acral
+5le
+7s
+5mple
+9d
+9s
+8ing
+5tellite
+9ites
+6urated
+9tion
+9tions
+4cale
+8s
+6pular
+9ars
+5hema
+9ta
+5ience
+9es
+5ribable
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+7pt
+9ion
+9ions
+9ive
+9s
+4ea
+5cive
+6retaries
+9ary
+6t
+7ion
+9ns
+7or
+9s
+7s
+5gment
+9ts
+5izure
+9es
+5llia
+8um
+5nse
+8s
+7ible
+6tence
+9ces
+5quence
+9ces
+9t
+9tial
+9tly
+9tness
+9ts
+5re
+7s
+6ies
+6ve
+8d
+8s
+7ience
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+9nts
+8ng
+5ssile
+5t
+6s
+4haft
+8s
+5ell
+8s
+5rub
+8by
+8s
+4ide
+7d
+7nce
+9es
+9ies
+9y
+7r
+8s
+7s
+6iaries
+9ily
+9iness
+9ities
+9ity
+9y
+7es
+7ng
+7sable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6y
+5st
+7ed
+8nce
+9ces
+9t
+9tial
+8r
+9s
+7ing
+7s
+5te
+7s
+5zar
+8s
+4kill
+8s
+4ocial
+9ly
+7eties
+9y
+5il
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5lar
+5ng
+7s
+6ic
+8ally
+4pace
+8s
+5ecialise
+9lised
+9lises
+9lising
+9list
+9lists
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lties
+9lty
+8es
+8fic
+9ically
+5inous
+5ontaneous
+4tage
+8s
+6nce
+9less
+9s
+7dard
+7tial
+9alise
+9alised
+9alises
+9alism
+9alisms
+9alist
+9alists
+9ality
+9alize
+9alized
+9alizes
+9ally
+9alness
+9als
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+9ator
+9ators
+9val
+9vally
+9ve
+9vely
+9veness
+9ves
+9vise
+9vised
+9vises
+9vising
+9vities
+9vity
+9vize
+9vized
+9vizes
+9vizing
+6te
+8s
+7ion
+9ns
+5ellar
+6rnal
+5ituent
+9nts
+8table
+9e
+9ed
+9es
+9ing
+9ion
+9ional
+9ionary
+9ions
+9ive
+9ively
+9ivity
+5ract
+9ed
+9ing
+9ion
+9ions
+9or
+9ors
+9s
+7ta
+9l
+8e
+9s
+8ive
+8osphere
+8um
+9ms
+6uct
+9ed
+9ing
+9ion
+9ions
+9s
+9ural
+9ure
+9ures
+5ylar
+7e
+8s
+4ultive
+7orily
+9y
+7us
+9es
+5mable
+6e
+7d
+7s
+6ing
+6ption
+9ons
+9ve
+5rface
+9es
+4ystem
+9s
+3tack
+7s
+8man
+9en
+5lar
+5ngent
+9ts
+5sk
+7s
+5xa
+6on
+8s
+4een
+7s
+5mperate
+5nancies
+9y
+8t
+9s
+6d
+7ed
+7ing
+7s
+6se
+8s
+6ure
+9s
+5rfuge
+9es
+6minal
+6natural
+6rain
+9ns
+8ne
+9ean
+9eanly
+9eans
+9eous
+9eously
+9es
+7ene
+9es
+8strial
+9trials
+5st
+7s
+5xt
+7s
+7ual
+4heme
+8s
+6rapeutic
+5reshold
+4idal
+5l
+6e
+7ly
+7ness
+9sses
+7r
+7st
+6in
+8s
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8in
+9ng
+9ns
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ties
+7y
+5tle
+8d
+8s
+7ing
+6ular
+4le
+6ness
+9ses
+6r
+6st
+6ties
+7y
+5y
+4one
+7s
+6ic
+8s
+5pia
+8n
+8s
+7c
+8s
+5rrid
+5tal
+8ed
+8ing
+8led
+9ing
+9y
+8s
+4ract
+8ed
+9r
+9rs
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+8s
+6hend
+9ds
+5easurer
+9rers
+9ries
+9ry
+6nd
+8s
+5iangular
+6be
+8s
+6plicate
+6st
+5opic
+9al
+9ally
+9s
+5ude
+8d
+8s
+7ing
+4unic
+8s
+4ype
+7s
+6ical
+3ucula
+8s
+4late
+4mbrella
+9lar
+9las
+4ngulate
+9tes
+5it
+7s
+4rb
+6an
+8isation
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9te
+9tes
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8s
+6ed
+6ia
+8s
+7carian
+6s
+5sine
+3varieties
+9y
+5ssal
+9s
+4ene
+7d
+7s
+6ing
+6tion
+9nary
+9ns
+5rsal
+9s
+7e
+8d
+8s
+7ing
+8on
+9naries
+9nary
+9ns
+8ve
+9ely
+9eness
+9es
+7t
+6t
+7ebral
+8d
+8r
+9s
+7ical
+8ng
+7s
+4icar
+8s
+5ral
+6us
+8es
+5sible
+6ual
+5treous
+4ocal
+8isation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+3warden
+9s
+5y
+6ed
+6ing
+6s
+4oofer
+9s
+5rld
+8s
+4riter
+9s
+3zero
+4onal
+6e
+7s
+2ccade
+7s
+5h
+6s
+4edanea
+9ous
+9um
+9ums
+6ent
+5ed
+7able
+7ed
+8r
+9s
+7ing
+9gly
+7s
+5ntor
+9s
+9ship
+9ships
+5s
+6s
+7antly
+7es
+7ful
+9lly
+9lness
+7ion
+9nal
+9nally
+9nist
+9nists
+9nless
+9ns
+8ve
+9ely
+9eness
+7less
+9ssly
+9ssness
+7or
+9al
+9s
+9ship
+9ships
+4i
+5nate
+9s
+6ct
+8er
+9st
+8ly
+8ness
+9esses
+8oria
+9ries
+9rium
+9ry
+6ic
+7te
+9s
+6yl
+8choline
+8s
+5se
+4or
+6able
+6ed
+7r
+8s
+6ies
+7ng
+6less
+6s
+6y
+5s
+6e
+5t
+6ash
+9es
+6h
+5ur
+7able
+7ed
+8r
+9s
+7ing
+7less
+7s
+6s
+4uba
+7e
+7s
+6i
+7ne
+6ous
+6us
+8es
+5lence
+9es
+9ies
+9y
+8t
+9ly
+9s
+5mb
+7ed
+8r
+9s
+7ing
+7s
+5rsal
+9e
+9es
+9s
+5s
+6s
+7ation
+9ions
+7ed
+8s
+7ing
+8on
+9ns
+8ve
+3h
+4like
+4ness
+8es
+4wise
+3ken
+6er
+8s
+6s
+5r
+6ed
+6fish
+9hes
+6ing
+6s
+5t
+6s
+4fish
+8es
+4hole
+8s
+4ier
+6st
+5ng
+7s
+4le
+6d
+6r
+7s
+6s
+7s
+5ing
+8s
+3ralfate
+9es
+6ose
+9s
+5se
+7s
+4e
+5s
+4ier
+7s
+4ose
+7s
+3tion
+7al
+7ed
+7ing
+7s
+4orial
+8n
+9s
+3uruju
+8s
+2d
+3amen
+5ina
+8l
+4ria
+6es
+6um
+5y
+4te
+6d
+6s
+5ing
+6on
+8s
+5oria
+8es
+8um
+9ms
+7y
+3d
+4en
+6ly
+6ness
+9ses
+6s
+6ties
+7y
+5r
+6s
+4s
+3or
+5al
+5iferous
+7ic
+9s
+6parous
+5ous
+5s
+3s
+4ed
+5r
+6s
+5s
+4ier
+6st
+5ng
+4less
+4y
+2e
+3abilities
+9y
+5le
+3d
+4e
+5d
+5s
+5tte
+8s
+4ing
+3nt
+3r
+4s
+3s
+3t
+4ier
+6st
+4s
+4tier
+7st
+5y
+4y
+2ffari
+7s
+4ect
+5r
+6able
+9eness
+9y
+7nce
+9es
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+5te
+7s
+4ice
+7d
+7r
+8s
+7s
+6ience
+9ces
+9cies
+9cy
+9t
+9tly
+9ts
+7ng
+9ness
+9nesses
+5gance
+9es
+5sance
+9es
+5x
+6al
+7tion
+9ons
+6ed
+7s
+6ing
+7on
+9s
+4late
+8d
+8s
+7ing
+8on
+9ns
+4ocate
+9d
+9s
+8ing
+9ngly
+9ngs
+9on
+9ons
+9ve
+4ragan
+9s
+9ship
+9ships
+7e
+8s
+8tte
+9tes
+9tism
+9tisms
+7ism
+9ms
+9t
+9ts
+5utescent
+7icose
+4umigate
+9ted
+9tes
+9ting
+9tion
+9tions
+5se
+7d
+7s
+6ing
+7on
+9s
+7ve
+2g
+3an
+5s
+4r
+5allie
+9es
+8y
+5berries
+9y
+6ush
+9es
+5cane
+9s
+6oat
+9ed
+9ing
+9s
+5ed
+6r
+7s
+5house
+9es
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5less
+6ike
+6oaf
+8ves
+5plum
+9s
+5s
+5y
+3ged
+5st
+7ed
+8r
+9s
+7ibility
+9le
+9leness
+9ly
+8ng
+8on
+9nise
+9nised
+9nises
+9nising
+9nism
+9nisms
+9nist
+9nists
+9nize
+9nized
+9nizes
+9nizing
+9ns
+8ve
+9ely
+9eness
+7s
+4ing
+7s
+3h
+4ed
+4ing
+4s
+3o
+4s
+3s
+2hur
+5s
+2i
+3cidal
+8ly
+6e
+7d
+7s
+6ing
+6ologies
+9gist
+9gists
+9gy
+3d
+4ian
+7s
+4s
+3lline
+3ng
+5s
+4t
+5s
+3plap
+7s
+3t
+4abilities
+9ty
+6le
+8ness
+9esses
+7y
+4case
+8s
+4e
+5d
+5r
+6s
+5s
+4ing
+7s
+4like
+4or
+6ed
+6ing
+6s
+4ress
+8es
+4s
+3vante
+8s
+4ez
+2jee
+5s
+2k
+3h
+4s
+3iyaki
+8s
+3kah
+6s
+4os
+5t
+6h
+3s
+3uk
+5s
+2lcal
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+5te
+7d
+6ion
+9s
+4i
+4us
+3dan
+6s
+3fa
+5cetamide
+9mides
+5diazine
+9ines
+7midine
+9dines
+6oxine
+9nes
+5methazine
+9azines
+5nilamide
+9mides
+5s
+5tase
+9s
+6e
+7d
+7s
+6hiazole
+9zoles
+6ic
+7ng
+7on
+9s
+4hydryl
+9ls
+4id
+6e
+7s
+6s
+5npyrazone
+9azones
+6yl
+8s
+5te
+7s
+6ic
+4o
+5namide
+9des
+7te
+9d
+9s
+8ing
+9on
+9ons
+6e
+7s
+6ic
+7um
+9s
+6yl
+8s
+8urea
+9reas
+5xide
+9s
+4ur
+6ate
+9d
+9s
+8ing
+6ed
+7t
+8ed
+8ing
+8s
+8ted
+9ing
+6ic
+7ng
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6ous
+9ly
+9ness
+9nesses
+6s
+6y
+7l
+8s
+3k
+4ed
+5r
+6s
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+4s
+4y
+3lage
+7s
+4en
+6er
+7st
+6ly
+6ness
+9ses
+6s
+4iable
+5ed
+6s
+4y
+5ing
+3ph
+5a
+6cetamide
+9amides
+6diazine
+9zines
+6nilamide
+9amides
+6s
+6tase
+9es
+7e
+8d
+8s
+7hiazole
+9azoles
+7ic
+8ng
+8on
+9ns
+5hydryl
+9yls
+5id
+7e
+8s
+7s
+6npyrazone
+7yl
+9s
+6te
+8s
+7ic
+5onamide
+9ides
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+7e
+8s
+7ic
+8um
+9ms
+7methane
+9thanes
+7yl
+9s
+9urea
+9ureas
+5s
+5ur
+7ate
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7ed
+8ous
+9usly
+9usness
+8t
+9ed
+9ing
+9s
+9ted
+9ting
+7ic
+8ng
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ous
+9sly
+9sness
+7s
+7wort
+9rts
+7y
+8l
+9s
+3tan
+6a
+7s
+7te
+9s
+6ess
+9es
+6ic
+6s
+7hip
+9ps
+4rier
+7st
+6ly
+6ness
+9ses
+5y
+3u
+4s
+2m
+3ac
+5h
+6s
+5s
+4tra
+7s
+3less
+3ma
+5bilities
+9ty
+6le
+5e
+5nd
+7s
+5r
+6ies
+7ly
+7ness
+9sses
+7sable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8t
+9s
+7zable
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6y
+5s
+5t
+6e
+7d
+7s
+6ing
+7on
+9al
+9s
+7ve
+6s
+4ed
+5r
+6ed
+6house
+9ses
+6ier
+8st
+7ness
+9sses
+8g
+9s
+6less
+7ike
+7ong
+7y
+6s
+7ault
+9lted
+9lting
+9lts
+7et
+9s
+9ted
+9ting
+6tide
+9es
+8me
+9es
+6weight
+7ood
+9ds
+6y
+4ing
+7s
+5st
+7s
+5t
+6al
+6ed
+7er
+9s
+6ing
+6less
+6ries
+7y
+6s
+4on
+6able
+6ed
+7r
+8s
+6ing
+6s
+7ed
+8s
+7ing
+3o
+4ist
+7s
+4s
+4tori
+8s
+3p
+4h
+5ish
+8ness
+9esses
+5s
+4it
+6an
+8s
+6s
+4s
+5imus
+9es
+4ter
+7s
+5uary
+6osities
+9ty
+7us
+9ly
+9ness
+9nesses
+4weed
+8s
+3s
+3y
+2n
+3back
+5ke
+7d
+7s
+6ing
+5th
+7e
+8d
+8r
+9s
+8s
+7ing
+9gs
+7s
+4eam
+7ed
+7s
+7y
+6t
+7en
+5d
+6s
+5lt
+7s
+5rries
+7y
+4ird
+7s
+4lind
+8s
+5ock
+8s
+4onnet
+9ed
+9s
+5w
+6s
+4right
+4urn
+7ed
+7ing
+7s
+7t
+6st
+8s
+3choke
+8s
+3dae
+6s
+5ri
+7s
+4eck
+7s
+5r
+6able
+7nce
+9es
+6ed
+7r
+8s
+6ing
+9s
+6ment
+9ts
+6s
+5w
+6s
+4ial
+7s
+4og
+6s
+5wn
+7ed
+8r
+9s
+7ing
+7s
+4ra
+6s
+5enched
+6ss
+8es
+5i
+6es
+6ly
+6s
+5ops
+5y
+3fast
+4ish
+7es
+4lower
+9s
+3g
+4ar
+6s
+5zer
+8s
+6ing
+9s
+4lass
+8es
+5ow
+7s
+4rebe
+8s
+3hat
+6s
+3i
+4s
+3k
+4en
+5t
+6s
+4ie
+6s
+4s
+3lamp
+7s
+5nd
+7s
+4ess
+7ly
+7ness
+9sses
+4ight
+8s
+5ke
+5t
+4ounger
+9rs
+3n
+4a
+5h
+6s
+5s
+4ed
+4ier
+6s
+7t
+5ly
+5ness
+9es
+6g
+4s
+4y
+3porch
+8es
+4roof
+3ray
+6s
+4ise
+7s
+6ing
+9s
+4oof
+7s
+6m
+7s
+3s
+4cald
+8s
+5reen
+9ing
+9s
+4eeker
+9s
+5t
+6s
+6ting
+9gs
+4hade
+8s
+5ine
+8s
+7y
+4pot
+7s
+7ted
+4tar
+7s
+5one
+8s
+5roke
+9s
+6uck
+4uit
+7s
+3tan
+6ned
+7ing
+6s
+4rap
+7s
+3up
+5s
+3ward
+7s
+4ise
+4orshipper
+9ppers
+2ovetaurilia
+2p
+3awn
+6s
+3e
+4r
+5abilities
+9ity
+7le
+9ness
+9nesses
+8y
+7ound
+9nded
+9nding
+9nds
+7sorbent
+9rbents
+7undance
+9dances
+9dant
+9dantly
+6chiever
+9evers
+7tive
+9vities
+9vity
+7ute
+6dd
+8ed
+8ing
+9tion
+9tional
+9tions
+8s
+6gencies
+9cy
+9t
+9ts
+6lloy
+9ys
+7tar
+9rs
+8ern
+9rns
+6mbitious
+6nnuable
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+6te
+8d
+8s
+7hlete
+9etes
+7ing
+8on
+9ns
+7om
+9s
+5b
+6ad
+7nk
+9s
+7zaar
+9ars
+9r
+9rs
+6er
+7st
+6ike
+9s
+7ties
+8y
+6lock
+9ks
+7y
+6ness
+9ses
+6oard
+9ds
+7ld
+7mb
+9er
+9ers
+9s
+6rain
+9ns
+8t
+9s
+7ight
+6ug
+8s
+7reaucrat
+5cabinet
+9nets
+7lender
+9ndered
+9nders
+7r
+8go
+9oes
+9os
+9oship
+9oships
+8rier
+9iers
+8s
+7utious
+6ede
+9d
+9s
+8ing
+7lestial
+7nter
+9ers
+6harge
+9ged
+9ger
+9gers
+9ges
+9ging
+7erie
+9ies
+7ic
+7urch
+9ches
+6iliaries
+9ary
+9ous
+9ously
+7ties
+8y
+7vilised
+9lized
+6lass
+9ses
+7ean
+7ub
+9s
+8ster
+9ters
+6oil
+9ed
+9ing
+9s
+7ld
+8lider
+9iders
+8ossal
+8umnar
+7mputer
+9uters
+9uting
+9utings
+7nduct
+9ucted
+9ucting
+9uction
+9uctive
+9uctor
+9uctors
+9ucts
+8fidence
+9ident
+8tinent
+9inents
+8venient
+7ol
+9ed
+9ing
+9s
+7p
+8s
+7w
+8s
+6riminal
+9inals
+8tical
+6urrent
+9ents
+7te
+5dainty
+6elegate
+9gates
+8uxe
+7nse
+6iplomat
+9omats
+6ominant
+9nants
+5ed
+6ffective
+8iciency
+9cient
+6go
+8ist
+9sts
+8s
+6lastic
+7evate
+9ated
+9ates
+9ating
+9ation
+9ations
+7ite
+9es
+6minence
+9ences
+9ent
+9ently
+6ncipher
+9phered
+9phers
+6rogant
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+9ator
+9ators
+9atory
+6ssential
+6tte
+9s
+6vident
+6xalt
+9tation
+9ted
+9ting
+9ts
+7cellence
+9llent
+7pensive
+8ress
+9esses
+5families
+9ly
+7n
+8s
+7rm
+9s
+7st
+7tted
+6ecta
+9as
+7male
+9les
+7tate
+9ted
+9tes
+9ting
+9tion
+9tions
+6icial
+9alise
+9alised
+9alises
+9ality
+9alize
+9alized
+9alizes
+9ally
+9alness
+9als
+9es
+7ne
+9ness
+9nesses
+7rm
+9s
+7t
+7x
+8es
+6lack
+9ks
+7uid
+9dities
+9dity
+9ds
+9ties
+9ty
+8ous
+9usly
+9usness
+8x
+9es
+6oetation
+9ations
+7od
+9s
+6rontal
+9tals
+6und
+9s
+7se
+9d
+9s
+8ing
+9on
+9ons
+5gene
+9s
+6iant
+9ts
+6lacial
+7ue
+9d
+9s
+8ing
+6ood
+7vernment
+6raphics
+8ss
+9ses
+8vities
+9ity
+7oup
+9ps
+8wth
+9ths
+6un
+8s
+5harden
+9ened
+9ening
+9ens
+6eat
+9ed
+9er
+9ers
+9ing
+9s
+8vies
+9y
+7lical
+9ces
+9x
+9xes
+7ro
+9es
+9ine
+9ines
+7t
+8erodyne
+8s
+6igh
+9way
+9ways
+7t
+8s
+7ve
+9s
+6ot
+6uman
+9nise
+9nised
+9nises
+9nising
+9nities
+9nity
+9nize
+9nized
+9nizes
+9nizing
+9nly
+9nness
+8eral
+9rals
+6ype
+9d
+9s
+8ing
+5important
+9sable
+9se
+9sed
+9ses
+9sing
+9sition
+6ncumbence
+9mbency
+9mbent
+7dividual
+8uce
+9ced
+9cement
+9ces
+9cing
+9ction
+9ctions
+7fect
+9cted
+9cting
+9ction
+9ctions
+9cts
+7g
+7sulated
+7tend
+9nded
+9ndence
+9ndency
+9ndent
+9ndents
+9nding
+9nds
+9nsity
+6or
+8ess
+9sses
+8ities
+9ty
+8ly
+8s
+9hip
+9hips
+5jacent
+6et
+8s
+6ock
+9s
+6umbo
+9os
+5kingdom
+9doms
+5lain
+7rge
+7tive
+9vely
+9veness
+9ves
+7wyer
+9ers
+7y
+6ie
+8s
+7ght
+7ner
+9rs
+6oad
+9s
+7bbyist
+9yists
+7ng
+7o
+8s
+7yalist
+9lists
+6uminal
+7nar
+9ry
+7xuries
+9rious
+9ry
+6ying
+5macho
+9os
+7jorities
+9rity
+7le
+9s
+7n
+7rket
+9ets
+8t
+9s
+7sculine
+8sive
+7x
+8es
+6embrane
+9ranes
+7n
+6icro
+9os
+7litant
+9tants
+7nd
+9s
+8i
+9s
+9ster
+9sters
+6odel
+9ls
+9rn
+7m
+8s
+7to
+9s
+6undane
+5nacula
+9lar
+9lum
+7l
+8ly
+7nnies
+9y
+7tant
+9nts
+9tion
+9tions
+8e
+9s
+8ion
+9onal
+9onally
+9ons
+8ural
+9ralise
+9ralism
+9ralist
+9ralize
+9rally
+9rals
+9re
+9res
+6ormal
+9ality
+9ally
+7va
+9e
+9s
+6umeraries
+9rary
+7rse
+9es
+7trient
+9ients
+9ition
+9itions
+5octave
+9ves
+6rder
+9rs
+8inal
+9nary
+9nate
+9nated
+9nates
+9nating
+9nation
+7ganic
+9nicism
+9nicist
+9nism
+9nisms
+6vulate
+9ated
+9ates
+9ating
+9ation
+9ations
+6xide
+9es
+5parasitism
+8ticle
+9icles
+7triot
+9iotic
+9iotism
+9iots
+6erson
+9onal
+9ons
+6henomena
+9omenon
+7osphate
+9phates
+7yla
+9um
+8sical
+6imp
+9s
+6lane
+9es
+8stic
+9ticity
+9tics
+8yer
+9ers
+7us
+9es
+6olite
+8ymer
+9mers
+7rt
+9s
+7sable
+8e
+9d
+9s
+8ing
+9tion
+9tions
+7wer
+9red
+9rful
+9rs
+6raise
+9sed
+9ses
+9sing
+7emium
+9iums
+7o
+8fit
+9its
+8s
+5qualities
+9ity
+5race
+9s
+6eal
+9ism
+9isms
+9ist
+9ists
+7fine
+9ned
+9nes
+9ning
+7gional
+9onals
+6ich
+6oad
+9s
+7mantic
+5s
+6afe
+9ties
+9ty
+7le
+9s
+9sman
+9smen
+8t
+9s
+7turate
+9rated
+9rates
+9rating
+9ration
+7ur
+9s
+7ver
+9rs
+6calar
+9e
+9es
+7hool
+9ols
+7out
+9ts
+7reen
+9ens
+8ibe
+9bed
+9bes
+9bing
+9pt
+9ption
+9ptions
+9pts
+6ecrecies
+9ecy
+9et
+9ets
+7dable
+8e
+9as
+9ases
+9d
+9nce
+9nces
+9r
+9re
+9res
+9rs
+9s
+8ing
+8ure
+9res
+7ll
+9er
+9ers
+9ing
+9s
+7nsible
+9ibly
+9itive
+9ory
+9ual
+7ssion
+9ions
+7x
+8es
+8uality
+6harp
+7ow
+9s
+6inger
+9ers
+7ze
+9d
+9s
+8ing
+6leuth
+9ths
+7ick
+6mart
+7ooth
+6oft
+7ld
+7nic
+9cally
+9cs
+7und
+9ds
+6pecial
+9ialist
+9ials
+9ies
+9tacle
+9tacles
+8ed
+9ds
+7ies
+7y
+6tar
+9dom
+9doms
+9s
+8te
+9es
+9ion
+9ions
+7imulate
+9ulated
+9ulates
+8tion
+9ions
+9ious
+9iously
+7ock
+9ks
+8re
+9es
+7rata
+9tum
+9tums
+8ength
+9ngths
+8ike
+9kes
+9ng
+9ngs
+8ong
+8uct
+9cted
+9cting
+9ction
+9ctions
+9ctive
+9cts
+9ctural
+9cture
+9ctures
+7ud
+9s
+6ubtile
+9le
+9leties
+9lety
+7rgeon
+9eons
+6weet
+6ymmetric
+9etries
+9etry
+7stem
+9ems
+5tanker
+9ers
+7x
+8es
+6eacher
+9hers
+7rranean
+9ific
+6hick
+8n
+7riller
+9llers
+6ight
+7tle
+9es
+6onic
+9cs
+6ram
+9s
+7uck
+9ks
+6wist
+9ts
+5vene
+9d
+9s
+8ience
+9ences
+9ent
+9ng
+8tion
+9ions
+6irile
+8tuosi
+9uoso
+9uosos
+8ulent
+7sal
+9ls
+8e
+9d
+9e
+9es
+9s
+8ing
+9on
+9ons
+8or
+9rs
+9rship
+9rships
+9ry
+6olute
+5waif
+9s
+7ve
+9s
+6eapon
+9ons
+7ed
+9s
+6ide
+9s
+7fe
+7ves
+6oman
+8en
+4s
+3inate
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+5e
+6ly
+6ness
+9ses
+6s
+3lex
+6es
+3pawn
+7s
+4eago
+8es
+5d
+6anea
+9um
+5r
+6ed
+6ing
+6less
+6s
+6time
+9es
+4ing
+4lant
+8ation
+9tions
+8ed
+9r
+9rs
+8ing
+8s
+5e
+6d
+6jack
+9ks
+6ly
+6ment
+9tal
+9tally
+9tals
+9taries
+9tarily
+9tary
+9tation
+9ted
+9ter
+9ters
+9ting
+9ts
+6ness
+9ses
+6r
+6s
+7t
+6tion
+9ns
+8ve
+9es
+7orily
+9y
+5iable
+7l
+8s
+7nce
+9es
+8t
+9ly
+9s
+6cant
+9ts
+8t
+9e
+9ed
+9es
+9ing
+9ingly
+9ion
+9ions
+9ory
+9s
+8vit
+9its
+6ed
+7r
+8s
+7s
+6ng
+5y
+6ing
+6ment
+9ts
+4ort
+7ability
+9le
+9leness
+9ly
+8nce
+9ces
+7ed
+8r
+9s
+7ing
+9gs
+8ve
+9ely
+9eness
+7less
+7ment
+9nts
+7ress
+9sses
+7s
+7ure
+9es
+5sable
+9y
+7l
+8s
+6e
+7d
+8ly
+7r
+8s
+7s
+6ing
+9s
+7tion
+9onal
+9onally
+9onary
+9onless
+9ons
+9ous
+9ously
+9tious
+9ve
+9vely
+9ves
+8ories
+9ry
+4ress
+8ant
+9nts
+8ed
+9dly
+9r
+9rs
+9s
+8ibility
+9ble
+9ng
+9on
+9ons
+9ve
+9veness
+8or
+9rs
+4urate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9ves
+3ra
+5chiasmic
+6iliary
+6ostal
+6rustal
+5glottal
+5lapsarian
+9arians
+6iminal
+9nally
+6unar
+5maxillary
+6olecular
+9cule
+9cules
+6undane
+5national
+9onally
+5optic
+6rbital
+5pubic
+5rational
+6enal
+9ls
+5segmental
+7nsible
+5temporal
+5vital
+9lly
+4ema
+7cies
+9sm
+9sms
+9st
+9sts
+8y
+7tism
+9sms
+9st
+9sts
+6e
+7ly
+7ness
+9sses
+7r
+7s
+8t
+6ities
+8y
+6o
+7s
+6um
+8s
+3s
+2q
+3s
+2r
+3a
+4ddition
+9ons
+4h
+5s
+4l
+4min
+7s
+4nce
+7s
+4s
+4t
+5s
+3bahar
+8s
+5se
+7d
+7ment
+9nts
+7s
+5te
+7d
+7s
+6ing
+4ed
+6ded
+7ing
+6s
+5t
+3cease
+8d
+8s
+7ing
+4harge
+9d
+9ment
+9ments
+9r
+9rs
+9s
+8ing
+4ingle
+9d
+9s
+8ing
+4oat
+7s
+4uli
+6ose
+6us
+8es
+3d
+4ities
+6y
+4s
+3e
+4d
+4fire
+5ooted
+9dly
+9dness
+4ly
+4ness
+8es
+4r
+4s
+5t
+4tied
+7s
+5y
+6ing
+6ship
+9ps
+3f
+4able
+5ce
+7d
+7less
+7man
+8en
+7r
+8s
+7s
+6ing
+9s
+6tant
+9ts
+4bird
+8s
+5oard
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+7t
+8s
+4caster
+9rs
+8ing
+9ngs
+4ed
+5it
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5r
+6s
+4fish
+8es
+4icial
+5e
+6r
+6s
+7t
+5ng
+7s
+4like
+4man
+5en
+4perch
+9es
+4rider
+9s
+4s
+5ide
+4y
+3ge
+5d
+5ful
+5less
+5nt
+5on
+7cies
+8y
+7fish
+9shes
+7s
+8hip
+9ips
+5r
+6ies
+6s
+6y
+5s
+4ical
+8ly
+5er
+6st
+5ng
+7s
+4y
+3icate
+8s
+4mi
+6s
+4ng
+3jection
+9ns
+8ve
+3lier
+6st
+5ly
+5ness
+9es
+4oin
+7s
+4y
+3master
+9s
+4isable
+7l
+8s
+6e
+7d
+7r
+8s
+7s
+6ing
+9s
+6tress
+9sses
+4ount
+8able
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+4ullet
+9s
+3name
+7d
+7r
+8s
+7s
+6ing
+4ominal
+3pass
+7able
+7ed
+8r
+9s
+8s
+7ing
+9gly
+9gness
+4lice
+8d
+8s
+5us
+7age
+9es
+7ed
+8s
+7ing
+7sed
+9s
+8ing
+4rint
+8ed
+8ing
+8s
+6sal
+9s
+7e
+8d
+9ly
+8r
+9s
+8s
+7ing
+9gly
+9gness
+9gs
+6ze
+8d
+8s
+7ing
+3quedies
+7ries
+8y
+7y
+3ra
+5s
+4eal
+7ism
+9ms
+9t
+9tic
+9ts
+7ly
+7s
+5but
+8s
+8tal
+9als
+9ed
+9er
+9ers
+9ing
+5ined
+5join
+9der
+9ders
+9ed
+9ing
+9s
+5nder
+9ed
+9ee
+9ees
+9er
+9ers
+9ing
+9or
+9ors
+9s
+7ries
+8y
+5ptitious
+9iously
+5y
+6s
+4ogacies
+8y
+7te
+9d
+9s
+9ship
+9ships
+8ing
+9on
+9ons
+8um
+9ms
+5und
+8ed
+8ing
+9ngs
+8s
+5yal
+8s
+3tarbrand
+9nds
+5x
+6ed
+7s
+6ing
+4itle
+8s
+4out
+7s
+4urbrand
+9nds
+3ucucu
+8s
+3veil
+7ed
+7ing
+7lance
+9nces
+9nt
+9nts
+8e
+9d
+9s
+8ing
+7s
+5y
+6able
+7l
+8s
+7nce
+9es
+6ed
+6ing
+9s
+6or
+8s
+9hip
+9hips
+6s
+4iew
+7ed
+7ing
+7s
+5vabilities
+9lity
+8le
+7l
+8ism
+9sms
+9st
+9sts
+8s
+7nce
+9es
+6e
+7d
+7r
+8s
+7s
+6ing
+6or
+8s
+9hip
+9hips
+2s
+3ceptance
+9ces
+7ibility
+9le
+9leness
+9ly
+8ve
+9eness
+9ities
+9ity
+7or
+9s
+4ipient
+9ts
+5tate
+9d
+9s
+8ing
+9on
+9ons
+3es
+3hi
+5s
+3lik
+6s
+3pect
+7able
+7ed
+9ly
+9ness
+9nesses
+8r
+9s
+7ful
+7ing
+7less
+7s
+5nce
+6d
+7ed
+8r
+9ed
+9s
+7ibility
+9le
+8ng
+7s
+6s
+7e
+8ful
+9ully
+9ulness
+8less
+8r
+9s
+8s
+7ibility
+9le
+8on
+9ns
+8ve
+9ely
+9eness
+7oid
+9ds
+8r
+9ia
+9ial
+9ies
+9ium
+9s
+9y
+5rcollate
+9lated
+9lates
+9lating
+4icion
+9al
+9ed
+9ing
+9less
+9s
+8us
+9sly
+9sness
+5ration
+9ons
+6e
+7d
+7s
+6ing
+7ous
+3s
+4ed
+5s
+4ing
+3tain
+7ability
+9le
+7ed
+9ly
+8r
+9s
+7ing
+9gly
+9gs
+7ment
+9nts
+7s
+4enance
+9es
+6tacula
+9ular
+9ulum
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9or
+9ors
+7ion
+9ns
+8ve
+4inent
+3u
+4rrant
+7te
+9d
+9s
+8ing
+9on
+9ons
+6ous
+6us
+8es
+4s
+2tile
+3ler
+6ies
+6s
+7hip
+9ps
+6y
+3or
+5ial
+7n
+5s
+3ra
+5s
+3ta
+5s
+4ee
+6ism
+9s
+6s
+4le
+6d
+6s
+6tie
+9s
+5ing
+5y
+3ural
+7ly
+6tion
+9ns
+5e
+6d
+6s
+5ing
+2zerain
+8s
+8ties
+9y
+1varabhakti
+9tis
+5j
+6es
+3stika
+8s
+2edberg
+8s
+3lte
+6ly
+6ness
+9ses
+6r
+6st
+1wab
+4bed
+6r
+7s
+5ie
+7s
+6ng
+5y
+4s
+3ck
+5ed
+3d
+4die
+7s
+5le
+7d
+7r
+8s
+7s
+6ing
+5y
+4s
+3g
+4e
+5d
+5r
+6s
+5s
+4ged
+6r
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7s
+5ie
+7s
+6ng
+4ing
+4man
+5en
+4s
+5hop
+8s
+5man
+6en
+3il
+5s
+4n
+5ing
+8s
+6sh
+8ness
+9esses
+5s
+3le
+5d
+5s
+4ier
+6st
+5ng
+7s
+4let
+7s
+5ow
+7able
+7ed
+8r
+9s
+7ing
+7s
+7tail
+9ils
+7wort
+9rts
+4y
+3m
+4i
+5es
+5s
+4p
+5ed
+6r
+7s
+5ier
+7st
+6ness
+9ses
+7g
+6sh
+5land
+9s
+6ess
+5s
+5y
+4y
+3n
+4g
+4herd
+8s
+4k
+5ed
+6r
+7s
+6st
+6y
+7s
+5ie
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5pot
+8s
+5s
+5y
+4like
+4ned
+6ries
+7y
+5ie
+7r
+7s
+8t
+6ng
+8s
+5y
+4pan
+7s
+4s
+5down
+9s
+5kin
+8s
+5ong
+8s
+3p
+4ped
+6r
+7s
+5ing
+8s
+4s
+4t
+5ion
+8s
+3raj
+6es
+6ism
+9s
+8t
+9s
+4d
+5ed
+5ier
+7st
+6ng
+5s
+5y
+4e
+4f
+5ed
+5ing
+5s
+4m
+5ed
+6r
+7s
+5ing
+8s
+5s
+4t
+5h
+6ier
+8st
+7ly
+7ness
+9sses
+6ness
+9ses
+6s
+6y
+5ness
+9es
+5y
+4ve
+6d
+6s
+5ing
+3sh
+5buckle
+9led
+9ler
+9lers
+9les
+9ling
+5ed
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+5work
+9s
+5y
+4tica
+8s
+3t
+4ch
+6book
+9ks
+6es
+4h
+5able
+5e
+6able
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+5s
+5y
+4s
+4ted
+6r
+7ed
+7ing
+7s
+5ier
+7st
+6ng
+8s
+5y
+3y
+4able
+4back
+8ed
+8s
+4ed
+5r
+6s
+4ful
+4ing
+7s
+4l
+5ed
+5ing
+8s
+5s
+4s
+3zzle
+7s
+2eal
+5ed
+5ing
+8s
+5s
+4r
+5d
+6s
+5er
+7s
+5ier
+7st
+6ng
+8s
+5s
+5word
+9s
+5y
+4t
+5band
+9s
+6ox
+8es
+5ed
+6r
+7dress
+9esses
+7s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5less
+5pants
+5s
+6hirt
+9ts
+7op
+9s
+6uit
+9s
+5y
+3de
+5s
+4ger
+7s
+3e
+4d
+4ing
+4l
+5ed
+5ing
+5s
+4ney
+7s
+5ies
+5y
+4p
+5back
+9s
+5er
+7s
+5ier
+7st
+6ng
+8ly
+8ness
+9esses
+8s
+5s
+6take
+9es
+5y
+4r
+5ed
+5ing
+5s
+5t
+4s
+4t
+5bread
+9ds
+7iar
+9rs
+8er
+9rs
+5corn
+9s
+5ed
+6n
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6r
+6st
+5fish
+9es
+5heart
+9ted
+9ting
+9ts
+5ie
+7s
+7wife
+9ves
+6ng
+8s
+6sh
+8ly
+8ness
+9esses
+5lip
+8s
+6y
+5man
+6eal
+8t
+9s
+7n
+5ness
+9es
+5s
+6hop
+9s
+6op
+8s
+5veld
+9s
+5water
+9rs
+6ood
+9s
+5y
+3ir
+5ed
+6r
+6st
+5ing
+5ness
+9es
+5s
+5t
+3lchie
+8s
+4l
+5dom
+8s
+5ed
+6r
+7s
+6st
+5fish
+9es
+5head
+9ed
+9edness
+9s
+5ing
+8ly
+8s
+6sh
+5s
+4t
+5ed
+6r
+7ed
+7ing
+9gly
+9gs
+7s
+5ing
+5rier
+8st
+6y
+5s
+3pt
+5back
+5wing
+9s
+3rf
+5ed
+5ing
+5s
+4vable
+5e
+6d
+6less
+6r
+7s
+6s
+5ing
+8s
+3ven
+6s
+3y
+4ed
+4ing
+4s
+2idden
+7s
+3es
+3ft
+5ed
+6r
+7s
+6st
+5ie
+7s
+6ng
+5let
+8s
+6y
+5ness
+9es
+5s
+5y
+3g
+4ged
+6r
+7s
+5ing
+4s
+3ler
+6s
+4l
+5ed
+6r
+7s
+5ing
+8s
+5s
+3m
+4feeder
+9rs
+4mable
+5er
+7et
+9s
+7s
+5ier
+7st
+6ly
+6ng
+8ly
+8ness
+9esses
+8s
+5y
+4s
+5uit
+8s
+4wear
+8s
+3ndge
+7d
+7s
+6ing
+5le
+7d
+7r
+8s
+7s
+6ing
+9s
+4e
+5herd
+9s
+6ood
+9s
+5like
+5pox
+8es
+5ries
+6y
+5s
+6tone
+9es
+4g
+5arm
+8s
+5beat
+9s
+6in
+8s
+6oat
+9s
+6y
+7s
+5e
+6d
+6ing
+9ly
+6s
+5ier
+7st
+6ng
+8est
+8ly
+8s
+6sm
+8s
+5le
+7d
+7s
+7tree
+9ees
+6ing
+9s
+5man
+6en
+5ometer
+9ers
+5s
+5tail
+6ree
+9s
+5y
+4ish
+7ly
+7ness
+9sses
+4k
+5ed
+6r
+7s
+5ing
+5s
+4ney
+7s
+3pe
+5d
+5r
+6s
+5s
+5y
+4ier
+6st
+5ng
+4le
+6s
+4ple
+7s
+3re
+5s
+4l
+5ed
+5ier
+7st
+6ng
+8ly
+5s
+5y
+3sh
+5ed
+6r
+7s
+6s
+7t
+5ier
+7st
+6ng
+8ly
+8s
+5y
+4s
+5es
+5ing
+8s
+3tch
+6able
+6back
+9ked
+9king
+9ks
+7lade
+9des
+7oard
+9rds
+6ed
+7l
+8s
+7r
+8oo
+9os
+8s
+7s
+6gear
+9rs
+7irl
+9ls
+7rass
+9sses
+6ier
+8st
+7ng
+9s
+6like
+6man
+7en
+6over
+9rs
+6y
+7ard
+9ds
+4h
+5e
+6r
+7ed
+7ing
+7s
+5ly
+4s
+5es
+3ve
+5d
+5l
+6block
+9cks
+6ed
+6ing
+6led
+7ing
+6s
+5s
+5t
+6s
+4ing
+3z
+4z
+5ed
+6s
+5ing
+5le
+7d
+7r
+8s
+7s
+6ing
+2ob
+4bed
+6r
+7s
+5ing
+4s
+3ffer
+7s
+5ing
+8s
+3llen
+7ly
+7ness
+9sses
+4n
+3on
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5s
+5y
+4p
+5ed
+6r
+7s
+5ier
+7st
+6ng
+5s
+6take
+5y
+4sh
+6ed
+7s
+6ing
+3p
+4ped
+6r
+7s
+5ing
+8s
+4s
+4t
+3rd
+5bearer
+9ers
+6ill
+9s
+5craft
+9ts
+5ed
+6r
+7s
+5fish
+9es
+5ing
+5less
+6ike
+5man
+6en
+5play
+9er
+9ers
+9s
+6roof
+5s
+6man
+9ship
+9ships
+7en
+6tick
+9ks
+5tail
+9s
+4e
+4n
+3t
+4s
+4ted
+6r
+7s
+5ier
+7st
+6ng
+8s
+5y
+3un
+5d
+6ed
+6ing
+6s
+5e
+6d
+6s
+5ing
+5s
+3wnd
+6s
+5e
+6s
+3zzle
+7s
+2um
+3ng
+2y
+1ybarite
+8s
+7ic
+9al
+9ally
+8sh
+9m
+9ms
+3be
+5s
+3il
+5s
+3o
+4e
+5s
+4tic
+6sm
+8s
+4w
+5s
+2camine
+8s
+5ore
+8s
+3e
+4e
+5s
+4s
+3omore
+8s
+4nia
+6um
+4phancies
+9y
+8t
+9ic
+9ical
+9ically
+9ise
+9ised
+9ises
+9ish
+9ishly
+9ising
+9ism
+9isms
+9ize
+9ized
+9izes
+9izing
+9ly
+9ries
+9ry
+9s
+4ses
+5is
+2e
+3d
+3ing
+3n
+4ite
+7s
+6ic
+4s
+3s
+2ke
+4r
+4s
+2li
+4s
+3labaria
+9es
+9um
+8y
+6i
+7c
+8al
+9lly
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+8ities
+9ty
+8s
+7fication
+9ed
+9es
+8y
+9ing
+7se
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+6le
+8d
+8s
+7ing
+6ogram
+9ams
+9aphies
+9aphy
+6ub
+8s
+7s
+8es
+4epses
+7is
+6tic
+9al
+9ally
+4oge
+7s
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ical
+9ically
+9ics
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+3ph
+5ic
+6d
+7e
+8s
+7ine
+7s
+6er
+7st
+6ne
+6sh
+5like
+5s
+5y
+3va
+5e
+5n
+6er
+8s
+6ite
+9s
+6s
+5s
+5tic
+4estral
+8ian
+4ia
+6s
+5cultural
+9ure
+9ures
+5ine
+5n
+6e
+7s
+6ite
+9s
+6s
+5te
+7s
+2mar
+5s
+3bion
+7s
+7t
+8ic
+9cally
+8s
+6ses
+7is
+6t
+7e
+8s
+7ic
+9al
+9ally
+7s
+4ol
+6e
+7d
+7s
+6ic
+8al
+9lly
+9lness
+8s
+7ng
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ical
+9ically
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6led
+7ing
+6ogical
+9es
+9st
+9sts
+8raphies
+9aphy
+8y
+7latries
+9try
+8ogies
+9gy
+6s
+3itar
+7e
+8s
+7s
+3metalism
+9sms
+8lic
+9ism
+9isms
+6ral
+7ian
+9ns
+8c
+9al
+9ally
+9alness
+8es
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ophobia
+9hobias
+7y
+3pathectomies
+9tomy
+8tic
+9ical
+9ically
+9ics
+7ies
+8n
+9s
+8que
+8se
+9ed
+9er
+9ers
+9es
+9ing
+8ze
+9ed
+9er
+9ers
+9es
+9ing
+7olytic
+9ytics
+8mimetic
+7y
+6ico
+6ric
+9ally
+8es
+7y
+4etalies
+8ous
+8y
+4hile
+8s
+7ies
+8sm
+9ms
+7ous
+7y
+5onic
+9ally
+8es
+8on
+9ns
+9us
+9usly
+8st
+9ts
+7y
+5ylous
+6seal
+8otomies
+9tomy
+8s
+7ial
+8otomies
+9tomy
+8s
+7tic
+6tic
+4iesometer
+9eters
+4last
+8ic
+8s
+5oce
+8s
+4odia
+8l
+9ly
+7um
+5sia
+8c
+9s
+8l
+8rch
+9chs
+8st
+9ts
+7um
+9s
+4tom
+7atic
+9ical
+9ically
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9ologic
+9ology
+7less
+7ological
+9ogies
+9ogy
+7s
+6ses
+7is
+6tic
+2n
+3adelphite
+9ites
+4ereses
+8is
+5stheses
+9sia
+9sias
+9sis
+9tic
+4gog
+7al
+7ical
+7s
+7ue
+9s
+4lepha
+9s
+5lagmatic
+5oepha
+9as
+4ndria
+8um
+7ous
+5gia
+7um
+5on
+7s
+5therous
+8ses
+9is
+8tic
+7ic
+8es
+7ous
+7y
+4phea
+8s
+7ia
+9s
+5osematic
+9atism
+9atisms
+5se
+7d
+7s
+6id
+8s
+7ng
+7s
+5tase
+9s
+6e
+7s
+6ic
+8al
+9lly
+6osomal
+9me
+9mes
+4rchies
+7y
+5throdial
+9dially
+9ses
+9sis
+4stries
+7y
+4xaria
+8on
+5es
+5is
+3c
+4arp
+7ies
+7ous
+7s
+7y
+4ed
+4h
+5ed
+5ing
+5ondroses
+9osis
+6reses
+9is
+5ro
+7flash
+9ashes
+7mesh
+9shes
+7nal
+8eities
+9ity
+8ic
+9cal
+9cally
+9cities
+9city
+9es
+9sation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9sm
+9sms
+9stic
+9stical
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8ologies
+9logy
+9scope
+9scopes
+9us
+9usly
+9usness
+8y
+7s
+8cope
+9opes
+7tron
+9ons
+5s
+5yses
+7is
+4ing
+4lastic
+5inal
+9s
+7e
+8s
+7oria
+9ium
+4om
+6s
+5pal
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+6e
+7s
+6ic
+6tic
+4retic
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9tic
+9ts
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+4s
+4ytia
+8l
+7um
+3d
+4actyl
+9ies
+9ism
+9isms
+9ous
+9s
+9y
+4ed
+5reses
+8is
+5ses
+6is
+8es
+6moses
+9is
+8tic
+5t
+6ic
+8al
+9lly
+6on
+8s
+6s
+4ic
+6al
+8ism
+9sms
+9st
+9stic
+9sts
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6s
+7hip
+9ps
+5ng
+7s
+5otactic
+4rome
+8s
+7ic
+4s
+4yasmian
+3e
+4cdoche
+9es
+9ic
+9ical
+9ically
+9ism
+9isms
+5hia
+8s
+5ious
+5ologic
+9ical
+9ically
+9ies
+9ist
+9ists
+9y
+5phoneses
+9esis
+5tic
+8ally
+8s
+4d
+5ria
+8l
+7on
+7um
+4ideses
+8is
+4reses
+7is
+5getic
+9cally
+6ia
+8s
+7c
+8ally
+7d
+8s
+7es
+7se
+9d
+9s
+8ing
+8m
+9s
+8t
+9ic
+9ically
+9s
+7ze
+9d
+9s
+8ing
+6y
+4s
+5es
+5is
+7es
+5thesia
+9ias
+8tic
+3fuel
+7s
+3gamic
+7es
+6ous
+6y
+5s
+6es
+6ses
+4eneic
+7ses
+8ious
+9s
+7tic
+6ic
+4nathous
+4raph
+8s
+3ing
+4zeses
+7is
+3karya
+7on
+9ic
+9s
+3od
+5al
+7s
+5ic
+7al
+9ly
+5s
+6man
+7en
+4ecete
+9s
+6ioses
+9is
+8us
+7se
+9d
+9s
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+6ologies
+9gy
+5kete
+9s
+4icous
+4nym
+7atic
+7e
+8s
+7ic
+9al
+9on
+9ons
+8es
+8se
+9ed
+9es
+9ing
+9t
+9ts
+8ties
+9y
+8ze
+9ed
+9es
+9ing
+7ous
+9sly
+9sness
+7s
+7y
+4pses
+6is
+8e
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+5tic
+8al
+9lly
+8s
+7st
+9ic
+9s
+4stoses
+8is
+4via
+7l
+8ly
+7s
+6tic
+8s
+9es
+3roc
+6s
+3sepalous
+3tactic
+9al
+9ally
+9s
+5gm
+7a
+8s
+8ta
+9ic
+9ite
+9ites
+7ic
+7s
+5n
+6s
+5x
+6es
+4ectic
+9al
+5nic
+7es
+6oses
+8is
+6y
+5reses
+8is
+5xis
+8es
+4h
+5ase
+8s
+5eses
+7is
+9ation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9t
+9ts
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7pian
+9ans
+6tase
+9es
+7ic
+9al
+9ally
+9ism
+9isms
+9s
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+9t
+9ts
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+5on
+7s
+5pop
+8s
+5roni
+8us
+5s
+4onic
+8ally
+7es
+7n
+8s
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6ous
+6y
+3ura
+6e
+2pe
+4d
+4s
+3h
+4er
+6ed
+6ing
+9s
+6s
+4ilis
+8ation
+9tions
+8e
+9d
+9s
+8ing
+7tic
+9cally
+9cs
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6oid
+7logies
+9gist
+9gists
+9gy
+7ma
+9s
+9ta
+7phobia
+9obias
+4on
+6ed
+6ing
+6s
+4s
+3ing
+2rah
+5s
+3en
+5s
+4tte
+7s
+3inga
+7s
+6e
+7al
+7d
+7s
+6ing
+7tis
+9ses
+6omyelia
+9elias
+9elic
+7tomies
+9my
+5x
+6es
+3phian
+8s
+6d
+7s
+3tes
+4is
+3up
+5ed
+5ier
+7st
+6ng
+5like
+5s
+5y
+2sadmin
+8s
+3op
+5s
+3sarcoses
+9is
+8tic
+4itia
+8s
+3taltic
+4em
+6atic
+9cal
+9cally
+9cian
+9cians
+9cness
+9cs
+9sation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+8ologies
+9logy
+6ed
+6ic
+8ally
+8s
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6less
+6s
+4ole
+7s
+6ic
+4yle
+7s
+2the
+5s
+2ver
+5s
+2zygal
+5etic
+9ally
+5ial
+6es
+5y
+0ta
+2al
+4s
+3ta
+5s
+2b
+3anid
+7s
+4rd
+6ed
+6s
+5et
+7s
+4sheer
+9s
+6ir
+8s
+3bed
+4ied
+6s
+5net
+8s
+6g
+5s
+6es
+4ouleh
+9s
+7i
+8s
+4y
+5hood
+9s
+5ing
+3efaction
+9ons
+5ied
+7s
+5y
+6ing
+4llion
+9s
+4r
+5d
+6ar
+8s
+6s
+5ed
+5ing
+5nacle
+9ed
+9es
+9ing
+8ular
+5s
+4s
+5cence
+9es
+8t
+4tic
+7s
+3i
+4d
+4net
+7s
+3la
+5nette
+9es
+5s
+5ture
+9s
+4e
+5au
+7s
+7x
+5cloth
+9hs
+5d
+5ful
+8s
+5land
+9s
+6ess
+5mate
+9s
+5s
+6ful
+6poon
+9nful
+9nfuls
+9ns
+9nsful
+5t
+6ed
+6ing
+6op
+8s
+6s
+6ted
+7ing
+5ware
+9s
+6ise
+4ier
+7s
+5ng
+7s
+4oid
+7s
+7y
+3oggan
+8ed
+8ing
+8s
+4o
+5ed
+5ing
+5ley
+8s
+5s
+4pareses
+9is
+4r
+5ed
+6r
+7s
+6t
+7s
+5in
+7e
+8s
+7g
+7s
+5s
+4uleh
+8s
+6i
+7s
+5r
+6ed
+7r
+8s
+7t
+8s
+6in
+8g
+8s
+6s
+3rere
+7s
+5t
+6s
+3s
+3u
+4ed
+4ing
+4la
+6ble
+6e
+6r
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+9y
+5i
+6s
+4n
+5s
+4s
+2cahout
+8s
+4mahac
+9s
+4n
+5s
+3e
+4s
+4t
+3h
+4e
+5ometer
+9ers
+9ric
+9rical
+9ries
+9ry
+5s
+4ina
+6id
+8s
+5sm
+7e
+8s
+7s
+6t
+7e
+8s
+7oscope
+9copes
+9copic
+7s
+4o
+5gram
+9s
+8ph
+9hs
+5meter
+9rs
+8ric
+9ical
+9ically
+9ies
+9y
+5s
+4s
+4yarrhythmia
+5cardia
+9iac
+9ias
+5graph
+9her
+9hers
+9hic
+9hical
+9hies
+9hist
+9hists
+9hs
+9hy
+5lite
+9s
+8ic
+6yte
+9s
+8ic
+5meter
+9rs
+8ric
+9ical
+9ically
+9ies
+9y
+5on
+7ic
+7s
+5phasia
+9ias
+7rasia
+9sias
+7ylaxes
+9axis
+6nea
+9s
+7oea
+9as
+3it
+5ly
+5ness
+9es
+5urn
+8ities
+9ty
+8ly
+3k
+4board
+9s
+4ed
+5r
+6s
+5t
+6s
+6y
+5y
+4ier
+6s
+7t
+5fied
+8r
+9s
+8s
+6y
+7ing
+5ly
+5ness
+9es
+6g
+7s
+4le
+6d
+6r
+7s
+6s
+7s
+5ing
+8s
+4s
+5man
+6en
+4y
+3mahack
+9s
+3node
+7s
+3o
+4nite
+8s
+4s
+3rine
+7s
+3t
+4ful
+7ly
+7ness
+9sses
+4ic
+6al
+8ly
+6ian
+9s
+7ties
+8y
+6s
+5le
+7ly
+6ist
+9s
+7ties
+8y
+5on
+7s
+5sm
+7s
+4less
+8ly
+8ness
+9esses
+4s
+4ual
+7ities
+9y
+7ly
+2d
+3die
+6s
+3pole
+7s
+3s
+2e
+3d
+4ium
+7s
+3ing
+3kwondo
+9s
+3l
+4s
+3nia
+6cide
+9es
+6e
+6fuge
+9es
+6s
+7es
+7is
+6te
+5oid
+3s
+2ffarel
+8s
+4erel
+8s
+5ta
+7s
+8es
+6ized
+6y
+4ia
+6s
+5es
+4rail
+8s
+4y
+3ia
+5s
+2g
+3along
+8s
+4reen
+8s
+3board
+8s
+3etes
+3gant
+7s
+4ed
+5e
+6s
+5r
+6s
+4ier
+6st
+5ng
+7s
+4y
+3hairm
+8s
+3ine
+6s
+3less
+4iarini
+9is
+6telle
+9les
+5ke
+5ne
+7s
+5oni
+8s
+3ma
+5ta
+4eme
+7s
+6ic
+8s
+3rag
+6s
+3s
+3uan
+6s
+2ha
+4s
+3ina
+6s
+5i
+6s
+3r
+4s
+3sil
+6dar
+9s
+6s
+2i
+3aha
+6s
+3g
+4a
+5s
+4lach
+5e
+6d
+6s
+5ing
+4s
+3hoa
+3ko
+5naut
+9s
+5s
+3l
+4ard
+7s
+4back
+8s
+5oard
+9s
+6ne
+8s
+4coat
+8ed
+8s
+4ed
+5nder
+9s
+5r
+6on
+8s
+6s
+4fan
+7s
+5in
+7s
+5lies
+6y
+4gate
+8d
+8r
+9s
+8s
+7ing
+4ing
+7s
+4lamp
+8s
+5e
+6s
+7s
+8ly
+8ness
+9esses
+6ur
+8s
+5ie
+7s
+6ght
+9s
+6ke
+4or
+6bird
+9ds
+6ed
+7ss
+9es
+6ing
+9s
+6made
+8ke
+9es
+9ing
+6s
+4piece
+9s
+6pe
+8d
+8s
+7ing
+5lane
+9s
+4race
+8s
+4s
+5kid
+8s
+5lide
+9s
+5pin
+8ned
+9ing
+8s
+5tock
+9s
+4water
+9s
+5heel
+9s
+5ind
+8s
+4ye
+6s
+4zie
+7s
+3n
+4s
+4t
+5ed
+5ing
+5less
+9ly
+5s
+5ure
+8s
+3pan
+6s
+3ra
+5s
+3s
+4ch
+6es
+4h
+5es
+3t
+4s
+3ver
+6ed
+6ing
+6s
+6t
+2j
+3es
+3ine
+6s
+2k
+3a
+4ble
+4he
+6s
+4maka
+8s
+4s
+3e
+4able
+5way
+8s
+4down
+8s
+4n
+4off
+7s
+5ut
+7s
+5ver
+8s
+4r
+5s
+4s
+4up
+6s
+3hi
+5s
+3i
+4er
+5st
+4n
+5g
+6ly
+6ness
+9ses
+6s
+5s
+4s
+3kies
+3s
+3y
+2la
+4k
+5s
+4nt
+6s
+4poin
+8s
+4q
+5s
+4r
+5ia
+5s
+4s
+4unt
+7s
+4yot
+7s
+3bot
+6s
+6ype
+9s
+3c
+4ed
+4ier
+6st
+5ng
+4ked
+5ier
+7st
+6ng
+5y
+4ose
+5us
+4s
+4um
+6s
+4y
+3e
+4a
+5e
+4bearer
+9rs
+8ing
+9ngs
+4ful
+4galla
+9s
+5gio
+8s
+4nt
+6ed
+6less
+6s
+4r
+5s
+4s
+5man
+6en
+4ysim
+3i
+4grade
+4on
+6ic
+6s
+4pat
+7s
+5ed
+7s
+6s
+5ot
+7s
+4sman
+8ic
+9cal
+9cally
+8s
+3k
+4abilities
+9ty
+6le
+5thon
+9s
+6ive
+9ly
+9ness
+9nesses
+4back
+8s
+5ox
+7es
+4ed
+5r
+6s
+4fest
+8s
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+7s
+4s
+4time
+8s
+4y
+3l
+4age
+7d
+7s
+6ing
+5isim
+5t
+6s
+4boy
+7s
+4ent
+7s
+5r
+5st
+5t
+6s
+4grass
+9es
+4iable
+6te
+8d
+8s
+7ing
+5ed
+6r
+7s
+6s
+5s
+6es
+6h
+6im
+5t
+6es
+6h
+7es
+7im
+7s
+6im
+6ot
+8h
+6s
+4ness
+8es
+4ol
+6s
+5t
+6s
+5w
+6ed
+6ing
+7sh
+6s
+6y
+4s
+4y
+5ho
+7ed
+7ing
+7s
+5ing
+5man
+6en
+5shop
+9s
+5woman
+8en
+3ma
+5s
+4ud
+6ic
+7sm
+9s
+6s
+3on
+5ed
+5s
+4oka
+7s
+3pa
+5e
+5s
+3uk
+5a
+6s
+5dar
+8s
+5s
+4s
+5es
+3weg
+6s
+2m
+3abilities
+9y
+5le
+7ness
+9sses
+4l
+5e
+6s
+5s
+4ndu
+7a
+8s
+7s
+5oir
+8s
+5u
+6s
+4ra
+6ck
+8s
+6o
+7s
+6s
+6u
+7s
+5i
+6llo
+9s
+6n
+7d
+8s
+7s
+6s
+7k
+8s
+4sha
+7s
+3bac
+6s
+5k
+6s
+5la
+7s
+4er
+6s
+4our
+7a
+8s
+7ed
+8r
+9s
+7in
+9e
+9es
+9g
+9ist
+9ists
+9s
+7s
+4ur
+6a
+7s
+6in
+8s
+6s
+3e
+4abilities
+9ty
+6le
+8ness
+9esses
+4d
+4in
+6s
+4less
+8ness
+9esses
+5y
+4ness
+8es
+4r
+5s
+4s
+5t
+3in
+5e
+6s
+5g
+6s
+5s
+4s
+5e
+6s
+3mar
+6s
+4ie
+6d
+6s
+4y
+5ing
+3oxifen
+9s
+3p
+4ala
+7s
+5n
+6s
+4ed
+5r
+6ed
+7r
+8s
+6ing
+9s
+6proof
+6s
+4ing
+7s
+5on
+7s
+4on
+6ade
+9s
+7ge
+9s
+6ed
+6ing
+6s
+4s
+3s
+3worth
+8s
+2n
+3a
+4dar
+7s
+4ger
+7s
+5ra
+7s
+6ine
+4lised
+6zed
+4s
+3bark
+7s
+3dem
+6s
+6wise
+4oor
+7i
+8s
+7s
+3e
+3g
+4a
+5s
+4ed
+5lo
+7s
+5nce
+8s
+7ies
+7y
+6t
+7al
+9ly
+7ial
+9lities
+9lity
+9lly
+7s
+5rine
+9s
+4hin
+7in
+9s
+7s
+4i
+5bilities
+9ty
+6le
+8ness
+9esses
+8s
+7y
+5e
+6r
+6s
+7t
+5ness
+9es
+6g
+5s
+4le
+6d
+6foot
+9ts
+6ment
+9ts
+6r
+7s
+6s
+7ome
+6weed
+9ds
+5ier
+7st
+6ng
+8ly
+8s
+5y
+4o
+5ed
+5ing
+6st
+8s
+5like
+5s
+4ram
+7s
+4s
+4un
+6s
+4y
+3h
+4s
+3ist
+6ries
+7y
+6s
+4wha
+7s
+3k
+4a
+5ge
+7s
+5rd
+7s
+5s
+4buster
+9rs
+8ing
+9ngs
+4ed
+5r
+6s
+4ful
+7s
+4ia
+6s
+5es
+5ng
+7s
+6i
+7s
+4less
+5ike
+4s
+5hip
+8s
+4y
+3ling
+7s
+3na
+5ble
+5ge
+7s
+5h
+6s
+5s
+5te
+7s
+4ed
+5r
+6ies
+6s
+6y
+5st
+4ic
+5e
+6s
+5n
+6g
+7s
+6s
+5sh
+4oy
+6ed
+6ing
+6s
+3orexic
+9s
+3rec
+6s
+3s
+4ies
+4y
+3talate
+9s
+6ic
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+9ngs
+8m
+9s
+7te
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+9ngs
+6ous
+6um
+8s
+7s
+8es
+5mount
+5ra
+7ra
+9s
+7s
+4i
+5vies
+6y
+4o
+5nies
+6y
+4ra
+6s
+5ic
+6sm
+8s
+5um
+7s
+3uki
+6s
+3yard
+7s
+3zanite
+9s
+2o
+3nga
+6s
+3s
+2p
+3a
+4colo
+8s
+5ulo
+8s
+4dera
+8s
+7o
+8s
+4lo
+6s
+4s
+3e
+4able
+4d
+4less
+5ike
+6ne
+8s
+4n
+5ade
+8s
+4r
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5ness
+9es
+5s
+6tick
+9ks
+5wise
+4s
+5cript
+9ts
+5tried
+9s
+7y
+8ing
+4t
+5a
+6l
+5i
+6s
+5s
+5um
+4worm
+8s
+3hephobia
+9ias
+9ic
+4ole
+7s
+5nomic
+9cal
+9es
+9st
+9sts
+8y
+5phobia
+9ias
+5use
+8s
+4rogeneses
+9esis
+3ing
+4oca
+7s
+4r
+5oid
+5s
+4s
+5es
+5t
+6s
+3lash
+7es
+3otement
+9ts
+3pa
+5ble
+5s
+4ed
+5r
+6s
+5t
+6s
+4ice
+7d
+7s
+6ing
+5ng
+7s
+5t
+3room
+7s
+6t
+7ed
+7s
+3s
+4alteerie
+9ries
+4ieteerie
+9ries
+4man
+5en
+4ter
+7s
+5ress
+9es
+6y
+3u
+4ed
+4ing
+4s
+2queria
+8s
+2r
+3a
+4diddle
+9es
+4ire
+7s
+4kihi
+8s
+4ma
+6s
+7alata
+9atas
+5ea
+7s
+4nd
+6s
+5tara
+9ed
+9ing
+9s
+7s
+8es
+8s
+9es
+6ella
+9as
+6ism
+9s
+8t
+9s
+6ula
+9e
+9s
+4s
+4tantara
+9raed
+9raing
+9ras
+4xacum
+9s
+3boggin
+9ed
+9ing
+9s
+5osh
+8es
+5uche
+9s
+6sh
+8es
+5y
+6s
+4ush
+7es
+3cel
+6s
+3died
+6r
+6s
+7t
+5grade
+9es
+5ly
+5ness
+9es
+5ve
+4o
+4y
+5ing
+5on
+7s
+3e
+4d
+4s
+3ga
+4e
+5d
+5s
+5t
+6able
+6ed
+7er
+9s
+6ing
+7tis
+9ses
+6less
+6s
+4ing
+3iff
+6ed
+6ication
+9tions
+7ng
+6less
+6s
+4ng
+6s
+3latan
+8s
+4etan
+8s
+3mac
+6adam
+9ms
+6ked
+7ing
+6s
+3n
+4al
+6ly
+5tion
+9s
+4ish
+7able
+7ed
+8r
+9s
+8s
+7ing
+4s
+3o
+4c
+5s
+4k
+5s
+4s
+4t
+5s
+3p
+4an
+6s
+5per
+8s
+5ulin
+9g
+9gs
+9s
+4on
+6s
+4s
+3radiddle
+9les
+5gon
+8s
+5s
+6es
+4e
+5d
+5s
+4iance
+9s
+5ed
+6r
+7s
+6s
+7t
+5ness
+9es
+6g
+7s
+4ock
+7s
+5w
+6ed
+6ing
+6s
+4y
+5ing
+3s
+4al
+6gia
+9s
+6s
+4eal
+7s
+5l
+6s
+4i
+5a
+6s
+5er
+7s
+5oid
+5ped
+8s
+4ometatarsal
+9tarsi
+9tarsus
+4us
+3t
+4an
+6a
+7lia
+9as
+7s
+6e
+7d
+7s
+6ries
+7y
+6s
+5r
+6e
+7ous
+7s
+6ic
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+6ous
+6s
+4ed
+5r
+5st
+4ier
+6st
+5ly
+5ne
+7s
+8s
+9es
+6g
+5sh
+7ly
+4let
+7s
+5y
+4ness
+8es
+4rate
+8d
+8s
+6zine
+9es
+4s
+4ufe
+7s
+6fe
+8s
+6o
+7s
+4y
+3weed
+7s
+4hine
+8s
+3zan
+6s
+2s
+3ar
+5s
+3bih
+6s
+3eometer
+9rs
+4r
+5ed
+5ing
+5s
+3h
+4ed
+5s
+4ing
+3imeter
+9s
+7ric
+9es
+8y
+3k
+4bar
+7s
+4ed
+5r
+6s
+4ing
+7s
+4less
+4master
+9rs
+5istress
+9esses
+4s
+4work
+8s
+3let
+6s
+3s
+4e
+5l
+6ed
+6ing
+6l
+7ed
+7ing
+9gs
+7s
+7y
+6s
+5s
+5t
+6s
+4ie
+6s
+3table
+4e
+5able
+5d
+5ful
+8ly
+8ness
+9esses
+5less
+9ly
+9ness
+9nesses
+5maker
+9rs
+5r
+6s
+5s
+5vin
+8s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+4y
+2t
+3ahash
+8es
+4mi
+6s
+4r
+5s
+3e
+4r
+5s
+4s
+3h
+4ed
+4ing
+4s
+3ie
+5s
+3ler
+6s
+3ou
+5ay
+7s
+5s
+3purusha
+9as
+3s
+4oi
+6s
+3t
+4ed
+5r
+6demalion
+9alions
+9allion
+6ed
+6ing
+6s
+7all
+9ls
+6y
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+4le
+6d
+6r
+7s
+6s
+6tale
+9ed
+9es
+9ing
+5ing
+8ly
+8s
+4oo
+6ed
+7r
+8s
+6ing
+7st
+9s
+6s
+5w
+6ed
+6ing
+6s
+4s
+4y
+3u
+4ed
+4ing
+4s
+2u
+3be
+5s
+3ght
+3hinu
+7s
+4ou
+6s
+3iwi
+6s
+3ld
+3nt
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5s
+3on
+5s
+3pata
+7s
+4e
+5s
+4ie
+6s
+3rean
+4ic
+5form
+5ne
+7s
+4obolia
+9um
+5machian
+9ies
+9y
+6orphous
+3s
+3t
+4aug
+7s
+4ed
+5n
+6ed
+6ing
+6s
+5r
+5st
+4ing
+5t
+4ly
+4ness
+8es
+4ochrone
+9nes
+9nism
+9nisms
+9nous
+5g
+6s
+5logic
+9cal
+9cally
+9es
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+8ous
+9usly
+8y
+5mer
+8ic
+9sm
+9sms
+8s
+7tric
+9ical
+5nym
+8ic
+9es
+8ous
+8s
+8y
+5phonic
+9ical
+9ies
+9y
+4s
+2v
+3a
+4h
+5s
+4s
+3er
+5ed
+5ing
+5n
+6a
+7s
+6er
+8s
+6s
+5s
+5t
+3s
+2w
+3a
+4i
+5s
+4s
+3drier
+7s
+8t
+6ly
+6ness
+9ses
+5y
+3ed
+4r
+5ies
+5s
+5y
+3hai
+6s
+4eowheo
+9os
+4iri
+7s
+3ie
+5r
+5st
+4ng
+6s
+3ney
+6s
+4ier
+6s
+7t
+5ly
+5ness
+9es
+4y
+3pie
+6s
+3s
+4e
+5d
+5s
+4ing
+3t
+4ed
+4ie
+6r
+6st
+5ng
+4s
+2x
+3a
+4bilities
+9y
+5le
+7ness
+9sses
+7s
+6y
+4ceous
+4meter
+9s
+4tion
+8al
+8s
+6ve
+3ed
+4me
+6s
+5ic
+4r
+5s
+4s
+3i
+4arch
+8s
+4cab
+7s
+4dermal
+8ic
+9es
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+8y
+4ed
+5s
+4ing
+4man
+5en
+6ter
+9s
+4ng
+6ly
+6s
+4plane
+9s
+4s
+4te
+6s
+5ic
+4way
+7s
+3less
+3man
+4en
+3ol
+5s
+4n
+5omer
+9s
+7ic
+9al
+9ally
+8es
+8st
+9ts
+7y
+5s
+4r
+5s
+3paid
+5yer
+8s
+6ing
+9s
+3us
+3wise
+3ying
+2y
+3assuid
+9s
+3berries
+7y
+3ra
+5s
+3s
+2zza
+5s
+4e
+1chick
+6ed
+6ing
+6s
+3otchke
+9s
+4ukball
+9ls
+1e
+2a
+3bag
+6s
+4erries
+7y
+4oard
+8s
+5wl
+7s
+5x
+6es
+4read
+8s
+3cake
+7s
+5rt
+7s
+4h
+5abilities
+9ity
+7le
+9ness
+9nesses
+8y
+5er
+7less
+8y
+7s
+8hip
+9ips
+6s
+5ie
+6ng
+8s
+5less
+4up
+6ful
+9s
+6s
+7ful
+3d
+4e
+5s
+4s
+3ed
+3gle
+6d
+6s
+5ing
+3house
+8s
+3ing
+3k
+4ettle
+9s
+4s
+4wood
+8s
+3l
+4ight
+8s
+5ke
+4s
+3m
+4aker
+8s
+4ed
+5r
+6s
+4ing
+7s
+4mate
+8s
+4s
+5ter
+8s
+4wise
+5ork
+8s
+3pot
+6s
+5y
+6s
+3r
+4able
+5way
+8s
+4down
+8s
+5rop
+8s
+4ed
+5r
+6s
+4ful
+7ly
+7ness
+9sses
+4gas
+7es
+7sed
+9s
+8ing
+4ier
+6st
+5ly
+5ness
+9es
+6g
+4jerker
+9rs
+4less
+4oom
+7s
+4s
+5heet
+9s
+5tain
+9ed
+9s
+6rip
+9s
+4y
+3s
+4able
+4e
+5d
+5l
+6ed
+7r
+8s
+6ing
+9s
+6led
+8r
+9s
+7ing
+9gs
+6s
+5r
+6s
+5s
+4hop
+7s
+4ing
+7ly
+7s
+4poon
+8ful
+9uls
+8s
+9ful
+3t
+4aster
+9s
+4ed
+4ime
+7s
+4s
+3ware
+7s
+3ze
+5d
+5l
+6ed
+6ing
+6led
+7ing
+6s
+5s
+4ing
+4le
+6d
+6s
+5ing
+2bbad
+6s
+2c
+3h
+4ed
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+4netium
+9ms
+7ronic
+5ic
+7al
+9ise
+9ised
+9ises
+9ising
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+9ly
+9ness
+9nesses
+9s
+7ian
+9ns
+8se
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9ts
+8ze
+9ed
+9es
+9ing
+7olour
+9oured
+7s
+6kon
+9s
+6que
+9s
+5o
+6babble
+9bles
+6cracies
+9cy
+9t
+9tic
+9ts
+6fear
+9rs
+6graphies
+9phy
+6junkie
+9kies
+6logic
+9ical
+9ically
+9ies
+9ise
+9ised
+9ises
+9ising
+9ist
+9ists
+9ize
+9ized
+9izes
+9izing
+9y
+6mania
+9iac
+9iacs
+9ias
+7usic
+9ics
+6phile
+9les
+8obe
+9bes
+9bia
+9bias
+9bic
+9bics
+7ole
+9es
+9is
+9ises
+9itan
+9itans
+8p
+9s
+6s
+7peak
+9aks
+7tress
+9esses
+9ucture
+4s
+4y
+3kel
+6s
+3s
+3ta
+5l
+4ibranch
+9chiate
+9chs
+5form
+5te
+7s
+4onic
+8ally
+8s
+7sm
+9s
+5rial
+4rices
+7ial
+6x
+4um
+6s
+2d
+3ded
+5r
+6ed
+6ing
+6s
+4ie
+6s
+5ng
+4y
+3ier
+5st
+4osities
+8y
+5us
+7ly
+7ness
+9sses
+7ome
+4some
+4um
+6s
+3s
+3y
+2e
+3d
+3ing
+3k
+3l
+4s
+3m
+4ed
+5r
+6s
+4ful
+4ing
+7ly
+7ness
+9sses
+4less
+4s
+3n
+4age
+7d
+7r
+8s
+7s
+4d
+5ed
+5ing
+5s
+4e
+5d
+5r
+6s
+5s
+4ful
+4ier
+6st
+5ng
+4s
+5ier
+7st
+5y
+4tier
+7st
+5sier
+8st
+6y
+5y
+4y
+5bop
+8per
+9ers
+3pee
+6s
+3r
+4ed
+4ing
+4s
+3s
+3ter
+6board
+9rds
+6ed
+6ing
+6s
+4h
+5e
+6d
+6r
+7s
+6s
+5ing
+8s
+5less
+5ridge
+9es
+4otal
+8ed
+9r
+9rs
+8ing
+9sm
+9sms
+9st
+9sts
+8led
+9er
+9ers
+9ing
+9y
+8s
+6um
+8s
+2f
+3f
+4s
+3illah
+6in
+3lon
+6s
+3s
+2g
+3g
+4s
+3men
+6ta
+8l
+7um
+4ina
+7l
+3s
+3u
+4a
+5s
+4exin
+8s
+4la
+6e
+6r
+7ly
+6ted
+4men
+7t
+8al
+9ry
+8s
+5ina
+4s
+2hr
+4s
+3sil
+6dar
+9s
+6s
+2ichopsia
+9as
+3glach
+3id
+5s
+3l
+4s
+3n
+4d
+5ed
+5ing
+5s
+4oscope
+9es
+4s
+2kkie
+6s
+3nonymies
+8ous
+8y
+3tite
+7s
+6ic
+2l
+3a
+4e
+5sthesia
+9sias
+9tic
+4mon
+7es
+7s
+4ngiectases
+9tasia
+9tasias
+9tasis
+9tatic
+4ry
+4utographic
+9aphies
+9aphy
+3co
+5s
+3d
+3e
+4archics
+4banking
+9ngs
+5ridge
+9es
+4camera
+9as
+6st
+8ed
+9r
+9rs
+8ing
+8s
+5hir
+8ic
+8s
+5ine
+8s
+5om
+7mand
+9nds
+8ute
+9ted
+9ter
+9ters
+9tes
+9ting
+9tings
+7s
+6nference
+9renced
+9rences
+7nection
+9ctions
+7trol
+9ols
+7verter
+9rters
+6ttage
+9ges
+9ging
+9gings
+6urse
+9es
+4dildonics
+5u
+6s
+4facsimile
+9miles
+6x
+7ed
+8s
+7ing
+5erique
+9ues
+5ilm
+8s
+4ga
+6s
+5enic
+9ally
+5noses
+8is
+8tic
+5onic
+8es
+7ous
+7y
+5ram
+8matic
+9ed
+9ic
+9ing
+8s
+7ph
+9ed
+9er
+9ers
+9ese
+9eses
+9ic
+9ically
+9ies
+9ing
+9ist
+9ists
+9s
+9y
+4health
+9hs
+4journalism
+9alisms
+9alist
+9alists
+4kineses
+9is
+8tic
+9ically
+4man
+6rk
+8ed
+9ter
+9ters
+9ting
+9tings
+8ing
+8s
+6tic
+9s
+5edicine
+9ines
+6n
+6ter
+9ed
+9ing
+9s
+7ric
+9cal
+9cally
+9es
+8y
+4ncephala
+9alic
+9alon
+9alons
+4ologic
+9cal
+9cally
+9es
+9sm
+9sms
+9st
+9sts
+8y
+5nomic
+9es
+8y
+5saur
+9ian
+9ians
+9s
+6t
+7ean
+9ns
+7ome
+9es
+9ous
+7s
+4path
+8ed
+8ic
+9cally
+9es
+9ng
+9se
+9sed
+9ses
+9sing
+9st
+9sts
+9ze
+9zed
+9zes
+9zing
+8s
+8y
+5heme
+9s
+7rique
+9ques
+6one
+9d
+9r
+9rs
+9s
+8ic
+9cally
+9es
+9ng
+9st
+9sts
+8y
+7to
+9graph
+9graphs
+9graphy
+9s
+5ic
+7s
+5lay
+8s
+5oint
+9s
+6rt
+8ation
+9tions
+8ed
+8ing
+8s
+5resence
+9nces
+6inter
+9ers
+6ocessing
+9ssings
+4ran
+7s
+5ecord
+9ded
+9ding
+9dings
+9ds
+5gic
+8ally
+7es
+6y
+4s
+5ale
+8s
+5cience
+9ces
+6ope
+9d
+9s
+8ic
+9cal
+9cally
+9es
+9form
+9ng
+9st
+9sts
+8y
+6reen
+9ns
+5elling
+9ngs
+6me
+8s
+6rvices
+6s
+5hop
+8ped
+9ing
+9ings
+8s
+5is
+5m
+6atic
+9cal
+9cally
+6s
+5oftware
+9ares
+5tereoscope
+6hesia
+9ias
+8tic
+6ic
+8h
+9s
+8s
+5urgeries
+9ry
+4tex
+7es
+7t
+8s
+5hon
+8s
+5ron
+8s
+5ype
+8d
+8s
+9etting
+8writer
+9riters
+7ing
+4utospore
+9ores
+9oric
+4vangelical
+9lism
+9lisms
+9list
+9lists
+5erite
+9es
+5iew
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+6se
+8d
+8r
+9s
+8s
+7ing
+8on
+9nal
+9nally
+9nary
+9ns
+7or
+9s
+7ual
+9lly
+4work
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+5riter
+9rs
+4x
+5ed
+6s
+5ing
+3fer
+6age
+9s
+6ed
+6ic
+7ng
+6s
+4ord
+7s
+3ia
+5l
+4c
+5ally
+4ospore
+9es
+4um
+3l
+4able
+5r
+6ed
+6ing
+6s
+4en
+6s
+5r
+6ed
+6ing
+6s
+7hip
+9ps
+4ies
+5n
+6g
+7ly
+7s
+6oid
+6s
+4s
+4tale
+8s
+4ural
+7te
+9s
+6etted
+6ian
+9s
+7c
+7de
+9s
+7on
+9s
+7se
+9d
+9s
+8ing
+7te
+9s
+7um
+9s
+7ze
+9d
+9s
+8ing
+6ometer
+9ters
+7us
+5s
+6es
+4y
+5s
+3net
+6ed
+6ing
+6s
+6ted
+7ing
+3ocentric
+9ics
+4i
+4me
+6rase
+9es
+7e
+8s
+7isation
+9ations
+8zation
+9ations
+6s
+5ic
+4phase
+9s
+8ic
+4s
+4taxes
+7is
+3pher
+7age
+9es
+7ed
+7ic
+8ng
+7line
+9nes
+7man
+8en
+7s
+7way
+9ys
+3s
+4on
+6ic
+6s
+3t
+2mazepam
+9s
+3blor
+7es
+7s
+3e
+4d
+4ne
+5os
+4rarious
+9usly
+9usness
+5ities
+7y
+5ous
+8ly
+4s
+3p
+4ed
+5h
+6s
+5r
+6a
+7bilities
+9lity
+8le
+7litie
+9ties
+7ment
+9ntal
+9ntally
+9ntful
+9nts
+7nce
+9es
+7s
+7te
+9d
+9ly
+9ness
+9nesses
+9s
+8ing
+9ve
+8ure
+9res
+6ed
+7r
+8s
+6ing
+9s
+6s
+5st
+7ed
+7ing
+8ve
+7s
+7uous
+9usly
+9usness
+4i
+5ng
+4lar
+7s
+6te
+8s
+5e
+6d
+6s
+6t
+7s
+4o
+5labile
+5ral
+8ise
+9sed
+9ses
+9sing
+9ties
+9ty
+9ze
+9zed
+9zes
+9zing
+8ly
+8ness
+9esses
+8s
+8ties
+9y
+7neous
+7ries
+9ly
+9ness
+9nesses
+8y
+6e
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+9ngs
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+9ngs
+5s
+4s
+4t
+5abilities
+9ity
+7le
+9ness
+9nesses
+6tion
+9ns
+9us
+5ed
+6r
+7s
+5ing
+8ly
+8ness
+9esses
+8s
+5ress
+9es
+5s
+4ura
+7s
+3s
+4e
+5d
+5s
+4ing
+3ulence
+9s
+8ies
+8y
+7t
+8ly
+2n
+3abilities
+9y
+5le
+7ness
+9sses
+6y
+4ce
+6s
+5ious
+9ly
+9ness
+9nesses
+6ties
+7y
+5ula
+7um
+9s
+4il
+6le
+8s
+7on
+9s
+6s
+4ncies
+6y
+5t
+6able
+6ed
+6ing
+6less
+6ries
+7y
+6s
+7hip
+9ps
+3ch
+5es
+3d
+4ance
+8s
+4ed
+5nce
+8s
+7ially
+8es
+8ous
+9usly
+9usness
+7y
+6tial
+9lly
+8ous
+9usly
+9usness
+6z
+7en
+5r
+6able
+6ed
+7r
+8s
+7st
+6feet
+7oot
+9ts
+6hearted
+9rtedly
+6ing
+9s
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ling
+9gs
+7oin
+9ns
+7y
+6ness
+9ses
+6ometer
+9ters
+6s
+4ing
+6ites
+8ides
+9s
+9ses
+6ous
+4on
+6ites
+8ides
+9s
+9ses
+6s
+5vaginitis
+4re
+6s
+7se
+9s
+5il
+7ed
+7lar
+8ed
+8ous
+7ous
+7s
+5on
+7s
+4s
+4u
+5s
+3e
+4brae
+6ific
+7o
+8nid
+9ids
+8s
+8us
+9sness
+7sm
+9s
+8t
+9s
+7ties
+8y
+6ose
+8ities
+9ty
+7us
+9ness
+9nesses
+4ment
+8al
+9ry
+8ed
+8s
+4ndum
+8s
+4s
+5mic
+6us
+8es
+4t
+5s
+3fold
+7s
+3ge
+5s
+3ia
+5cide
+9s
+5e
+5fuge
+9s
+5s
+6es
+6is
+4oid
+3nantite
+9es
+4e
+5r
+6s
+5s
+4ies
+5s
+6es
+6t
+7s
+4o
+5s
+4y
+3on
+5ed
+6r
+7s
+5ing
+5s
+4r
+5ist
+8s
+6te
+8s
+5less
+5oon
+8s
+5rhaphies
+9hy
+5s
+4synovitis
+9itises
+4tomies
+8st
+9ts
+7y
+4ur
+6s
+4vaginitis
+9itises
+3pence
+8s
+6ny
+4in
+6s
+4ounder
+9rs
+3rec
+6s
+3s
+4e
+5d
+5less
+6y
+5ness
+9es
+5r
+5s
+6t
+4ibilities
+9ty
+6le
+8ness
+9esses
+7y
+5le
+7ly
+7ness
+9sses
+6ities
+8y
+5meter
+9rs
+5ng
+5ometer
+9ers
+9ric
+9ries
+9ry
+6n
+7al
+9ly
+7ed
+8r
+9s
+7ing
+7less
+7s
+5ties
+6y
+5ve
+4on
+6s
+5r
+6ial
+6s
+3t
+4acle
+8d
+8s
+6ula
+9r
+9te
+8iferous
+9te
+9tes
+8oid
+8um
+5ge
+7s
+5tion
+9s
+7ve
+9ly
+9ness
+9nesses
+9s
+4ed
+5r
+6ed
+6hook
+9ks
+6ing
+6s
+4ful
+7s
+4h
+5ly
+5s
+4ie
+6r
+6st
+5ginous
+6o
+7s
+5ng
+7s
+4less
+5ike
+4maker
+9s
+4oria
+8l
+7um
+9s
+4s
+4wise
+4y
+3ue
+5s
+4ious
+5rostral
+5s
+5ties
+6y
+4ous
+7ly
+7ness
+9sses
+4rable
+5e
+6d
+6s
+5ial
+8ly
+6ng
+4ti
+5o
+6s
+3zon
+6s
+2ocalli
+8s
+3pan
+6s
+3sinte
+8s
+2pa
+4l
+5s
+4s
+3ee
+5s
+4faction
+9ons
+5ied
+7s
+5y
+6ing
+3higram
+9s
+5llah
+7in
+4ra
+6s
+5ite
+8s
+7ic
+5oite
+9s
+6mancies
+9cy
+3id
+5aria
+8um
+5er
+6st
+5ities
+7y
+5ly
+5ness
+9es
+3oy
+5s
+2quila
+7s
+6la
+8s
+2rabyte
+8s
+4flop
+8s
+4glin
+8s
+4hertz
+9es
+4i
+5s
+4kihi
+8s
+4ohm
+7s
+4ph
+6im
+8s
+4s
+4ta
+5ism
+8s
+5ocarcinoma
+6gen
+9eses
+9esis
+9ic
+9icist
+9icists
+9icity
+9ies
+9s
+9y
+6id
+6logic
+9ical
+9ies
+9ist
+9ists
+9y
+6ma
+8s
+8ta
+9ous
+6phobia
+9bias
+4watt
+8s
+3bia
+6s
+5c
+5um
+7s
+3ce
+5l
+6et
+8s
+6s
+5ntenaries
+9ary
+9nial
+9nials
+5s
+5t
+6s
+4io
+6s
+3ebene
+8s
+5ic
+6nth
+9ine
+9s
+5ra
+7e
+7nt
+9s
+7s
+7te
+9d
+9s
+8ing
+9on
+9ons
+8ula
+9lae
+9las
+4dines
+5o
+6s
+4fa
+6h
+4k
+5s
+4phthalate
+9lates
+9lic
+4s
+4te
+6s
+3f
+4e
+5s
+4s
+3ga
+5l
+4ite
+7s
+5versant
+9ants
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ator
+9ators
+9atory
+4um
+3iyaki
+8s
+3m
+4agancies
+9y
+8t
+9ly
+9s
+4ed
+5r
+6s
+4inabilities
+9lity
+8le
+9eness
+9y
+7l
+8ly
+8s
+7te
+9d
+9s
+8ing
+9on
+9onal
+9ons
+9ve
+9vely
+8or
+9rs
+9ry
+6er
+8s
+6g
+6i
+7sm
+9s
+8t
+9s
+6ological
+9gies
+9gist
+9gists
+9gy
+6us
+8es
+5taria
+9es
+9um
+9ums
+8y
+6e
+7s
+6ic
+4less
+5ies
+5y
+4or
+6s
+4s
+4time
+8s
+3n
+4al
+5ries
+6y
+5te
+7ly
+4e
+5d
+5plate
+9es
+5s
+4ing
+5on
+7s
+4s
+3otechnology
+3pene
+7less
+7s
+6ic
+6oid
+9s
+4ineol
+9s
+6ol
+8s
+4olymer
+9rs
+4sichoreal
+9rean
+3ra
+5ce
+7d
+7less
+7s
+7tte
+9es
+6ing
+9s
+6otta
+9as
+5e
+5form
+9ed
+9ing
+9ings
+9s
+5in
+7s
+5mara
+8e
+9s
+5ne
+7s
+5pin
+8s
+5queous
+5ria
+7um
+9s
+5s
+6es
+5zzo
+8s
+4een
+7s
+5lla
+8s
+5motive
+5ne
+7ly
+7s
+5plein
+9ns
+5strial
+9ally
+9alness
+9als
+5t
+6s
+4ibilities
+9ty
+6le
+8ness
+9esses
+8s
+7y
+5cole
+9s
+8ous
+5er
+7s
+6s
+5fic
+8ally
+7ed
+8r
+9s
+8s
+6y
+7ing
+9gly
+5genous
+5ne
+7s
+5t
+6orial
+9alise
+9alised
+9alises
+9alism
+9alisms
+9alist
+9alists
+9ality
+9alize
+9alized
+9alizes
+9ally
+9als
+9ed
+9es
+8y
+6s
+4oir
+7s
+5r
+6ful
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6less
+6s
+4y
+3sanctus
+9ses
+4e
+5ly
+5ness
+9es
+5r
+5st
+4ion
+7s
+3tia
+6l
+7s
+6n
+7s
+6ries
+7y
+6s
+5um
+6s
+7es
+4s
+3valencies
+9y
+8t
+3ylene
+8s
+3zetta
+8s
+7i
+7o
+8s
+2s
+3chenite
+9es
+3la
+5s
+3saraglot
+4elate
+9d
+9s
+8ing
+6la
+8e
+8r
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+5ra
+7ct
+9s
+7e
+7l
+4itura
+9s
+8e
+3t
+4a
+5bilities
+9ty
+6le
+5cean
+9s
+7ous
+6ies
+6y
+5e
+5ment
+9al
+9ar
+9arily
+9ary
+9s
+6ur
+8s
+5te
+7s
+6ion
+9s
+6or
+8s
+6rices
+8x
+9es
+6um
+8s
+4cross
+9ed
+9es
+9ing
+4e
+5d
+5e
+6s
+5r
+6n
+7ed
+7ing
+7s
+6s
+5s
+4iculated
+5er
+6st
+5ficate
+9tes
+9tion
+9tions
+9tor
+9tors
+9tory
+7ed
+8r
+9s
+8s
+6y
+7ing
+5ly
+5monial
+9alise
+9alised
+9alises
+9alize
+9alized
+9alizes
+9als
+9ed
+9es
+8y
+9ing
+5ness
+9es
+6g
+7s
+5s
+4on
+6s
+5on
+7s
+5sterone
+9ones
+4ril
+7l
+8s
+7s
+4s
+4udinal
+9ry
+8eous
+9s
+6o
+7s
+4y
+2t
+3anal
+5ic
+7al
+9ly
+7s
+6es
+6sation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5oid
+5us
+7es
+5y
+4rtohedral
+9drally
+9drism
+9drisms
+3ched
+5ier
+7st
+6ly
+6ness
+9ses
+5y
+3e
+4s
+3h
+4er
+6ball
+9ls
+6ed
+6ing
+6s
+4s
+3otum
+7s
+3ra
+5basic
+9cities
+9city
+6rach
+9hs
+8nchiate
+5caine
+9es
+6hloride
+9rides
+7ord
+9dal
+9ds
+8tomies
+9omous
+9omy
+6id
+8s
+6t
+7inal
+9e
+7s
+6yclic
+9ine
+9ines
+5d
+6actyl
+9ylies
+9ylous
+9yls
+9yly
+6ic
+7te
+9s
+6rachm
+9hms
+6s
+6ymite
+9tes
+7namous
+5ethyl
+9ls
+5fluoride
+9rides
+5gon
+8al
+9lly
+9lness
+8ous
+8s
+6ram
+9maton
+9matons
+9s
+6ynian
+8ous
+5hedra
+9al
+9ally
+9ite
+9ites
+9on
+9ons
+6ydrofuran
+7mena
+9nas
+5logies
+8y
+5mer
+8al
+8ic
+9sm
+9sms
+8ous
+8s
+7ter
+9rs
+8hyllead
+6orphic
+5ndrian
+8ous
+5pla
+8s
+7egia
+9ias
+9ic
+7oid
+9dies
+9ds
+9dy
+6od
+8ic
+9es
+8ous
+8s
+8y
+7lis
+9ses
+9tan
+6teran
+9ous
+7ote
+9es
+6yrrole
+9oles
+5rch
+8ate
+9tes
+8ic
+9cal
+9es
+8s
+8y
+5s
+6emic
+6porangia
+9angium
+9e
+9es
+9ic
+9ous
+6tich
+9hal
+9hic
+9hous
+9hs
+7yle
+9es
+6yllabic
+9abical
+9able
+9ables
+5theism
+9sms
+7lon
+9ns
+6omic
+5valencies
+9ncy
+9nt
+9nts
+5xon
+8s
+5zolium
+9ums
+6zini
+4i
+5s
+4ode
+7s
+6otoxin
+9xins
+5nal
+8s
+5toxin
+9ns
+5xid
+8e
+9s
+8s
+4yl
+6s
+3s
+3ter
+6ed
+6ing
+6ous
+6s
+4ix
+6es
+2uch
+5at
+7s
+5er
+6st
+5ter
+8s
+3gh
+5er
+6st
+5ly
+3tonise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+2vatron
+8s
+2w
+3art
+6s
+3ed
+4l
+5s
+3hit
+6s
+3ing
+4t
+5s
+3s
+2x
+3as
+5es
+3es
+3t
+4book
+8ish
+8s
+4ed
+5r
+6s
+4ile
+7s
+5ng
+7s
+4less
+4orial
+4phone
+9s
+4s
+4ual
+7ism
+9ms
+9t
+9ts
+7ly
+6ries
+7y
+5ral
+8ly
+6e
+7d
+7less
+7s
+6ing
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+1hack
+5ed
+5ing
+5s
+3e
+3gi
+5s
+3im
+4rm
+6s
+3lamencephala
+6i
+7c
+8ally
+7floral
+6us
+5ssaemia
+9mias
+9mic
+7emia
+9ias
+9ic
+9ics
+7ian
+9ns
+8c
+7ocracies
+9racy
+9rat
+9rats
+8grapher
+9raphic
+9raphy
+8therapy
+5ttocracies
+9racy
+4e
+5r
+6s
+4i
+5an
+5ctrum
+9ms
+5domide
+9des
+5s
+4li
+6c
+6form
+6ne
+6ous
+6um
+8s
+5oid
+6phyte
+9tes
+9tic
+6us
+5us
+7es
+4weg
+7s
+3n
+4a
+5dar
+8s
+5ge
+7s
+5h
+6s
+5s
+5tism
+9s
+8t
+9s
+6ognomonic
+8raphies
+9aphy
+7id
+7logical
+9gies
+9gist
+9gists
+9gy
+7phobia
+9obias
+8ses
+9is
+7s
+8es
+8is
+4e
+5dom
+8s
+5hood
+9s
+5s
+6hip
+9s
+4g
+5ka
+7s
+5s
+4k
+5ed
+6e
+6r
+7s
+5ful
+8ler
+9est
+9y
+8ness
+9esses
+5ing
+8s
+6t
+5less
+9ly
+9ness
+9nesses
+5s
+6giver
+9ers
+9ing
+9ings
+5worthily
+9hiness
+9hy
+5you
+8s
+4na
+6h
+7s
+6s
+4s
+3r
+4borough
+9ghs
+4m
+5s
+4s
+3t
+4away
+4ch
+6ed
+7r
+8s
+7s
+6ier
+8st
+7ng
+9s
+6less
+6t
+6y
+4ness
+8es
+3umasite
+9es
+6tin
+9s
+7ogenies
+9eny
+9raphy
+8latries
+9atry
+9ogies
+9ogy
+7rope
+9pes
+9pical
+7urge
+9ges
+9gic
+9gical
+9gics
+9gies
+9gism
+9gisms
+9gist
+9gists
+9gus
+9guses
+9gy
+3w
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7s
+4less
+4s
+4y
+2e
+3aceous
+4ndric
+5thropic
+9pies
+9pism
+9pisms
+9pist
+9pists
+9py
+4rchic
+8es
+7y
+4ter
+7goer
+9ers
+9ing
+9ings
+7s
+5ral
+6e
+7s
+6ic
+8al
+9lise
+9lised
+9lises
+9lising
+9lism
+9lisms
+9lities
+9lity
+9lize
+9lized
+9lizes
+9lizing
+9lly
+9lness
+9ls
+8ise
+9sed
+9ses
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+8s
+6omania
+9nias
+7phone
+9ones
+4ve
+6s
+3baine
+8s
+4e
+5s
+3ca
+5e
+5l
+5te
+4odont
+9s
+3e
+4d
+4ing
+4k
+5ed
+5ing
+5s
+4lin
+7s
+5ol
+7s
+4s
+3ft
+5less
+5s
+5uous
+9ly
+3gither
+4n
+5ly
+5s
+3ic
+5s
+4n
+5e
+6s
+5s
+4r
+5s
+6elf
+8ves
+4sm
+6s
+5t
+6ic
+8al
+9lly
+6s
+3lement
+9s
+4f
+4itis
+8es
+4ves
+4ytokies
+8ous
+8y
+3m
+4a
+5ta
+6ic
+8ally
+8s
+7sation
+9tions
+7zation
+9tions
+4e
+5d
+5less
+5s
+4ing
+4self
+7ves
+3n
+4about
+9s
+5ge
+7s
+5l
+5r
+6dite
+9es
+6s
+4ce
+6forth
+9ward
+9wards
+4s
+3obromine
+9nes
+4centric
+9icism
+9icisms
+9icity
+9ism
+9isms
+5on
+7s
+5racies
+8y
+7sies
+8y
+7t
+8ic
+9cal
+9cally
+8s
+4dicean
+9ns
+7ies
+7y
+5olite
+9es
+9ic
+4gonic
+9al
+8es
+8st
+9ts
+7y
+4log
+7aster
+9ters
+8te
+9es
+7er
+9s
+7ian
+9ns
+8c
+9al
+9ally
+8es
+8sation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9t
+9ts
+8zation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+7oumena
+9menon
+7s
+7ue
+9s
+7y
+4machies
+9st
+9sts
+8y
+6ncies
+8y
+7ia
+9c
+9cs
+9s
+7tic
+5orphic
+9ism
+9isms
+4nomies
+7ous
+7y
+4pathetic
+8ic
+9es
+8y
+5hagies
+8ous
+8y
+7nic
+9es
+8ous
+8y
+6obia
+9ac
+9acs
+9as
+9st
+9sts
+7ric
+6ylline
+9ines
+5neust
+9tic
+9ties
+9ty
+4rbist
+9s
+6o
+7s
+5em
+7atic
+9ical
+9ically
+9ist
+9ists
+7ic
+7s
+6tic
+9al
+9ally
+9ian
+9ians
+9s
+5ic
+7s
+6es
+6que
+9s
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7t
+8s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5y
+4soph
+8er
+9rs
+8ic
+9cal
+9cally
+9es
+9se
+9sed
+9ses
+9sing
+9sm
+9sms
+9st
+9stical
+9sts
+9ze
+9zed
+9zes
+9zing
+8s
+8y
+4technic
+9ies
+9y
+5okoi
+8s
+4w
+5s
+3ralite
+9s
+5peuses
+9is
+8tic
+9ically
+9ics
+9ist
+9ists
+6ies
+7st
+9s
+6sid
+9s
+6y
+4blig
+8s
+4e
+5about
+9ts
+6fter
+6gainst
+6mong
+6nent
+6t
+6way
+5beside
+6y
+5for
+8e
+6rom
+5in
+7after
+7before
+7to
+5min
+8s
+5ness
+9es
+5of
+6n
+6ut
+5s
+5through
+6o
+7fore
+5under
+7to
+6pon
+5with
+9al
+9in
+4iac
+7a
+8l
+8s
+7s
+6n
+7s
+7thropic
+9ropism
+5olatries
+9ry
+6morph
+9phic
+9phism
+9phisms
+9phoses
+9phosis
+9phous
+9phs
+4m
+5ae
+7sthesia
+9hesias
+6l
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7s
+5e
+6l
+7s
+6s
+7thesia
+9esias
+6tte
+9s
+5ic
+7al
+9ly
+6dor
+9s
+6on
+8ic
+9cs
+8s
+6stor
+9rs
+6t
+7e
+8s
+7s
+5obaric
+9ograph
+9ometer
+6chemical
+9mist
+9mistry
+9mists
+8romic
+9omies
+9omism
+9omisms
+9omy
+7line
+9nes
+7ouple
+9ples
+6duric
+7ynamic
+9amical
+9amics
+6electric
+9ctron
+9ctrons
+9ment
+9ments
+6form
+9mable
+9med
+9ming
+9ms
+6geneses
+9esis
+9etic
+9ic
+9ous
+7ram
+9ms
+9ph
+9pher
+9phers
+9phic
+9phies
+9phs
+9phy
+6haline
+6junction
+9ctions
+6labile
+9ility
+7ogies
+9y
+7yses
+9is
+8tic
+6magnetic
+7eter
+9ers
+9ric
+9rical
+9ries
+9ry
+7otor
+9ors
+6nasties
+9ty
+7uclear
+6periodic
+9iodism
+7hil
+9le
+9les
+9lic
+9lous
+9ls
+8yllous
+7ile
+9es
+7lastic
+9stics
+6receptor
+9eptors
+8gulate
+9ulated
+9ulates
+9ulator
+8manence
+9anent
+6s
+7cope
+9pes
+9pic
+9pical
+7es
+8t
+9s
+9ting
+7iphon
+9hons
+7phere
+9eres
+9eric
+7tability
+9ble
+9t
+9ted
+9tic
+9tics
+9ting
+9ts
+9tted
+9tting
+6tactic
+8xes
+9ic
+9is
+7ensile
+7herapies
+9rapy
+7ic
+9al
+9s
+7olerant
+7ropic
+9pics
+9pism
+9pisms
+5s
+4oid
+5logies
+8y
+5phyte
+9es
+6od
+8an
+9ns
+8s
+4sitical
+3saural
+7i
+7us
+9es
+4e
+5s
+4is
+4mothete
+9tes
+4p
+5ian
+8s
+5s
+3ta
+5s
+4ch
+6ed
+7s
+6ing
+4e
+5s
+4her
+4ic
+6al
+8ly
+3urgic
+8al
+9lly
+7es
+7st
+9s
+6y
+3w
+4ed
+5s
+4ier
+6st
+4less
+4s
+4y
+3y
+2iabendazole
+9zoles
+4min
+7ase
+9es
+7e
+8s
+7s
+4sus
+7es
+4zide
+8s
+6n
+7e
+8s
+7s
+5ol
+7e
+8s
+7s
+3bet
+6s
+4le
+6s
+3ck
+5ed
+6n
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6r
+6st
+6t
+7ed
+7s
+7y
+5head
+9ed
+9edness
+9s
+5ie
+7s
+6ng
+6sh
+5leaf
+8ves
+6y
+5ness
+9es
+5o
+6es
+6s
+5s
+6et
+8s
+6kin
+9s
+5y
+3ef
+5like
+4ve
+6d
+6ries
+7y
+6s
+5ing
+8s
+6sh
+8ly
+8ness
+9esses
+3g
+4ger
+7s
+5ing
+8s
+6t
+4h
+5bone
+9s
+5ed
+5s
+4motactic
+8xes
+9is
+7ropic
+9pism
+9pisms
+4s
+3lk
+4l
+5er
+7s
+5s
+3mble
+7berries
+9rry
+7d
+7ful
+9ls
+7rig
+9gged
+9gger
+9ggers
+9gging
+9ggings
+9gs
+7s
+8ful
+7weed
+9eds
+8it
+9ts
+9tted
+6ing
+4erosal
+9ls
+3n
+4clad
+8s
+4down
+8s
+4e
+4g
+5amabob
+9obs
+8jig
+9igs
+7ies
+7y
+8bob
+9obs
+8jig
+9igs
+5hood
+9s
+5ier
+7s
+8t
+6ness
+9ses
+5liness
+9sses
+5ness
+9es
+5s
+5umabob
+9obs
+8jig
+9igs
+7bob
+9bs
+7mies
+8y
+9bob
+9bobs
+9jig
+9jigs
+5y
+4k
+5able
+9ness
+9nesses
+8y
+5er
+7s
+5ing
+8ly
+8ness
+9esses
+8s
+5piece
+9es
+5s
+4ly
+4ned
+6r
+7s
+6ss
+8es
+7t
+5ing
+8s
+6sh
+4s
+3o
+4alcohol
+9ols
+4bacilli
+9lus
+6rbiturate
+4carbamide
+9mides
+5yanate
+9tes
+8ic
+4diglycol
+9cols
+4furan
+9s
+4l
+5ic
+5s
+4nate
+8s
+5ic
+6n
+7e
+8s
+7s
+5yl
+7s
+4pental
+9ls
+8one
+9nes
+5hen
+8e
+9s
+8s
+6il
+4ridazine
+9ines
+4sinamine
+9ines
+5ulfate
+9tes
+7phate
+9ates
+9uric
+4tepa
+8s
+4uracil
+9ls
+6ea
+8s
+3r
+4am
+6s
+4d
+5borough
+9ughs
+5ed
+5hand
+5ing
+8s
+5ly
+5s
+6man
+7en
+6tream
+9ams
+4l
+5age
+8s
+5ed
+5ing
+5s
+4st
+6ed
+7r
+8s
+6ful
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+6less
+6s
+6y
+4teen
+8s
+8th
+9hly
+9hs
+5ies
+7th
+9s
+5y
+6fold
+6ish
+6something
+3s
+4away
+4ness
+8es
+4tle
+7down
+9wns
+7s
+6ier
+8st
+6y
+3ther
+7to
+7ward
+9rds
+3vel
+6s
+3xotrope
+9es
+9ic
+9ies
+9y
+2lipses
+6is
+2o
+3ft
+5s
+3le
+5d
+5iite
+9s
+8ic
+5pin
+8s
+5s
+4i
+5ng
+4obate
+9s
+5i
+5s
+4us
+3n
+4der
+4g
+5ed
+5s
+3racal
+6enteses
+9esis
+7s
+6ic
+8ally
+6ocenteses
+9ntesis
+7plasties
+9asty
+7scope
+9opes
+8tomies
+9omy
+7tomies
+9my
+5x
+6es
+4ia
+6nite
+9es
+6s
+5c
+5te
+7s
+5um
+7s
+4n
+5back
+9s
+6ill
+9s
+7rd
+9s
+6ush
+9es
+5ed
+5hedge
+9es
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5less
+6ike
+5proof
+9fs
+5s
+6et
+5tree
+9s
+5y
+4o
+5n
+6s
+5ugh
+8bass
+9asses
+9race
+9raced
+9races
+9red
+9reds
+8er
+9st
+8fare
+9ares
+8going
+9oingly
+8ly
+8ness
+9esses
+8paced
+9in
+9ins
+8s
+8wax
+9axes
+9ort
+9orts
+4p
+5e
+6s
+5s
+3se
+3ther
+3u
+4ed
+4gh
+6t
+7cast
+9sts
+7ed
+8n
+7ful
+9lly
+9lness
+7less
+9ssly
+9ssness
+7s
+7way
+9ys
+4ing
+4s
+5and
+8fold
+9olds
+8s
+8th
+9hs
+3wel
+6s
+4l
+5ess
+5s
+2rae
+4iping
+9s
+4ldom
+8s
+5l
+6dom
+9s
+6ed
+6ing
+6s
+4ng
+6ed
+6ing
+6s
+4pple
+8d
+8s
+7ing
+4sh
+6ed
+7r
+8s
+7s
+6ing
+9s
+5onic
+9al
+9ally
+4ve
+6s
+4w
+5ard
+7t
+5ed
+5ing
+5n
+6ly
+5s
+3ead
+6bare
+9eness
+6ed
+7n
+7r
+8s
+6fin
+9s
+6ier
+8st
+7ness
+9sses
+8g
+6less
+7ike
+6maker
+9ers
+6s
+6worm
+9ms
+6y
+5p
+6ed
+7r
+8s
+6ing
+7t
+6s
+5t
+6ed
+7n
+8ed
+9r
+9rs
+8ing
+9ngly
+9ngs
+8s
+6ful
+6ing
+6s
+5ve
+7s
+4e
+5fold
+9ness
+9nesses
+5ness
+9es
+5p
+6eat
+9ed
+9ing
+9s
+7d
+7nce
+9es
+9eworth
+8nies
+9y
+9yworth
+7r
+8s
+6ing
+7t
+6s
+5s
+6core
+9es
+4mmatologies
+9logy
+4ne
+6s
+6tic
+9al
+5ode
+8s
+7ial
+8c
+8es
+8st
+9ts
+7y
+6s
+7es
+4onine
+9s
+4sh
+6ed
+7l
+8s
+7r
+8s
+7s
+6ing
+9s
+6old
+9s
+4tties
+6y
+4w
+3ice
+4d
+5ace
+8s
+5ded
+6ing
+5s
+4ft
+6ier
+8st
+7ly
+7ness
+9sses
+6less
+9sly
+9sness
+6s
+6y
+4ll
+6ant
+6ed
+7r
+8s
+6ier
+8st
+7ng
+9ly
+9ness
+9nesses
+6s
+6y
+4msa
+7s
+4p
+5s
+6es
+4ssel
+8s
+5t
+6ed
+6ing
+6le
+8s
+6s
+6y
+4ve
+6d
+6less
+6n
+6r
+7s
+6s
+5ing
+8ly
+8ness
+9esses
+8s
+3o
+4at
+6ed
+6ier
+8st
+7ly
+7ness
+9sses
+6lash
+9hes
+8tch
+9ches
+6s
+6wort
+9ts
+6y
+4b
+5bed
+7r
+8s
+6ing
+9ly
+9s
+5less
+5s
+4e
+5d
+5ing
+5s
+4mbi
+7n
+8s
+6ocyte
+9tes
+9tic
+7embolic
+9bolism
+7gen
+9ns
+7kinase
+9nases
+7lyses
+9sis
+9tic
+9tics
+7philia
+9ilias
+8lastic
+9astin
+9astins
+7se
+9d
+9s
+8ing
+9s
+7tic
+7xane
+9nes
+6us
+4ne
+6d
+6less
+6s
+5g
+6ed
+6ful
+6ing
+9s
+6s
+5ing
+5ner
+8s
+4pple
+8d
+8s
+7ing
+4stle
+8s
+4ttle
+8able
+8d
+8hold
+9olds
+8r
+9s
+8s
+7ing
+9gs
+4ugh
+7fare
+9res
+7gaun
+9uns
+7ither
+7ly
+7other
+8ut
+7put
+9ts
+7way
+9ys
+4ve
+4w
+5away
+9s
+5back
+9s
+5down
+9s
+5e
+6r
+7s
+6s
+5ing
+8s
+5n
+5s
+6ter
+9s
+3u
+4m
+5med
+7r
+8s
+6ier
+8st
+7ng
+9ly
+9s
+6y
+5s
+4penny
+5pence
+9es
+8nies
+9y
+5ut
+7s
+4sh
+6es
+5t
+6ed
+7r
+8s
+6ful
+6ing
+9s
+6or
+8s
+6s
+4tch
+7ed
+8s
+7ing
+4way
+7s
+3ymsa
+7s
+2ud
+4ded
+5ing
+8ly
+4s
+3g
+4gee
+7s
+6ries
+7y
+5ish
+7m
+8s
+5o
+6s
+4s
+3ja
+5s
+3lia
+6s
+5te
+7s
+5um
+7s
+3mb
+5ed
+5hole
+9s
+5ier
+7st
+6kins
+6ng
+5kin
+8s
+5less
+6ike
+7ng
+9s
+5nail
+9s
+6ut
+8s
+5piece
+9es
+6ot
+8s
+6rint
+9ts
+5s
+6crew
+9ws
+6tall
+9ls
+5tack
+9ed
+9ing
+9s
+5wheel
+9ls
+5y
+4p
+5ed
+6r
+7s
+5ing
+8ly
+5s
+3nbergia
+9as
+4der
+7bird
+9rds
+8olt
+9lts
+9x
+9xes
+7clap
+9aps
+9oud
+9ouds
+7ed
+8r
+9s
+7flash
+9ashes
+7head
+9ads
+7ier
+9st
+8ng
+9gly
+9gs
+7less
+7ous
+9sly
+9sness
+7s
+8hower
+9owers
+8tone
+9ones
+9orm
+9orms
+9ricken
+9rike
+9rikes
+9riking
+9roke
+9rokes
+9ruck
+7y
+5rous
+4k
+5ed
+5ing
+5s
+3rible
+8s
+5fer
+8ous
+8s
+6ication
+9tions
+7ed
+8s
+6y
+7ing
+4l
+5s
+3s
+4es
+4ly
+4ness
+8es
+4wise
+3ya
+5s
+2wack
+6ed
+7r
+8s
+6ing
+9s
+6s
+4ite
+7s
+4rt
+6ed
+8ly
+7r
+8s
+6ing
+9ly
+9s
+6ly
+6s
+7hip
+9ps
+6ways
+7ise
+2y
+3ine
+3lacine
+9s
+5koid
+9s
+4ose
+7s
+6is
+3me
+5ctomies
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9y
+5laeaceous
+5s
+5y
+4i
+5c
+5dine
+9s
+6ylic
+5er
+6st
+5ne
+7s
+4ocyte
+9s
+5l
+6s
+5sin
+8s
+4us
+6es
+4y
+3ratron
+9s
+4eoid
+8s
+4istor
+9s
+4ocalcitonin
+5globulin
+9ulins
+5id
+7al
+7ectomies
+9tomy
+7ites
+9ides
+9is
+9ises
+7s
+5toxicoses
+9cosis
+6rophic
+9hin
+9hins
+9ic
+9in
+9ins
+5xin
+8e
+9s
+8s
+4se
+6s
+5i
+5oid
+8al
+5us
+3sanopterous
+6uran
+9ns
+8ous
+4elf
+1i
+2an
+4s
+3r
+4a
+5ed
+5s
+4s
+2bia
+5e
+5l
+5s
+4ofibula
+9lae
+9las
+5tarsi
+9us
+3ouchina
+9as
+2c
+3al
+5s
+3ca
+4ed
+4ing
+3e
+4d
+4s
+3h
+4es
+4ier
+6st
+4orrhine
+4y
+3ing
+3k
+4ed
+5n
+6s
+5r
+6s
+5t
+6ed
+6ing
+9s
+6less
+6s
+6tyboo
+5y
+6s
+4ies
+5ng
+7s
+4lace
+8s
+5e
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8s
+6sh
+8ly
+8ness
+9esses
+5y
+4s
+5eed
+8s
+4tack
+8ed
+8ing
+8s
+8toe
+9oes
+5ock
+8ed
+8ing
+8s
+4y
+3s
+3tac
+6ked
+7ing
+6s
+4oc
+6ked
+7ing
+6s
+2d
+3al
+5ly
+3bit
+6s
+3dier
+6s
+7t
+4le
+6d
+7ywink
+9inks
+6r
+7s
+6s
+6y
+7s
+5ier
+7s
+8t
+6ng
+5y
+6wink
+9ks
+4y
+3e
+4d
+4land
+8s
+5ess
+5ike
+6ne
+8s
+4mark
+8s
+5ill
+8s
+4rip
+7s
+4s
+5man
+6en
+4waiter
+9rs
+6ter
+9s
+6ve
+8s
+6y
+7s
+3ied
+5r
+6s
+5s
+6t
+4ly
+4ness
+8es
+5g
+6s
+4vate
+8d
+8s
+7ing
+8on
+9ns
+3s
+3y
+4ing
+4tips
+2e
+3back
+7s
+4reak
+8er
+9rs
+8s
+3clasp
+8s
+3d
+3ing
+3less
+3mannite
+9es
+3pin
+6s
+3r
+4ce
+6d
+6l
+7et
+9s
+7s
+6ron
+9s
+6s
+6t
+7s
+4ed
+4ing
+4s
+3s
+3tac
+6k
+7s
+6s
+2ff
+4anies
+6y
+4ed
+4in
+6ed
+6g
+7s
+6ing
+6s
+4s
+3osi
+5o
+3t
+4ed
+4ing
+4s
+2g
+3e
+4r
+5eye
+8s
+5ish
+8ly
+8ness
+9esses
+7m
+8s
+5like
+6y
+5s
+5wood
+9s
+5y
+4s
+3ged
+4ing
+4ywinkle
+9les
+3ht
+5assed
+9s
+5en
+7ed
+8r
+9s
+7ing
+7s
+6r
+6st
+5fisted
+9edness
+5ish
+8ly
+5knit
+5ly
+5ness
+9es
+5rope
+9s
+5s
+5wad
+8s
+6ire
+9s
+3lic
+4on
+6s
+3on
+5s
+3ress
+7es
+4idia
+8s
+5ne
+5sh
+7ly
+7ness
+9sses
+4oid
+3s
+2k
+3a
+4nga
+7s
+4s
+3e
+4s
+3i
+4ed
+4ing
+4s
+3ka
+5s
+3oloshe
+9s
+3s
+3taalik
+9s
+2l
+3ak
+5s
+4pia
+7s
+3buries
+6y
+3de
+5s
+3e
+4d
+4fish
+8es
+4like
+4r
+5ies
+5s
+5y
+4s
+3iaceous
+4ng
+6s
+3l
+4able
+5ge
+7s
+5ndsia
+9as
+4ed
+5r
+6ed
+6ing
+6less
+6man
+7en
+6s
+4icum
+8s
+5er
+6st
+5ng
+7s
+5te
+7s
+4s
+4y
+3s
+3t
+4able
+4ed
+5r
+6s
+4h
+5s
+4ing
+7s
+4meter
+9s
+4rotor
+9s
+4s
+4yard
+8s
+2marau
+7s
+5iot
+8s
+3bal
+6e
+7s
+6s
+4er
+6doodle
+9dles
+6ed
+6head
+9ds
+6ing
+9s
+6land
+9ds
+7ine
+9es
+6man
+7en
+6s
+6work
+9ks
+6y
+7ard
+9ds
+4o
+5s
+4ral
+5e
+6l
+7led
+7s
+6s
+5ologies
+9ist
+9ists
+9y
+6mania
+9iac
+9iacs
+9ias
+6philies
+9list
+9lists
+9ly
+3e
+4bomb
+8s
+4card
+8s
+4d
+4frame
+9s
+4keeper
+9rs
+8ing
+9ngs
+4less
+8ly
+8ness
+9esses
+5ier
+7st
+6ne
+8s
+9s
+9ses
+5y
+4noguy
+9s
+4ous
+7ly
+6t
+7s
+4pass
+8ed
+9s
+8ing
+5iece
+9s
+5leaser
+9ers
+4r
+5s
+4s
+5aver
+9s
+7ing
+5cale
+9s
+5erver
+9rs
+8ing
+9ngs
+5hare
+9s
+5tamp
+9ed
+9ing
+9s
+4table
+9d
+9s
+8ing
+4work
+8er
+9rs
+8s
+7n
+3id
+5er
+6st
+5ities
+7y
+5ly
+5ness
+9es
+4ng
+6s
+4st
+6s
+3ocracies
+8y
+7tic
+9cal
+4lol
+7s
+4n
+5eer
+8s
+5s
+4rous
+8ly
+8ness
+9esses
+5some
+4thies
+6y
+4us
+6ly
+3pana
+6i
+7st
+9s
+6o
+6um
+8s
+4s
+2n
+3a
+4ja
+6s
+4mou
+7s
+4s
+3cal
+6s
+4hel
+7s
+4t
+5ed
+5ing
+5orial
+9lly
+5s
+5ure
+8d
+8s
+7ing
+3d
+4al
+6s
+4ed
+5r
+6box
+9es
+6s
+6y
+4ing
+4s
+3e
+4a
+5l
+5s
+4d
+4id
+6s
+4s
+3foil
+7s
+4ul
+6s
+3g
+4e
+5d
+5ing
+5s
+4ing
+4le
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8ly
+8s
+6sh
+5y
+4s
+4uaite
+9s
+3horn
+7s
+3ier
+5s
+6t
+4ly
+4ness
+8es
+5g
+3k
+4ed
+5r
+6ed
+7r
+8s
+6ing
+9s
+6man
+7en
+6s
+6toy
+9s
+4ing
+4le
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8ly
+8s
+5y
+4s
+3like
+3man
+4en
+3ned
+5r
+6s
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+7s
+5tus
+8es
+4y
+3plate
+8d
+8s
+7ing
+4ot
+6s
+3s
+4el
+6ed
+6ing
+6led
+7ing
+7y
+6ries
+7y
+6s
+5y
+6s
+4mith
+8ing
+9ngs
+8s
+4nips
+4tone
+8s
+3t
+4ack
+7s
+4ed
+5r
+6s
+4ier
+6st
+5ness
+9es
+6g
+7s
+6nabula
+9ulant
+9ular
+9ulary
+9ulate
+9ulated
+9ulates
+9ulous
+9ulum
+4less
+4ometer
+9rs
+5okie
+9s
+4s
+4y
+5pe
+7s
+3ware
+7s
+4ork
+7s
+3y
+2p
+3cart
+7s
+5t
+6s
+3i
+4s
+3less
+3off
+6s
+3pable
+4ed
+5e
+6s
+5r
+6s
+5t
+6s
+4ier
+6st
+5ng
+7s
+4le
+6d
+6r
+7s
+6s
+5ing
+4y
+5toe
+8d
+8ing
+8s
+3s
+4heet
+8s
+4ier
+6st
+5fied
+8s
+6y
+7ing
+5ly
+5ness
+9es
+4taff
+8s
+6ves
+5er
+7s
+5ock
+8s
+4y
+3t
+4oe
+6d
+6ing
+6s
+5p
+6s
+4ronic
+9s
+3ula
+6s
+4na
+6s
+2rade
+6s
+4ge
+6s
+4illeur
+9rs
+4misu
+8s
+4sse
+7s
+3e
+4d
+5er
+6st
+5ly
+5ness
+9es
+4less
+8ly
+8ness
+9esses
+5ing
+8s
+4s
+5ome
+8ly
+8ness
+9esses
+4woman
+7en
+3ing
+6s
+4ti
+6s
+3l
+4ed
+4ing
+4s
+3o
+4cinium
+9ms
+4es
+4nic
+4s
+3r
+4ed
+4ing
+5t
+6s
+5vee
+8s
+6ie
+8s
+4s
+2s
+3ane
+6s
+3ick
+6s
+3sual
+5e
+6d
+6s
+6y
+5ing
+5lar
+3was
+6es
+2tan
+5ate
+8s
+5ess
+8es
+5ia
+7s
+6c
+7ally
+6ferous
+6s
+7es
+7m
+8s
+6te
+8s
+6um
+8s
+5osaur
+9rs
+6there
+9res
+6us
+5s
+4rakura
+9as
+3bit
+6s
+3ch
+5es
+5ier
+7st
+5y
+3e
+4ly
+4r
+5s
+3fer
+6s
+3hable
+4e
+5d
+5r
+6s
+5s
+4ing
+7man
+8en
+7s
+4onia
+8s
+3i
+4an
+6s
+4llate
+9d
+9s
+8ing
+9ngly
+9on
+9ons
+9ve
+8or
+9rs
+4pounamu
+9mus
+4s
+4vate
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+3lark
+7s
+4e
+5d
+5holder
+9ers
+9ing
+5less
+5r
+6s
+5s
+4ing
+7s
+5st
+7s
+3man
+4en
+4ice
+4ose
+5use
+3oki
+6s
+3rable
+5nt
+7s
+5table
+6e
+7d
+7s
+6ing
+7on
+9s
+6or
+8s
+4e
+5s
+4imetric
+3ted
+5r
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+4ing
+5sh
+5vate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+4le
+6bat
+9s
+6d
+6s
+5ing
+4up
+6ed
+6ing
+6ped
+7ing
+7y
+6s
+6y
+3ubancies
+8y
+7t
+6te
+8d
+8s
+7ing
+8on
+9ns
+4lar
+7ies
+8ties
+9y
+7ly
+7s
+7y
+5e
+6d
+6s
+5i
+6ng
+5us
+4p
+5ed
+5ing
+5ped
+6ing
+5s
+5y
+2vy
+2x
+2yin
+5s
+2zwas
+6es
+3z
+4es
+4ies
+4y
+1janting
+8s
+1meses
+4is
+1o
+2ad
+4eater
+9s
+4fish
+8es
+5lax
+8es
+4grass
+9es
+4ied
+6s
+5sh
+4less
+5ike
+4rush
+8es
+4s
+5tone
+9s
+7ol
+9s
+4y
+5ing
+6sh
+7m
+8s
+3st
+5ed
+6r
+7s
+5ie
+7r
+7s
+8t
+6ng
+8s
+5master
+9ers
+6istress
+9resses
+5s
+5y
+3ze
+5d
+5s
+4ing
+2baccanalian
+9lians
+6o
+7es
+7less
+7nist
+9sts
+7s
+3ies
+3oggan
+8ed
+9r
+9rs
+8ing
+9ngs
+9st
+9sts
+8s
+6in
+8ed
+8ing
+8s
+3y
+2c
+3cata
+7s
+6e
+7lla
+9as
+6ina
+9s
+3her
+6ed
+6ing
+6less
+6s
+3k
+4ed
+4ier
+6st
+5ng
+4ley
+7s
+4s
+4y
+3o
+4logies
+7y
+4pherol
+9ls
+4s
+3s
+4in
+6s
+2d
+3ay
+5s
+3de
+5d
+5s
+4ies
+5ng
+4le
+6d
+6r
+7hood
+9ods
+7s
+6s
+5ing
+4y
+3ger
+6s
+3ies
+3s
+3y
+2e
+3a
+4s
+3bie
+6s
+3cap
+6s
+4lip
+7s
+3d
+3hold
+7s
+3ier
+5st
+4ng
+3less
+4ike
+3nail
+7ed
+7ing
+7s
+3piece
+8s
+4late
+8s
+3rag
+6ger
+9s
+6s
+3s
+4hoe
+7s
+3toe
+6s
+3y
+2ff
+4ee
+6s
+4ier
+6s
+7t
+5sh
+7ness
+9sses
+4s
+4y
+3ore
+3t
+4s
+3u
+4s
+4tti
+7s
+2g
+3a
+4e
+5d
+4s
+4te
+6d
+4virus
+9es
+3e
+4d
+4s
+4ther
+8ness
+9esses
+3ged
+5r
+6ed
+6ies
+7ng
+6s
+6y
+4ing
+4le
+6d
+6r
+7s
+6s
+5ing
+3s
+3ue
+5s
+2heroa
+7s
+3o
+3unga
+7s
+2il
+4e
+5d
+5r
+6s
+5s
+5t
+6ed
+6ing
+6ries
+7y
+6s
+6te
+8s
+4ful
+7ly
+7ness
+9sses
+4inet
+8s
+8te
+9es
+6g
+7s
+4less
+4s
+5ome
+8ly
+8ness
+9esses
+4worn
+3ng
+5s
+3se
+5ach
+8s
+5ch
+7s
+5s
+4on
+6s
+3t
+4ed
+4ing
+4oi
+6s
+4s
+2kamak
+7s
+4y
+5s
+3e
+4d
+4n
+5ed
+5ing
+6sm
+8s
+7tic
+5s
+4r
+5s
+4s
+3ing
+3o
+4logies
+7y
+6she
+9s
+8i
+9s
+4mak
+7s
+4noma
+8s
+4s
+4toko
+8s
+3tokkie
+9s
+2la
+4n
+5e
+6s
+5s
+4r
+5jev
+6i
+5s
+4s
+3booth
+8s
+4utamide
+9des
+3d
+3e
+4d
+5o
+6s
+4rabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6nce
+9s
+7t
+8ly
+6te
+8d
+8s
+7ing
+8on
+9nism
+9nisms
+9nist
+9nists
+9ns
+8ve
+7or
+9s
+4s
+4ware
+8s
+3idin
+7e
+8s
+7s
+4ng
+6s
+3l
+4able
+5ge
+7s
+4bar
+7s
+5ooth
+9s
+5ridge
+9es
+4dish
+8es
+4ed
+5r
+6s
+5y
+6s
+4gate
+8s
+4house
+9s
+4ie
+6s
+5ng
+7s
+4man
+5en
+4s
+4way
+7s
+4y
+3sel
+6s
+5y
+6s
+3t
+4er
+6ed
+6ing
+6s
+4s
+3u
+4ate
+7s
+4ene
+7s
+4ic
+5d
+6e
+7s
+6ide
+9s
+7n
+8e
+9s
+8s
+6s
+4ol
+6e
+7s
+6s
+4s
+4yl
+6s
+3yl
+5s
+3zey
+6s
+2m
+3ahawk
+8ed
+8ing
+8s
+4lley
+8s
+4n
+5s
+4tillo
+9es
+9s
+5o
+6es
+7y
+3b
+4ac
+6k
+7s
+6s
+5k
+6s
+5l
+4ed
+4ic
+5ng
+4less
+5ike
+4oc
+6s
+5la
+7s
+6o
+7s
+5y
+6ish
+9ly
+9ness
+9nesses
+6s
+4s
+5tone
+9s
+3cat
+6s
+6ted
+7ing
+4od
+6s
+3e
+4nta
+6ose
+7us
+6um
+4s
+3fool
+7ed
+8ries
+9y
+7ing
+8sh
+9hness
+7s
+3ia
+5l
+4um
+3med
+4ied
+6s
+5ng
+4y
+5ing
+5rot
+8s
+3o
+4gram
+8s
+7ph
+9ic
+9ies
+9s
+9y
+4rrow
+8s
+4s
+3pion
+7s
+4on
+6ed
+6ing
+6s
+3s
+3tit
+6s
+2n
+3al
+5ite
+8s
+7ic
+8es
+8ve
+7y
+5ly
+4nt
+3di
+5ni
+6o
+7s
+4o
+5s
+3e
+4arm
+7s
+4d
+4less
+8ly
+8ness
+9esses
+4me
+6s
+5ic
+4pad
+7s
+4r
+5s
+4s
+4tic
+7ally
+7s
+5te
+7s
+4y
+3g
+4a
+5s
+4ed
+5r
+6s
+4ing
+4man
+5en
+4s
+5ter
+8s
+4ue
+6d
+6less
+8t
+9s
+7ike
+6s
+7ter
+9rs
+5ing
+8s
+3ic
+5ally
+5ities
+7y
+5s
+4er
+5s
+6t
+4ght
+7s
+4ng
+6s
+4sh
+6ly
+6ness
+9ses
+4te
+6s
+3k
+4a
+4ed
+5r
+6s
+4ing
+4s
+3let
+6s
+3nag
+6e
+7s
+6s
+4e
+5au
+7s
+7x
+5ll
+7s
+5r
+6s
+5s
+4ish
+7ly
+7ness
+9sses
+3ometer
+9s
+7ric
+9es
+8y
+4plast
+9s
+3s
+4il
+6ar
+6itis
+9ses
+6lar
+9y
+7ectomies
+9tomy
+7ites
+9ic
+9ides
+9is
+9ises
+7otomies
+9omy
+6s
+4or
+6ial
+6s
+4ure
+7d
+7s
+6ing
+3tine
+7r
+8s
+7s
+3us
+5es
+3y
+2o
+3art
+6s
+3k
+3l
+4bag
+7s
+6r
+7s
+5ox
+7es
+4ed
+5r
+6s
+4head
+8s
+5older
+9rs
+6use
+9s
+4ie
+6s
+5ng
+7s
+4kit
+7s
+4less
+4maker
+9s
+7ing
+9gs
+6n
+5en
+4pusher
+9rs
+4room
+8s
+4s
+5et
+7s
+5hed
+8s
+3m
+4ed
+5r
+5st
+4ing
+4s
+3n
+4ie
+6s
+4s
+3rie
+6s
+3shie
+7r
+7st
+3t
+4ed
+5r
+6s
+4h
+5ache
+9s
+5brush
+9hes
+9hing
+9hings
+5comb
+9s
+5ed
+5fish
+9es
+6ul
+8s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+5less
+6ike
+5paste
+9es
+6ick
+9s
+5s
+6hell
+9ls
+6ome
+9ly
+9ness
+9nesses
+5wash
+9es
+6ort
+9s
+5y
+4ing
+4le
+6d
+6r
+7s
+6s
+5ing
+4s
+5ed
+6s
+5ie
+7s
+6ng
+5y
+2p
+3agnoses
+8ia
+9as
+9s
+4lgia
+8s
+4rch
+7ies
+7s
+7y
+4z
+5es
+5ine
+5olite
+9es
+3coat
+7s
+4ross
+8es
+3dressing
+9ngs
+3e
+4ctomies
+8y
+4d
+4e
+5s
+4k
+5s
+4r
+5s
+4s
+3flight
+4ul
+6l
+3gallant
+9ts
+3h
+4aceous
+4e
+5s
+4i
+4s
+4us
+3i
+4arian
+7es
+7st
+9s
+6y
+4c
+5al
+7ities
+9y
+7ly
+5s
+4ng
+4s
+3kick
+7s
+4not
+7s
+7ted
+3line
+7d
+7r
+8s
+7s
+6ing
+4oftical
+8er
+9st
+8ly
+8ness
+9esses
+7y
+3maker
+8s
+6ing
+9s
+5n
+5st
+7s
+4en
+4innow
+9s
+4ost
+3notch
+8er
+9rs
+3o
+4centric
+5hemistries
+9stry
+4graph
+9er
+9ers
+9ic
+9ical
+9ically
+9ies
+9s
+9y
+4i
+4logic
+9al
+9ally
+8es
+8st
+9ts
+7y
+4nym
+7al
+7ic
+9al
+9s
+8es
+8st
+9ts
+7s
+7y
+4philia
+9as
+4s
+4type
+8s
+3ped
+5r
+6s
+4ier
+6st
+5ng
+7ly
+7s
+4le
+6d
+6s
+5ing
+4y
+3s
+4ail
+7s
+4core
+8d
+8s
+7ing
+4ide
+7r
+8s
+7s
+4man
+5en
+4oil
+7ed
+7ing
+9gs
+7s
+4pin
+7s
+4titch
+9ed
+9es
+9ing
+5one
+8s
+3work
+7ed
+7ing
+7s
+2que
+5s
+5t
+6s
+4illa
+8s
+2r
+3a
+4h
+5s
+4n
+5a
+6s
+5s
+4s
+3banite
+9s
+4ernite
+9es
+3c
+4h
+5able
+5bearer
+9ers
+5ed
+6r
+7e
+8s
+7s
+6s
+5ier
+8e
+9s
+8s
+7st
+6ng
+8s
+5light
+9ts
+7ke
+5on
+7s
+5wood
+9s
+5y
+4s
+4ular
+8s
+3dion
+7s
+3e
+4ador
+8s
+4ro
+6s
+4s
+4utic
+8s
+3goch
+7s
+3i
+4c
+5s
+4es
+4i
+3ment
+7a
+7ed
+9ly
+8r
+9s
+7il
+9s
+8ng
+9gly
+9gs
+7or
+9s
+7s
+7um
+9s
+4ina
+7l
+6ous
+3n
+4ade
+7s
+6ic
+6o
+7es
+7s
+4illo
+8s
+3o
+4id
+6al
+8ly
+6s
+4s
+5e
+5ities
+7y
+4t
+5h
+4us
+3pedinous
+6o
+7ed
+8r
+9s
+8s
+7ing
+8st
+9ts
+7s
+5fied
+8s
+6y
+7ing
+5scence
+9ces
+9t
+4id
+6ities
+8y
+6ly
+6ness
+9ses
+6s
+5tude
+9s
+4or
+6ific
+6s
+3quate
+8d
+5e
+6d
+6r
+7s
+6s
+7es
+5ing
+3r
+4efaction
+9ions
+6ied
+8s
+6y
+7ing
+5nt
+7ial
+9lities
+9lity
+9lly
+7s
+7uous
+5t
+6s
+4id
+6er
+7st
+6ities
+8y
+6ly
+6ness
+9ses
+5fied
+8s
+6y
+7ing
+4s
+3s
+4ade
+7s
+4e
+5l
+6s
+5s
+4i
+5bilities
+9ty
+5ograph
+9phs
+6n
+7al
+9ly
+7s
+5ve
+4k
+5s
+4o
+5s
+3t
+4a
+5s
+4e
+5lli
+8ni
+9is
+5n
+5s
+4feasor
+9rs
+4icollar
+9is
+9ises
+5le
+6ities
+8y
+6la
+8s
+7on
+9s
+5ous
+8ly
+5ve
+4oise
+8s
+9hell
+9hells
+5ni
+7s
+4rices
+7id
+9s
+6x
+7es
+4s
+4uosities
+9y
+6us
+8ly
+8ness
+9esses
+5re
+7d
+8ly
+7r
+8s
+7s
+8ome
+6ing
+9ly
+9s
+6ous
+9ly
+3ula
+6e
+6s
+5i
+6n
+7s
+5ose
+8s
+7is
+5us
+4s
+3y
+2sa
+4s
+3e
+4d
+4s
+3h
+4ach
+7s
+4ed
+5r
+6s
+5s
+4ier
+6st
+5ng
+4y
+3ing
+3s
+4ed
+5n
+5rs
+5s
+4icated
+5er
+6st
+5ly
+5ng
+7s
+4pot
+7s
+4up
+6s
+4y
+3t
+4ada
+7s
+6o
+7s
+4icated
+8ion
+9ons
+2t
+3able
+4l
+5ed
+5ing
+6sation
+9ions
+9or
+9ors
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+8s
+6tarian
+9ianise
+9ianism
+9ianize
+9ians
+7ies
+7y
+6zation
+9ions
+9or
+9ors
+7e
+8d
+8r
+9s
+8s
+7ing
+5led
+6ing
+6y
+5s
+4nus
+7es
+4quine
+9s
+4ra
+6s
+3e
+4able
+4d
+4m
+5ic
+7ally
+6sm
+8s
+7t
+8ic
+8s
+6te
+8s
+5s
+4r
+5s
+4s
+3her
+3ient
+7s
+4ng
+4palmate
+9tion
+9tions
+5otencies
+9cy
+9t
+4tive
+8s
+3s
+3ted
+5r
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+6y
+4ie
+6r
+6s
+7t
+5ng
+7s
+4y
+2ucan
+6et
+8s
+6s
+4h
+5able
+9ness
+9nesses
+5back
+9s
+5down
+9s
+5e
+6d
+6r
+7s
+6s
+5hole
+9s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+8ness
+9esses
+8s
+5less
+6ine
+9s
+5mark
+9s
+5pad
+8s
+7per
+9rs
+5stone
+9es
+5tone
+9s
+5up
+7s
+5wood
+9s
+5y
+3gh
+5ed
+6n
+7ed
+8r
+9s
+7ing
+9gs
+7s
+6r
+6st
+5ie
+7s
+6ng
+6sh
+5ly
+5ness
+9es
+5s
+5y
+3k
+4ed
+4ing
+4s
+3n
+4s
+3pee
+6d
+6s
+5t
+6s
+3r
+4aco
+7s
+4billion
+9ons
+8on
+9ns
+4ed
+5r
+6s
+4ie
+6s
+5ng
+7s
+5sm
+7s
+6t
+7a
+8s
+7ed
+7ic
+9ally
+7s
+7y
+4maline
+9es
+9ic
+4nament
+9ts
+5edos
+6y
+7ed
+8r
+9s
+7ing
+7s
+5iquet
+9ts
+5ure
+8s
+4s
+4tiere
+9s
+3se
+5d
+5r
+6s
+5s
+4ier
+6st
+5ng
+7s
+4le
+6d
+6s
+5ing
+4tie
+7r
+7st
+4y
+3t
+4ed
+5r
+6s
+4ie
+6r
+6st
+5ng
+4s
+3ze
+5d
+5s
+4ier
+6st
+5ng
+4le
+6d
+6s
+5ing
+4y
+2varich
+8es
+6sch
+9es
+7h
+8es
+2w
+3able
+4ge
+6s
+4rd
+6liness
+9esses
+7y
+6ness
+9ses
+6s
+4way
+7s
+3bar
+6s
+4oat
+7s
+3ed
+4l
+5ed
+6tte
+9s
+5ing
+8s
+5led
+6ing
+9s
+5s
+4r
+5ed
+5ier
+7st
+6ng
+8ly
+5less
+6ike
+5s
+5y
+3head
+7ed
+7s
+5e
+6s
+3ie
+5r
+5s
+6t
+4ng
+6s
+3kay
+6s
+3line
+7s
+3mon
+6d
+7s
+6s
+6t
+7s
+3n
+4ee
+6s
+4folk
+4hall
+5ome
+8s
+6use
+9s
+4ie
+6r
+6s
+7t
+5sh
+4land
+8s
+5ess
+6t
+7s
+5ier
+7st
+6ng
+8s
+5y
+4s
+5cape
+9d
+9s
+8ing
+9ngs
+5folk
+9s
+5hip
+8s
+5kip
+8s
+5man
+6en
+5people
+9les
+5woman
+8en
+4wear
+4y
+3path
+7s
+4lane
+8s
+3rope
+7s
+3s
+4ack
+7s
+4e
+5d
+5r
+6s
+5s
+4ier
+6st
+5ng
+4y
+3t
+4ed
+4ing
+4s
+3y
+3ze
+5d
+5s
+4ier
+6st
+5ng
+4y
+2xaemia
+8s
+7c
+4lbumin
+9ns
+4phene
+9s
+3emia
+7s
+6c
+3ic
+5al
+7ly
+6nt
+8s
+6tion
+9ns
+5ities
+7y
+5ogenic
+6logic
+9ical
+9ically
+9ies
+9ist
+9ists
+9y
+6mania
+9ias
+6phagous
+8obia
+9bias
+6ses
+7is
+5s
+4genic
+9ities
+9ity
+4n
+5e
+6s
+5s
+4phagous
+6obia
+9ac
+9acs
+9as
+3ocara
+8l
+8s
+7iases
+9sis
+4id
+6s
+4philies
+9te
+9tes
+9tic
+8y
+5lasma
+9as
+9ic
+9oses
+9osis
+2y
+3ed
+4r
+5s
+4tic
+3ing
+6s
+4sh
+6ly
+6ness
+9ses
+3lesome
+6s
+4ike
+4som
+3man
+4en
+3o
+4n
+5s
+4s
+3s
+4hop
+7s
+4ome
+3town
+3woman
+6en
+2ze
+4d
+4s
+3ie
+5s
+4ng
+1rabeate
+8d
+7ion
+9ns
+5cula
+9e
+9r
+9s
+9te
+9ted
+4s
+3casserie
+9ies
+4e
+5abilities
+9ity
+7le
+9ness
+9nesses
+8y
+5d
+5less
+9ly
+5r
+6ied
+8s
+6s
+6y
+5s
+5ur
+7s
+4hea
+7e
+7l
+7rian
+9ans
+9es
+8y
+7s
+7te
+9d
+9s
+6id
+8al
+8e
+9s
+8s
+7tes
+8ides
+9s
+9ses
+6late
+6olar
+8e
+9s
+7phyte
+9ytes
+7scopies
+9opy
+8tomies
+9omy
+7tomies
+9my
+5inus
+9es
+6tis
+9es
+5le
+7d
+7s
+6ing
+5oma
+8s
+8tous
+5ypterus
+9ruses
+6te
+8s
+7ic
+7oid
+4ing
+7s
+4k
+5able
+6ge
+8s
+5ball
+9s
+6ed
+8s
+5ed
+6r
+7ball
+9lls
+7s
+5ing
+8s
+5layer
+9rs
+8ing
+9ngs
+6ement
+9nts
+7ss
+9ly
+9ness
+9nesses
+5man
+6en
+5pad
+8s
+5road
+9s
+5s
+6ide
+9s
+6uit
+9s
+5walker
+9ers
+7y
+8s
+4t
+5abilities
+9ity
+7le
+9ness
+9nesses
+8y
+6rian
+9ns
+6te
+8s
+7or
+9s
+5ed
+5ile
+7ities
+9y
+6ng
+6on
+8al
+8s
+6ve
+5or
+7ation
+9ions
+7feed
+9eds
+7s
+5rices
+7x
+5s
+5us
+7es
+3d
+4able
+4e
+5able
+5craft
+9ts
+5d
+5ful
+5less
+5mark
+9ed
+9ing
+9s
+5name
+9s
+5off
+8s
+5r
+6s
+7hip
+9ps
+5s
+6cantia
+9tias
+6folk
+9ks
+6man
+9like
+7en
+6people
+9ples
+6woman
+9en
+4ing
+7s
+5tion
+9al
+9alise
+9alised
+9alises
+9alism
+9alisms
+9alist
+9alists
+9ality
+9alize
+9alized
+9alizes
+9ally
+9arily
+9ary
+9er
+9ers
+9ist
+9ists
+9less
+9s
+7ve
+6or
+8es
+8s
+4s
+4uce
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ian
+9ism
+9isms
+9ist
+9istic
+9ists
+9s
+7ble
+7ng
+9ly
+9s
+6tion
+9ns
+8ve
+3ffic
+7ability
+9le
+8tor
+9ors
+7ked
+9r
+9rs
+8ing
+9ngs
+8y
+7less
+7s
+3gacanth
+9hs
+5l
+4edian
+9s
+7enne
+9nes
+8s
+6y
+5laph
+9ine
+9s
+4i
+5c
+6al
+8ly
+8ness
+9esses
+6omedies
+9dy
+8ic
+9cal
+9cally
+6s
+4opan
+8s
+4ule
+7s
+6ine
+5s
+3hison
+8s
+3ik
+5ed
+5ing
+6t
+5s
+4l
+5able
+5baston
+9ons
+6lazer
+9ers
+9ing
+9ings
+6reaker
+9kers
+5ed
+6r
+7able
+7ed
+7ing
+9gs
+8st
+9ts
+8te
+9es
+7s
+5head
+9s
+5ing
+8ly
+5less
+5s
+6ide
+4n
+5abilities
+9ity
+7le
+5band
+9s
+6earer
+9ers
+5ed
+6e
+7s
+8hip
+9ips
+6r
+7s
+5ful
+8s
+5ing
+8s
+5less
+6oad
+9s
+5man
+6en
+5s
+6potterish
+5way
+8s
+4pse
+7d
+7s
+6ing
+9s
+4t
+5or
+7ess
+9ses
+7hood
+9ods
+7ism
+9ms
+7ly
+7ous
+9sly
+9sness
+7s
+8hip
+9ips
+5ress
+9es
+5s
+3ject
+7ed
+7ile
+8ng
+8on
+9ns
+7ories
+9y
+7s
+3laticious
+7tious
+3m
+4car
+7s
+4el
+6ed
+6ing
+6l
+7ed
+7ing
+7s
+6s
+4less
+5ine
+8d
+8s
+4med
+6l
+7ed
+8r
+9s
+7ing
+7led
+9r
+9rs
+8ing
+7s
+5ie
+7s
+6ng
+4ontana
+9as
+9e
+9es
+4p
+5ed
+6r
+7s
+6t
+7s
+7te
+9s
+5ier
+7st
+6ng
+8s
+6sh
+5le
+7d
+7r
+8s
+7s
+6ing
+9s
+5olin
+9e
+9ed
+9er
+9ers
+9es
+9ing
+9ings
+9ist
+9ists
+9s
+5s
+5y
+4road
+8s
+4s
+4way
+7s
+3nce
+6d
+7ly
+6like
+6s
+6y
+5he
+7s
+7t
+8s
+5ier
+7st
+6ng
+4ect
+7s
+4gam
+7s
+5le
+7s
+4k
+5s
+5um
+7s
+4nie
+7s
+4q
+5s
+5uil
+8er
+9st
+8isation
+9se
+9sed
+9ser
+9sers
+9ses
+9sing
+9singly
+9ties
+9ty
+9zation
+9ze
+9zed
+9zer
+9zers
+9zes
+9zing
+9zingly
+8ler
+9est
+9ise
+9ised
+9iser
+9isers
+9ises
+9ising
+9ities
+9ity
+9ize
+9ized
+9izer
+9izers
+9izes
+9izing
+9y
+8ness
+9esses
+4s
+5act
+8ed
+8ing
+9nide
+9nides
+9on
+9onal
+9onally
+9ons
+8or
+9rs
+8s
+6lpine
+9nes
+6minase
+9ases
+9ation
+9ations
+6ndean
+8ine
+6tlantic
+6xle
+9s
+5calencies
+9ncy
+9nt
+7ucasian
+6eiver
+9ers
+7nd
+9ed
+9ence
+9ences
+9encies
+9ency
+9ent
+9ental
+9entals
+9ently
+9ents
+9ing
+9ingly
+9s
+6ode
+9d
+9s
+8ing
+6ranial
+7ibable
+9e
+9ed
+9er
+9ers
+9es
+9ing
+8pt
+9tase
+9tases
+9tion
+9tional
+9tions
+9tive
+9tively
+9tome
+9tomes
+9ts
+6ultural
+7rrent
+7taneous
+5dermal
+6uce
+9d
+9r
+9rs
+9s
+8ing
+8tant
+9ants
+9ion
+9ional
+9ions
+9or
+9ors
+5e
+6ct
+8ed
+8ing
+9on
+9ons
+8s
+6nna
+9s
+6pt
+8al
+9te
+8s
+6s
+6unt
+6xual
+9lism
+9lisms
+9ls
+5fard
+6ect
+9ed
+9ing
+9ion
+9ions
+9s
+7r
+8ability
+9ble
+9l
+9ls
+9se
+9ses
+8ee
+9es
+9nce
+9nces
+9ntial
+8or
+9rs
+8rable
+9al
+9als
+9ed
+9er
+9ers
+9ible
+9in
+9ing
+9ins
+8s
+6iguration
+9re
+9red
+9rement
+9res
+9ring
+7nite
+7x
+8ed
+9s
+8ing
+9on
+9ons
+8t
+6orm
+9able
+9ation
+9ations
+9ative
+9ed
+9er
+9ers
+9ing
+9ings
+9ism
+9isms
+9ist
+9istic
+9ists
+9s
+6usable
+8e
+9d
+9r
+9rs
+9s
+8ible
+9ng
+9on
+9onal
+9onist
+9onists
+9ons
+9ve
+9vely
+5gender
+9ered
+9ers
+8e
+9s
+9ses
+9sis
+8ic
+9cs
+6ress
+9sed
+9ses
+9sing
+9sion
+9sional
+9sions
+9sive
+9sively
+9sor
+9sors
+5hip
+8ment
+9ents
+8ped
+9er
+9ers
+9ing
+9ings
+8s
+7storical
+6umance
+9nces
+9nt
+9nts
+8e
+9d
+9s
+8ing
+5ience
+9es
+9ies
+9y
+8t
+9ly
+9ness
+9nesses
+9s
+6lience
+9nces
+9ncies
+9ncy
+9nt
+7luminate
+6re
+8s
+6sthmian
+8or
+9rise
+9rised
+9rises
+9rising
+9rize
+9rized
+9rizes
+9rizing
+9rs
+6t
+7able
+7ed
+7ing
+8on
+9nal
+9nally
+9nals
+9nary
+9ns
+8ve
+9ely
+9eness
+9es
+9ities
+9ity
+7orily
+9iness
+9y
+7s
+5latability
+9ble
+8e
+9d
+9s
+8ing
+9on
+9onal
+9onally
+9ons
+9ve
+9ves
+8or
+9rial
+9rs
+9ry
+6eithan
+6iterate
+9rated
+9rates
+9rating
+9ration
+9rator
+9rators
+6ocate
+9ted
+9tes
+9ting
+9tion
+9tions
+6ucence
+9nces
+9ncies
+9ncy
+9nt
+9ntly
+8id
+9dities
+9dity
+7menal
+8inal
+7nar
+9ry
+5manche
+7rine
+6embrane
+7w
+8ed
+8ing
+8s
+6igrant
+9ants
+9ate
+9ated
+9ates
+9ating
+9ation
+9ations
+9ative
+9ator
+9ators
+9atory
+7ssible
+9ion
+9ional
+9ions
+9ive
+9ively
+9ivity
+9ometer
+7t
+8s
+8table
+9al
+9als
+9ance
+9ances
+9ancies
+9ancy
+9ed
+9er
+9ers
+9ible
+9ing
+9ivity
+6ogrified
+9ifies
+9ify
+9ifying
+7ntane
+9anes
+7untain
+7ve
+9d
+9s
+8ing
+6undane
+7tability
+9ble
+9bly
+9tion
+9tional
+9tions
+9tive
+8e
+9d
+9r
+9rs
+9s
+8ing
+5national
+8ural
+5oceanic
+6m
+7ed
+7s
+6nic
+9s
+5pacific
+7dane
+7rence
+9nces
+9ncies
+9ncy
+9nt
+9ntise
+9ntised
+9ntises
+9ntize
+9ntized
+9ntizes
+9ntly
+9ntness
+6ersonal
+6icuous
+9ously
+7erce
+9ced
+9ces
+9cing
+7rable
+9tion
+9tional
+9tions
+9tory
+8e
+9d
+9s
+8ing
+6lacental
+8nt
+9table
+9tation
+9ted
+9ter
+9ters
+9ting
+9tings
+9ts
+6olar
+7nder
+9ers
+9or
+9ors
+8tine
+7rt
+9able
+9al
+9als
+9ance
+9ances
+9ation
+9ations
+9ed
+9edly
+9edness
+9ee
+9ees
+9er
+9ers
+9ing
+9ingly
+9ings
+9ive
+9s
+7sability
+9ble
+9l
+9ls
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+9tion
+9tional
+9tions
+9tive
+8on
+9ns
+6uter
+9rs
+5sexual
+9alism
+9alisms
+9ality
+9als
+6hape
+9ed
+9es
+9ing
+7ip
+9ment
+9ments
+9ped
+9per
+9pers
+9ping
+9pings
+9s
+6onic
+5thoracic
+5ubstantial
+6date
+9es
+9ion
+9ions
+9ory
+7e
+8d
+8s
+7ing
+6me
+8d
+8s
+7ing
+7pt
+9ion
+9ions
+9ive
+9s
+6ranian
+9ic
+9ics
+9ium
+5vaginal
+7luate
+9ated
+9ates
+9ating
+9ation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+6ersal
+9ality
+9ally
+9als
+9e
+9ed
+9ely
+9eness
+9es
+9ing
+9ion
+9ions
+8ter
+9ers
+7st
+9ed
+9ic
+9ing
+9ism
+9isms
+9ist
+9ists
+9ite
+9ites
+9itism
+9itisms
+9s
+4t
+5ed
+6r
+7s
+5ing
+5s
+3p
+4an
+6ned
+8r
+9s
+7ing
+6s
+4ball
+8s
+4door
+8s
+4e
+5d
+5s
+6ed
+7s
+6ing
+9s
+5ze
+7d
+7s
+6ia
+8l
+7form
+7i
+7ng
+7st
+9s
+7um
+9s
+8s
+9es
+6ohedra
+9dral
+9dron
+9drons
+7id
+9al
+9s
+4fall
+8s
+4ing
+4like
+6ne
+8s
+4nest
+8ed
+8ing
+8s
+4pean
+6d
+6r
+7s
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5ose
+6us
+5y
+4rock
+8s
+4s
+5hooter
+9ers
+9ing
+9ings
+4t
+4unto
+8s
+3sh
+5can
+8s
+5ed
+6r
+7ies
+7s
+7y
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5man
+6en
+5trie
+9s
+5y
+4s
+5es
+3t
+4s
+4t
+5oria
+9s
+8e
+5s
+3uchle
+8d
+8s
+7ing
+4ma
+6s
+6ta
+7ic
+9ally
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ological
+9ogies
+9ogy
+8nasties
+9asty
+3vail
+7ed
+7ing
+7s
+4e
+5l
+6ator
+9rs
+6ed
+7r
+8s
+6ing
+9s
+6led
+8r
+9s
+7ing
+9gs
+6og
+8s
+8ue
+9es
+6s
+5rsable
+8l
+9s
+7e
+8d
+8r
+9s
+8s
+7ing
+9gs
+6tin
+9e
+9es
+9s
+5s
+6tied
+9s
+7y
+8ing
+4is
+6es
+4ois
+7e
+8s
+5lator
+9rs
+3wl
+5ed
+6r
+7man
+8en
+7s
+6y
+7s
+5ing
+8s
+5net
+8s
+5s
+3y
+4bit
+7s
+4ful
+7s
+4mobile
+9es
+4ne
+6d
+6s
+5ing
+4s
+3zodone
+9s
+2eacher
+8er
+9rs
+8ies
+8ous
+9usly
+9usness
+8s
+8y
+7tour
+9urs
+6our
+9s
+5le
+7d
+7s
+6ier
+8st
+7ness
+9sses
+8g
+6y
+4d
+5ed
+6r
+7s
+5ing
+8s
+5le
+7d
+7r
+8s
+7s
+8s
+6ing
+9s
+5mill
+9s
+5s
+5wheel
+9ls
+4gue
+7s
+4son
+7able
+9leness
+9ly
+7ous
+7s
+5urable
+7e
+8d
+8less
+8r
+9s
+9ship
+9ships
+8s
+7ies
+8ng
+7y
+4t
+5abilities
+9ity
+7le
+5ed
+6r
+7s
+5ies
+6ng
+8s
+6se
+8s
+5ment
+9s
+5s
+5y
+6less
+3bbiano
+9s
+4le
+6d
+6ness
+9ses
+6s
+5ing
+5y
+4uchet
+9s
+6ket
+9s
+3centist
+9ts
+7o
+8s
+4k
+5ed
+5ing
+5s
+3ddle
+7d
+7s
+6ing
+4ecillion
+9ions
+4ille
+8s
+4rille
+9s
+3e
+4d
+4hopper
+9rs
+6use
+9s
+4ing
+4lawn
+8s
+5ess
+8ness
+9esses
+5ike
+4n
+5ail
+8s
+5s
+5ware
+9s
+4s
+5hip
+8s
+4top
+7s
+4ware
+8s
+6x
+7es
+3f
+4a
+5h
+4oil
+7ed
+7s
+3getour
+9s
+3hala
+7s
+6ose
+9s
+3if
+5a
+4llage
+9d
+9s
+6e
+7s
+3k
+4ked
+6r
+7s
+5ing
+8s
+4s
+5chuit
+9ts
+3llis
+7ed
+8s
+7ing
+7work
+9rks
+3ma
+5s
+5tic
+6ode
+9s
+7id
+9s
+4blant
+6e
+7d
+7ment
+9nts
+7r
+8s
+7s
+6ier
+8st
+7ng
+9ly
+9s
+6y
+4endous
+9sly
+9sness
+4ie
+6s
+4olandi
+9o
+9os
+8t
+9s
+6ite
+9s
+8ic
+6o
+7s
+5r
+6ed
+6ing
+6less
+6ous
+6s
+4ulant
+9s
+7te
+9d
+9s
+8ing
+6ous
+9ly
+9ness
+9nesses
+3nail
+7s
+4ch
+6ancies
+9y
+8d
+8t
+9ly
+7rd
+9s
+6ed
+7r
+8man
+9en
+8s
+7s
+6ing
+4d
+5ed
+5ier
+7s
+8t
+6fied
+9s
+7y
+8ing
+6ly
+6ness
+9ses
+7g
+5oid
+8s
+5s
+6etter
+9ers
+9ing
+9ings
+5y
+6ism
+9s
+4ise
+7s
+4tal
+7s
+3pan
+6ation
+9ons
+6g
+7s
+6ned
+8r
+9s
+7ing
+9gs
+6s
+4hination
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+9gs
+4id
+6ant
+7tion
+9ons
+8ory
+4onema
+9l
+9s
+9ta
+9toses
+9tosis
+9tous
+8e
+9s
+3s
+4pass
+8ed
+9r
+9rs
+9s
+8ing
+4s
+5ed
+6l
+7s
+6s
+5ier
+7st
+6ng
+5our
+8s
+5ure
+8d
+8s
+5y
+4t
+5le
+7s
+7tree
+9ees
+7work
+9rks
+5s
+3t
+4inoin
+9s
+4s
+3vallies
+7y
+8s
+4et
+6s
+4is
+6es
+6s
+7es
+3w
+4s
+5man
+6en
+3y
+4bit
+7s
+4s
+3z
+4es
+2iable
+7ness
+9sses
+4c
+5etate
+9es
+5id
+7s
+5onter
+9rs
+5s
+5t
+6inal
+8e
+4d
+5elphous
+5ic
+7ally
+7s
+6sm
+8s
+7t
+8s
+5s
+4ge
+6d
+6s
+5ing
+4l
+5ism
+8s
+7t
+8s
+6ties
+7y
+5led
+6ing
+9s
+7st
+9s
+5ogue
+9s
+5s
+5ware
+9s
+4mcinolone
+9lones
+4ndrian
+7ous
+5gle
+8d
+8s
+6ular
+9rities
+9rity
+9rly
+9te
+9ted
+9tely
+9tes
+9ting
+9tion
+9tions
+4psal
+6idal
+4rch
+7ies
+7s
+7y
+4ssic
+4thlete
+9es
+7on
+9s
+5ic
+7s
+5omic
+9ally
+4xial
+8ities
+9ty
+8s
+5on
+7s
+4zin
+7e
+8s
+7s
+5ole
+8s
+7ic
+3bade
+7s
+6ic
+7es
+6y
+5l
+6ism
+9s
+8t
+9ic
+9s
+6ly
+6s
+5sic
+4ble
+7s
+4e
+5less
+5s
+6man
+7en
+6people
+6woman
+9en
+4let
+7s
+4oelectric
+5logical
+9es
+9st
+9sts
+8y
+5meter
+9rs
+4rach
+8ial
+9c
+8s
+5omoethanol
+8methane
+4ulate
+9d
+9s
+8ing
+9on
+9ons
+5nal
+8s
+7ry
+7te
+9s
+6e
+7s
+8hip
+9ips
+6icial
+9an
+7tial
+9an
+5taries
+9ly
+9ness
+9nesses
+8y
+6e
+7r
+8s
+7s
+3cameral
+5r
+6boxylic
+6pellary
+6s
+4e
+5d
+5ntenaries
+9ary
+9nial
+9nials
+5p
+6halous
+6s
+7es
+5ratops
+9pses
+6ion
+9s
+5s
+4hiases
+8is
+6na
+8e
+8l
+8s
+7ella
+9lae
+9las
+7iases
+9sis
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ose
+9ed
+9es
+9ing
+9is
+9ises
+8tic
+8us
+6te
+8s
+7ic
+5loracetic
+8fon
+9ons
+8ide
+9des
+8oacetic
+9ethane
+8phon
+9hons
+5obacteria
+6cyst
+9tic
+9ts
+6gyne
+9es
+9ial
+9ic
+6id
+6logical
+9ies
+9ist
+9ists
+9y
+6me
+8s
+7ic
+7onacidal
+9acide
+9acides
+9ad
+9adal
+9ads
+9al
+9iases
+9iasis
+6phyton
+9tons
+9toses
+9tosis
+7teran
+9rans
+9rist
+9rists
+9rous
+6rd
+8s
+6ses
+7is
+6thecene
+9cenes
+7omic
+9ies
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9ous
+9ously
+9y
+5roic
+8sm
+9ms
+7mat
+9tic
+9tism
+9tisms
+9ts
+8e
+8ic
+9cs
+7nous
+5uriases
+9sis
+4ing
+4k
+5ed
+6r
+7ies
+7s
+7y
+5ie
+7r
+7st
+6ly
+6ness
+9ses
+7g
+8s
+6sh
+8ly
+8ness
+9esses
+5le
+7d
+7s
+8s
+7t
+8s
+6ier
+8st
+7ng
+9ly
+9s
+6y
+5s
+6ier
+8st
+7ly
+7ness
+9sses
+6ome
+6ter
+9ing
+9ings
+9s
+6y
+5track
+9ks
+5y
+4lad
+7s
+5inia
+8c
+8um
+5osan
+9s
+4olette
+9es
+6or
+8ed
+8s
+7ur
+9ed
+9s
+5nsonantal
+9antic
+5rn
+7e
+8red
+8s
+7s
+6porate
+9ated
+5state
+5t
+6euse
+9es
+6ine
+9s
+6s
+4rotic
+8sm
+9ms
+7ous
+4trac
+8s
+4uspid
+9al
+9ate
+9s
+4ycle
+8d
+8r
+9s
+8s
+7ic
+9s
+8ng
+9gs
+8st
+9ts
+3dacna
+8s
+6tyl
+9ous
+5rn
+7s
+4e
+5nt
+7al
+8te
+7ed
+7s
+4imensional
+4ominia
+9um
+4uan
+5um
+7s
+4ymite
+9s
+3e
+4cious
+4d
+4lla
+7s
+4ne
+6s
+5nia
+8l
+9ly
+9s
+7um
+9s
+5s
+5tes
+4r
+5arch
+9al
+9ies
+9s
+9y
+5s
+4s
+4teric
+5hyl
+8amine
+9mines
+3facial
+9s
+5rious
+4ecta
+8s
+4f
+5er
+6st
+5ic
+6d
+7ian
+7s
+7y
+4id
+4le
+6d
+6r
+7s
+6s
+5ing
+8ly
+8ness
+9esses
+8s
+5uoperazine
+6ralin
+9ins
+4ocal
+8s
+5ld
+6iate
+9ed
+7es
+7olate
+7um
+9s
+6y
+5ria
+8l
+7um
+6m
+7ed
+4urcate
+9ed
+9es
+9ing
+9ion
+9ions
+3g
+4amies
+7st
+9s
+6ous
+6y
+4eminal
+9ls
+8i
+8us
+4ged
+6r
+7ed
+7fish
+9shes
+7ing
+7less
+7man
+8en
+7s
+6st
+5ing
+4lot
+7s
+5y
+6ceride
+9ides
+6ph
+8ic
+9cal
+8s
+4ness
+8es
+4o
+5n
+6al
+8ly
+6ic
+6ometer
+9ters
+9tric
+9trical
+9tries
+9try
+7us
+6s
+5s
+4ram
+7matic
+8ic
+7s
+6ph
+8ic
+8s
+4s
+4ynian
+6ous
+3halomethane
+9thanes
+4edra
+8l
+9s
+7on
+9s
+4ybrid
+9s
+5drate
+9ed
+9es
+7ic
+7oxy
+3iodomethane
+9thanes
+3jet
+6s
+4ugate
+6ous
+3ke
+5s
+3lateral
+9lism
+9lisms
+9list
+9lists
+9lly
+9ls
+9tion
+9tions
+4bies
+5y
+6s
+4d
+4emma
+8s
+4inear
+8te
+6gual
+9lism
+9lisms
+9lly
+5teral
+9lism
+9lisms
+9ls
+6h
+7ic
+7on
+9s
+7s
+4l
+5ed
+6r
+7s
+5ing
+8s
+6on
+8aire
+9ires
+8s
+8th
+9hs
+6um
+8s
+5o
+6es
+5s
+4obal
+7te
+9d
+6e
+7d
+7s
+6ite
+9s
+8ic
+5cular
+5gies
+6y
+3m
+4aran
+8s
+4er
+6ic
+7sm
+9s
+6ous
+6s
+5ster
+9s
+7ral
+8ial
+5ter
+8s
+6hadione
+9iones
+7oprim
+9rims
+7yl
+9amine
+9amines
+9ene
+9enes
+6ric
+9al
+7ogon
+9ons
+4ix
+6es
+4ly
+4med
+6r
+7s
+6st
+5ing
+8ly
+8s
+4ness
+8es
+4olecular
+5nthly
+5rph
+8ic
+9sm
+9sms
+8ous
+8s
+5tor
+8s
+4s
+4tab
+7s
+3n
+4acrian
+8form
+5l
+5ry
+4dle
+7d
+7s
+6ing
+4e
+5d
+5s
+4gle
+7s
+4ing
+5scope
+9es
+5tarian
+6ies
+6rate
+9es
+7in
+9s
+7obenzene
+8cresol
+9resols
+8phenol
+9henols
+8toluene
+9oluol
+9oluols
+6y
+4ket
+7ed
+8r
+9s
+7ing
+9gs
+7ries
+8y
+7s
+5um
+7s
+4ocular
+5dal
+5mial
+9ism
+9isms
+9ist
+9ists
+9ly
+9s
+4s
+4ucleotide
+9tides
+3o
+4de
+6s
+4ecious
+4l
+5ein
+8s
+6t
+7s
+5s
+4nes
+5ym
+7al
+7s
+4r
+5s
+4s
+5e
+6s
+4xid
+7e
+8s
+7s
+5oboric
+5ygen
+9s
+3p
+4ack
+7s
+5lmitin
+9ins
+5rt
+7ism
+9ms
+8te
+9ely
+9ion
+9ions
+4e
+5dal
+5hound
+9ds
+5ries
+6sonal
+9alism
+9alisms
+9alist
+9alists
+9ality
+6y
+5s
+5talous
+5y
+4hammer
+9rs
+6se
+5enylamine
+9amines
+5ibious
+5one
+8s
+6sphate
+9ates
+5thong
+9gal
+9gs
+5ylite
+9es
+7lous
+4ier
+6st
+5nnate
+9ely
+5taka
+9s
+4lane
+8s
+5e
+6d
+6ness
+9ses
+6s
+6t
+7ail
+9ls
+7s
+6x
+7es
+5icate
+9ed
+9es
+9ing
+9ion
+9ions
+7ities
+9y
+6ed
+7s
+6ng
+8s
+6te
+8s
+5oblastic
+6id
+8ies
+8s
+8y
+5y
+6ing
+4od
+6al
+6ic
+7es
+6s
+6y
+5li
+7s
+5s
+6es
+4pant
+5ed
+6r
+7ish
+7s
+7y
+6t
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5le
+7d
+7r
+8s
+7s
+6ing
+5y
+4s
+5es
+5is
+4tan
+7e
+8s
+7s
+5erous
+5ote
+8s
+5yca
+8s
+7h
+8s
+6que
+9s
+4udia
+8ry
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+7um
+9s
+4wire
+8s
+4y
+3quetra
+9e
+9l
+8ous
+9usly
+8um
+3radial
+8te
+9ely
+4eme
+7s
+3saccharide
+9rides
+5gion
+9s
+4cele
+8s
+4ect
+7ed
+7ing
+8on
+9ns
+7or
+9s
+7rices
+9x
+7s
+5me
+7s
+6ic
+5rial
+4haw
+7s
+4kele
+8s
+7ia
+8on
+9ns
+4mic
+5us
+7es
+4octahedra
+9edral
+9edron
+9edrons
+5dium
+5me
+7s
+6ic
+8s
+7es
+6y
+4t
+5ate
+5e
+6arin
+9ns
+6sse
+9s
+6za
+8s
+5ful
+8ly
+8ness
+9esses
+5ich
+8ic
+8ous
+8s
+6mulus
+4ubstituted
+5l
+6a
+7s
+6cate
+6fide
+9es
+6phide
+9des
+6s
+4yllabic
+9ical
+9ically
+9le
+9les
+3tagonist
+9sts
+5nope
+9s
+8ia
+9as
+9c
+4e
+5ly
+5ness
+9es
+5r
+6nate
+5s
+6t
+4heism
+9s
+8t
+9ic
+9ical
+9s
+5ing
+8s
+6onate
+9tes
+8ic
+4iate
+8d
+8s
+7ing
+8on
+9ns
+5cal
+8e
+9s
+8ly
+8ness
+9esses
+6eous
+6ism
+9s
+6um
+8s
+5de
+7s
+5um
+7s
+4oma
+7s
+5n
+6e
+7s
+6ia
+8s
+6s
+4ubercular
+9ulate
+9ulies
+9ulism
+9ulisms
+9uly
+5rable
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+3umph
+7al
+9ism
+9isms
+9ist
+9ists
+9s
+8nt
+9tly
+7ed
+8r
+9ies
+9s
+9y
+7ing
+9gs
+7s
+5vir
+8al
+9te
+9tes
+8i
+9es
+8s
+8y
+4ne
+6s
+5ities
+7y
+3valence
+9es
+9ies
+9y
+8t
+6ve
+8d
+8s
+7ular
+4et
+6s
+4ia
+6l
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9ts
+8ties
+9y
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7ly
+7ness
+9sses
+5um
+7s
+3weeklies
+8y
+3zonal
+6e
+7s
+2oad
+5e
+6s
+5s
+4k
+5ed
+5ing
+5s
+4t
+5ed
+5ing
+5s
+3car
+6s
+4haic
+8ally
+8s
+6l
+6nter
+9ral
+9ric
+9rs
+6r
+7s
+5e
+6ameter
+9ters
+6e
+7s
+6lminth
+9nths
+6s
+5i
+6l
+7i
+8c
+7s
+7us
+9es
+6scus
+9ses
+7k
+8s
+6te
+8s
+5lea
+8e
+8r
+9s
+8s
+5oid
+8al
+9lly
+8s
+6meter
+9ers
+6phore
+9res
+6sphere
+9eres
+6tron
+9ns
+5us
+7es
+4k
+5ed
+6n
+5ing
+5s
+4tolite
+9es
+3d
+4den
+4e
+5s
+4s
+3elie
+7s
+5y
+3ffer
+7s
+3g
+4ged
+5ing
+5s
+4lodyte
+9es
+9ic
+9ical
+9ism
+9isms
+4on
+6s
+4s
+3ika
+6s
+4lism
+8s
+7t
+8s
+6te
+8s
+5us
+7es
+4s
+3ke
+5d
+5s
+4ing
+3land
+7s
+4l
+5ed
+6r
+7s
+6y
+7bus
+9ses
+9sses
+7ed
+7ing
+7s
+5ied
+7s
+6ng
+8s
+6us
+8es
+5op
+7ed
+8e
+9s
+7ing
+8sh
+7s
+7y
+5s
+5y
+6ing
+3mbiculid
+9ids
+6diases
+9sis
+5one
+8s
+7ist
+9ts
+4ino
+7es
+7s
+4mel
+7s
+4ometer
+9rs
+8ric
+4p
+5e
+6d
+6s
+5ing
+5s
+3n
+4a
+5s
+4c
+5s
+4e
+5s
+4k
+5s
+4s
+3olie
+7s
+4p
+5ed
+6r
+7s
+5ial
+8s
+6ng
+5s
+6hip
+9s
+4stite
+9s
+4z
+3p
+4aeola
+8in
+9ns
+8um
+9ms
+5ria
+7on
+4e
+5d
+5olin
+9s
+5s
+4hallactic
+9xes
+9xis
+5esial
+8es
+7y
+5i
+6c
+7ally
+6ed
+7s
+5obioses
+9sis
+9tic
+7last
+9stic
+9sts
+6logies
+9y
+6neuroses
+9rosis
+6plasm
+9sms
+6tactic
+8xes
+9is
+7ropic
+9pism
+9pisms
+6zoite
+9tes
+5y
+6ing
+4ic
+6al
+8isation
+9se
+9sed
+9ses
+9sing
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+8s
+6bird
+9ds
+6s
+5n
+6e
+7s
+6g
+6s
+5sm
+7atic
+7s
+6t
+7ic
+7s
+4ocollagen
+9agens
+5logic
+9cal
+9cally
+9es
+8y
+5myosin
+9ins
+5nin
+8s
+5pause
+9es
+6hilous
+7yte
+9es
+9ic
+5scatter
+9ters
+6phere
+9res
+9ric
+5taxes
+8is
+4po
+3ssers
+3t
+4h
+5ed
+5ful
+5ing
+5less
+5plight
+9hted
+9hting
+9hts
+5s
+4line
+8s
+4s
+4ted
+6r
+7s
+5ing
+8s
+5oir
+8s
+4yl
+6s
+3ubadour
+9rs
+5le
+7d
+8ly
+7free
+7maker
+9kers
+9king
+9kings
+7r
+8s
+7s
+8hoot
+9ooter
+9ooters
+9ooting
+9oots
+9ot
+8ome
+9mely
+9meness
+6ing
+9s
+6ous
+9ly
+9ness
+9nesses
+4ch
+6es
+4gh
+6ed
+6ing
+6like
+6s
+4le
+6d
+6s
+5ing
+4nce
+7d
+7r
+8s
+7s
+6ing
+9s
+4pe
+6d
+6r
+7s
+6s
+5ial
+8s
+6ng
+4se
+6r
+7ed
+7ing
+9gs
+7less
+7s
+6s
+5seau
+9s
+9x
+4t
+5er
+7s
+5ful
+5ier
+7st
+6ng
+8s
+5less
+7t
+8s
+6ing
+9s
+5s
+6tone
+9es
+5y
+4vaille
+9es
+5ere
+8s
+6ur
+8s
+3ve
+5r
+6s
+5s
+3w
+4ed
+5l
+6ed
+7r
+8s
+6ing
+6led
+8r
+9s
+7ing
+6s
+4ing
+4s
+5ers
+4th
+6s
+3y
+4s
+2uancies
+6y
+5t
+6ed
+6ing
+6ly
+6ries
+7y
+6s
+7hip
+9ps
+3cage
+7s
+4e
+5d
+5less
+5s
+4hman
+8s
+6en
+4ial
+5ng
+4k
+5able
+6ge
+8s
+5ed
+6r
+7s
+5ful
+8s
+5ie
+7s
+6ng
+8s
+5le
+7d
+7r
+8s
+7s
+6ine
+9s
+8g
+9s
+6oad
+9s
+5man
+7ster
+9ers
+6en
+5s
+6top
+9s
+4ulence
+9es
+9ies
+9y
+8t
+9ly
+3dge
+6d
+6n
+7s
+6on
+8s
+6r
+7s
+6s
+5ing
+8s
+3e
+4blue
+8s
+5orn
+5red
+4d
+4hearted
+9edness
+4ing
+4love
+8s
+4man
+5en
+4ness
+8es
+4pennies
+8y
+4r
+4s
+5t
+3ffe
+6s
+5le
+7d
+7s
+6ing
+9s
+3g
+4o
+5s
+4s
+3ing
+4sm
+6s
+5tic
+3ll
+5s
+4y
+3meau
+7x
+4p
+5ed
+6ries
+7y
+6t
+7ed
+8r
+9s
+7ing
+9gs
+7like
+7s
+7weed
+9eds
+5ing
+8s
+5less
+5s
+3ncal
+6te
+8d
+8ly
+8s
+7ing
+8on
+9ns
+5heon
+9ed
+9er
+9ers
+9ing
+9s
+4dle
+7d
+7r
+8s
+7s
+6ing
+4k
+5ed
+5fish
+9es
+6ul
+8s
+5ing
+8s
+5less
+5s
+6ful
+6leeve
+9ves
+5work
+9s
+4nel
+7s
+5ion
+8ed
+8s
+3quage
+8s
+5eur
+8s
+3ss
+5ed
+6r
+7s
+6s
+5ing
+8s
+4t
+5abilities
+9ity
+7le
+6farian
+9ians
+5buster
+9ers
+9ing
+9ings
+5ed
+6e
+7d
+7ing
+7s
+8hip
+9ips
+6r
+7s
+5ful
+8ly
+8ness
+9esses
+5ier
+7s
+8t
+6ly
+6ness
+9ses
+7g
+8ly
+8ness
+9esses
+5less
+9ly
+9ness
+9nesses
+5or
+7s
+5s
+5worthily
+9hiness
+9hy
+5y
+3th
+5ful
+8ly
+8ness
+9esses
+5ier
+7st
+6ness
+9ses
+5less
+9ness
+9nesses
+6ike
+5s
+5y
+2y
+3e
+4r
+5s
+3ing
+6ly
+6ness
+9ses
+6s
+3ke
+5s
+3ma
+5ta
+3out
+6s
+3p
+4aflavine
+9ines
+5n
+6ocidal
+9de
+9des
+7somal
+9me
+9mes
+9miases
+9miasis
+9mic
+5rsamide
+9ides
+4s
+5in
+7ogen
+9ens
+7s
+4tamine
+9es
+5ic
+5ophan
+9ne
+9nes
+9ns
+3sail
+7s
+4t
+5e
+6d
+6r
+7s
+6s
+5ing
+5s
+3works
+1saddik
+7im
+7s
+6q
+7im
+7s
+4e
+5s
+4i
+5s
+3mba
+6s
+3ntsa
+7s
+3r
+4dom
+7s
+4evich
+9es
+7tch
+9hes
+6na
+8s
+4ina
+7s
+5sm
+7s
+6t
+7s
+5tsa
+8s
+6za
+8s
+4s
+3tske
+7s
+2chernosem
+9ems
+2esarevich
+9ches
+9tch
+9tches
+8na
+9as
+7wich
+9ches
+9tch
+9tches
+4sebe
+8s
+3tse
+6s
+2igane
+7s
+3mmes
+7es
+3tsith
+2k
+3ed
+3ing
+3s
+3tsk
+6ed
+6ing
+6s
+2ooris
+3res
+4is
+4riss
+3tsi
+6s
+6taal
+9ls
+3uris
+7es
+2uba
+5s
+3nami
+7c
+7s
+3ris
+6es
+3tsugamushi
+9ushis
+6mu
+8s
+1uan
+4s
+3rt
+5s
+3tara
+7s
+4era
+7s
+4h
+5s
+4ua
+6s
+2b
+3a
+4e
+4ge
+6s
+4ist
+7s
+4l
+4r
+4s
+4te
+3bable
+4ed
+5r
+6s
+4ier
+6st
+5ness
+9es
+6g
+7s
+5sh
+4y
+3e
+4ctomies
+8y
+4d
+4ful
+7s
+4less
+5ike
+4nose
+8s
+4r
+5aceous
+5cle
+8d
+8s
+6ula
+9r
+9rly
+9rs
+9te
+9ted
+9tely
+9tion
+9tions
+8e
+9s
+8in
+9ns
+9sation
+9se
+9sed
+9ses
+9sing
+9zation
+9ze
+9zed
+9zes
+9zing
+8oid
+9ma
+9mas
+9mata
+9se
+9sed
+9ses
+9sis
+9us
+9usly
+8um
+5iferous
+7orm
+5oid
+6se
+8s
+7ities
+9y
+6us
+5s
+4s
+4work
+8s
+7m
+8s
+3fast
+7s
+4ish
+7es
+4ul
+6s
+3icolar
+7e
+8s
+7ous
+4fex
+7es
+5icid
+9s
+5lorous
+5orm
+4ng
+6s
+4st
+6s
+3like
+3ocurarine
+9ines
+4plasties
+9y
+3s
+3ular
+7ian
+9ns
+8ties
+9y
+7ly
+6te
+8d
+8s
+7ing
+8on
+9ns
+7or
+9s
+7ure
+9es
+5e
+6s
+5ifloral
+9rous
+6n
+7s
+5ose
+6us
+8ly
+5ure
+8s
+2chun
+6s
+3k
+4ahoe
+8s
+4ed
+5r
+6bag
+9s
+7ox
+9es
+6ed
+6ing
+6s
+5t
+6s
+4ing
+4s
+5hop
+8s
+3otuco
+8s
+3utuco
+8s
+7u
+8s
+2fa
+4ceous
+4s
+3f
+4aceous
+4e
+5s
+5t
+6s
+4s
+4taffeta
+9tas
+9ties
+9ty
+3oli
+3t
+4affeta
+9as
+9ies
+9y
+4ed
+5r
+6s
+4ier
+6st
+5ly
+5ng
+7s
+4s
+4y
+2g
+3boat
+7s
+3ged
+5r
+6s
+4ing
+7ly
+7s
+3hra
+6s
+5ik
+7s
+3less
+3ra
+5s
+4ik
+6s
+3s
+2i
+3lle
+6s
+6tte
+9s
+4yie
+7d
+7ing
+7s
+4zie
+7d
+7ing
+7s
+3na
+5s
+3s
+4m
+5s
+3tion
+7al
+8ry
+7s
+2ktoo
+6s
+4u
+5s
+2ladi
+6s
+4raemia
+9as
+9c
+5emia
+9s
+8c
+3ban
+6s
+3chan
+7s
+3e
+4s
+3ip
+5ant
+8s
+5like
+5omania
+9ias
+5s
+5wood
+9s
+3le
+5s
+4ibee
+8s
+3pa
+5s
+3war
+6s
+2m
+3atakuru
+9us
+3ble
+6bug
+9s
+6d
+7own
+6home
+9es
+6r
+7ful
+9ls
+7s
+8ful
+6s
+7et
+9s
+6weed
+9ds
+5ing
+8s
+4rel
+7s
+5il
+7s
+3efacient
+7tion
+9ons
+5ied
+7s
+5y
+6ing
+4sce
+7d
+7nce
+9es
+8t
+9ly
+7s
+6ing
+3id
+5ities
+7y
+5ly
+5ness
+9es
+3mies
+4ler
+7s
+4y
+3or
+5al
+5genic
+9cities
+9city
+5igeneses
+9esis
+9ic
+9icity
+5like
+5ous
+5s
+4ur
+6s
+3p
+4ed
+4hies
+5y
+4ier
+6st
+5ng
+4line
+8s
+4s
+4y
+3s
+4hie
+7s
+3ular
+7y
+5i
+5ose
+7ities
+9y
+6us
+5t
+6ed
+6ing
+6s
+6uary
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+7ous
+9sly
+9sness
+5us
+7es
+2n
+3a
+4bilities
+9y
+5le
+7ness
+9sses
+6y
+4s
+3bellied
+9s
+7y
+3d
+4ed
+4ing
+5sh
+7es
+4ra
+6s
+4s
+4un
+6s
+3e
+4able
+7y
+4d
+4ful
+7ly
+7ness
+9sses
+4less
+8ly
+8ness
+9esses
+4r
+5s
+4s
+5mith
+9s
+4up
+6s
+3g
+4s
+5tate
+9s
+6en
+8s
+6ic
+7te
+9s
+6ous
+3ic
+5a
+6e
+6te
+8d
+8s
+5in
+7s
+5ked
+5le
+7s
+5s
+4er
+5st
+4ng
+6s
+3nage
+7s
+4ed
+5l
+6ed
+7r
+8s
+6ing
+9s
+6led
+8r
+9s
+7ike
+8ng
+9gs
+6s
+4ies
+5ng
+7s
+4y
+3s
+3y
+2p
+3ek
+5s
+4lo
+6s
+3ik
+5s
+3le
+5s
+3ped
+5nce
+8s
+6nies
+7y
+4ing
+3s
+3towing
+3una
+6s
+2que
+5s
+2racin
+7s
+5o
+6s
+6u
+7s
+6verdin
+9dins
+4ngawaewae
+9ewaes
+3ban
+6d
+7s
+6ed
+6ned
+6s
+6t
+7s
+5ries
+6y
+4ellarian
+9ians
+5th
+7s
+4id
+6imeter
+9ters
+9tric
+9tries
+9try
+7te
+9s
+8ies
+8y
+6ly
+6ness
+9ses
+5nacious
+7l
+8s
+7te
+9d
+9s
+8ion
+9ons
+6e
+7d
+7s
+5t
+6h
+7s
+6s
+4o
+5car
+8s
+6harged
+9ger
+9gers
+9ging
+9gings
+5electric
+5fan
+8s
+5generator
+9rators
+5jet
+8s
+5machinery
+5nd
+7s
+5prop
+9s
+5s
+6haft
+9ts
+5t
+6s
+4ulator
+9rs
+6ence
+9es
+9ies
+9y
+8t
+9ly
+3copole
+9s
+8ier
+9ers
+3dine
+5on
+7s
+4oid
+4s
+4ucken
+9s
+3een
+6s
+3f
+4ed
+5n
+4grass
+9es
+4ier
+6st
+5ness
+9es
+6g
+7s
+5te
+7s
+4less
+5ike
+4man
+5en
+4s
+5ki
+7ing
+9gs
+7s
+4y
+3gencies
+7y
+6t
+7ly
+5scence
+9ces
+9cies
+9cy
+9t
+4id
+6er
+7st
+6ities
+8y
+6ly
+6ness
+9ses
+5te
+7s
+4or
+6s
+3ion
+6s
+4sta
+7s
+3k
+4ey
+6s
+4ies
+7es
+5s
+6es
+4ois
+7es
+4s
+3lough
+8s
+3m
+4e
+5ric
+8s
+5s
+4oil
+7ed
+7ing
+7s
+4s
+3n
+4able
+6out
+9s
+5gain
+9s
+5round
+9ds
+4back
+8s
+5roach
+9hes
+5uckle
+9es
+4coat
+8s
+6ck
+8s
+4down
+8s
+5un
+7s
+4ed
+5r
+6ies
+6s
+6y
+4hall
+8s
+4ing
+7s
+5p
+6ed
+6ing
+6s
+6y
+4key
+7s
+4off
+7s
+5n
+6s
+5ut
+7s
+5ver
+8s
+4pike
+8s
+4round
+9s
+4s
+5kin
+8s
+5ole
+8s
+5pit
+8s
+5tile
+9s
+6one
+9s
+4table
+9s
+4up
+6s
+4verein
+9ns
+3ophile
+9s
+3pentine
+9ed
+9es
+9ing
+9y
+5th
+7s
+4itude
+9s
+4s
+3quois
+8e
+9s
+3ret
+6ed
+6s
+4ibant
+9s
+5cal
+6ulate
+9ted
+3tle
+6back
+9ks
+6d
+7ove
+9es
+6head
+9ds
+6neck
+9ked
+9ks
+6r
+7s
+6s
+5ing
+8s
+3ves
+2sche
+6s
+3h
+4ed
+5ries
+6y
+5s
+4ie
+6s
+5ng
+4kar
+7s
+5er
+7s
+3k
+4ar
+6s
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7s
+4less
+5ike
+4s
+4y
+3sac
+5h
+6s
+5l
+5r
+6s
+4eh
+6s
+5r
+6s
+5s
+4is
+6es
+5ve
+4le
+6d
+6s
+5ing
+4ock
+7ed
+7s
+7y
+5r
+6e
+7s
+6s
+4uck
+7s
+5r
+6s
+2t
+3ania
+7s
+3ee
+5s
+4lage
+8s
+6r
+7ies
+7s
+7y
+4nag
+7s
+3iorism
+9s
+8t
+9s
+3man
+4en
+3or
+5age
+8s
+5ed
+6ss
+8es
+5ial
+8ly
+8s
+6ng
+8s
+6se
+8d
+8s
+7ing
+7m
+8s
+6ze
+8d
+8s
+7ing
+5s
+6hip
+9s
+4yed
+6r
+7ed
+7ing
+7s
+3ress
+7es
+4ices
+5x
+6es
+3s
+4an
+6s
+4ed
+5s
+4ing
+3ted
+4i
+5es
+5ng
+7s
+5s
+4y
+3u
+4ed
+4s
+3work
+7er
+9s
+7man
+8en
+7s
+2x
+3edo
+6ed
+7s
+6s
+4s
+2yer
+5e
+6s
+5s
+2zz
+4es
+1wa
+3ddle
+7d
+7r
+8s
+7s
+6ier
+8st
+7ng
+9s
+6y
+3e
+4s
+3fald
+3in
+5s
+4te
+6s
+3l
+4pennies
+8y
+4s
+3ng
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5le
+7d
+7r
+8s
+7s
+6ing
+9ly
+9s
+5s
+5y
+4k
+5ay
+7s
+5ies
+5s
+5y
+3s
+4ome
+7s
+3ttle
+7d
+7r
+8s
+7s
+6ing
+9s
+3y
+4blade
+9s
+4s
+2eak
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8s
+5s
+5y
+3e
+4d
+5ier
+7st
+6ly
+6ness
+9ses
+5le
+7d
+8ee
+9ed
+9eing
+9es
+7r
+8s
+7s
+6ing
+5s
+5y
+4l
+5ed
+5ing
+5s
+5y
+4n
+5age
+8r
+9s
+5ed
+6r
+7s
+6ss
+8es
+5ie
+7s
+6ng
+5s
+5y
+4r
+5ed
+5ing
+5s
+4st
+4t
+5ed
+6r
+7s
+5ing
+5s
+4ze
+6d
+6r
+7s
+6s
+5ing
+3lfth
+7ly
+7s
+4ve
+6fold
+6mo
+8nth
+9ths
+8s
+6s
+3nties
+7th
+9s
+5y
+6fold
+9ds
+6ish
+3rk
+5ing
+5s
+4p
+5ier
+7st
+5s
+5y
+2ibil
+6l
+7s
+6s
+3ce
+5r
+6s
+4hild
+8ren
+3ddle
+7d
+7r
+8s
+7s
+6ier
+8st
+7ng
+9s
+6y
+3er
+5s
+3fold
+5rked
+6med
+3g
+4ged
+6n
+6r
+7s
+5ier
+7st
+6ng
+5y
+4ht
+6ed
+6ing
+6s
+4less
+6t
+7s
+5ike
+5oo
+7s
+4s
+5ome
+3light
+8ed
+8ing
+8s
+5t
+4l
+5ed
+5ies
+6ng
+8s
+5s
+5y
+4t
+5ed
+5ing
+5s
+3n
+4berries
+8y
+5orn
+4e
+5d
+5r
+6s
+5s
+4flower
+9rs
+4ge
+6d
+6ing
+6s
+5ing
+4ier
+6st
+5ght
+5ng
+7ly
+7s
+4jet
+7s
+4ked
+5ies
+6ng
+5le
+7d
+7r
+8s
+7s
+6ing
+9s
+6y
+5s
+4ling
+8s
+4ned
+5ing
+8s
+4s
+5et
+7s
+5hip
+8s
+4ter
+7s
+4y
+3re
+5d
+5s
+4ing
+4l
+5ed
+6r
+7s
+5ier
+7st
+6ng
+5s
+5y
+4p
+5ier
+7st
+5s
+5y
+3scar
+7s
+4t
+5abilities
+9ity
+7le
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8s
+5or
+7s
+5s
+5y
+3t
+4ch
+6ed
+7r
+8s
+7s
+6ier
+8st
+7ly
+7ng
+9s
+6y
+4e
+5s
+4s
+4ted
+6n
+7s
+6r
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7s
+7y
+5ing
+8ly
+8s
+3xt
+3zzle
+7d
+7s
+6ing
+2o
+3ccer
+7s
+5ing
+8s
+4ker
+7s
+5ing
+8s
+3er
+5s
+3fer
+6s
+4old
+7ness
+9sses
+7s
+3ness
+7es
+4ie
+6s
+3onie
+7s
+3pence
+8s
+8worth
+9orths
+6nies
+7y
+3s
+4eater
+9s
+4ome
+7s
+4troke
+2p
+2yer
+5e
+6s
+5s
+3fold
+1ychism
+7s
+3oon
+6ate
+9s
+6eries
+8y
+6s
+2de
+2e
+3d
+3e
+4s
+3ing
+3r
+4s
+3s
+2g
+3s
+2in
+4g
+3yn
+5s
+2ke
+4s
+3ish
+2lectomies
+8y
+4r
+5s
+3opod
+7s
+4ses
+5in
+7s
+6s
+4te
+6s
+2mbal
+6s
+3p
+4an
+6a
+7l
+6i
+7c
+8s
+7es
+7form
+7st
+9s
+7tes
+9ses
+8ic
+9s
+9ses
+6o
+6s
+6um
+8s
+6y
+4s
+2nd
+4allimetries
+9etry
+4e
+3e
+4d
+4s
+3ing
+2pable
+4l
+3e
+4able
+4bar
+7s
+4case
+8s
+7t
+8er
+9rs
+8ing
+8s
+4d
+4face
+8s
+5ounder
+9ers
+9ing
+9ings
+4s
+5cript
+9ts
+5et
+7s
+7ter
+9rs
+8ing
+9ngs
+5tyle
+9s
+4write
+9r
+9rs
+9s
+8ing
+9ngs
+8ten
+6ote
+4y
+3haceous
+4litic
+8s
+9es
+5ologies
+9y
+6sole
+9es
+4ogenic
+5id
+7al
+7in
+9s
+7s
+5n
+6ian
+7c
+6s
+5on
+7s
+5se
+5us
+4us
+6es
+3ic
+5al
+7ities
+9y
+7ly
+7ness
+9sses
+4er
+5st
+4fication
+9ions
+6ed
+7r
+8s
+7s
+5y
+6ing
+4ng
+6s
+4st
+6s
+3o
+4graph
+9ed
+9er
+9ers
+9ia
+9ic
+9ical
+9ically
+9ies
+9ing
+9ist
+9ists
+9s
+9y
+4logic
+9al
+9ally
+8es
+8st
+9ts
+7y
+4mania
+9s
+4s
+4thetae
+3p
+4s
+3to
+5ed
+5ing
+5s
+3y
+2ramine
+8s
+4n
+5ed
+5ing
+5ne
+7d
+7s
+8s
+9es
+6ic
+8al
+9lly
+9lness
+8idal
+9de
+9des
+7es
+7ng
+7s
+8e
+9d
+9r
+9rs
+9s
+8ing
+7ze
+9d
+9r
+9rs
+9s
+8ing
+6osaur
+9urs
+9urus
+9uruses
+7us
+9ly
+9ness
+9nesses
+6y
+5s
+5t
+6ed
+6ing
+6s
+3e
+4d
+4less
+4s
+3ing
+3o
+4cidin
+9e
+9es
+9s
+4es
+4glyphid
+9ids
+4nes
+5ic
+4pitta
+9s
+4s
+5inase
+9es
+7e
+8s
+4thricin
+9ins
+2stie
+6s
+2te
+3he
+5d
+5s
+4ing
+1zaddi
+6k
+7im
+7s
+6q
+7im
+7s
+6s
+3r
+4dom
+7s
+4evna
+8s
+4ina
+7s
+5sm
+7s
+6t
+7s
+5tza
+8s
+4s
+3tziki
+8s
+2etse
+6s
+4ze
+6s
+2igane
+7s
+6ies
+6y
+3mmes
+7es
+3tzis
+6t
+7h
+2uris
+0uakari
+6s
+1berous
+4sexual
+9ls
+4ties
+5y
+2ieties
+5y
+3quarian
+5e
+5inone
+9es
+6tarian
+9ianism
+9ians
+9y
+7ies
+8n
+9ation
+9ations
+9s
+7ous
+9sly
+9sness
+7y
+2untu
+6s
+1ckers
+1dal
+4ler
+7s
+4s
+2der
+5ed
+5ful
+5less
+5s
+2o
+3meter
+8s
+6ric
+8es
+7y
+3n
+4s
+3s
+2s
+1ey
+3s
+1fo
+3logical
+7es
+7st
+9s
+6y
+3s
+1g
+2ali
+5s
+2ged
+3ing
+2h
+3s
+2lied
+5r
+5s
+6t
+4fication
+9ions
+6ed
+7r
+8s
+7s
+5y
+6ing
+4ly
+4ness
+8es
+3y
+4ing
+2s
+3ome
+6ness
+9ses
+1h
+2lan
+5s
+2uru
+5s
+1illean
+7n
+2ntahite
+9s
+5ite
+8s
+5there
+9es
+2tlander
+9s
+1jamaa
+6s
+1kase
+5s
+2e
+3lele
+7s
+3s
+2ulele
+7s
+1lama
+5s
+3n
+4s
+2cer
+5ate
+8d
+8s
+7ing
+8on
+9ns
+8ve
+5ed
+5ing
+5ogenic
+6us
+8ly
+8ness
+9esses
+5s
+2e
+3ma
+5s
+3s
+3x
+4es
+4ite
+7s
+2ices
+4on
+6s
+3ginose
+7us
+3kon
+6s
+3tis
+6es
+2lage
+6d
+6s
+5ing
+3ing
+6s
+2maceous
+3in
+5s
+2na
+4d
+4e
+4r
+5e
+5ia
+4s
+2oses
+4is
+3trichies
+8ous
+8y
+2pan
+5im
+2ster
+6ed
+7tte
+9es
+6s
+2terior
+8ly
+3ima
+6cies
+7y
+6s
+6ta
+7e
+8d
+8ly
+8ness
+9esses
+8s
+7ing
+7um
+9s
+5o
+6geniture
+9itures
+4on
+6s
+3ra
+5basic
+9cs
+5careful
+7sual
+7utious
+6entrifuge
+6hic
+6ivilised
+9lized
+6lean
+6old
+7mmercial
+8pact
+9etent
+7nvenient
+7ol
+6repidate
+9idated
+9idates
+7itical
+5democratic
+7nse
+6istance
+9ances
+9ant
+6ry
+5efficient
+6nergetic
+6xclusive
+5familiar
+7st
+9idious
+6eminine
+6iche
+9es
+7lter
+9ered
+9ering
+9ers
+9rate
+9rates
+9ration
+7ne
+5glamorous
+5hazardous
+6eat
+9ed
+9ing
+9s
+8vy
+6igh
+7p
+6ot
+6uman
+5ism
+8s
+7t
+8ic
+8s
+5large
+6eft
+9ism
+9isms
+9ist
+9ists
+6iberal
+9ralism
+9rals
+7ght
+9ts
+6ow
+5mafic
+7rathon
+9thoner
+9thons
+8ine
+9nes
+7sculine
+6icro
+9ometer
+9oscope
+9oscopy
+9otome
+9otomes
+9otomy
+7litant
+9tants
+7niature
+6odern
+9rnism
+9rnisms
+9rnist
+9rnists
+7ntane
+9anes
+9anism
+9anisms
+9anist
+9anists
+6undane
+5national
+5orthodox
+5patriotic
+6hysical
+6osh
+7werful
+6ractical
+7ecise
+9ision
+9isions
+6ure
+5quiet
+5radical
+9cals
+7pid
+7re
+9fied
+7tional
+6ealism
+9isms
+9ist
+9istic
+9ists
+7d
+8s
+7fined
+7liable
+6ich
+7ght
+9tist
+9tists
+6omantic
+7yalist
+9lists
+5s
+6afe
+6ecret
+7nsitive
+9ual
+7rious
+6harp
+7ort
+6imple
+6lick
+7ow
+6mall
+8rt
+7ooth
+6oft
+7nic
+9cally
+9cs
+8ography
+7und
+9ds
+6tructural
+9cture
+9ctures
+5thin
+6iny
+5vacua
+9um
+9ums
+6iolence
+9ences
+9ent
+9et
+9ets
+7rile
+9lities
+9lity
+8us
+9ses
+5wide
+9band
+9bands
+4oneous
+9sly
+9sness
+2u
+3lant
+5te
+7d
+7s
+6ing
+7on
+9s
+3s
+2va
+4s
+2yie
+5s
+2zie
+5s
+1m
+2ami
+5s
+3ngite
+8s
+2bel
+5ed
+5lar
+7te
+9d
+9ly
+6ed
+7t
+8s
+6ifer
+9rous
+9rs
+6ulate
+8e
+9s
+5s
+4r
+5ed
+5ing
+5s
+5y
+3ilical
+9ly
+9s
+8te
+9ed
+9ion
+9ions
+7i
+7us
+9es
+6form
+3le
+5s
+3o
+4nal
+6te
+7ion
+9ns
+5es
+5ic
+4s
+3ra
+5cula
+9te
+8iform
+8um
+5e
+5ge
+7d
+7ous
+9sly
+9sness
+7s
+6ing
+5l
+5s
+5ted
+6ic
+8al
+7le
+8ous
+4e
+5l
+6la
+8ed
+8ing
+8s
+7o
+8es
+8s
+6s
+5re
+7s
+5s
+5tte
+8s
+4iere
+8s
+5ferous
+5l
+6s
+4ose
+5us
+2fazi
+6s
+2iac
+5k
+6s
+5s
+4k
+5s
+4q
+5s
+2laut
+6ed
+6ing
+6s
+3ungu
+7s
+2m
+3a
+4h
+5s
+4s
+3ed
+3ing
+2p
+3ed
+3h
+3ie
+5s
+4ng
+4rage
+8s
+5e
+6d
+6s
+7hip
+9ps
+5ing
+3s
+3teen
+7th
+9s
+4ieth
+4y
+3y
+2quhile
+2ra
+4h
+5s
+4s
+2s
+2teenth
+2u
+3s
+2welt
+6s
+3hile
+1n
+2abashed
+9ly
+5ted
+8ly
+6ing
+4breviated
+4etted
+4iding
+4jured
+4le
+4olished
+5rted
+4raded
+5idged
+5ogated
+4solved
+6rbed
+9nt
+4used
+6ive
+3cademic
+9cally
+4cented
+8uated
+6ptability
+9ble
+9bly
+9nce
+9nces
+8ed
+5limated
+9tised
+9tized
+5ommodated
+9dating
+7panied
+8lished
+6untable
+9ably
+9ed
+5redited
+6ued
+5ulturated
+6sable
+9ly
+7ed
+7tomed
+9medly
+4erbic
+4hievable
+8ed
+6ng
+4idic
+4knowledged
+4quaint
+9tance
+9tances
+9ted
+4table
+5ed
+5ive
+5orish
+5uated
+3daptable
+7ed
+4ded
+5ressed
+4ept
+7ly
+4judicated
+6sted
+4mired
+7ing
+6tted
+5onished
+4optable
+7ed
+5red
+6ned
+4ult
+7erate
+9ated
+9atedly
+4ventrous
+8urous
+6rtised
+5isable
+9leness
+9ly
+7ed
+9ly
+9ness
+9nesses
+3esthetic
+3ffected
+9dly
+9dness
+8ing
+9onate
+5iliated
+5luent
+5ordable
+4raid
+3ged
+5ing
+4gressive
+4ile
+5ng
+4reeable
+7d
+3i
+4dable
+5ed
+7ly
+4med
+4red
+4s
+3kin
+6g
+5te
+7s
+3larmed
+4erted
+4ienable
+9ly
+8ted
+5gned
+5ke
+5st
+7s
+5ve
+4layed
+5eged
+6viated
+5ied
+5ocated
+6tted
+6wable
+7ed
+6yed
+5uring
+4terability
+9le
+9leness
+9ly
+7ed
+7ing
+3massed
+5zed
+4biguous
+9usly
+6tious
+9usly
+6valent
+9ently
+4enable
+6dable
+7ed
+5rced
+4iabilities
+9ity
+7le
+9ness
+9nesses
+4ortised
+8zed
+4plified
+4usable
+6ed
+6ing
+9ly
+3nalysable
+8ed
+7tic
+9cal
+7zable
+8ed
+4chor
+8ed
+8ing
+8s
+4eled
+5sthetised
+9tized
+4imated
+6ities
+8y
+6ous
+9ly
+9ness
+9nesses
+4nealed
+6xed
+5otated
+6unced
+6yed
+4swerability
+9ble
+9bly
+8ed
+4ticipated
+9atedly
+4xious
+3pologetic
+8ising
+9zing
+5stolic
+9ical
+9ically
+4palled
+6rel
+9led
+9ling
+9s
+8nt
+5ealable
+9bly
+8ing
+9ngly
+7sable
+9bly
+8ed
+6tising
+9ingly
+8zing
+9ingly
+5lausive
+6icable
+7ed
+5ointed
+5reciated
+9ation
+9ations
+9ative
+7hended
+9nsible
+9nsive
+6ised
+6oachable
+9hably
+9hed
+7priate
+9iated
+7ved
+8ing
+9ngly
+4t
+5ly
+5ness
+9es
+3rched
+4guable
+9y
+6ed
+4isen
+4m
+5ed
+5ing
+5ored
+6ured
+5s
+4oused
+4ranged
+6yed
+5ogant
+4tful
+8ly
+5iculate
+9ated
+6ficial
+9ially
+6stic
+8like
+4y
+3scendable
+8ed
+8ible
+6rtainable
+9ined
+4hamed
+9ly
+9ness
+9nesses
+4ked
+4pirated
+7ing
+9gly
+9gness
+4sailability
+9ble
+9bly
+8ed
+6yed
+5embled
+6rtive
+9vely
+5ignable
+8ed
+6milable
+9ated
+6sted
+9dly
+8ing
+5ociated
+5uageable
+9d
+6med
+7ing
+9gly
+9gness
+6red
+3thletic
+4onable
+6ed
+4tached
+6inable
+9bly
+8ted
+5empted
+6nded
+8ing
+7tive
+7uated
+6sted
+5ired
+5ractive
+9ively
+6ibutable
+9ted
+5uned
+3u
+4dited
+4gmented
+4s
+5picious
+4thentic
+9icated
+9icity
+6orised
+9tative
+9zed
+5omated
+3vailability
+9le
+9leness
+9ly
+7ing
+9gly
+9gness
+4enged
+5rage
+6table
+7ed
+7ible
+4oidability
+9le
+9leness
+9ly
+7ed
+5wed
+8ly
+3wake
+7d
+7ned
+8ing
+5rded
+6e
+7ly
+7ness
+9sses
+7s
+4ed
+5some
+3xed
+2backed
+4ffled
+4g
+5ged
+6ing
+5s
+4ilable
+5ted
+4ked
+4lance
+9d
+9s
+8ing
+5e
+6d
+6s
+5ing
+5lasted
+4n
+5dage
+9d
+9s
+8ing
+6ed
+5ked
+5ned
+6ing
+5s
+4ptise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+4r
+5bed
+7red
+5e
+6d
+6s
+5ing
+5k
+6ed
+6ing
+6s
+5red
+6icade
+9ded
+9des
+9ding
+7ng
+5s
+4sed
+5hful
+5ted
+4ted
+5hed
+5tered
+3e
+4ar
+6able
+9eness
+9y
+6ded
+6ed
+6ing
+6s
+5table
+9y
+6en
+5utiful
+9ully
+5vered
+4coming
+9gly
+9gness
+9gs
+4d
+5ded
+6ing
+5immed
+6nned
+5s
+4en
+4fitting
+5riended
+4get
+7s
+7ting
+5ged
+5inning
+5ot
+7ten
+5uile
+9d
+9s
+8ing
+6n
+4holden
+4ing
+7s
+4known
+9st
+4lief
+8s
+7vability
+9ble
+9bly
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngly
+9ngness
+5ligerent
+5oved
+5t
+6ed
+6ing
+6s
+4mused
+4nd
+6able
+6ed
+6ing
+9ly
+9ness
+9nesses
+9s
+6s
+5eficed
+9ial
+8ted
+5ighted
+7n
+8ant
+8ly
+5t
+4reft
+5ufen
+4seem
+8ed
+8ing
+9ngly
+8s
+5ought
+5peak
+9ing
+9s
+6oke
+9n
+5towed
+4trayed
+5terable
+8ed
+4wailed
+3ias
+6ed
+8ly
+8ness
+9esses
+7s
+6ing
+6sed
+9ly
+9ness
+9nesses
+8s
+7ing
+4blical
+4d
+5den
+4goted
+4lled
+4nd
+6ing
+9s
+6s
+4rthday
+9ys
+4shop
+8ed
+8ing
+8s
+4tt
+6ed
+7n
+7r
+6ing
+6s
+3lamable
+9y
+6eable
+9ly
+7d
+4eached
+5mished
+5nched
+8ing
+6ded
+6t
+5ss
+7ed
+9ness
+9nesses
+8s
+7ing
+6t
+4ind
+7ed
+7fold
+9lded
+9lding
+9lds
+7ing
+7s
+6king
+9gly
+5ssful
+4ock
+7ed
+7ing
+7s
+5oded
+7ied
+7y
+5tted
+5wed
+6n
+4unted
+5rred
+5shing
+9gly
+9gness
+3oarded
+5stful
+4bbed
+4died
+6ng
+4iled
+4lt
+6ed
+6ing
+6s
+4nded
+5e
+6d
+6s
+5ing
+5net
+8ed
+8ing
+8s
+4oked
+6ish
+5t
+6ed
+6ing
+6s
+4re
+5n
+6e
+5rowed
+4som
+7ed
+8r
+9s
+7ing
+7s
+4ttle
+8d
+8s
+7ing
+6omed
+4ught
+5ncy
+6d
+7ed
+9ly
+9ness
+9nesses
+4wdlerised
+9ized
+5ed
+5ing
+4x
+5ed
+6s
+5ing
+3race
+7d
+7s
+6ing
+6keted
+5id
+7ed
+7ing
+7s
+5ke
+7d
+7s
+6ing
+5nched
+6ded
+5ste
+4eachable
+8ed
+6kable
+6thable
+8ed
+8ing
+5d
+5ech
+8ed
+9s
+8ing
+4ibable
+5dgeable
+8d
+6le
+8d
+9ly
+9ness
+9nesses
+8s
+7ing
+5efed
+5ght
+5lliant
+5zzed
+4oiled
+5ke
+7n
+8ly
+8ness
+9esses
+5therlike
+9ly
+5wned
+4uised
+5sed
+6hed
+3uckle
+8d
+8s
+7ing
+4dded
+5geable
+9ly
+7ted
+6ing
+9ly
+4ffered
+4ild
+7able
+7ing
+7s
+6t
+4lky
+4ndle
+8d
+8r
+9s
+8s
+7ing
+9gs
+4rden
+8ed
+8ing
+8s
+5eaucratic
+5ied
+7s
+5nable
+6ed
+6ished
+6t
+5row
+8ed
+8ing
+8s
+5then
+9ed
+9ing
+9s
+5y
+6ing
+4sinesslike
+5ted
+5y
+4ttered
+6on
+8ed
+8ing
+8s
+2cage
+6d
+6s
+5ing
+4ke
+6d
+6s
+5ing
+4lcified
+7ned
+6ulated
+9ting
+5ibrated
+5led
+6oused
+4nceled
+5did
+8ly
+8ness
+9esses
+6led
+6our
+9s
+5ned
+6ier
+8st
+7ly
+7ness
+9sses
+6y
+5onic
+9al
+9alness
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+4p
+5able
+5e
+6d
+6s
+5ing
+6talised
+9ized
+5ped
+6ing
+5s
+6izable
+5tioned
+6urable
+4rded
+5ed
+6ful
+5ing
+5peted
+5t
+6ed
+6ing
+6s
+5ved
+4se
+6d
+6s
+5hed
+5ing
+5ked
+5t
+6rated
+4taloged
+9ued
+5chable
+7y
+5e
+6gorisable
+9izable
+6red
+4ught
+5sed
+3e
+4asing
+9ly
+9ness
+9nesses
+4ded
+4lebrated
+4nsored
+8ious
+6ured
+4rebral
+6monious
+9iously
+5tain
+9ly
+9ness
+9nesses
+9ties
+9ty
+6ificated
+9ed
+4s
+5sant
+3hain
+7ed
+7ing
+7s
+6r
+7ed
+7ing
+7s
+5llengeable
+9geably
+9ged
+9ging
+5ncier
+9st
+7y
+6geability
+9ble
+9bly
+8d
+7ing
+9gly
+9gness
+6neled
+5peroned
+5rge
+8d
+8s
+7ing
+6ismatic
+7table
+9bly
+8ies
+8y
+6m
+7ed
+7ing
+7s
+6nel
+9led
+9ling
+9s
+6red
+6ted
+8red
+6y
+5ste
+8ly
+8ned
+9ess
+9esses
+8r
+8st
+7isable
+9ed
+8ties
+9y
+8zable
+9ed
+5uvinistic
+4eck
+7able
+7ed
+7ing
+7s
+5ered
+7ful
+9lly
+9lness
+5wable
+6ed
+4ic
+6ly
+5ld
+7ed
+7ing
+7like
+7s
+6led
+5valrous
+9ously
+4lorinated
+4oke
+7d
+7s
+6ing
+5reographed
+5sen
+4risom
+7ten
+9ned
+9ning
+9ns
+8ian
+9aned
+9aning
+9anise
+9anised
+9anises
+9anize
+9anized
+9anizes
+9anlike
+9anly
+9ans
+5onicled
+7ological
+4urch
+8ed
+9s
+8ing
+8ly
+3i
+4a
+5e
+5l
+6ly
+6s
+4form
+8s
+4liated
+4nal
+6ria
+9s
+9ses
+9sis
+6te
+8d
+5ematic
+5i
+5us
+4pher
+8ed
+8ing
+8s
+4rculated
+7mcised
+9ision
+9isions
+8scribed
+4ted
+4vil
+7ised
+9edly
+9edness
+8ties
+9y
+8zed
+9edly
+9edness
+7ly
+7ness
+9sses
+3lad
+5imed
+5mp
+7ed
+7ing
+7s
+5rified
+7ties
+8y
+5sp
+7ed
+7ing
+7s
+6sed
+7ical
+8fiable
+9ied
+7y
+5wed
+4e
+5an
+7ed
+8r
+8st
+7lier
+9est
+9ness
+9nesses
+8y
+7ness
+9sses
+7sed
+6r
+7ed
+8r
+8st
+7ly
+7ness
+9sses
+5d
+5ft
+5nch
+8ed
+9s
+8ing
+5rical
+5s
+6hip
+9s
+5w
+6ed
+6ing
+6s
+4iched
+5mbable
+9leness
+7ed
+5nch
+8ed
+9s
+8ing
+6g
+5p
+6ped
+7ing
+6s
+6t
+4oak
+7ed
+7ing
+7s
+5g
+6ged
+7ing
+6s
+5ister
+9red
+9ring
+9rs
+5se
+7d
+7s
+6ing
+5the
+8d
+8s
+7ing
+5ud
+7ed
+9ly
+9ness
+9nesses
+7ing
+7s
+7y
+5ven
+5yed
+6ing
+4ubable
+6bable
+5tch
+8ed
+9s
+8ing
+6ter
+9ed
+9ing
+9s
+3o
+4alesce
+9ed
+9es
+9ing
+5ted
+6ing
+9s
+4bbled
+4ck
+6ed
+6ing
+6s
+4ded
+5ified
+4er
+6ced
+7ive
+9ely
+5s
+6t
+4ffin
+8ed
+8ing
+8s
+4il
+6ed
+6ing
+6s
+5ned
+4llected
+9ible
+9ibles
+5ored
+6ured
+5t
+6ed
+6ing
+6s
+4matable
+5bative
+6ed
+6ine
+9d
+9s
+8ing
+5eatable
+6liness
+9esses
+7y
+5fier
+8st
+6ortable
+9ably
+9ed
+6y
+5ic
+5mendable
+9ably
+9ed
+7rcial
+6itted
+6on
+8er
+9st
+8ly
+8ness
+9esses
+6unicable
+9cated
+9cative
+7ted
+5pacted
+7nied
+9onable
+9oned
+7ssionate
+6elled
+9ing
+7nsated
+7titive
+6lacent
+8ining
+9ningly
+9sant
+9santly
+7eted
+7iant
+8cated
+8mentary
+7ying
+6osable
+7unded
+6rehended
+9ending
+9ensive
+7omisable
+9ising
+6uterised
+9rized
+4ncealable
+9ed
+9ing
+7ivable
+9ably
+9ed
+7rn
+9ed
+9edly
+9edness
+9ing
+9ment
+9ments
+9s
+8ted
+6iliatory
+6lusive
+6octed
+5ditional
+9onally
+9oned
+5federated
+7ssed
+6inable
+8e
+9d
+9dly
+9s
+8ing
+7rmed
+6orm
+9able
+9ably
+9ing
+9ities
+9ity
+7unded
+6use
+9d
+9dly
+9s
+8ing
+5geal
+9ed
+9ing
+9s
+7nial
+9ality
+5jectured
+6ugal
+9ted
+7nctive
+5nected
+9edly
+9edness
+6iving
+5querable
+9ably
+9ed
+5scientious
+8onable
+9nably
+9us
+9uses
+9usly
+9usness
+6ecrate
+9ated
+9ates
+9ating
+7ntaneous
+9ing
+6idered
+9ring
+6oled
+8idated
+6tant
+7rainable
+9ined
+9inedly
+9int
+9ints
+8icted
+8ucted
+9ctive
+6umed
+8mated
+5tainable
+7minated
+6emned
+8plated
+9orary
+7ntious
+7stable
+9ed
+6racted
+8dicted
+7ived
+7ollable
+9lably
+9led
+9ledly
+8versial
+9erted
+5ventional
+7rsable
+9ant
+8ted
+9ible
+6icted
+7nced
+9ing
+9ingly
+6oyed
+4oked
+5l
+6ed
+5perative
+9tively
+5rdinated
+4pe
+6d
+6s
+5ing
+5yrightable
+4quettish
+4rd
+6ed
+6ial
+7ng
+6s
+5k
+6ed
+6ing
+6s
+5rectable
+9ed
+7lated
+6oborated
+6upt
+9ed
+5seted
+4s
+5tly
+4unselled
+6table
+7ed
+5ple
+8d
+8r
+9s
+8s
+7ing
+5rageous
+6teous
+7liness
+9nesses
+8y
+5th
+7er
+8st
+7ly
+7ness
+9sses
+4venanted
+6r
+7ed
+7ing
+7s
+4wl
+6ed
+6ing
+6s
+4y
+5ned
+3racked
+5te
+7d
+7s
+6ing
+5zy
+4eate
+8d
+9ness
+9nesses
+8s
+7ing
+8ve
+5dentialed
+6ible
+7table
+8ed
+5wed
+4ippled
+5tical
+9lly
+4opped
+5ss
+7able
+7ed
+8s
+7ing
+5wded
+6n
+7ed
+7ing
+7s
+4udded
+5mple
+9d
+9s
+8ing
+5shable
+7ed
+4ystallised
+9lized
+3tion
+7less
+7s
+4uosities
+9y
+6us
+8ly
+8ness
+9esses
+3uckolded
+4ff
+6ed
+6ing
+6s
+4lled
+5tivable
+9table
+9ted
+6ured
+4mbered
+4rable
+8y
+5b
+6able
+6ed
+6ing
+6s
+5dled
+5ed
+5ious
+5l
+6ed
+6ing
+6s
+5rent
+5se
+7d
+7s
+6ing
+5tailed
+8n
+9ed
+9ing
+9s
+5ved
+4s
+5tomarily
+9ry
+8ed
+4t
+5e
+3ynical
+9ly
+2dam
+5aged
+5med
+6ing
+5ned
+5ped
+5s
+4nceable
+4ring
+4shed
+4table
+5e
+6d
+4untable
+7ed
+9ly
+9ness
+9nesses
+4wning
+4zzle
+8d
+8s
+7ing
+3e
+4ad
+5f
+6ed
+6ing
+6s
+5lt
+5r
+4barred
+6sed
+6table
+9ly
+7ed
+6uched
+4cadent
+6gon
+9s
+6yed
+5eivable
+8e
+9d
+9r
+9rs
+9s
+8ing
+6nt
+5idability
+9le
+7ed
+9ly
+9ness
+9nesses
+9s
+6llion
+9ons
+6mal
+7ole
+9es
+6pherable
+9red
+6sive
+5k
+6ed
+6ing
+6s
+5lared
+6ining
+5omposable
+9sed
+6rated
+4dicated
+4e
+5ded
+4faced
+5eated
+6nded
+5ide
+6ed
+6led
+6nable
+7ed
+5oliated
+6rmed
+4ified
+8s
+6y
+7ing
+4layed
+7ing
+5ectable
+6gated
+6te
+8d
+8s
+7ing
+5iberate
+6ght
+9ed
+9ful
+9s
+6verable
+9ed
+5uded
+4manding
+5ocratic
+6nstrable
+9rative
+4niable
+9eness
+9y
+6ed
+5ted
+4pendable
+8ing
+5lored
+5raved
+6eciated
+7ssed
+6ived
+4r
+5achieve
+9eved
+9ever
+9evers
+9eves
+9eving
+7t
+8ed
+8ing
+9on
+9ons
+9ve
+9vities
+9vity
+8or
+9rs
+8s
+6ge
+8d
+8nt
+9ts
+8s
+6rm
+8s
+6te
+5bake
+9d
+9s
+8ing
+6ear
+9er
+9ers
+9ing
+9ings
+9s
+7llies
+9y
+6id
+8der
+9ers
+9ing
+8s
+7t
+8e
+9s
+8ing
+8ten
+6lanket
+9kets
+6odies
+8y
+7re
+8ne
+7ss
+9es
+7ugh
+9hs
+9ht
+6reath
+9ths
+8d
+8eding
+9dings
+7idge
+9ges
+8m
+9s
+7ush
+9hed
+9hes
+9hing
+6ud
+8ded
+9ing
+8get
+9eted
+9eting
+9ets
+8s
+7ild
+9der
+9ders
+9ding
+9ds
+9t
+7rnt
+7sh
+9ed
+9es
+9ing
+7y
+8ing
+8s
+5capitalise
+9talize
+7rd
+9s
+8riage
+9iages
+8t
+9s
+7st
+9s
+6harge
+9ged
+9ges
+9ging
+6lad
+8ss
+9ses
+9sman
+9smen
+8y
+9s
+7iff
+9fs
+7othe
+9hed
+9hes
+9hing
+9hings
+7ub
+9bed
+9bing
+9s
+6oat
+9ed
+9ing
+9ings
+9s
+7ok
+9ed
+9ing
+9s
+8l
+9ed
+9ing
+9s
+7unt
+9ted
+9ting
+9ts
+7ver
+9rt
+9rts
+6rackers
+7est
+9ted
+9ting
+9ts
+7oft
+9ts
+6urrent
+9ents
+7t
+8s
+8ting
+5daks
+7mper
+9ers
+6eck
+9s
+7velop
+9loped
+9loping
+9lops
+6id
+6o
+7er
+9s
+8s
+7g
+8s
+7ing
+7ne
+7se
+9d
+9s
+8ing
+6rain
+9nage
+9nages
+9ned
+9ning
+9ns
+8w
+9ers
+9ing
+9ings
+9n
+9s
+7ess
+9sed
+9ses
+9sing
+8w
+7ive
+9es
+5earth
+7t
+8en
+8ing
+8s
+6ducated
+6mphases
+9asis
+9asise
+9asised
+9asises
+9asize
+9asized
+9asizes
+8loyed
+9oyment
+6stimate
+9mated
+9mates
+9mating
+9mation
+6xpose
+9sed
+9ses
+9sing
+9sure
+9sures
+5fed
+7ed
+9ing
+9s
+7lt
+9s
+6inanced
+8ished
+7re
+9d
+9s
+8ing
+7sh
+9ed
+9es
+9ing
+6loor
+8w
+9s
+6ong
+9ed
+9ing
+9s
+7ot
+9ed
+9ing
+9s
+6ulfil
+9illed
+9illing
+9ils
+7nd
+9ed
+9ing
+9ings
+9s
+7r
+8s
+5garment
+9ents
+6ird
+9ed
+9ing
+9s
+8t
+6laze
+9es
+6o
+7d
+8s
+7er
+9s
+8s
+7ing
+7ne
+7wn
+9s
+6rad
+9s
+9uate
+9uates
+9uette
+9uettes
+7ound
+9nder
+9nders
+9nds
+8ve
+9es
+8wn
+9th
+9ths
+5hair
+9s
+7nd
+9ed
+9edly
+9edness
+9s
+6eat
+9ed
+9ing
+9s
+6onest
+6ung
+5inflated
+9ation
+9ations
+7sured
+7vestment
+6ved
+5jaw
+8ed
+8s
+5keep
+9er
+9ers
+9ing
+9s
+7pt
+6ill
+9s
+7ng
+9dom
+9doms
+9s
+5laid
+8n
+7p
+8ped
+9ing
+8s
+7y
+8er
+9rs
+8ing
+8ment
+9ents
+8s
+6eaf
+8se
+9ed
+9es
+9ing
+8ves
+7t
+8s
+8ter
+9ers
+9ing
+9ings
+6ie
+8r
+9s
+8s
+7ne
+9d
+9n
+9ns
+9s
+8g
+9s
+8ing
+7p
+8s
+7t
+6oad
+9ed
+9ing
+9s
+7oker
+9ers
+6ying
+9gly
+5man
+8ned
+9ing
+8s
+7sted
+6eaning
+9ings
+7n
+8tioned
+6inde
+9ed
+9es
+9ing
+8e
+9d
+9r
+9rs
+9s
+8ing
+9ngs
+6ost
+5n
+6amed
+6eath
+9hs
+6iceness
+9nesses
+6ote
+9d
+9s
+8ing
+7urish
+9ished
+9ishes
+9ishing
+6s
+6time
+9es
+6utrition
+9itions
+5paid
+8nting
+9tings
+7nts
+7rt
+9s
+7ss
+9es
+9ion
+9ions
+7y
+8ing
+8ment
+9ents
+8s
+6eep
+9ed
+9ing
+9s
+7opled
+7rform
+9ormed
+9orming
+9orms
+6in
+8ned
+9ing
+9ings
+8s
+7tch
+6lant
+9ted
+9ting
+9ts
+8y
+9ed
+9ing
+9s
+7ot
+9s
+6opulated
+7wered
+6raise
+9sed
+9ses
+9sing
+7epared
+7ice
+9ed
+9es
+9ing
+8se
+9ed
+9es
+9ing
+8vileged
+8ze
+9ed
+9es
+9ing
+7oduction
+8of
+8p
+9ped
+9per
+9pers
+9ping
+9s
+6ublicised
+9icized
+5qualified
+7ote
+9ed
+9es
+9ing
+5ran
+7te
+9d
+9s
+8ing
+6eact
+9ted
+9ting
+9ts
+7port
+9rted
+9rting
+9rts
+6ipe
+6un
+8ning
+9ings
+8s
+5said
+7turated
+7y
+8ing
+8s
+6core
+9ed
+9es
+9ing
+7rub
+9bs
+6ea
+8l
+9ed
+9ing
+9ings
+9s
+8s
+7cretary
+7lf
+8l
+9er
+9ers
+9ing
+9s
+8ves
+7nse
+9es
+7rved
+7t
+8s
+8ting
+7xed
+6hapen
+7eriff
+9iffs
+7irt
+9ted
+9ts
+7oot
+9ting
+9ts
+8rts
+8t
+7rub
+9bs
+6ide
+9s
+7gn
+9ed
+9ing
+9s
+7ze
+9d
+6kies
+8nker
+9kers
+8rt
+9ts
+7y
+6leeve
+9ves
+7ung
+6oil
+9s
+7ld
+7ng
+9s
+6pend
+9ding
+9ds
+9t
+7in
+9s
+6taffed
+9fing
+9fings
+8nd
+9dable
+9dably
+9ded
+9der
+9ders
+9ding
+9dingly
+9dings
+9ds
+8te
+9ed
+9edly
+9ement
+9ements
+9es
+9ing
+7eer
+9red
+9ring
+9rs
+7ock
+9ked
+9king
+9ks
+8od
+8rey
+9eys
+9ies
+9y
+7rapper
+9ppers
+9pping
+9ta
+9tum
+8ength
+7udied
+9ies
+9y
+9ying
+6upplied
+9lies
+9ly
+9lying
+7rface
+9aces
+5takable
+8e
+9n
+9r
+9rs
+9s
+8ing
+9ngs
+7ne
+7x
+8ed
+9s
+8ing
+6enancies
+9ncy
+9nt
+9nts
+6hings
+8rst
+9sts
+7rust
+9sting
+9sts
+6ime
+9d
+9s
+7nt
+9s
+6one
+9d
+9s
+7ok
+7w
+8s
+6rick
+9ks
+7ump
+9ped
+9ping
+9ps
+5use
+8d
+8s
+7ing
+6tilise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+5valuation
+9ations
+9e
+9ed
+9er
+9ers
+9es
+9ing
+6est
+9s
+6iewer
+9ers
+6oice
+9es
+7te
+9s
+5water
+9rs
+7y
+6ear
+9s
+7ight
+9hts
+7nt
+6helm
+9med
+9ming
+9ms
+6ing
+9s
+7re
+9d
+9s
+8ing
+9ngs
+7t
+8s
+6ood
+9s
+8l
+9s
+7rk
+9ed
+9er
+9ers
+9ing
+9s
+8ld
+9ds
+6rite
+9er
+9ers
+9es
+9ing
+9ings
+9ten
+7ote
+8ught
+4scendable
+9ed
+9ible
+6ribable
+9ed
+8ed
+5ert
+8s
+7ve
+9d
+9dly
+9dness
+9r
+9rs
+9s
+8ing
+9ngly
+5ignated
+8ed
+9dly
+9dness
+8ing
+6rability
+9le
+9leness
+9les
+9ly
+7ed
+7ing
+7ous
+5pairing
+9ingly
+6oiled
+5troyed
+4tectable
+8ed
+6rminable
+9nate
+9nation
+9ned
+7red
+4veloped
+5iating
+9ngly
+5oted
+6ut
+3iagnosable
+9ed
+5lectical
+4d
+5actic
+4es
+4fferenced
+4gested
+8ible
+5ht
+7ing
+7s
+5nified
+9es
+8y
+9ing
+4luted
+4minishable
+9hed
+5med
+4ne
+6s
+5ism
+8s
+5ted
+4plomatic
+5ped
+4rected
+4sappointing
+5cerned
+9edly
+9ible
+9ibly
+9ing
+9ings
+6harged
+6iplinable
+9ine
+9ined
+9ines
+6losed
+6omfited
+7rdant
+9ing
+7uraged
+7verable
+9rably
+9red
+6ussable
+9ed
+9ible
+5guisable
+9ed
+9edly
+5honoured
+5mantled
+7yed
+5ordered
+5patched
+6ensed
+6osed
+6utable
+8ed
+9dly
+5sembled
+6ociated
+7lved
+9ing
+5tempered
+6illed
+7nctive
+8guished
+6orted
+6racted
+9tedly
+9ting
+7ibuted
+6urbed
+9edly
+9ing
+4versified
+7ted
+8ing
+6sted
+9dly
+5idable
+7ed
+9ly
+9ness
+9nesses
+6ne
+5orced
+5ulged
+3o
+4able
+4cile
+5k
+6ed
+6ing
+6s
+5tored
+6rinaire
+5umented
+4er
+6s
+5s
+4gmatic
+9cally
+4ing
+7s
+4mestic
+9cate
+9cated
+9cates
+9cating
+4ne
+4omed
+4tted
+4uble
+8d
+8s
+7ing
+6table
+7ed
+9ly
+7ful
+7ing
+9gly
+3rainable
+7ed
+5matic
+9cally
+9sed
+9zed
+5pe
+7d
+7s
+6ing
+5w
+6ing
+6n
+6s
+4eaded
+7ing
+6med
+7ing
+7t
+5st
+5w
+4ied
+5lled
+5nkable
+5veable
+7n
+4ooping
+5ssy
+5wned
+4unk
+3ubbed
+4e
+4g
+4lance
+9s
+8ies
+8y
+7t
+6r
+6te
+8d
+8ly
+8s
+7ing
+9gly
+8on
+9nist
+9nists
+9ns
+7or
+9s
+9y
+5led
+5ose
+6us
+5y
+4plicated
+4teous
+5iful
+9ly
+9ness
+9nesses
+3y
+4ed
+4ing
+7ly
+7ness
+9sses
+4namic
+2eager
+7ly
+4red
+5marked
+5ned
+5th
+7ed
+7ing
+7lier
+9est
+9ness
+9nesses
+8y
+7s
+4se
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+5y
+4table
+9ness
+9nesses
+5en
+5h
+6es
+3ccentric
+4lipsed
+4ological
+5nomic
+9cal
+3dge
+6d
+6s
+5ing
+4ible
+5fying
+5ted
+4ucable
+7ted
+3ffaced
+5ected
+3laborate
+9ted
+5ted
+4ectable
+7ed
+7rified
+3mbarrassed
+5ellished
+5ittered
+5odied
+4otional
+9ally
+9ed
+4phatic
+9cally
+5irical
+5loyability
+9ble
+9bles
+8ed
+9ds
+8ment
+9ents
+5tied
+3nchanted
+5losed
+5ouraging
+5umbered
+4dangered
+5eared
+8ing
+6d
+5ing
+8ly
+8ness
+9esses
+5owed
+5urable
+9leness
+9ly
+4forceable
+9d
+4gaged
+4joyable
+7ed
+4larged
+5ightened
+9ening
+4quiring
+4riched
+4slaved
+5ured
+4tailed
+5ered
+7prising
+7tained
+9ining
+5hralled
+6usiastic
+5itled
+4viable
+9y
+6ed
+6ous
+5ying
+3quable
+6l
+7ed
+7led
+8y
+7s
+5ipped
+6table
+6vocably
+9al
+9ally
+9alness
+3rasable
+6ed
+4ring
+8ly
+8ness
+9esses
+3scapable
+5orted
+4pied
+4sayed
+5ence
+9d
+9s
+8ing
+7tial
+9ally
+9als
+4tablished
+3th
+5ical
+3vaded
+5luated
+5ngelical
+4en
+6er
+7st
+6ly
+6ness
+9ses
+6tful
+9lly
+9lness
+4idenced
+4olved
+3xacting
+5ggerated
+5lted
+5mined
+6pled
+4cavated
+5elled
+6ptionable
+9onably
+9onal
+9onally
+5itable
+7ed
+7ing
+5luded
+7sive
+9vely
+5used
+4ecuted
+5mplified
+5rcised
+4hausted
+4otic
+4panded
+5ectant
+8ed
+9dly
+9dness
+6nded
+7sive
+9vely
+6rienced
+9nt
+7t
+5iated
+6red
+5lainable
+9ed
+6oded
+7ited
+7red
+5osed
+5ressed
+9ible
+9ive
+5ugnable
+6rgated
+4tended
+7uated
+5inct
+7guished
+5raordinary
+6eme
+3yed
+2fabled
+4ct
+6s
+4dable
+5ed
+5ing
+8ly
+8ness
+9esses
+4iling
+9ly
+9ness
+9nesses
+5r
+6ed
+7r
+7st
+6ing
+6ly
+6ness
+9ses
+6s
+5th
+7ful
+9lly
+9lness
+7s
+4ked
+4llen
+6ible
+5sifiable
+5tering
+9ngly
+4med
+5iliar
+9rities
+9rity
+9rly
+5ous
+4ncied
+6y
+5ned
+4shionable
+9ably
+9ed
+5ten
+8ed
+8ing
+8s
+6idious
+4thered
+8ly
+6omable
+9bly
+8ed
+4ulty
+4vorable
+9leness
+9ly
+7ed
+7ite
+6urable
+9bly
+8ed
+4zed
+3eared
+6ful
+9ly
+6ing
+5sible
+5thered
+6ured
+4d
+4ed
+5ling
+9ly
+9ness
+9nesses
+4igned
+9ly
+9ness
+9nesses
+7ing
+4lled
+6owed
+5t
+6ed
+4minine
+4nce
+7d
+7s
+6ing
+4rmented
+5tile
+8ised
+9zed
+4tter
+8ed
+8ing
+8s
+4udal
+8ise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+5ed
+3igured
+4lde
+5ed
+5ial
+8ly
+5lable
+6ed
+7ted
+5med
+5terable
+8ed
+6rable
+4ndable
+5e
+5ished
+8ing
+9ngs
+4red
+5m
+4shed
+4t
+5ly
+5ness
+9es
+5s
+5ted
+8ness
+9esses
+7r
+7st
+6ing
+9ly
+4x
+5ed
+7ness
+9sses
+6s
+5ing
+6ties
+7y
+5t
+3lagging
+9gly
+5mboyant
+5ppability
+9le
+9leness
+9ly
+7ed
+5shy
+5ttering
+9ingly
+5voured
+5wed
+4edged
+5sh
+7ed
+8s
+7ing
+7ly
+5xed
+4inching
+9ngly
+4oored
+4ush
+7ed
+8s
+7ing
+6tered
+5ted
+4yable
+3ocused
+7sed
+4iled
+4ld
+6ed
+7r
+8s
+6ing
+9s
+6ment
+9ts
+6s
+4nd
+4ol
+6ed
+6ing
+6s
+5ted
+4rbid
+8den
+5ced
+8ly
+6ible
+5dable
+5eboding
+6knowable
+9wn
+6seeable
+9ing
+9n
+7kinned
+7ted
+6told
+6warned
+5feited
+5ged
+7ttable
+9ably
+6ivable
+8en
+9ness
+9nesses
+8ing
+9ngness
+6ot
+8ten
+5ked
+5m
+6al
+8ised
+9zed
+7tted
+6ed
+6idable
+7ng
+6s
+6ulated
+5saken
+5thcoming
+6ified
+6unate
+9tely
+9teness
+9tes
+8e
+9d
+9s
+4ssiliferous
+9sed
+9zed
+5tered
+4ught
+8en
+5nd
+7ed
+9ly
+9ness
+9nesses
+3ramed
+5nchised
+6ked
+5ught
+9ed
+9ing
+9s
+4ee
+6d
+7om
+9s
+6ing
+6man
+7en
+6s
+6ze
+8s
+7ing
+5quent
+9ted
+9tly
+5tted
+4iend
+8ed
+9dness
+8lier
+9iest
+9ily
+9iness
+9y
+8s
+9hip
+9hips
+5ghted
+9ned
+5volous
+4ock
+7ed
+7ing
+7s
+5ze
+7n
+4uctuous
+5itful
+9lly
+9lness
+3uelled
+4lfillable
+9ed
+4med
+4nded
+5nier
+8st
+6y
+4rl
+6ed
+6ing
+6s
+5nish
+9ed
+9es
+9ing
+5red
+6owed
+4sed
+5sier
+8st
+7ly
+6y
+2gag
+5ged
+6ing
+5s
+4in
+6ful
+6lier
+9st
+8ness
+9esses
+7y
+6said
+8yable
+4llant
+9ly
+6ed
+4rbed
+6led
+5mented
+5nered
+6ished
+5tered
+4ted
+5hered
+4uged
+4zed
+5ing
+3ear
+6ed
+6ing
+6s
+4lded
+4nerosities
+9ity
+8us
+9sly
+5ial
+6tured
+5teel
+9ly
+6ilities
+9ty
+6le
+8manlike
+9anly
+8ness
+9esses
+7y
+6rified
+5uine
+9ness
+9nesses
+4rmane
+6inated
+4t
+5atable
+5s
+5ting
+3hostly
+3ifted
+4ld
+6ed
+6ing
+6s
+5t
+4mmicky
+4rd
+6ed
+6ing
+6s
+5t
+6h
+7ed
+7ing
+7s
+4ving
+3lad
+5morised
+9zed
+8ous
+5zed
+4ossed
+5ve
+7d
+7s
+6ing
+4ue
+6d
+6s
+5ing
+3od
+5ded
+6ing
+5lier
+8st
+7ke
+7ly
+7ness
+9sses
+6y
+5s
+4rd
+5ed
+5ged
+4t
+5ten
+4vernable
+9bly
+8ed
+4wn
+6ed
+6ing
+6s
+3raced
+7ful
+9lly
+9lness
+6ious
+9sly
+9sness
+5ded
+5mmatic
+9ical
+9ically
+5spable
+6sed
+5teful
+9lly
+9lness
+6ified
+5vely
+5zed
+4eased
+5edy
+6n
+4oomed
+5und
+8ed
+9dly
+9dness
+6ped
+5wn
+4udged
+7ing
+9gly
+3ual
+5rd
+7ed
+9ly
+9ness
+9nesses
+7ing
+7s
+4ent
+7a
+8ria
+9ies
+9ium
+9y
+7s
+7um
+5rdoned
+5s
+6sable
+7ed
+4iculate
+9ted
+9tes
+5ded
+5form
+5lty
+5nous
+5s
+4la
+6e
+6r
+6te
+8s
+5ed
+5igrade
+4m
+5med
+6ing
+5s
+3yve
+6d
+6s
+5ing
+2habitable
+7uated
+5le
+4cked
+6neyed
+4iled
+5r
+6ed
+7r
+8s
+6ing
+6s
+4llow
+8ed
+8ing
+8s
+5sed
+5ved
+4mpered
+4nd
+6ed
+6icapped
+7er
+8st
+7ly
+7ness
+9sses
+8g
+6led
+6s
+7elled
+7ome
+9ely
+9eness
+6y
+5g
+6ed
+6ing
+6s
+4ppied
+8r
+8s
+9t
+7ly
+7ness
+9sses
+6y
+7ing
+4rbour
+9ed
+9ing
+9s
+5dened
+6y
+5med
+6ful
+9ly
+6ing
+6onious
+5ness
+9ed
+9es
+9ing
+5ried
+5vested
+4sp
+6ed
+6ing
+6s
+5ting
+6y
+4t
+5ched
+5s
+5ted
+6ing
+9s
+4unted
+4zarded
+8ous
+3ead
+6ed
+6ing
+6s
+5l
+6able
+6ed
+6ing
+6s
+6th
+8ful
+9ully
+9ulness
+8ier
+9est
+9ly
+9ness
+9nesses
+8s
+8y
+5rd
+6se
+8d
+8s
+7ing
+6t
+7ed
+7ing
+7s
+5ted
+4dged
+4eded
+8ly
+6ful
+9ly
+6ily
+7ng
+9ly
+6y
+4le
+6d
+6s
+5ing
+5m
+6ed
+7ted
+6ing
+6s
+5pable
+6ed
+6ful
+9ly
+4ppen
+4ralded
+5oic
+8al
+9lly
+5st
+4sitating
+9ingly
+4wn
+3idden
+5ebound
+4ndered
+5ge
+7d
+7ment
+9nts
+7s
+6ing
+4p
+5per
+7st
+4rable
+5ed
+4storic
+9cal
+4tch
+7ed
+8s
+7ing
+4ve
+6d
+6s
+5ing
+3oard
+7ed
+7ing
+7s
+4lier
+7st
+6ly
+6ness
+9ses
+5pen
+5y
+4melike
+7y
+5ogenised
+9ized
+4nest
+5ored
+6ured
+4od
+6ed
+6ing
+6s
+5k
+6ed
+6ing
+6s
+5p
+6ed
+6ing
+6s
+4ped
+6ful
+9ly
+4rse
+7d
+7s
+6ing
+4spitable
+5tile
+4use
+7d
+7led
+7s
+6ing
+5zzled
+3uman
+7ise
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7ly
+5bled
+5orous
+4ng
+5ted
+4rried
+9ly
+6ying
+5t
+6ful
+9ly
+9ness
+9nesses
+4sbanded
+5k
+6ed
+6ing
+6s
+3ydrolysed
+9zed
+4gienic
+4phenated
+4sterical
+9cally
+2i
+3algal
+4xial
+8ly
+3body
+4row
+7s
+3cameral
+9lism
+9lisms
+9list
+9lists
+9lly
+4ellular
+9arity
+5ntral
+4ities
+6y
+4olor
+8ate
+8ous
+7ur
+9ed
+5rn
+7s
+5state
+4ycle
+8d
+8s
+7ing
+8st
+9ts
+3deaed
+6l
+7ism
+9ms
+9tic
+5ntifiable
+9ied
+5ological
+4imensional
+5omatic
+9ically
+5rectional
+3face
+7s
+4iable
+5c
+6ation
+9ons
+5ed
+6r
+7s
+6s
+5lar
+4lorous
+4oliate
+7olate
+5rm
+7ed
+8r
+8st
+7ing
+8tarian
+9arians
+9ies
+9y
+7ly
+7ness
+9sses
+7s
+4y
+5ing
+8s
+3geniture
+9res
+4norable
+3jugate
+3labiate
+5teral
+9lism
+9lisms
+9list
+9lists
+9lities
+9lity
+9lly
+4ineal
+8r
+6gual
+9lism
+9lisms
+9ls
+5teral
+4lumed
+7inated
+9ating
+9ed
+6sioned
+7trated
+4obar
+6ed
+6ular
+5cular
+3maginable
+9bly
+9tive
+9tively
+8ed
+4bued
+4mortal
+5unised
+8zed
+4olecular
+4paired
+6rted
+6ssioned
+5eachable
+9ably
+9ed
+6ded
+9ly
+5lemented
+6ored
+5ortance
+9nces
+9nt
+8uned
+6sed
+7ing
+5regnated
+7ssed
+9ible
+9ive
+6isoned
+6oved
+5ugnable
+3naugurated
+4chanted
+5ited
+5losed
+5orporated
+5umbered
+4deared
+6xed
+5icted
+4fected
+5lamed
+8mable
+7ted
+6ected
+6uenced
+9tial
+5orceable
+9d
+7mative
+9tively
+8ed
+8ing
+4gratiating
+4habitable
+9ed
+5ibited
+9edly
+9edness
+4itiate
+9ed
+9es
+4jured
+4oculated
+4quiring
+7sitive
+4scribed
+5pected
+6ired
+8ing
+5tall
+9ed
+9ing
+9s
+6ructed
+9tive
+5ulated
+6rable
+7ed
+9s
+4tegrated
+6llectual
+8igence
+9gences
+9gent
+9gently
+9gible
+9gibly
+6nded
+7tional
+9onally
+6rest
+9ted
+9tedly
+9ting
+9tingly
+9ts
+7mitted
+9ttedly
+9tting
+7pretable
+7rupted
+9ptedly
+5imidated
+5oxicating
+5roduced
+4uclear
+9te
+5red
+4ventive
+6sted
+5idious
+6ted
+7ing
+5oked
+6lved
+3on
+5isation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+8s
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5s
+3parental
+9ally
+6ous
+6tite
+4ed
+6s
+5rsonal
+9ality
+4lanar
+4od
+6s
+5lar
+8ities
+9ty
+5tent
+3que
+6ly
+6ness
+9ses
+6r
+6s
+7t
+3ramose
+7us
+4oned
+6ic
+8ally
+4radiated
+5igated
+3s
+4eptate
+5rial
+9ly
+8te
+9ely
+5x
+6es
+6ual
+9ities
+9ity
+9ly
+4ize
+4on
+6al
+8ly
+7nce
+9es
+8t
+6ous
+6s
+4sued
+3t
+4age
+7s
+5l
+5rd
+7s
+6ian
+9ism
+9isms
+9s
+7ly
+6y
+4e
+5d
+6ly
+6ness
+9ses
+5r
+6s
+5s
+4holder
+9rs
+4ies
+5ng
+7s
+5on
+7s
+5sation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+5ve
+7ly
+5zation
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+4rust
+8s
+4s
+4y
+3valence
+9es
+9ies
+9y
+8t
+9s
+6ve
+8d
+8s
+7ular
+5riant
+8te
+4ersal
+9ise
+9ised
+9ises
+9ising
+9ism
+9isms
+9ist
+9istic
+9ists
+9ities
+9ity
+9ize
+9ized
+9izes
+9izing
+9ly
+9ness
+9nesses
+9s
+7e
+8s
+7itarian
+9ies
+9y
+4ocal
+8ly
+8s
+5ltine
+2jaded
+4m
+5med
+6ing
+5s
+4undiced
+3ealous
+3oined
+6t
+7ed
+7ing
+7s
+4yful
+5ous
+3udged
+4st
+6er
+7st
+6ifiable
+9ably
+9ed
+6ly
+6ness
+9ses
+2ked
+4eled
+4mpt
+7ly
+7ness
+9sses
+4nd
+5ned
+7l
+8ed
+8ing
+8led
+9ing
+8s
+5t
+4pt
+4t
+3id
+4nd
+6er
+7st
+6led
+7ier
+9st
+8ness
+9esses
+7y
+6ness
+9ses
+5g
+6ed
+6ing
+6lier
+9st
+8ke
+7y
+6s
+5k
+6ed
+6ing
+6s
+4ss
+6ed
+7s
+6ing
+3nelled
+4ight
+8ed
+8ing
+8liness
+9y
+8s
+5t
+6s
+6ted
+7ing
+4ot
+6s
+6ted
+7ing
+5wabilities
+9lity
+8le
+9eness
+9es
+9y
+6ing
+9ly
+9ness
+9nesses
+9s
+6ledgeable
+6n
+7ness
+9sses
+7s
+3osher
+2labeled
+7led
+5ored
+7ious
+6ured
+8ing
+4ce
+6d
+6s
+5ing
+4de
+6d
+6n
+6s
+5ing
+8s
+5ylike
+4id
+4mented
+4sh
+6ed
+7s
+6ing
+5t
+6e
+4tch
+7ed
+8s
+7ing
+4undered
+4w
+5ed
+5ful
+8ly
+8ness
+9esses
+5ing
+5s
+4y
+5ing
+5s
+3ead
+6ed
+8s
+6ing
+6s
+5l
+5rn
+7able
+7ed
+9ly
+9ness
+9nesses
+7ing
+7s
+7t
+5sed
+6h
+7ed
+8s
+7ing
+5vened
+4d
+4isured
+9ly
+4ss
+6oned
+4t
+5hal
+5table
+6ed
+7red
+4vel
+7ed
+7ing
+7led
+8ing
+7s
+5ied
+3iberated
+5idinous
+4censed
+5h
+5ked
+4d
+5ded
+6ing
+5s
+4felike
+4ghted
+8ned
+7some
+4kable
+5e
+6able
+6d
+6lier
+9st
+8hood
+9oods
+8ness
+9esses
+7y
+6ness
+9ses
+6s
+4mber
+8ed
+8ing
+8s
+5e
+6d
+6s
+5ing
+6ted
+9ly
+9ness
+9nesses
+4ne
+6al
+6d
+6s
+5ing
+5k
+6ed
+6ing
+6s
+4quefied
+6idated
+6ored
+4sted
+7nable
+8ed
+8ing
+4t
+5erary
+4vable
+5e
+6able
+6d
+6liness
+9esses
+7y
+6s
+5ing
+3oad
+6ed
+7r
+8s
+6ing
+9s
+6s
+4bed
+4calised
+8zed
+6ted
+5k
+6able
+6ed
+6ing
+6s
+4gical
+4oked
+5se
+7d
+7n
+8ed
+8ing
+8s
+7s
+6ing
+4pped
+4rd
+6ed
+6ing
+6ly
+6s
+4sable
+5t
+4vable
+5e
+6able
+6d
+6lier
+9st
+8ness
+9esses
+7y
+6rlike
+6s
+5ing
+8ly
+8ness
+9esses
+3uckier
+8st
+7ly
+7ness
+9sses
+6y
+4xuriant
+8ous
+3yrical
+2macadamised
+9ized
+5ho
+4de
+4gnified
+4idenly
+5lable
+6ed
+5med
+5ntainable
+9ned
+4kable
+5e
+6r
+7s
+6s
+5ing
+8s
+4licious
+9usly
+5leability
+9le
+4n
+5acle
+9d
+9s
+8ing
+6geable
+9bly
+8d
+5ful
+8ly
+5ipulated
+5lier
+8st
+7ke
+7ness
+9sses
+6y
+5ned
+7red
+9dly
+8liness
+9y
+6ing
+7sh
+5s
+5tle
+8d
+8s
+7ing
+5ufactured
+6red
+4pped
+4rd
+5ked
+7table
+5red
+6iable
+8geable
+7ed
+9s
+8s
+6y
+7ing
+4sculine
+5k
+6ed
+7r
+8s
+6ing
+9s
+6s
+5tered
+4tchable
+7ed
+5ed
+6rial
+9lised
+9lized
+7nal
+5hematical
+5riculated
+5ted
+5ured
+3eaning
+9ly
+9ness
+9nesses
+6t
+5surable
+9bly
+8ed
+9dly
+4chanic
+9cal
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+4diated
+6cated
+7inable
+6tated
+4ek
+5t
+6ly
+6ness
+9ses
+4llow
+8ed
+5odious
+9usness
+5ted
+4morable
+9ly
+4nded
+5tionable
+9ables
+9ably
+9ed
+4rcenary
+6hantable
+6iful
+9lly
+9lness
+5itable
+7ed
+9ly
+7ing
+5ry
+4sh
+6ed
+7s
+6ing
+4t
+5abolised
+9ized
+6lled
+6phorical
+8ysical
+5ed
+5hodical
+9sed
+9zed
+5rical
+4w
+5ed
+5ing
+5s
+3ilitary
+5ked
+5led
+4nded
+6ful
+9ly
+9ness
+9nesses
+5ed
+5gle
+8d
+8s
+7ing
+5isterial
+4raculous
+5y
+4ssable
+6ed
+5takable
+9bly
+8eable
+9ably
+9n
+6rustful
+4ter
+7ed
+7ing
+7s
+5igable
+9ly
+8ted
+9edly
+9edness
+5re
+7d
+7s
+6ing
+4x
+5able
+5ed
+7ly
+6s
+5ing
+5t
+3oaned
+4derated
+7nised
+9zed
+5ifiable
+8ed
+6sh
+5ulated
+4istened
+4ld
+6ed
+6ing
+6s
+5ested
+5ten
+4neyed
+5ied
+6tored
+4or
+6ed
+6ing
+6s
+4ral
+7ised
+9ing
+8ties
+9y
+8zed
+9ing
+7ly
+5tgaged
+6ified
+7se
+9d
+9s
+8ing
+4therly
+5ivated
+7ed
+4uld
+7ed
+7ing
+7s
+5nt
+7ed
+7ing
+7s
+5rned
+4vable
+8y
+5eable
+9y
+6d
+7ly
+5ing
+4wn
+3uffle
+8d
+8s
+7ing
+4nitioned
+4rmuring
+9ngly
+4sical
+9ly
+9ness
+9nesses
+4tilated
+4zzle
+8d
+8s
+7ing
+9gs
+3yelinated
+2nail
+6ed
+6ing
+6s
+4mable
+5eable
+6d
+4neld
+4tive
+5ural
+9ise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+9ly
+9ness
+9nesses
+4vigable
+8ted
+3eath
+4cessarily
+9riness
+9ry
+4eded
+6ful
+9ly
+4gotiable
+4ighboured
+9urly
+4rve
+7d
+7s
+6ing
+9ly
+4st
+6ed
+6ing
+6s
+4thes
+5ted
+4urotic
+4wsworthy
+3ilhexium
+9ums
+5pentium
+9iums
+5quadium
+9iums
+5septium
+9iums
+3oble
+7d
+7s
+6ing
+4isy
+4ted
+5iceable
+9bly
+8d
+7ing
+4urished
+9ing
+3uanced
+4mbered
+4rtured
+2oaked
+3bedient
+5yed
+4jectionable
+9onably
+4noxious
+4scured
+5ervable
+9nce
+9nces
+9nt
+8ed
+9dly
+8ing
+5tructed
+9tive
+4tainable
+8ed
+5rusive
+9vely
+9veness
+4vious
+3ccupied
+3ffended
+8ing
+7sive
+6red
+5icered
+7ial
+9lly
+8ous
+4ten
+3iled
+3pen
+6able
+6ed
+5rative
+4posed
+5ressive
+3rdained
+5er
+7ed
+7ing
+7ly
+7s
+5inary
+4ganised
+8zed
+4iginal
+9lities
+9lity
+9te
+9ted
+4namental
+9ted
+6te
+4thodox
+9xies
+9xly
+9xy
+3ssified
+4tentatious
+3vercome
+6thrown
+3wed
+4ned
+3xidised
+7zed
+4ygenated
+2paced
+5ified
+5k
+6ed
+7r
+8s
+6ing
+9s
+6s
+4dded
+4ged
+4id
+5ned
+6ful
+6t
+7able
+7ed
+7ing
+7s
+5red
+4latability
+9le
+9ly
+5sied
+4mpered
+4nel
+7led
+8ing
+7s
+5ged
+5nel
+8led
+9ing
+8s
+4per
+7ed
+7ing
+7s
+4radise
+9ed
+9es
+9ing
+6goned
+6llel
+9led
+6sitised
+9ized
+5donable
+9bly
+8ed
+8ing
+5ed
+6ntal
+8ed
+5liamentary
+5ted
+6ial
+4ssable
+9eness
+6ionate
+9ed
+5teurised
+9ized
+6oral
+6ured
+4tched
+5entable
+8ed
+5hed
+7tic
+6wayed
+5riotic
+9ically
+6onised
+9zed
+5terned
+4ved
+5ilioned
+4y
+5able
+5ing
+5s
+3eaceable
+9leness
+7ful
+9lly
+4dantic
+5igreed
+4eled
+5rable
+6ed
+4g
+5ged
+6ing
+5s
+4n
+5ned
+6ied
+7ng
+5s
+6ioned
+5t
+4ople
+8d
+8s
+7ing
+4ppered
+4rceivable
+9ably
+9ed
+9edly
+7ptive
+6h
+7ed
+8s
+7ing
+5fect
+9ed
+9ion
+9ions
+9ly
+9ness
+9nesses
+6orated
+8mable
+9ed
+9ing
+6umed
+5ilous
+6shable
+8ed
+8ing
+5jured
+5petrated
+6lex
+9ed
+9es
+9ing
+5secuted
+6on
+8ed
+8ing
+8s
+6uadable
+9ed
+8sive
+5turbed
+5vert
+9ed
+9ing
+9s
+3hilosophic
+9phical
+4onetic
+3ick
+6able
+6ed
+6ing
+6s
+5turesque
+4erced
+4le
+6d
+6s
+5ing
+5lared
+6owed
+5oted
+4n
+5ked
+6t
+5ned
+6ing
+5s
+4tied
+6ful
+9ly
+9ness
+9nesses
+5ted
+5ying
+9ly
+3lace
+7d
+7s
+6ing
+5gued
+5ined
+6t
+7ed
+7ing
+7s
+5nked
+6ned
+6ted
+5stered
+5usible
+9ly
+8ve
+5yable
+6ed
+4easant
+9tly
+9tness
+9tries
+9try
+7ed
+7ing
+9gly
+7urable
+9ably
+6ted
+5dged
+4iable
+8y
+6nt
+4oughed
+5wed
+4ucked
+5g
+6ged
+7ing
+6s
+5mb
+7ed
+7ing
+7s
+6e
+7d
+7s
+6ing
+3oetic
+8al
+9lly
+9lness
+4inted
+5sed
+6on
+8ed
+8ing
+8s
+4larisable
+9ed
+8zable
+9ed
+5iced
+7ied
+6sh
+8able
+8ed
+9s
+8ing
+6te
+8ly
+8ness
+9esses
+7ic
+9al
+5led
+6uted
+4pe
+6d
+6s
+5ing
+5ular
+9ities
+9ity
+9ly
+8ted
+7ous
+4rtioned
+4sed
+5sessed
+9ing
+6ible
+5ted
+4table
+5ted
+4wdered
+5ered
+3racticable
+9al
+9ality
+9ally
+9alness
+9ed
+8sed
+9edness
+5ise
+8d
+8s
+8worthy
+7ing
+5y
+6ed
+6ing
+6s
+4each
+8ed
+9s
+8ing
+5cedented
+9ntedly
+6ise
+5dict
+9able
+9ables
+9ably
+9ed
+9ing
+9s
+5ferred
+5gnant
+5judiced
+9cedly
+5latical
+5meditable
+9tated
+9tation
+5occupied
+5pare
+9d
+9dly
+9dness
+9s
+8ing
+6ossessed
+9essing
+5scribed
+6entable
+6sed
+7ured
+9ised
+9ized
+6uming
+8ptuous
+5tending
+9ingly
+8tious
+9iously
+6tiness
+9esses
+7y
+5vailing
+6entable
+9ed
+4iced
+5est
+8ed
+8ing
+8ly
+8s
+5med
+5ncely
+7ipled
+6table
+9leness
+9ly
+7ed
+5sable
+6on
+8ed
+8ing
+8s
+5vileged
+5zable
+6ed
+4obed
+6lematic
+5cedural
+7ssed
+6laimed
+6urable
+5duced
+8tive
+9ively
+9ivity
+5faned
+6essed
+9ional
+9ionals
+6itability
+9ble
+9bly
+8ed
+8ing
+5grammable
+9med
+7essive
+9sively
+5hibited
+5jected
+5lific
+5mised
+8ing
+9ngly
+6pted
+5nounceable
+9ced
+5p
+6er
+8ly
+8tied
+6hetic
+9ical
+6itious
+9ously
+6ortionate
+9ioned
+7sed
+6ped
+7ing
+6s
+5sperous
+9ously
+5tected
+9edness
+7stantise
+9antize
+9ed
+9ing
+5vable
+6ed
+7n
+6ide
+9d
+9dly
+9nt
+9s
+8ing
+7sioned
+6ocative
+7ke
+9d
+9dly
+9s
+8ing
+4uned
+3ublicised
+9zed
+7shable
+9ed
+4cker
+8ed
+8ing
+8s
+4lled
+4nctual
+9lities
+9lity
+9ted
+5ishable
+9bly
+8ed
+4rchasable
+9eable
+9ed
+5e
+6ly
+5ged
+5ified
+5posed
+5se
+7d
+7s
+6ing
+6ued
+5vaide
+6eyed
+4tdownable
+4zzle
+8d
+8s
+7ing
+2quaking
+5lifiable
+9ed
+9edly
+9edness
+9es
+8y
+9ing
+7ted
+8ied
+5ntifiable
+9ied
+8sed
+8zed
+5rried
+4een
+7ed
+7ing
+7lier
+9est
+9ke
+8y
+7s
+5lled
+5nchable
+9bly
+8ed
+5stionable
+9nably
+9ned
+9ning
+9ningly
+4ickened
+5et
+7ed
+8r
+8st
+7ing
+7ly
+7ness
+9sses
+7s
+4otable
+6e
+7d
+7s
+6ing
+2raced
+5ked
+4ised
+4ke
+6d
+6s
+5ing
+4nked
+5somed
+4ted
+5ified
+4vaged
+5el
+7ed
+7ing
+7led
+9r
+9rs
+8ing
+9ngs
+7ment
+9nts
+7s
+5ished
+4zed
+5ored
+3eachable
+7ed
+6tive
+5d
+6abilities
+9lity
+8le
+9eness
+9y
+6ier
+8st
+7ly
+7ness
+9sses
+6y
+5l
+6isable
+8e
+9d
+9s
+8ing
+8m
+9s
+8tic
+9ically
+7ties
+8y
+7zable
+8e
+9d
+9s
+8ing
+6ly
+5ped
+5son
+8able
+9bly
+8ed
+8ing
+9ngly
+8s
+5ve
+7d
+7s
+6ing
+4bated
+5uked
+4callable
+8ed
+8ing
+6pturable
+5eipted
+7ved
+6ptive
+5iprocated
+5ked
+6onable
+8ed
+5laimable
+9ably
+9ed
+5ognisable
+9sably
+9sed
+9sing
+9zable
+9zably
+9zed
+9zing
+6llected
+6mmendable
+9nded
+7pensed
+6ncilable
+9lably
+9led
+9liable
+7structed
+6rded
+6unted
+6verable
+9ably
+9ed
+5tified
+5uring
+5yclable
+4d
+5eemable
+8ed
+5ressed
+8t
+5uced
+7ible
+5y
+4el
+6ed
+7r
+8s
+6ing
+6s
+5ve
+7d
+7s
+6ing
+4fined
+5lected
+9ing
+9ingly
+9ive
+9ively
+5ormable
+8ed
+5racted
+6eshed
+9ing
+6igerated
+5uted
+4garded
+8ing
+5eneracies
+9acy
+9ate
+9ated
+9ately
+9ates
+5imented
+6stered
+5ulated
+4hearsed
+4in
+6ed
+6forced
+6ing
+6s
+4joiced
+8ing
+4lated
+7ive
+6xed
+5enting
+9ngly
+9ngness
+8or
+9rs
+5iabilities
+9lity
+8le
+9eness
+6evable
+8ed
+9dly
+6gious
+9usly
+6shed
+5uctant
+4maining
+6rkable
+9bly
+8ed
+5edied
+6mbered
+9ring
+5iniscent
+6tted
+9dly
+9nt
+9ntly
+8ing
+9ngly
+9ngness
+5orseful
+9fully
+9less
+6vable
+7ed
+5unerative
+4ndered
+5ewed
+5t
+6ed
+4paid
+7r
+8able
+8ed
+8s
+5ealable
+8ed
+7table
+8ed
+6lled
+6ntance
+9nces
+9nt
+9ntly
+8ed
+8ing
+9ngly
+5ining
+9gly
+5laceable
+6enished
+5ortable
+8ed
+6seful
+7ing
+5resented
+8sed
+6ievable
+9ed
+7manded
+6oached
+9hful
+9hing
+7ducible
+7vable
+8ed
+8ing
+5ugnant
+6lsable
+4quired
+7site
+7ted
+9dly
+4scinded
+5ented
+8ful
+8ing
+6rve
+9d
+9dly
+9dness
+9s
+5istant
+8ed
+8ible
+9ng
+9ngly
+5olvable
+8ed
+9dness
+5pectable
+9ed
+9ive
+6ited
+6onsive
+9ively
+5t
+6ed
+6ful
+9ness
+9nesses
+6ing
+9ly
+9ness
+9nesses
+6ored
+6rainable
+9ned
+9nedly
+9nt
+9nts
+7icted
+9tedly
+6s
+4tentive
+5ire
+8d
+8s
+7ing
+5ouched
+5urnable
+8ed
+8ing
+9ngly
+4vealable
+8ed
+8ing
+6nged
+9ful
+6rend
+9t
+7sed
+7ted
+5iewable
+8ed
+6sed
+5oked
+6lutionary
+4warded
+9dly
+8ing
+3hetorical
+4ymed
+5thmic
+9cal
+9cally
+3ibbed
+4d
+5able
+5den
+6le
+8able
+8d
+8r
+9s
+8s
+7ing
+5eable
+4fled
+4g
+5ged
+6ing
+5ht
+7eous
+9usly
+9usness
+7ful
+9lly
+9lness
+7s
+5s
+4med
+4nged
+5sed
+4p
+5e
+6ly
+6ned
+8ss
+9ses
+6r
+6st
+5ped
+6ing
+9s
+5s
+4sen
+4valed
+7led
+5en
+6t
+7ed
+7ing
+7s
+3oasted
+4be
+6d
+6s
+5ing
+4ll
+6ed
+6ing
+6s
+4manised
+8zed
+7tic
+9cal
+9cally
+9cised
+9cized
+4of
+6ed
+6ing
+6s
+5st
+7ed
+7ing
+7s
+5t
+6ed
+6ing
+6s
+4pe
+6d
+6s
+5ing
+4sined
+4tted
+7n
+4uged
+6h
+5nd
+7ed
+7ing
+7s
+5sed
+4ve
+6n
+4yal
+7ly
+3ubbed
+4de
+4ffable
+6e
+6le
+8d
+9ness
+9nesses
+8s
+7ing
+4le
+6d
+6s
+5ier
+7st
+6ment
+9ts
+6ness
+9ses
+5y
+4mpled
+4shed
+5ted
+2s
+3addle
+8d
+8s
+7ing
+4fe
+6ly
+6ness
+9ses
+6r
+6st
+6ties
+7y
+4id
+5led
+5ned
+6t
+7ed
+7ing
+7lier
+9est
+9ness
+9nesses
+8y
+7s
+4labilities
+9ity
+7le
+8y
+6ried
+5eabilities
+9lity
+8le
+5ted
+5uted
+5vageable
+4mpled
+4nctified
+9ies
+9y
+9ying
+8oned
+5dalled
+5itary
+4pped
+4shed
+4table
+5ed
+5iable
+7te
+9d
+8ing
+6ng
+6rical
+6sfaction
+9ctions
+9ctory
+8iable
+9ed
+9edness
+8ying
+5urate
+9ed
+9es
+9ion
+9ions
+4ved
+5orily
+8ness
+9esses
+7y
+6urily
+9ness
+9nesses
+8y
+4wed
+5n
+4y
+5able
+9s
+5ing
+5s
+3cabbard
+9ded
+9ding
+9ds
+5lable
+6e
+7d
+7s
+6ing
+5nned
+5rred
+6y
+5thed
+5vengered
+4ented
+5ptred
+4heduled
+5olarlike
+9ly
+6oled
+4ientific
+5ssored
+4orched
+5ttified
+5ured
+4ramble
+9ed
+9er
+9ers
+9es
+9ing
+6tched
+5eened
+6w
+7ed
+7ing
+7s
+5ipted
+8ural
+9rally
+5upled
+7ulosity
+9ous
+9ously
+6tinised
+9ized
+4ulptured
+4ythed
+3eal
+6able
+6ed
+6ing
+6s
+5m
+6ed
+6ing
+6s
+5rchable
+9bly
+8ed
+6ed
+5son
+8able
+9bly
+8ed
+9dness
+8ing
+8s
+5t
+6ed
+6ing
+6s
+5worthiness
+9hy
+4conded
+5ret
+5tarian
+9anism
+9anisms
+5ular
+6red
+4duced
+4eable
+5ded
+5ing
+5l
+6ed
+6ie
+7ng
+6s
+5ming
+9s
+6lier
+9st
+8ness
+9esses
+7y
+5n
+6s
+4gmented
+5regated
+4isable
+5zable
+6ed
+4ldom
+5ected
+8ive
+9vely
+5f
+6conscious
+6ed
+6ing
+7sh
+9ly
+9ness
+9nesses
+6s
+5l
+6able
+6ing
+6s
+5ves
+4minaried
+4nsational
+6e
+7d
+7s
+6ible
+9y
+7ng
+7tised
+9ve
+9zed
+6ualise
+9ised
+9ises
+9ising
+9ize
+9ized
+9izes
+9izing
+5t
+6enced
+6imental
+4parable
+8ted
+5ulchred
+4rious
+9ness
+9nesses
+5ved
+6iceable
+4t
+5s
+5ting
+6le
+8d
+9ly
+9ness
+9nesses
+8ment
+9ents
+8s
+7ing
+9gly
+9gs
+4vered
+4w
+5ed
+5ing
+5n
+5s
+4x
+5ed
+6s
+5ing
+6st
+5ual
+5y
+3hackle
+9d
+9s
+8ing
+5ded
+6ow
+8able
+8ed
+8ing
+8s
+5kable
+9eness
+9y
+6eable
+9leness
+9ly
+7d
+7n
+8ly
+5le
+7d
+7s
+6ing
+5med
+5pe
+7d
+7lier
+9est
+8y
+7n
+7s
+6ing
+5red
+6p
+7ened
+5ved
+7n
+4eathe
+9d
+9s
+8ing
+5d
+5ll
+7ed
+7ing
+7s
+6tered
+5nt
+5wn
+4ielded
+5ft
+7ed
+7ing
+7s
+5ngled
+5p
+6ped
+7ing
+6s
+5rted
+4ockable
+7ed
+5d
+5e
+6d
+6ing
+6s
+5ot
+7ed
+7ing
+7s
+5rn
+5t
+5ut
+7ed
+7ing
+7s
+5wered
+6n
+6y
+4rinkable
+8ing
+9ngly
+6ved
+8n
+5oud
+8ed
+8ing
+8s
+5ubbed
+7d
+6nk
+4unnable
+7ed
+5t
+6s
+6ter
+9ed
+9ing
+9s
+7ing
+3icker
+6led
+4fted
+4ghing
+6t
+7ed
+9ly
+7ing
+7lier
+9est
+9ness
+9nesses
+8y
+7s
+5ned
+4lent
+4milar
+4new
+7ed
+7ing
+7s
+5ful
+5kable
+5nowed
+4stered
+8liness
+9y
+6ing
+4zable
+5eable
+6d
+3kilful
+9ly
+9ness
+9nesses
+6led
+7ful
+9lly
+9lness
+5mmed
+5nned
+3lain
+5kable
+6ed
+4eeping
+4iced
+6k
+5ng
+7ing
+7s
+5pping
+4uice
+8d
+8s
+7ing
+5mbering
+7rous
+5ng
+3mart
+4iling
+9ly
+5rched
+5tten
+4oked
+5oth
+8ed
+8ing
+8s
+5te
+6herable
+3nag
+6ged
+7ing
+6s
+5p
+6ped
+7ing
+6s
+5rl
+7ed
+7ing
+7s
+4eck
+7ed
+7ing
+7s
+4uffed
+3oaked
+5ped
+4ber
+7ly
+4ciabilities
+9lity
+8le
+9eness
+9y
+7l
+8ised
+9sm
+9sms
+9ties
+9ty
+9zed
+8ly
+5ket
+8ed
+8ing
+8s
+4d
+5den
+4ft
+6ened
+8ing
+4iled
+4laced
+5d
+6er
+8ed
+8ing
+8s
+6ierlike
+9ly
+5emn
+5icited
+9ous
+6d
+7ities
+9y
+7ly
+5vable
+6ed
+4ncy
+5sie
+6y
+4ote
+6hed
+4phisticate
+9icated
+4rted
+4ught
+5l
+6ed
+6ing
+6s
+5nd
+7able
+7ed
+8r
+8st
+7ly
+7ness
+9sses
+5rced
+6ed
+4wed
+5n
+3par
+6ed
+6ing
+9ly
+9ness
+9nesses
+6red
+7ing
+6s
+4eak
+7able
+9leness
+9ly
+7ing
+7s
+5cialised
+9ized
+7fiable
+9c
+9ed
+6tacled
+9ular
+6ulative
+5d
+5ll
+7ed
+7ing
+7s
+5nt
+4here
+8d
+8s
+7ing
+4ide
+5ed
+5lled
+6t
+5rited
+8ual
+9alise
+9alised
+9alises
+9alize
+9alized
+9alizes
+9ally
+4linterable
+6t
+4oiled
+7t
+5ke
+7n
+5ol
+7ed
+7ing
+7s
+5rting
+7smanlike
+5tted
+9ness
+9nesses
+4rayed
+5inkled
+5ung
+4un
+3quared
+3table
+8ness
+9esses
+8r
+8st
+7y
+5ck
+7ed
+7ing
+7s
+5id
+7ness
+9sses
+6nable
+7ed
+5lked
+5mped
+5nchable
+8ed
+6dardised
+9dized
+5rch
+8ed
+9s
+8ing
+6red
+7y
+6tling
+5te
+7d
+7s
+8manlike
+6ing
+6utable
+9bly
+5unchable
+9ed
+5yed
+6ing
+4eadfast
+9stly
+9stness
+7ied
+9r
+9s
+9st
+8ly
+8ness
+9esses
+7y
+8ing
+5el
+7ed
+7ing
+7s
+6pled
+5mmed
+5p
+6ped
+7ing
+6s
+5rcorated
+6ile
+8ised
+9zed
+4ick
+7ing
+7s
+5fled
+5gmatised
+9ized
+5lled
+5mulated
+5nted
+7ing
+9gly
+5rred
+5tch
+8ed
+9s
+8ing
+4ock
+7ed
+7ing
+9ged
+7s
+5ned
+5oping
+5p
+6pable
+9ly
+7ed
+8r
+9ed
+9ing
+9s
+7ing
+6s
+5w
+6ed
+6ing
+6s
+4rained
+6p
+7ped
+8ing
+7s
+6tified
+5eamed
+6ngthened
+6ss
+8ed
+9s
+5iated
+6ng
+8ed
+8ing
+8s
+6p
+7ed
+7ped
+8ing
+7s
+5uck
+7tured
+6ng
+4uck
+5died
+5ffed
+7y
+6t
+5ng
+4ylish
+3ubduable
+7ed
+5ject
+9ed
+5limated
+8ed
+5merged
+6issive
+7tting
+5scribe
+9bed
+9bes
+9bing
+6idised
+9zed
+6tantial
+9tially
+9tiated
+5tle
+7y
+4cceeded
+7ss
+9es
+9ful
+9fully
+9ive
+6oured
+5ked
+4fferable
+6icient
+4it
+6abilities
+9lity
+8le
+9eness
+9y
+6ed
+6ing
+6s
+4llied
+4mmed
+7red
+6oned
+4ng
+5k
+5ned
+6y
+4perfluous
+7vised
+5ple
+8ness
+9esses
+7ied
+6ortable
+9ed
+9edly
+7sable
+6ressed
+4re
+6d
+6ly
+6r
+6st
+5faced
+5mised
+6ountable
+5passable
+9ably
+9ed
+6rised
+9ing
+9ingly
+5veyed
+4sceptible
+5pect
+9ed
+9edly
+9edness
+9ing
+9ingly
+7nded
+6icion
+9ons
+9ous
+9ously
+5tainable
+9ed
+9ing
+3waddle
+9d
+9s
+8ing
+5llowed
+5the
+8d
+8s
+7ing
+5yable
+6ed
+4ear
+7ing
+9gs
+7s
+5et
+7ened
+5pt
+5rving
+9gly
+4ollen
+5re
+6n
+3yllabled
+4mmetrical
+9ically
+9ies
+9ised
+9ized
+9y
+5pathetic
+9ies
+9ising
+9izing
+9y
+6tomatic
+4nchronised
+9nized
+4stematic
+9tical
+9tised
+9tized
+2tack
+6ed
+6ing
+6le
+8d
+8s
+7ing
+6s
+5tful
+4gged
+4iled
+5nted
+9ly
+9ness
+9nesses
+7ing
+4ken
+4lented
+4mable
+9ness
+9nesses
+8y
+5e
+6able
+9eness
+9y
+6d
+7ness
+9sses
+6s
+5ing
+4ngible
+6le
+8d
+8s
+7ing
+5ned
+4pped
+4rnished
+5red
+4sted
+7ful
+4ught
+4x
+5ed
+6s
+5ing
+3each
+7able
+9leness
+7es
+7ing
+5m
+6ed
+6ing
+6s
+5rable
+4chnical
+4llable
+4mper
+8ed
+8ing
+8s
+6ted
+4nabilities
+9ity
+7le
+9ness
+9nesses
+8y
+6nt
+8able
+8ed
+8ing
+8s
+5ded
+7r
+8ed
+8ly
+5t
+6ed
+6ing
+6s
+6y
+5ured
+4rminated
+5restrial
+6ified
+8ying
+4stable
+6ed
+4ther
+8ed
+8ing
+8s
+3hanked
+7ful
+9lly
+9lness
+5tch
+8ed
+9s
+8ing
+5w
+6ed
+6ing
+6s
+4eological
+6retical
+4ickened
+5nk
+7ability
+9le
+9leness
+9ly
+7ing
+9gly
+9gness
+7s
+4orough
+5ught
+9ful
+9fully
+4read
+8ed
+8ing
+8s
+7tened
+9ning
+5ift
+8ily
+9ness
+9nesses
+8s
+8y
+9head
+9heads
+9hed
+9heds
+5one
+8d
+8s
+7ing
+3idied
+7r
+7s
+8t
+6ly
+6ness
+9ses
+5y
+6ing
+4e
+5d
+5ing
+5s
+4l
+5e
+6d
+6s
+5ing
+5lable
+6ed
+5ted
+4mbered
+5ed
+6lier
+9st
+8ness
+9esses
+7y
+6ous
+9ly
+4n
+5ctured
+5ged
+5ned
+6ing
+5s
+4pped
+4rable
+5ed
+5ing
+8ly
+4tled
+3o
+4chered
+4gether
+4iling
+4ld
+4mb
+6ed
+6ing
+6s
+4ned
+4rmented
+5n
+5tured
+4uchability
+9le
+9les
+7ed
+4ward
+8liness
+9y
+8ness
+9esses
+3race
+7able
+7d
+7s
+6ing
+6k
+7ed
+7ing
+7s
+6table
+9leness
+5ded
+6itional
+9onally
+5ined
+5mmeled
+9led
+6pled
+5nquil
+6sferable
+9rrable
+8ormed
+7latable
+9tably
+9ted
+7migrated
+9ssible
+9tted
+8utable
+9ted
+7parent
+5pped
+5veled
+8led
+7rsable
+9ed
+4ead
+7ed
+7ing
+7s
+6sure
+9ed
+9es
+9ing
+6table
+7ed
+5mbling
+9ngly
+6endous
+6ulous
+5nched
+6dy
+5spassing
+6sed
+4ide
+5ed
+5m
+6med
+7ing
+6s
+4od
+6den
+5ubled
+9dly
+4ue
+6ness
+9ses
+6r
+6st
+5ism
+8s
+5ly
+5ss
+7ed
+8r
+9s
+8s
+7ing
+9gs
+6t
+7ful
+7iness
+9esses
+9g
+7s
+7worthily
+9rthy
+7y
+5th
+7ful
+9lly
+9lness
+7s
+3uck
+6ed
+7red
+6ing
+6s
+4fted
+4mbled
+5ultuous
+4nable
+9ness
+9nesses
+8y
+5e
+6able
+6d
+6ful
+9ly
+9ness
+9nesses
+6s
+5ing
+4rbid
+5f
+6ed
+6ing
+6s
+5n
+6able
+6ed
+6ing
+6s
+4tored
+3willed
+5ne
+7d
+7s
+6ing
+5st
+7ed
+7ing
+9gs
+7s
+3ying
+7s
+4pable
+5ical
+9ly
+4reable
+2unbium
+8s
+4ited
+4unium
+9s
+3plifted
+3rged
+3sable
+7y
+4ed
+5ful
+8ly
+8ness
+9esses
+4hered
+4ual
+7ly
+7ness
+9sses
+3tilised
+7zed
+4terable
+9leness
+9les
+9ly
+7ed
+2vaccinated
+4il
+6e
+7d
+7s
+6ing
+6s
+4luable
+6ed
+4nquishable
+9hed
+4riable
+6ed
+7gated
+5nished
+5ying
+3eil
+6ed
+7r
+8s
+6ing
+9s
+6s
+5ned
+4ndible
+5erable
+5ted
+6ilated
+4racious
+8ties
+9y
+5balised
+9zed
+5ifiability
+9ble
+8ed
+5sed
+4sted
+4tted
+4xed
+5t
+3iable
+4ewed
+4olated
+4rtue
+8s
+7ous
+9sly
+4sitable
+7ed
+5or
+7ed
+7ing
+7s
+4tal
+5iated
+5rifiable
+9ed
+4zard
+8ed
+8ing
+8s
+3ocal
+7ised
+8zed
+4ice
+7d
+7s
+6ing
+9s
+4yageable
+3ulgar
+8ise
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+5nerable
+2waged
+4ked
+6ned
+4lled
+4ndering
+5ing
+5ted
+4rded
+5e
+6ly
+6ness
+9ses
+6s
+5ie
+7r
+7st
+6ly
+6ness
+9ses
+5like
+5med
+5ned
+5ped
+5rantable
+9ably
+9ed
+9edly
+5y
+4shed
+8ness
+9esses
+8s
+7n
+5ted
+6ing
+4tchable
+7ed
+7ful
+9lly
+9lness
+5er
+7ed
+7ing
+7s
+7y
+4vering
+9gly
+4xed
+4yed
+3eakened
+5l
+6s
+5ned
+5pon
+8ed
+8ing
+8s
+5rable
+6iable
+9ly
+7ed
+9ly
+9ness
+9nesses
+6y
+7ing
+9gly
+5thered
+5ve
+7s
+6ing
+4bbed
+4d
+5ded
+5gable
+6eable
+4eded
+5ned
+5ting
+9ly
+4ighed
+7ing
+7t
+8ed
+8ing
+8s
+4lcome
+9d
+9ly
+9ness
+9nesses
+5ded
+6y
+5l
+6ness
+9ses
+4pt
+4t
+5ted
+3hipped
+6t
+5stleable
+5te
+4olesome
+9mely
+9meness
+3ieldier
+9st
+8ly
+8ness
+9esses
+7lily
+9ness
+9nesses
+8y
+7y
+4felier
+9st
+8ke
+7y
+4gged
+4lful
+5l
+6ed
+6ing
+9ly
+9ness
+9nesses
+6s
+4nd
+6able
+6er
+8s
+6ing
+9s
+6s
+5ged
+5king
+9ly
+5nable
+6owed
+4ped
+4re
+6d
+6s
+5ing
+4sdom
+8s
+5e
+6ly
+6ness
+9ses
+6r
+6st
+5h
+6ed
+7s
+6ful
+6ing
+5t
+4t
+5ch
+7ed
+8s
+7ing
+5hdrawing
+6ered
+8ing
+6held
+7olden
+9ding
+6stood
+5nessed
+5s
+5ted
+6ily
+7ng
+9ly
+9ness
+9nesses
+6y
+4ve
+6d
+6s
+5ing
+3oman
+7ed
+7ing
+7lier
+9est
+9ness
+9nesses
+8y
+7s
+4n
+5t
+6ed
+8ly
+8ness
+9esses
+4oded
+5ed
+4rded
+5k
+6abilities
+9lity
+8le
+9es
+6ed
+6ing
+6manlike
+6s
+5ldlier
+9est
+9ness
+9nesses
+8y
+5med
+5n
+5ried
+5shipful
+9ped
+5th
+7ier
+9s
+9st
+8ly
+8ness
+9esses
+7s
+7y
+4und
+7able
+7ed
+4ve
+6n
+3rap
+6ped
+7ing
+6s
+4eaked
+6the
+9d
+9s
+8ing
+4inkle
+9d
+9s
+8ing
+5te
+7s
+6ing
+6ten
+4ote
+5ught
+4ung
+2yeaned
+3ielding
+9gly
+9gness
+3oke
+6d
+6s
+5ing
+4ung
+2zealous
+3ip
+5ped
+6ing
+5s
+3oned
+1p
+2adaisy
+3ithric
+3s
+4es
+2bear
+6er
+8s
+6ing
+6s
+5t
+6s
+3ind
+6ing
+6s
+3lew
+4ow
+6ing
+6n
+6s
+3oil
+6ed
+6ing
+6s
+4re
+5ne
+4und
+7en
+4w
+5s
+3raid
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7s
+5st
+5y
+6ed
+6ing
+6s
+4eak
+7ing
+7s
+4ing
+7ing
+9gs
+7s
+4oke
+7n
+5ught
+3uild
+7er
+9s
+7ing
+9gs
+7s
+6t
+4oyance
+9es
+4rning
+5st
+7ing
+7s
+3y
+4e
+2cast
+6ing
+6s
+4tch
+7es
+7ing
+4ught
+3heer
+7ed
+7ing
+7s
+4uck
+7ed
+7ing
+7s
+3limb
+7ed
+7ing
+7s
+4ose
+7d
+7s
+6ing
+3oast
+4il
+6ed
+6ing
+6s
+4me
+6s
+5ing
+4untries
+8y
+5rt
+3url
+6ed
+6ing
+6s
+5ve
+7d
+7s
+6ing
+2dart
+6ed
+6ing
+6s
+4te
+6able
+6d
+6r
+7s
+6s
+5ing
+3ive
+6d
+6s
+5ing
+3o
+4s
+4ve
+3raft
+7s
+5g
+6ged
+7ing
+6s
+5ught
+9s
+5w
+6ing
+6n
+6s
+4ew
+4ied
+6s
+4y
+5ing
+2end
+5ed
+5ing
+5s
+2field
+4ll
+6ed
+6ing
+9s
+6s
+3lashing
+4ing
+7ing
+7s
+4ow
+6ed
+6ing
+6s
+4ung
+3old
+6ed
+6ing
+6s
+5low
+8ed
+8ing
+8s
+3ront
+3url
+6ed
+6ing
+6s
+2gang
+6s
+4ther
+8ed
+8ing
+8s
+4ze
+6d
+6s
+5ing
+3ird
+6ed
+6ing
+6s
+5t
+3o
+4es
+4ing
+7s
+4ne
+3radabilities
+9lity
+8le
+7tion
+9ons
+6e
+7ability
+9le
+7d
+7r
+8s
+7s
+6ing
+4ew
+4ow
+6ing
+9s
+6n
+6s
+6th
+8s
+3ush
+6ed
+7s
+6ing
+2hand
+5g
+6ing
+6s
+4ud
+6ing
+6s
+3eap
+6ed
+6ing
+9s
+6s
+5val
+8s
+6e
+7d
+7r
+8s
+7s
+6ing
+4ld
+3ild
+5l
+6s
+6ward
+3oard
+7ed
+7ing
+7s
+4ist
+7ed
+7ing
+7s
+4ld
+6er
+8s
+6ing
+9s
+6s
+5ster
+9ed
+9er
+9ers
+9ies
+9ing
+9s
+9y
+7ress
+9sses
+4ord
+7ed
+7ing
+7s
+4ve
+3roe
+6s
+3udden
+4ng
+4rl
+6ed
+6ing
+6s
+2jet
+5s
+5ted
+6ing
+2keep
+6s
+3nit
+6s
+6ted
+7ing
+2laid
+4nd
+6er
+8s
+6ish
+6s
+4y
+5ing
+5s
+3ead
+6ing
+6s
+5n
+6ed
+6ing
+6s
+6t
+5p
+6ed
+6ing
+6s
+6t
+4d
+3ift
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6s
+4ght
+7ed
+8r
+9s
+7ing
+7s
+4nk
+6ed
+6ing
+9s
+6s
+4t
+3oad
+6ed
+6ing
+6s
+4ck
+6ed
+6ing
+6s
+4ok
+6ed
+6ing
+6s
+3ying
+2make
+6r
+7s
+6s
+5ing
+8s
+4nship
+9s
+4rket
+8ed
+8ing
+8s
+3ost
+2o
+3n
+2ped
+4r
+5case
+9d
+9s
+8ing
+6lassman
+9smen
+6ut
+8s
+8ting
+5most
+5part
+9s
+5s
+5works
+3ile
+6d
+6s
+5ing
+4ng
+6s
+4sh
+6ly
+6ness
+9ses
+4tiness
+9ses
+5y
+6ness
+9ses
+3rop
+6ped
+7ing
+6s
+2raise
+7d
+7r
+8s
+7s
+6ing
+4n
+4te
+6d
+6s
+5ing
+3each
+7ed
+8s
+7ing
+5r
+6ed
+6ing
+6s
+4st
+6s
+3ight
+7ed
+8ously
+7ing
+7ly
+7ness
+9sses
+7s
+4sal
+7s
+5e
+6n
+6r
+7s
+6s
+5ing
+8s
+5t
+6s
+4ver
+7s
+3oar
+6ed
+6ing
+7ous
+9sly
+9sness
+6s
+4ll
+6ed
+6ing
+6s
+4ot
+6al
+8s
+6ed
+8ness
+9esses
+7r
+8s
+6ing
+9s
+6s
+4se
+4use
+7d
+7s
+6ing
+3un
+5ning
+5s
+4sh
+6ed
+7s
+6ing
+3yst
+2s
+3adaisy
+3cale
+7d
+7s
+6ing
+3ee
+5s
+4ll
+6ing
+6s
+4nd
+6ing
+6s
+5t
+4t
+5s
+5table
+6er
+8s
+6ing
+9ly
+9s
+4y
+5s
+3hift
+7ed
+7ing
+7s
+4oot
+7ing
+7s
+5t
+6s
+3ide
+6owne
+6s
+4es
+4lon
+7s
+4tting
+9s
+4ze
+6d
+6s
+5ing
+3kill
+7ed
+7ing
+7s
+3lope
+3oar
+6ed
+6ing
+6s
+4ld
+3pake
+4eak
+7ing
+7s
+6r
+7ed
+7ing
+7s
+4oke
+7n
+4rang
+5ing
+8ing
+8s
+5ung
+3tage
+7d
+7r
+8s
+7s
+6ing
+5ir
+7s
+5nd
+7ing
+9gness
+7s
+5re
+7d
+7s
+6ing
+6t
+7ed
+7ing
+7s
+5te
+7r
+8s
+7s
+5y
+6ed
+6ing
+6s
+4ep
+6ped
+7ing
+6s
+4ir
+6red
+7ing
+6s
+4ood
+4ream
+8ed
+8ing
+8s
+6tched
+5oke
+8s
+3urge
+7d
+7nce
+9es
+7s
+6ing
+3way
+6ed
+6ing
+6s
+4eep
+7ing
+7s
+5ll
+7ed
+7ing
+7s
+5pt
+4ing
+7ing
+7s
+4ollen
+4ung
+3y
+2ta
+4k
+5e
+6n
+6s
+5ing
+5s
+4lk
+6ed
+6ing
+9s
+6s
+3ear
+6ing
+6s
+4mpo
+7s
+4r
+3hrew
+5ow
+7ing
+7n
+7s
+5ust
+8ed
+8ing
+8s
+4under
+9ed
+9ing
+9s
+3ick
+6s
+4e
+5d
+5s
+4ght
+7er
+8st
+7ness
+9sses
+4lt
+6ed
+6ing
+6s
+4me
+6s
+4tling
+9s
+3ook
+4re
+5n
+4ss
+6ed
+7s
+6ing
+4wn
+6er
+8s
+6s
+3rain
+7ed
+7ing
+7s
+4end
+7s
+4illed
+3urn
+6ed
+6ing
+9s
+6s
+3ying
+2valuation
+9ons
+6e
+7d
+7s
+6ing
+2waft
+6ed
+6ing
+6s
+4rd
+6ly
+6ness
+9ses
+6s
+3ell
+6ed
+6ing
+9s
+6s
+4nt
+3hirl
+7ed
+7ing
+7s
+3ind
+6ing
+6s
+3ound
+3rap
+6s
+4ought
+1r
+2achi
+5us
+7es
+4il
+6s
+3ei
+4mia
+7s
+6c
+4us
+6es
+3li
+5s
+5te
+7s
+6ic
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+3nalyses
+8is
+4ia
+6n
+6s
+5c
+5de
+7s
+5n
+6ite
+9s
+6s
+5sci
+7us
+6m
+7s
+5te
+7s
+6ic
+5um
+7s
+4ographer
+9hers
+9hic
+9hical
+9hies
+9hist
+9hists
+9hy
+5logies
+8y
+5metries
+9y
+5plasties
+9ty
+5us
+4yl
+6ic
+6s
+3o
+4s
+3re
+5s
+4i
+5s
+3se
+5s
+3te
+5s
+4ic
+2b
+3an
+5e
+6ly
+6ness
+9ses
+6r
+6st
+5isation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8s
+7t
+8ic
+9cally
+8s
+6te
+8s
+7ies
+7y
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ologies
+9ist
+9ists
+9y
+3ia
+5s
+3s
+2ceolate
+6i
+6us
+8es
+3hin
+6s
+2d
+3e
+4e
+3s
+3y
+2e
+3a
+4l
+4s
+5e
+6s
+3dia
+6l
+5ne
+7s
+6ia
+8l
+7ospore
+9pores
+7um
+6ous
+5ospore
+9res
+5um
+4o
+5s
+6ori
+8us
+6pore
+9es
+3ic
+4de
+6s
+3mia
+6s
+5c
+3na
+5s
+4t
+3otelic
+8sm
+9ms
+3s
+4es
+4is
+3ter
+6al
+6ic
+7tis
+9ses
+6s
+4han
+7e
+8s
+7s
+5ra
+7e
+7l
+7s
+6ites
+8ic
+9des
+9s
+9ses
+6oscope
+9opes
+9opic
+9opies
+9opy
+4ic
+2ge
+4d
+4nce
+7s
+6ies
+6y
+5t
+6ly
+4r
+5s
+4s
+3ing
+6ly
+6s
+2ial
+5s
+3c
+4ase
+7s
+4osuric
+5telic
+9sm
+9sms
+3dine
+7s
+4ylic
+3nal
+6s
+6yses
+8is
+5nt
+5ries
+6y
+5te
+7d
+7s
+6ing
+7on
+9s
+7ve
+6or
+8s
+4e
+5d
+5mia
+8s
+7c
+5s
+4iferous
+5ng
+5parous
+4ogenital
+5logies
+8y
+5meter
+9rs
+5scopies
+9y
+6e
+5us
+3te
+5s
+2man
+5s
+2n
+3al
+3ed
+3field
+8s
+4ul
+6s
+3ing
+6s
+3like
+3s
+2obilin
+8ogen
+9gens
+8s
+4oros
+8es
+3chord
+8al
+9te
+9tes
+8s
+5rome
+9s
+3delan
+8s
+6e
+7s
+6ous
+4ynamics
+3genital
+6ous
+4raphic
+9es
+8y
+3kinase
+9s
+3lagnia
+9s
+4ith
+7iases
+9sis
+8c
+7s
+4ogic
+8al
+7es
+7st
+9s
+6y
+3mere
+7s
+3pod
+6al
+6ous
+6s
+5ieses
+8is
+4ygia
+8l
+7um
+9s
+3scopic
+8es
+8st
+9ts
+7y
+4es
+4is
+4ome
+7s
+4tege
+8s
+7ite
+9es
+5henic
+5omies
+7y
+5yle
+8s
+2p
+3ed
+3ing
+3s
+2sa
+4e
+3id
+5s
+4form
+4ne
+3on
+5s
+2text
+6s
+3ica
+6ceous
+6nt
+8s
+6ria
+9l
+9s
+8ous
+6s
+6te
+8d
+8s
+7ing
+8on
+9ns
+2ubu
+5s
+3s
+4es
+4hiol
+8s
+2va
+4s
+1s
+2abilities
+8y
+4le
+6ness
+9ses
+5y
+3ge
+5r
+6s
+5s
+3nce
+6s
+3unce
+7s
+2e
+3abilities
+9y
+5le
+7ness
+9sses
+6y
+3d
+3ful
+6ly
+6ness
+9ses
+6s
+3less
+7ly
+7ness
+9sses
+3r
+4name
+8s
+4s
+3s
+2her
+5ed
+6ss
+8es
+6tte
+9s
+5ing
+8s
+5s
+6hip
+9s
+2ing
+2nea
+5s
+2quabae
+8s
+4e
+5bae
+8s
+7ugh
+9hs
+5s
+2tilagineous
+9ous
+4on
+6s
+3ulate
+7ion
+9ns
+2ual
+5ly
+5ness
+9es
+5s
+3capient
+9ts
+7on
+9s
+6t
+7ed
+7ible
+8ng
+8on
+9ns
+7s
+3fruct
+8ed
+8ing
+8s
+8uaries
+9ary
+3re
+5d
+5r
+6s
+5s
+6s
+7es
+4ies
+5ng
+5ous
+8ly
+8ness
+9esses
+4ous
+4p
+5ation
+9ns
+8ve
+7ory
+7ure
+9es
+5ed
+7ly
+6r
+7s
+5ing
+8ly
+8s
+5s
+4y
+2ward
+6s
+1t
+2a
+3s
+4es
+2e
+3nsil
+7s
+3rectomies
+9y
+4i
+5ne
+5tis
+8es
+4ogestation
+9ations
+5tomies
+8y
+4us
+6es
+3s
+2ile
+4idor
+8s
+5sable
+7tion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+5tarian
+9anise
+9anised
+9anises
+9anism
+9anisms
+9anize
+9anized
+9anizes
+9ans
+6ies
+6y
+5zable
+7tion
+9ons
+6e
+7d
+7r
+8s
+7s
+6ing
+3s
+4es
+2most
+6s
+2opia
+6n
+7ise
+9ed
+9er
+9ers
+9es
+9ing
+9m
+9ms
+8ze
+9ed
+9er
+9ers
+9es
+9ing
+7s
+6s
+7t
+8s
+5sm
+7s
+6t
+7ic
+7s
+2ricle
+7s
+5ular
+9ia
+9ias
+8te
+7i
+8tis
+9ises
+7us
+2s
+2ter
+5able
+9ness
+9nesses
+6nce
+9s
+5ed
+6r
+7s
+6st
+5ing
+8s
+5less
+6y
+5most
+9s
+5ness
+9es
+5s
+2u
+3s
+1va
+3e
+3rovite
+9s
+3s
+2ea
+4l
+4s
+3itic
+6s
+7es
+3ous
+2ula
+5e
+5r
+6ly
+6s
+5s
+4itis
+8es
+1xorial
+7ly
+5cidal
+8e
+9s
+5local
+5ous
+8ly
+8ness
+9esses
+0vac
+3ance
+7s
+6ies
+6y
+5t
+6ly
+6ness
+9ses
+4table
+5e
+6d
+6s
+5ing
+6on
+8ed
+9r
+9rs
+8ing
+9st
+9sts
+8land
+9ands
+9ess
+8s
+5ur
+7s
+3cina
+7l
+7s
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+9ry
+6e
+7e
+8s
+7s
+6ia
+8l
+8s
+7um
+9s
+3herin
+8s
+3illant
+7te
+9d
+9s
+8ing
+9ngly
+9on
+9ons
+8or
+9rs
+9ry
+3ked
+4ing
+3s
+3ua
+5te
+7d
+7s
+6ing
+7on
+9s
+4ist
+7s
+5ties
+6y
+4olar
+7te
+9d
+8ion
+9ons
+6e
+7s
+6isation
+9tions
+7zation
+9tions
+5us
+7ly
+7ness
+9sses
+4um
+6ed
+6ing
+6s
+2de
+4d
+4s
+3ing
+3ose
+2e
+3s
+2g
+3abond
+8age
+9ges
+8ed
+8ing
+9se
+9sed
+9ses
+9sh
+9sing
+9sm
+9sms
+9ze
+9zed
+9zes
+9zing
+8s
+4l
+5ly
+4ries
+6ous
+9ly
+6sh
+5y
+3ged
+4ing
+3i
+4le
+5ities
+7y
+4nant
+6s
+6te
+8d
+5ectomies
+9my
+5icoline
+9ous
+6smus
+9ses
+6tis
+9es
+5oses
+7is
+5ula
+8e
+7e
+8s
+4tus
+7es
+3otomies
+7y
+6nia
+9s
+8c
+5ropic
+3rancies
+7y
+6t
+7ly
+7ness
+9sses
+7s
+4om
+3s
+3ue
+5d
+5ly
+5ness
+9es
+5r
+5s
+6t
+4ing
+4s
+2hana
+6s
+3ine
+6s
+2il
+4ed
+4ing
+4s
+3n
+4er
+5sse
+8s
+6t
+4gloried
+9es
+9ous
+9ously
+8y
+9ing
+4ly
+4ness
+8es
+3r
+4e
+4ier
+6st
+4s
+4y
+3vode
+7s
+8hip
+9ips
+2kas
+5es
+3eel
+6s
+3il
+5s
+2lance
+7d
+7s
+6ing
+3e
+4diction
+9ons
+8orian
+9rians
+9ries
+9ry
+4nce
+7s
+6ia
+8s
+7es
+6y
+5tine
+9s
+4rate
+8s
+5ian
+8aceous
+8s
+6c
+4s
+4t
+5a
+6s
+5e
+6d
+6s
+5ing
+8s
+5s
+5udinarian
+9arians
+9aries
+9ary
+3goid
+5us
+4us
+6es
+3i
+4ance
+8s
+7ies
+7y
+6t
+7ly
+7ness
+9sses
+7s
+4d
+5ate
+8d
+8s
+7ing
+8on
+9ns
+7ory
+5er
+6st
+5ities
+7y
+5ly
+5ness
+9es
+4ne
+6s
+4s
+5e
+6s
+4um
+3kyr
+6ie
+8s
+6s
+3lar
+6y
+5te
+6ion
+9s
+4ecula
+9e
+9r
+9te
+5y
+6ed
+6s
+4hund
+8s
+4onia
+8s
+4um
+6s
+3onea
+7s
+5ia
+7s
+4r
+5isation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ous
+8ly
+5s
+4ur
+6s
+3policella
+9llas
+4roate
+9s
+6ic
+3se
+5d
+5s
+4ing
+3uable
+8ness
+9esses
+8s
+7y
+5te
+7d
+7s
+6ing
+7on
+9al
+9ally
+9s
+6or
+8s
+4e
+5d
+5less
+9ness
+9nesses
+5r
+6s
+5s
+4ing
+4ta
+6s
+3val
+5r
+5ssor
+9s
+5te
+4e
+5d
+5less
+7t
+8s
+6ike
+5s
+4ing
+4ula
+7e
+7r
+6e
+7s
+6ites
+8ides
+9s
+9ses
+2mbrace
+8d
+8s
+3oose
+7d
+7s
+6ing
+4se
+6d
+6s
+5ing
+3p
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7s
+5re
+7d
+7s
+6ic
+7ng
+7se
+9d
+9s
+8h
+8ing
+8m
+9s
+7ze
+9d
+9s
+8ing
+5sh
+7ly
+4late
+8s
+4s
+4y
+2n
+3adate
+8s
+5iate
+9s
+6c
+6nite
+9es
+6um
+8s
+5ous
+4spati
+9s
+3comycin
+9ns
+3da
+5l
+6ic
+7sation
+9tions
+8e
+9d
+9s
+8h
+8ing
+8m
+9s
+8tic
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+5s
+4yke
+7d
+7s
+6ing
+3e
+4d
+4less
+4s
+5sa
+7s
+6id
+8s
+3g
+4s
+4uard
+8ism
+9sms
+9st
+9sts
+8s
+3illa
+7s
+6ic
+7n
+8s
+4sh
+6ed
+7r
+8s
+7s
+6ing
+9ly
+9s
+6ment
+9ts
+4tas
+7es
+5ied
+7s
+5ories
+7y
+5y
+3load
+7s
+3man
+4en
+3ned
+5r
+6s
+4ing
+7s
+3pool
+7ing
+9gs
+7s
+3quish
+8able
+8ed
+9r
+9rs
+9s
+8ing
+8ment
+9ents
+3s
+3t
+4age
+7d
+7less
+7s
+6ing
+4brace
+9s
+7ss
+9es
+4s
+3ward
+2pid
+5er
+6st
+5ities
+7y
+5ly
+5ness
+9es
+3or
+5abilities
+9ity
+7le
+5ed
+6r
+7s
+6scence
+9nces
+9nt
+6tti
+8o
+9s
+5ific
+7orm
+6meter
+9ers
+6ng
+8s
+6sable
+8tion
+9ions
+7e
+8d
+8r
+9s
+8s
+7h
+8ness
+9esses
+7ing
+6zable
+8tion
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5less
+6ike
+5osities
+9y
+6us
+8ly
+8ness
+9esses
+5s
+5ware
+9s
+5y
+4ur
+6abilities
+9lity
+8le
+6ed
+7r
+8s
+6ing
+9ly
+9s
+7sh
+9ness
+9nesses
+6less
+6s
+6ware
+9es
+6y
+3ulate
+8d
+8s
+7ing
+8on
+9ns
+2quero
+7s
+2r
+3a
+4ctor
+8s
+4n
+5s
+4s
+3dies
+4y
+3e
+4c
+5h
+6s
+5s
+4s
+4use
+7s
+3gueno
+8s
+3ia
+5bilities
+9ty
+6le
+8ness
+9esses
+8s
+7y
+5nce
+8s
+6t
+7s
+5s
+5te
+7d
+7s
+6ing
+7on
+9al
+9ally
+9ist
+9ists
+9s
+7ve
+4ceal
+6lla
+9r
+9s
+9te
+8oid
+9us
+6s
+5ocele
+9es
+6id
+6lored
+8ured
+6se
+8d
+8s
+7is
+8ties
+9y
+6tomies
+9y
+4ed
+6ly
+6ness
+9ses
+5gate
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+5r
+6s
+5s
+5tal
+8ly
+8s
+6ies
+6y
+4focal
+9s
+6rm
+8ly
+4ola
+7r
+7s
+7te
+9d
+9s
+8ing
+9on
+9ons
+8or
+9rs
+6e
+7s
+6isation
+9tions
+7te
+9s
+8ic
+7zation
+9tions
+6oid
+9s
+7us
+5meter
+9rs
+5rum
+8s
+5us
+7ly
+7ness
+9sses
+4scite
+9s
+5ized
+5tor
+8s
+4type
+8d
+8s
+7ing
+8st
+9ts
+4x
+3let
+6ess
+9es
+6ries
+7y
+6s
+6to
+8s
+3ment
+7s
+4int
+7s
+3na
+5s
+4ish
+7ed
+8r
+9s
+8s
+7ing
+9gs
+7y
+3oom
+6ed
+6ing
+6s
+3roa
+6s
+3s
+4al
+4ities
+6y
+4ovienne
+9nes
+3tabed
+8s
+3us
+5es
+3ve
+5d
+5l
+6led
+6s
+5s
+3y
+4ing
+7ly
+7s
+2s
+3a
+4l
+3cula
+7r
+8isation
+9se
+9sed
+9ses
+9sing
+9ties
+9ty
+9zation
+9ze
+9zed
+9zes
+9zing
+8ly
+7ture
+9res
+6iform
+7tides
+9s
+6um
+8s
+3e
+4ctomies
+9se
+9sed
+9ses
+9sing
+9ze
+9zed
+9zes
+9zing
+8y
+4like
+6ne
+8s
+4s
+3iform
+3oactive
+9ities
+9ity
+4constrictor
+4dilatation
+9ations
+9atory
+9ion
+9ions
+9or
+9ors
+9ory
+4inhibitor
+9itors
+9itory
+4motor
+4pressin
+9ins
+9or
+9ors
+4spasm
+9s
+8tic
+4tocin
+9s
+6mies
+7y
+4vagal
+3sail
+7s
+5l
+6age
+9s
+6ess
+9es
+6ise
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6led
+7ing
+6ries
+7y
+6s
+3t
+4er
+5st
+4idities
+8y
+5er
+6st
+5ties
+6ude
+9s
+6y
+4ly
+4ness
+8es
+4s
+4y
+2t
+3able
+3ful
+6s
+3ic
+5al
+5ide
+8s
+6nal
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+9ory
+3man
+4en
+3s
+3ted
+5r
+6s
+4ing
+3u
+4s
+2u
+3ch
+5ed
+6s
+5ing
+3deville
+9ean
+9eans
+9es
+9ian
+9ians
+9ist
+9ists
+4oo
+6s
+5ux
+3lt
+5age
+8s
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8s
+5like
+5s
+5y
+3nce
+6d
+6s
+5ing
+4t
+5age
+8s
+5ed
+6r
+7ies
+7s
+7y
+5ful
+5ie
+7r
+7st
+6ng
+8ly
+8s
+5s
+5y
+3rien
+7s
+3s
+3t
+4e
+5d
+5s
+4ing
+4s
+2v
+3asor
+7ies
+7s
+7y
+6ur
+8s
+5sor
+8s
+3s
+2w
+3ard
+6s
+3ntie
+7r
+7st
+3s
+3te
+5d
+5s
+4ing
+1eal
+4e
+5d
+5r
+6s
+5s
+4ier
+6st
+5ng
+4s
+4y
+2ctograph
+9hs
+5r
+6ed
+6ial
+9ly
+7ng
+9s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6s
+7cope
+9pes
+2dalia
+7s
+3ette
+7s
+3uta
+5e
+5ista
+8i
+2e
+3jay
+6s
+3na
+5s
+3p
+4ee
+6s
+4s
+3r
+4ed
+4ies
+5ng
+7ly
+7s
+4s
+4y
+3s
+2g
+3a
+4n
+5ic
+6sm
+8s
+5s
+4s
+3eburger
+9rs
+4late
+8s
+4mite
+8s
+4s
+4table
+9s
+8y
+6l
+7ly
+7s
+6nt
+6rian
+9nism
+9nisms
+9ns
+6te
+8d
+8s
+7ing
+9gs
+8on
+9nal
+9ns
+9us
+8ve
+9ely
+9eness
+5e
+5ist
+8s
+6ve
+8s
+3ged
+5s
+4ie
+6burger
+9gers
+6s
+5ng
+3ie
+5s
+3o
+4s
+2hemence
+9s
+8ies
+8y
+7t
+8ly
+3icle
+7s
+5ular
+3m
+4e
+4ic
+5que
+2il
+4ed
+6ly
+5r
+6s
+4ier
+6st
+5ng
+7s
+4less
+6use
+9s
+5ike
+4s
+4y
+3n
+4al
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7s
+4less
+6t
+7s
+5ike
+4ous
+4s
+5tone
+9s
+6uff
+9s
+4ule
+7s
+7t
+8s
+4y
+2la
+4men
+5ina
+4r
+5ia
+6c
+6sation
+9ions
+7e
+8d
+8s
+7ing
+6um
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5s
+4te
+6d
+5ura
+8s
+3cro
+6s
+3d
+4s
+5choen
+9ns
+5koen
+9s
+4t
+5s
+3e
+4s
+4ta
+6s
+3iger
+7s
+4tation
+9ns
+5es
+3l
+4eities
+7y
+5nage
+9s
+5t
+6s
+4icate
+9d
+9s
+8ing
+9on
+9ons
+9ve
+4on
+6s
+4s
+4um
+6s
+5s
+3oce
+5imeter
+9ers
+9ries
+9ry
+6pede
+9ean
+9eans
+9ed
+9er
+9ers
+9es
+9ian
+9ians
+9ing
+9ist
+9ists
+6raptor
+9tors
+6ties
+7y
+4drome
+9s
+4ur
+6s
+5te
+7s
+6ine
+9s
+3skoen
+8s
+3um
+4re
+6d
+6s
+5ing
+4tinous
+3veret
+8s
+5t
+6ed
+7en
+9ed
+9s
+6ier
+8st
+7ness
+9sses
+8g
+9s
+6like
+6s
+6y
+2na
+4e
+4l
+5ities
+7y
+5ly
+4tic
+7al
+9ly
+6on
+8al
+8s
+5or
+7ial
+7s
+3d
+4able
+8s
+5ce
+7s
+5ge
+7s
+5nge
+8s
+4ed
+5e
+6s
+5r
+6s
+5tta
+8s
+7ist
+9ts
+5use
+8s
+4ibilities
+9ty
+6le
+8ness
+9esses
+8s
+7y
+5ng
+7s
+5s
+6es
+6s
+7es
+5tation
+9ons
+6ion
+9s
+4or
+6s
+4s
+4ue
+6s
+3eer
+6ed
+7r
+8s
+6ing
+9s
+6s
+4fic
+7al
+9ly
+7ious
+9usly
+7ous
+9sly
+4nate
+8d
+8s
+7ing
+5e
+6s
+5ose
+4puncture
+9ures
+4rabilities
+9ity
+7le
+9ness
+9nesses
+9s
+8y
+6te
+8d
+8s
+7ing
+8on
+9nal
+9ns
+8veness
+7or
+9s
+5eal
+7n
+8s
+6ological
+9gies
+9gist
+9gists
+9gy
+7us
+6r
+7s
+5ies
+5y
+4section
+9ons
+4tian
+8s
+4we
+6s
+4y
+5s
+3ge
+5able
+8y
+6nce
+9s
+5d
+5ful
+8ly
+8ness
+9esses
+5ment
+9s
+5r
+6s
+5s
+4ing
+3ial
+6ities
+8y
+6ly
+6ness
+9ses
+4dium
+8s
+4n
+5e
+6s
+5s
+4puncture
+9ures
+4re
+6man
+7en
+6s
+4section
+9ons
+5on
+7s
+4te
+6s
+3nel
+6s
+3ogram
+8s
+7phic
+9ical
+9ies
+9y
+4logies
+7y
+4m
+5ed
+6r
+7s
+5ing
+5less
+5ous
+8ly
+8ness
+9esses
+5s
+4scleroses
+9osis
+5e
+5ities
+7y
+4us
+6ly
+6ness
+9ses
+3t
+4age
+7s
+5il
+7e
+8s
+7s
+5na
+7s
+5yle
+8s
+4ed
+5r
+6s
+4iduct
+9s
+5fact
+9s
+5ge
+7s
+5l
+6able
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+8or
+9rs
+9ry
+6s
+5ng
+7s
+4less
+4ose
+6ities
+8y
+5use
+8s
+4ral
+7ly
+7s
+5e
+6d
+6s
+5icle
+9s
+7ose
+9ities
+9ity
+8us
+7ular
+9e
+9es
+9i
+9us
+6loqual
+9uial
+9uially
+9uies
+9uise
+9uised
+9uises
+9uising
+9uism
+9uisms
+9uist
+9uistic
+9uists
+9uize
+9uized
+9uizes
+9uizing
+9uous
+9uy
+6ng
+8s
+6potent
+5olateral
+6medial
+6us
+4s
+4ure
+7d
+7r
+8s
+7s
+8ome
+9mely
+9meness
+6i
+7ng
+9ly
+9s
+7s
+6ous
+9ly
+9ness
+9nesses
+3ue
+5s
+4lar
+5e
+6s
+5ose
+6us
+4s
+5es
+3ville
+8s
+2ra
+4cious
+9ly
+9ness
+9nesses
+6ties
+7y
+4nda
+7ed
+7h
+8ed
+8s
+7s
+4pamil
+9s
+4tria
+8s
+7dine
+9nes
+7n
+8e
+9s
+8s
+6um
+8s
+3b
+4al
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9ic
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6led
+7ing
+7y
+6s
+5rian
+9s
+5scum
+9s
+5tim
+4ena
+7ceous
+7s
+5rate
+9d
+9s
+8ing
+9on
+9ons
+4iage
+8s
+5cide
+9s
+5d
+6s
+5fication
+9tions
+7ed
+8s
+6y
+7ing
+5gerate
+9ted
+9tes
+9ting
+9tion
+9tions
+5le
+7s
+5ng
+7s
+4less
+4ose
+7ly
+7ness
+9sses
+7r
+7st
+6ities
+8y
+5ten
+4s
+3d
+4ancies
+7y
+6t
+7ly
+4elho
+8s
+5rer
+8s
+6or
+8s
+5t
+6s
+4ict
+7s
+5gris
+9ed
+9es
+9ing
+5n
+6s
+5t
+6e
+7r
+8s
+7s
+6s
+4oy
+4ure
+7d
+7less
+7s
+6ous
+3ecund
+3ge
+5board
+9ds
+5d
+5nce
+8s
+7ies
+7y
+5r
+6s
+7hip
+9ps
+5s
+4ing
+4las
+7es
+3idic
+7al
+9ities
+9ity
+9ly
+7ous
+4er
+5st
+4fiabilities
+9lity
+8le
+9eness
+9y
+6cation
+9ions
+9ive
+9ory
+6ed
+7r
+8s
+7s
+5y
+6ing
+4ly
+4similar
+9arly
+9ities
+9itude
+9itudes
+9ity
+9ous
+5m
+6o
+7s
+6s
+5t
+6ic
+6s
+4table
+9ness
+9nesses
+8y
+6s
+6tes
+5e
+6s
+5ies
+5y
+3juice
+8d
+8s
+7ing
+3kramp
+8te
+9es
+3lan
+6s
+4ig
+6te
+8s
+3mal
+4eil
+7ed
+7ing
+7le
+9d
+9s
+8ing
+7s
+5ll
+7s
+5s
+4ian
+5celli
+9is
+6idal
+8e
+9s
+6ular
+9rly
+9te
+9ted
+9tes
+9ting
+9tion
+9tions
+8e
+9s
+8ite
+9tes
+8ous
+8ture
+9ures
+5form
+6ugal
+8e
+9s
+5l
+6ies
+7on
+9ed
+9ing
+9s
+6led
+7ing
+8on
+9ns
+6s
+6y
+5n
+6ate
+9d
+9s
+8ing
+9on
+9ons
+6ed
+6ous
+9ly
+9ness
+9nesses
+6s
+6y
+5s
+5vorous
+4oulu
+6th
+8s
+4uth
+7s
+3nacle
+8s
+6ular
+9rise
+9rised
+9rises
+9rising
+9rism
+9risms
+9rist
+9rists
+9rities
+9rity
+9rize
+9rized
+9rizes
+9rizing
+9rly
+9rs
+5l
+6isation
+9tions
+8e
+9d
+9s
+8ing
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6ly
+5nt
+5tion
+9s
+4icle
+8s
+5er
+7s
+5ssage
+9es
+5x
+6es
+3onal
+7s
+5ica
+8s
+6que
+3quere
+8s
+5ire
+8s
+3ra
+4el
+6s
+5y
+4uca
+7e
+7s
+6iform
+6ose
+8ities
+9ty
+7us
+5ga
+7s
+4y
+3s
+4abilities
+9ty
+5l
+6s
+5nt
+7s
+5tile
+9ly
+9ness
+9nesses
+8ities
+9ty
+4e
+5d
+5let
+8s
+5man
+6en
+5r
+6s
+5s
+5t
+6s
+4icle
+8s
+6olor
+9ur
+9ured
+6ular
+5fication
+9tions
+9tor
+9tors
+7ed
+8r
+9s
+8s
+6orm
+6y
+7ing
+5n
+6e
+7s
+6g
+7s
+6s
+5on
+7al
+7ed
+8r
+9s
+7ing
+9gs
+8st
+9ts
+7s
+4librist
+9ste
+9stes
+9sts
+4o
+5s
+4t
+5e
+6s
+5s
+4us
+5te
+3t
+4ebra
+8e
+8l
+9ly
+8s
+8te
+9ed
+9es
+9ion
+9ions
+5d
+5x
+6es
+4ical
+8ities
+9ty
+8ly
+8ness
+9esses
+8s
+6es
+6il
+8laster
+9asters
+9ate
+9ated
+9ately
+9ation
+9ations
+9ium
+9iums
+8s
+7ties
+8y
+5gines
+8ous
+9usly
+9usness
+6o
+7es
+7s
+5ng
+5port
+9s
+4s
+4u
+5e
+6s
+5ous
+5s
+3umontana
+9num
+9nums
+3vain
+7s
+4e
+5l
+6led
+6s
+5n
+6s
+5s
+5t
+6s
+3y
+2sica
+6e
+6l
+6nt
+8s
+6te
+8d
+8s
+7ing
+8on
+9ns
+7ories
+9y
+5le
+7s
+5ula
+8e
+8r
+9ities
+9ity
+9ly
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+7ose
+3pa
+5s
+4er
+6al
+8s
+6s
+6tilian
+9ionid
+9ionids
+9ionine
+8nal
+9e
+4iaries
+7y
+5d
+6s
+5ne
+4oid
+3sail
+7s
+4el
+6ed
+6s
+3t
+4a
+5l
+6ly
+6s
+5s
+4ed
+5e
+6s
+4iaries
+7y
+5bula
+9r
+8e
+9d
+9s
+8ing
+9tis
+9tises
+8um
+5ge
+7s
+6ia
+8l
+9ly
+7um
+5ment
+9al
+9ary
+9s
+5ng
+7s
+5ture
+9s
+4less
+5ike
+4ment
+8al
+8ed
+8s
+4ral
+5ies
+5y
+6man
+7en
+4s
+4ural
+6e
+7d
+7r
+8s
+7s
+6ing
+3uvian
+8ite
+9tes
+8s
+2t
+3ch
+5es
+5ier
+7st
+5ling
+9s
+5y
+3eran
+7s
+5inarian
+9ians
+9ies
+9y
+3iver
+7s
+7t
+8s
+3koek
+7s
+3o
+4ed
+5r
+6s
+5s
+4ing
+4less
+3s
+3ted
+5r
+6s
+4ing
+7s
+4ura
+7s
+6ini
+8o
+2x
+3ation
+8s
+7us
+9ly
+9ness
+9nesses
+5ory
+3ed
+5ly
+5ness
+9es
+4r
+5s
+4s
+3il
+5la
+7r
+8ies
+8y
+7te
+8ion
+9ons
+6ologic
+9gical
+9gies
+9gist
+9gists
+9gy
+6um
+5s
+4ng
+6ly
+6ness
+9ses
+6s
+3t
+2zir
+5s
+1ia
+3bilities
+8y
+4le
+5y
+3duct
+7s
+3e
+3l
+4ed
+4ful
+7s
+4ing
+4led
+5ing
+4s
+3meter
+8s
+3nd
+5s
+3s
+3tic
+6a
+7l
+8s
+6um
+8s
+4or
+6es
+6ial
+6s
+2be
+4s
+4x
+4y
+3ices
+4er
+5st
+4st
+6s
+3racula
+9r
+9ria
+9rium
+8oid
+8um
+5harp
+9ist
+9ists
+9s
+5nce
+8s
+7ies
+7y
+6t
+7ly
+7s
+5phone
+9es
+9ist
+9ists
+5te
+7d
+7s
+6ile
+8ities
+9ty
+7ng
+9ly
+7on
+9al
+9less
+9s
+7uncle
+9cles
+7ve
+6o
+7less
+7ry
+7s
+4io
+6id
+6n
+7ic
+7s
+6s
+7es
+7is
+5ssa
+8e
+8l
+4oflotation
+9ations
+5graph
+9hs
+5meter
+9rs
+5nic
+3s
+3urnum
+8s
+2car
+5age
+8s
+6te
+8s
+5ess
+8es
+5ial
+7nce
+9es
+8t
+9s
+7te
+9s
+6es
+6ous
+9ly
+9ness
+9nesses
+5ly
+5s
+6hip
+9s
+5y
+3e
+4d
+4geral
+7encies
+9cy
+9t
+9ts
+4less
+5ike
+4nary
+5nial
+4regal
+9ly
+7ent
+9ts
+6ine
+9s
+5oy
+7alties
+9ty
+7s
+8hip
+9ips
+4s
+5imal
+3hies
+4y
+5ssois
+9se
+9ses
+3iate
+7d
+7s
+6ing
+4nage
+8s
+6l
+5g
+5ities
+7y
+4osities
+8y
+5us
+7ly
+7ness
+9sses
+4ssitude
+9des
+9dinary
+9dinous
+3omte
+7s
+8se
+9es
+3tim
+6hood
+9ds
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6less
+6ologies
+9gist
+9gists
+9gy
+6s
+4or
+6ess
+9es
+6ia
+8na
+8s
+7es
+7ne
+9s
+7ous
+9sly
+9sness
+6s
+6y
+7less
+4ress
+8es
+5ix
+7es
+4ual
+7age
+9es
+7ed
+8r
+9s
+7ing
+7lage
+9ges
+8ed
+9r
+9rs
+9ss
+8ing
+7s
+3ugna
+7s
+4na
+6s
+2d
+3ame
+6s
+3e
+4licet
+4nda
+6um
+4o
+5cassette
+9ettes
+6onference
+5disc
+9s
+8k
+9s
+5ed
+5fit
+8s
+5gram
+9s
+8pher
+9hers
+9hies
+9hy
+5ing
+5land
+9s
+5phile
+9es
+7one
+9es
+9ic
+5s
+5tape
+9d
+9s
+8ing
+6elephone
+9phones
+7x
+8es
+8t
+9s
+4tte
+7s
+3icon
+7s
+4mus
+7es
+3s
+3uage
+7s
+5l
+4ities
+6y
+4ous
+2e
+3d
+3lle
+6s
+3nna
+3r
+4s
+3s
+3w
+4able
+4data
+8s
+4ed
+5r
+6s
+7hip
+9ps
+4finder
+9rs
+4ier
+6st
+5ness
+9es
+6g
+7s
+4less
+8ly
+5y
+4phone
+9s
+5oint
+9s
+4s
+4y
+2fda
+5s
+2g
+3a
+4s
+3esimal
+3ia
+5s
+4l
+5ance
+9s
+7t
+8e
+9s
+8ism
+9sms
+8ly
+8ness
+9esses
+5s
+4ntillion
+9ions
+3neron
+8s
+5tte
+8d
+8r
+9s
+8s
+7ing
+9gs
+8st
+9ts
+3or
+5ish
+8es
+5o
+6s
+7o
+6us
+8ly
+8ness
+9esses
+5s
+4ur
+6s
+3s
+2hara
+6s
+3uela
+7s
+2king
+6ism
+9s
+6s
+2layet
+7s
+3d
+4e
+4ly
+4ness
+8es
+3e
+4ly
+4ness
+8es
+4r
+4st
+3iaco
+7es
+7s
+5go
+7es
+7s
+4fication
+9ions
+6ed
+7r
+8s
+7s
+5y
+6ing
+4pend
+8ed
+9r
+9rs
+8ing
+8s
+3l
+4a
+5dom
+8s
+5e
+5ge
+7r
+8ies
+8s
+8y
+7s
+6io
+8es
+8s
+7sation
+9tions
+7zation
+9tions
+6ree
+9s
+5in
+7age
+9es
+7ess
+9ses
+7ies
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7ous
+9sly
+9sness
+7s
+7y
+5n
+6age
+9s
+6ella
+9as
+9e
+9es
+6ies
+6ous
+9ly
+6s
+6y
+5r
+5s
+5tic
+4eggiatura
+9turas
+5in
+7age
+9es
+7s
+5nage
+9s
+4i
+5aco
+8es
+8s
+6go
+8es
+8s
+5cation
+9ons
+5form
+4ose
+6ities
+8y
+5us
+7ly
+4s
+4us
+2m
+3ana
+6s
+3en
+3ina
+6l
+5eous
+3s
+2n
+3a
+4ceous
+4igrette
+9tes
+4l
+5s
+4s
+5se
+7s
+3blastine
+9nes
+3ca
+5s
+4ibilities
+9ty
+6le
+8ness
+9esses
+7y
+4ristine
+9nes
+4ula
+6um
+8s
+3daloo
+8s
+4emial
+8te
+9ed
+9es
+9ing
+4icabilities
+9lity
+8le
+7te
+9d
+9s
+8ing
+9on
+9ons
+9ve
+9veness
+8or
+9rily
+9rs
+9ry
+8ress
+9esses
+6tive
+9ely
+9eness
+3e
+4al
+4d
+5resser
+9ers
+4gar
+7ed
+8tte
+9tes
+7ing
+8sh
+7roon
+9ons
+7s
+7y
+4less
+5ike
+4r
+5ies
+5s
+5y
+4s
+4w
+5ed
+5ing
+5s
+4yard
+8ist
+9sts
+8s
+3ic
+5ultural
+9re
+9res
+9rist
+9rists
+4er
+5st
+4fera
+8s
+7ous
+5ication
+9ions
+9or
+9ors
+6ed
+7s
+5y
+6ing
+4ng
+3o
+4lent
+5ogies
+8st
+9ts
+7y
+4s
+5ities
+7y
+4us
+6ly
+3s
+3t
+4age
+7d
+7r
+8s
+7s
+6ing
+9s
+4ed
+4ing
+4ner
+7s
+4ries
+5y
+4s
+3y
+4l
+5cyanide
+9ides
+5ic
+6dene
+9es
+5s
+2ol
+4a
+5bilities
+9ty
+6le
+8ness
+9esses
+7y
+5ceous
+5s
+5te
+7d
+7r
+8s
+7s
+6ing
+7on
+9s
+7ve
+6or
+8s
+4d
+4ence
+8s
+6t
+7ed
+7ing
+7ly
+7s
+5r
+6s
+5t
+6s
+4in
+6ist
+9ic
+9ically
+9s
+6s
+5st
+7s
+4oncelli
+9list
+9lists
+9lo
+9los
+6e
+7s
+4s
+3mycin
+8s
+3sterol
+9s
+2per
+5fish
+9es
+5iform
+6ne
+6sh
+8ly
+5ous
+8ly
+5s
+2raemia
+8s
+7c
+4ginian
+7ous
+5o
+6es
+6ish
+6s
+4l
+5ly
+4nda
+7s
+6o
+7s
+3e
+4d
+4lai
+7s
+6y
+7s
+4ment
+8s
+5ia
+7s
+6c
+4nt
+4o
+5nine
+9s
+5s
+4s
+5cence
+9es
+8t
+4tot
+7s
+3ga
+5s
+5te
+7s
+4e
+5r
+6s
+5s
+4in
+6al
+8ist
+9sts
+8led
+9ing
+9y
+8s
+6ed
+6hood
+9ds
+6ia
+8s
+7ng
+7ties
+8y
+7um
+9s
+6ly
+6s
+4ulate
+6e
+7s
+3icidal
+7e
+8s
+4d
+5escence
+9nces
+9nt
+5ian
+8s
+6te
+8s
+7ies
+7y
+4le
+6ly
+6scence
+9nces
+9nt
+5isation
+9ions
+7e
+8d
+8s
+7ing
+7m
+8s
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5ocal
+4ng
+5o
+6s
+4on
+6s
+3l
+4s
+3ogene
+8s
+4id
+6s
+4logic
+9al
+9ally
+8es
+8st
+9ts
+7y
+4se
+6s
+5is
+4us
+3tu
+5al
+7ise
+9ed
+9es
+9ing
+9m
+9ms
+9t
+9ts
+8ties
+9y
+8ze
+9ed
+9es
+9ing
+7ly
+5e
+6less
+6s
+5osa
+8s
+7e
+7i
+8c
+8ties
+9y
+7o
+8s
+9hip
+9hips
+6us
+8ly
+8ness
+9esses
+5s
+3ucidal
+7e
+8s
+4lence
+9s
+8ies
+8y
+7t
+8ly
+5iferous
+4s
+5es
+5like
+5oid
+8s
+2s
+3a
+4ed
+4ge
+6d
+6s
+5ist
+8e
+9s
+8s
+4ing
+4rd
+6s
+4s
+3cacha
+8s
+7era
+9as
+5ria
+8s
+4era
+7l
+8ly
+7te
+9d
+9s
+8ing
+6omotor
+7ptoses
+9osis
+7tonia
+9nias
+9nic
+4id
+6ities
+8y
+6ly
+6ness
+9ses
+5n
+6s
+4oelastic
+9ticity
+5id
+7al
+5meter
+9rs
+8ric
+9ical
+9ies
+9y
+5se
+7s
+6imeter
+9ters
+9tric
+9trical
+9tries
+9try
+7ties
+8y
+5unt
+8cies
+9y
+8ess
+9sses
+8ies
+8s
+9hip
+9hips
+8y
+6s
+7ly
+7ness
+9sses
+4um
+6s
+5s
+3e
+4d
+4ed
+4ing
+4like
+4s
+3hing
+7s
+3ibilities
+9y
+5le
+7ness
+9sses
+7s
+6y
+4e
+5d
+5ing
+5r
+6s
+5s
+4le
+6s
+4ng
+4ogenic
+5n
+6al
+8ly
+7ries
+9ness
+9nesses
+8y
+6ed
+7r
+8s
+6ing
+9s
+7st
+9s
+6less
+6s
+5phone
+9es
+4t
+5able
+6nt
+8s
+6tion
+9nal
+9ns
+8ve
+7or
+9ial
+9s
+5e
+6d
+6e
+7s
+6r
+7s
+6s
+5ing
+8s
+5or
+7ial
+7s
+5ress
+9es
+5s
+4ve
+3ne
+5s
+4omie
+8s
+6y
+3on
+5s
+4r
+5ed
+5ing
+5less
+5s
+3ta
+5ed
+5ing
+5l
+6ess
+5s
+4o
+5s
+3ual
+6isation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8t
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ly
+6s
+2ta
+4ceous
+4e
+4l
+5isation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8ic
+9cally
+8s
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5ly
+5ness
+9es
+5s
+4mer
+7s
+5in
+7e
+8s
+7ic
+8se
+9ed
+9es
+9ing
+8ze
+9ed
+9es
+9ing
+7s
+4s
+5cope
+9s
+4tive
+8ness
+9esses
+3e
+4llary
+6i
+7cle
+9es
+7genous
+7n
+8e
+9s
+8s
+6ogeneses
+9nesis
+9nic
+6us
+8es
+4sse
+7s
+4x
+5es
+3iable
+5te
+7d
+7s
+6ing
+7on
+9s
+6or
+8s
+4ceta
+7um
+9s
+5ide
+8s
+5olous
+5ultural
+9rally
+9re
+9rer
+9rers
+9res
+9rist
+9rists
+4ferous
+4ligo
+8s
+6tigate
+9ated
+9ates
+9ating
+9ation
+9ations
+4osities
+8y
+5us
+3rage
+7s
+5il
+7led
+8ist
+9sts
+6n
+7s
+5ux
+4ectomies
+9y
+5osities
+9y
+6us
+8es
+8ly
+8ness
+9esses
+5scence
+9ces
+9t
+7ibility
+9le
+5um
+7s
+4ic
+6s
+5faction
+9ions
+9ure
+9ures
+6iability
+9le
+7cation
+9tions
+7ed
+8s
+6orm
+6y
+7ing
+5ne
+7s
+5ol
+7ate
+9ed
+9es
+9ing
+9ion
+9ions
+7ed
+7ic
+8ng
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7led
+8ing
+7s
+3ta
+5e
+5te
+4le
+6d
+6s
+5ing
+3ular
+5ine
+4perable
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9ive
+9ively
+9or
+9ors
+9ory
+2va
+4ce
+6s
+5ious
+9ly
+9ness
+9nesses
+6ssimo
+6ties
+7y
+4ed
+4ing
+4mente
+4ndier
+9e
+9es
+9s
+4ria
+6es
+6um
+8s
+5y
+4s
+4t
+5s
+3da
+5s
+3e
+4ly
+4ncies
+6y
+4r
+5ra
+7s
+6id
+8s
+7ne
+9s
+5s
+4s
+3ianite
+9s
+4d
+5er
+6st
+5ities
+7y
+5ly
+5ness
+9es
+4fic
+7ation
+9ions
+6ed
+7r
+8s
+7s
+5y
+6ing
+4para
+7ies
+8sm
+9ms
+8ties
+9y
+7ous
+9sly
+9sness
+7y
+4sect
+8ed
+8ing
+9on
+9onal
+9onally
+9onist
+9onists
+9ons
+9ve
+8or
+9rium
+9riums
+9rs
+8s
+6pulture
+9tures
+3o
+3res
+2xen
+5ish
+8ly
+8ness
+9esses
+5ly
+5s
+2zament
+8s
+4rd
+6ed
+6ing
+6s
+3cacha
+8s
+3ied
+5r
+6ate
+9s
+6ial
+6s
+7hip
+9ps
+5s
+4r
+5ate
+8s
+5ial
+5s
+6hip
+9s
+3or
+5ed
+5ing
+5less
+5s
+3sla
+6s
+3y
+4ing
+3zie
+6d
+6ing
+6s
+1lei
+4s
+2ies
+2og
+4ger
+7s
+5ing
+8s
+4s
+2y
+1oar
+4s
+2cab
+5le
+7s
+6y
+5s
+5ular
+9ian
+9ians
+9ied
+9ies
+9y
+7ist
+9ts
+4l
+5ese
+8s
+5ic
+7ally
+7s
+6on
+8s
+6sation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+7m
+8s
+7t
+8s
+6ties
+7y
+6zation
+9ions
+7e
+8d
+8r
+9s
+8s
+7ing
+5ly
+5ness
+9es
+5s
+4tion
+8al
+9lism
+9lisms
+9list
+9lists
+9lly
+8s
+6ve
+8ly
+8s
+3es
+3icultural
+4ferance
+9ces
+9t
+9ts
+8te
+9ed
+9es
+9ing
+9ion
+9ions
+9or
+9ors
+7osities
+9ity
+8us
+9sly
+9sness
+3oder
+7s
+3ular
+5e
+6s
+2dcast
+7ed
+8r
+9s
+7ing
+9gs
+7s
+3dies
+4y
+3ka
+5s
+3ou
+5n
+6s
+5s
+3un
+5s
+2e
+3ma
+5s
+3rtsak
+6ek
+3s
+3tganger
+9rs
+4sak
+5ek
+5toets
+7ots
+2gie
+5r
+5st
+3ue
+5d
+5ing
+8s
+5r
+6s
+5s
+5y
+4ier
+6st
+5ng
+7s
+5sh
+7ly
+7ness
+9sses
+2ice
+5d
+5ful
+8ness
+9esses
+5less
+9ly
+9ness
+9nesses
+5mail
+9s
+5over
+9s
+5print
+9ts
+5r
+6s
+5s
+4ing
+7s
+3d
+4able
+8ness
+9esses
+5nce
+8s
+4ed
+5e
+6s
+5r
+6s
+4ing
+7s
+4ness
+8es
+4s
+3la
+4e
+5s
+3p
+4s
+3sinage
+9s
+3ture
+7s
+6ier
+9s
+3vode
+7s
+8hip
+9ips
+2l
+3a
+4ble
+4e
+4ge
+4nt
+6e
+7s
+4r
+5ies
+5y
+4tic
+6le
+8ness
+9esses
+8s
+7isable
+9ation
+9ations
+9e
+9ed
+9es
+9ing
+8ties
+9y
+8zable
+9ation
+9ations
+9e
+9ed
+9es
+9ing
+3canian
+7c
+8ally
+8ities
+9ty
+8s
+7sation
+9tions
+8e
+9d
+9s
+8ing
+8m
+9s
+8t
+9s
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6o
+7es
+7logic
+9gical
+9gies
+9gist
+9gists
+9gy
+7s
+3e
+4d
+4ns
+4ries
+5y
+4s
+4t
+5s
+3ing
+4tant
+6te
+8d
+8s
+7ing
+8on
+9nal
+9ns
+5ient
+6on
+8al
+9lly
+9ry
+8less
+8s
+6ve
+8s
+5orial
+3k
+4s
+5lied
+9er
+5raad
+9s
+3ley
+6ball
+9ls
+6ed
+7r
+8s
+6ing
+6s
+3ost
+6s
+3pino
+7s
+4lane
+8d
+8s
+7ing
+3s
+3t
+4a
+5ge
+7s
+5ic
+6sm
+8s
+5meter
+9rs
+8ric
+6meter
+9ers
+4e
+5d
+5s
+4i
+5geur
+9s
+5ng
+6ism
+9s
+4meter
+9s
+4s
+3ubil
+7ities
+9y
+5le
+7ness
+9sses
+6y
+4crine
+4me
+6d
+6nometer
+9eters
+6s
+6ter
+9s
+7ric
+9cal
+9cally
+9es
+8y
+5inal
+7g
+7osities
+9ity
+8us
+9sly
+9sness
+6se
+8d
+8r
+9s
+8s
+7ing
+7t
+8s
+6ze
+8d
+8r
+9s
+8s
+7ing
+5ometer
+9ers
+4ntaries
+9ly
+9ness
+9nesses
+9sm
+9sms
+9st
+9stic
+9sts
+8y
+9ism
+9isms
+9ist
+9ists
+7tive
+6eer
+9ed
+9ing
+9ism
+9isms
+9s
+6ourism
+9isms
+4ptuaries
+9y
+7osities
+9ity
+8us
+9sly
+9sness
+4spa
+7s
+4tation
+9ns
+5e
+6d
+6s
+5in
+7s
+6on
+8s
+5oid
+3va
+5e
+5s
+5te
+4e
+5d
+5s
+4ing
+4ox
+6es
+4uli
+6us
+8es
+2mer
+5ine
+5onasal
+5s
+3ica
+6e
+6s
+4t
+5ed
+6r
+7s
+5ing
+8s
+6ve
+8s
+5o
+6ria
+8es
+8um
+7y
+6s
+6us
+5s
+5urition
+9ions
+6s
+7es
+2ngole
+2odoo
+6ed
+6ing
+7sm
+9s
+8t
+9ic
+9s
+6s
+3rkamer
+9s
+4skot
+8s
+4trekker
+9ers
+2r
+3acious
+9ly
+9ness
+9nesses
+6ties
+7y
+4ginous
+5o
+6es
+4nt
+3lage
+7s
+3pal
+3red
+4ing
+3s
+3tex
+6es
+4ical
+8ly
+6ella
+9ae
+9as
+7s
+6ism
+9s
+8t
+9s
+7ties
+8y
+6ose
+6ular
+5ginous
+2stro
+2table
+4ress
+8es
+5ies
+6st
+8s
+5y
+3e
+4able
+4d
+4en
+6s
+4less
+4r
+5s
+4s
+3ing
+6s
+4ve
+6ly
+6ness
+9ses
+6s
+3ress
+7es
+2uch
+5ed
+6e
+7s
+6r
+7ed
+7ing
+7s
+6s
+5ing
+5safe
+9d
+9ment
+9ments
+9s
+8ing
+9ngs
+3don
+6s
+5u
+6ed
+6ing
+6n
+7s
+6s
+3ge
+5s
+3lge
+6s
+4u
+3ssoir
+8ed
+8ing
+8s
+3tsafe
+8d
+8s
+7ing
+3vray
+7s
+2w
+3ed
+4l
+5isation
+9ions
+7e
+8d
+8s
+7ing
+6zation
+9ions
+7e
+8d
+8s
+7ing
+5led
+7ss
+6ing
+6y
+5s
+4r
+5s
+4ss
+6es
+3ing
+3less
+3s
+2x
+3el
+5s
+2yage
+6able
+6d
+6r
+7s
+6s
+6ur
+8s
+5ing
+3euristic
+9ically
+6s
+2zhd
+5s
+1raic
+5ker
+8s
+6ing
+9s
+5s
+4semblance
+9ances
+2il
+4s
+2oom
+5ed
+5ing
+5s
+3t
+3u
+4s
+4w
+5s
+3w
+4s
+1ug
+3g
+4ier
+6st
+4s
+4y
+3h
+4ier
+6st
+4s
+4y
+3s
+2lcan
+6ian
+7c
+8ities
+9ty
+7sable
+9te
+9tes
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+8t
+9s
+7te
+9s
+7zable
+9te
+9tes
+9tion
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ological
+9gies
+9gist
+9gists
+9gy
+6s
+3gar
+6er
+7st
+6ian
+9s
+7sation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+8m
+9s
+7ties
+8y
+7zation
+9tions
+8e
+9d
+9r
+9rs
+9s
+8ing
+6ly
+6s
+5te
+7s
+4o
+4us
+6es
+3n
+4ed
+5rabilities
+9lity
+8le
+9eness
+9y
+7ries
+8y
+7te
+9d
+9s
+8ing
+9on
+9ons
+4ing
+4s
+3pecular
+4icide
+9s
+5ne
+6ism
+9s
+7te
+9s
+3sella
+8e
+7um
+3ture
+7s
+6ine
+7sh
+8m
+9s
+6n
+7s
+6ous
+3val
+5r
+5s
+5te
+4iform
+5tis
+8es
+4ovaginal
+9nitis
+2m
+3med
+4ing
+3s
+2ttier
+6st
+4y
+2vuzela
+8s
+1ying
+5ly
+5s
+0waac
+4s
+2b
+3ain
+6s
+3bit
+4le
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+5y
+3oom
+6s
+3s
+4ter
+7s
+2ck
+4e
+5r
+6s
+5s
+6t
+4ier
+6st
+5ly
+5ness
+9es
+4o
+5s
+4s
+4y
+2d
+3able
+3d
+4ed
+5r
+6s
+4ie
+6d
+6s
+5ng
+7s
+4le
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+5y
+4s
+4y
+5ing
+3e
+4able
+4d
+4r
+5s
+4s
+3i
+4es
+4ng
+6s
+4s
+3maal
+7s
+5l
+6s
+4el
+6s
+4ol
+6l
+7s
+6s
+3s
+4et
+6s
+6t
+7ed
+8r
+9s
+7ing
+7s
+3t
+4s
+3y
+2e
+3ful
+3ness
+7es
+3s
+4ome
+4uck
+7s
+2fer
+5ed
+5ing
+5s
+5y
+3f
+4ed
+4ie
+6s
+5ng
+4le
+6d
+6r
+7s
+6s
+7tomper
+9mpers
+5ier
+7st
+6ng
+8s
+5y
+4s
+3t
+4age
+7s
+4ed
+5r
+6s
+4ing
+7s
+4s
+4ure
+7s
+2g
+3e
+4d
+4less
+8ness
+9esses
+4nboom
+9s
+4r
+5ed
+6r
+7s
+5ing
+5s
+4s
+4worker
+9rs
+3ga
+5s
+4ed
+5r
+6ies
+6s
+6y
+4ing
+5sh
+7ly
+7ness
+9sses
+4le
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+8ly
+5y
+4on
+6ed
+7r
+8s
+7tte
+9es
+6ing
+6less
+7oad
+9ds
+6s
+3halter
+9s
+3ing
+3moire
+8s
+3on
+5age
+8s
+5ed
+6r
+7s
+6tte
+9s
+5ful
+8s
+5ing
+5less
+6oad
+9s
+5s
+5wright
+9hts
+3s
+4ome
+3tail
+7s
+3yu
+5s
+2hconda
+8s
+3ine
+6s
+3oo
+5s
+2i
+3ata
+6s
+3d
+4e
+3f
+4ed
+4ing
+5sh
+4like
+4s
+4t
+5s
+3l
+4ed
+5r
+6s
+4ful
+7ly
+4ing
+7ly
+7s
+4s
+5ome
+3n
+4age
+7s
+4ed
+4ing
+4s
+5cot
+8ed
+8ing
+9ngs
+8s
+8ted
+9ing
+9ings
+4wright
+9ts
+3r
+4ed
+4ing
+4s
+5h
+6er
+7st
+4ua
+6s
+3s
+4t
+5band
+9s
+6elt
+9s
+5cloth
+9hs
+6oat
+9ed
+9eer
+9eers
+9ing
+9ings
+9s
+5ed
+6r
+7s
+5ing
+8s
+5less
+6ine
+9s
+5s
+3t
+4e
+5d
+5r
+6age
+9s
+6ed
+6hood
+9ds
+6ing
+9s
+6s
+5s
+4ing
+7ly
+7s
+4list
+8ed
+8ing
+8s
+4person
+9ns
+4ress
+8ed
+9s
+8ing
+9ngs
+5on
+7s
+4s
+5taff
+9s
+3ve
+5d
+5r
+6s
+5s
+4ing
+4ode
+7s
+3wode
+7s
+2ka
+4me
+6s
+4nda
+7s
+4s
+3e
+4board
+9ed
+9er
+9ers
+9ing
+9ings
+9s
+4d
+4ful
+7ly
+7ness
+9sses
+4less
+4man
+5en
+4n
+5ed
+6r
+7s
+5ing
+8s
+5s
+4r
+5ife
+5s
+4s
+3f
+4s
+3iki
+6s
+4ng
+6s
+2ld
+4flute
+9s
+4grave
+9s
+8ine
+9nes
+4horn
+8s
+4o
+5es
+5s
+4rapp
+8s
+4s
+5terben
+9ens
+3e
+4d
+4r
+5s
+4s
+3i
+4er
+5s
+6t
+4ng
+4s
+5e
+6s
+3k
+4able
+6out
+9s
+5thon
+9s
+5way
+8s
+4ed
+5r
+6s
+4ies
+5ng
+7s
+8tick
+9icks
+4mill
+8s
+4out
+7s
+5ver
+8s
+4s
+5horts
+4up
+6s
+4way
+7s
+4yrie
+8s
+3l
+4a
+5ba
+7s
+6ies
+6y
+5h
+6s
+5roo
+8s
+5s
+4board
+9s
+4chart
+9s
+5limber
+9ers
+5overing
+9ings
+4ed
+5r
+6s
+5t
+6s
+5ye
+7d
+7s
+4fish
+8es
+5lower
+9rs
+4ie
+6r
+6s
+7t
+5ng
+7s
+4op
+6ed
+7r
+8s
+6ing
+9s
+6s
+5w
+6ed
+7r
+8s
+6ing
+9s
+6s
+4paper
+9ed
+9ing
+9s
+5oster
+9rs
+4s
+5end
+8s
+4wort
+8s
+4y
+5ball
+9s
+5drag
+9s
+8igle
+9gles
+3nut
+6s
+6wood
+9ds
+3rus
+6es
+3tier
+6st
+4y
+4z
+5ed
+6r
+7s
+6s
+5ing
+8s
+5like
+3y
+2mbenger
+9s
+4le
+6d
+6s
+5ier
+7st
+6ness
+9ses
+7g
+8ly
+8s
+5y
+3e
+4d
+4fou
+7s
+5ul
+7s
+4s
+3mul
+6s
+5s
+6es
+3pee
+6s
+4ish
+7ed
+8s
+7ing
+4um
+6peag
+9gs
+6s
+5s
+6es
+3us
+5es
+2n
+3chancie
+8y
+3d
+4er
+6ed
+7r
+8s
+6ing
+9ly
+9s
+6lust
+9ts
+6oo
+8s
+6s
+4le
+5ike
+4oo
+6s
+4s
+3e
+4d
+4s
+4y
+3gan
+6s
+4le
+6d
+6r
+7s
+6s
+5ing
+8s
+4s
+4un
+6s
+3hope
+7s
+3ier
+5st
+4gan
+7s
+4ng
+6s
+4on
+6s
+3le
+4y
+3na
+5be
+7e
+8s
+7s
+4ed
+5l
+5r
+5ss
+7es
+6t
+4igan
+8s
+5ng
+5on
+7s
+5sh
+3restful
+3s
+3t
+4age
+7s
+5way
+8s
+4ed
+5r
+6s
+4hill
+8s
+5riven
+4ies
+5ng
+4on
+6ed
+7r
+8s
+7st
+6ing
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6ly
+6ness
+9ses
+6s
+4s
+4y
+3wordy
+6th
+8s
+3y
+3ze
+5d
+5s
+4ing
+2p
+3enschaw
+9ws
+6haw
+9s
+5take
+9s
+3inschaw
+9ws
+6haw
+9s
+4ti
+6s
+3ped
+5nd
+6schaw
+9awing
+9awings
+9aws
+7haw
+9wing
+9wings
+9ws
+5r
+6ed
+6ing
+6s
+4ing
+3s
+2qf
+4s
+2r
+3agi
+6s
+4tah
+7s
+3b
+4ier
+6st
+5rd
+7s
+4le
+6d
+6r
+7s
+6s
+5ing
+8ly
+8s
+4onnet
+9s
+4s
+4y
+3chalker
+9rs
+8ing
+9ngs
+4raft
+8s
+3d
+4corn
+8s
+4ed
+5n
+6ed
+6ing
+6ries
+7y
+6s
+7hip
+9ps
+5r
+6ed
+6ing
+6s
+7hip
+9ps
+4ian
+5ng
+7s
+4less
+4mote
+8s
+4og
+6s
+4ress
+8es
+5obe
+8d
+8r
+9s
+8s
+7ing
+6om
+8s
+6p
+7s
+4s
+5hip
+8s
+3e
+4d
+4hou
+7s
+8e
+9d
+9man
+9men
+9r
+9rs
+9s
+8ing
+9ngs
+4less
+4room
+8s
+4s
+4z
+3fare
+7d
+7r
+8s
+7s
+6in
+8g
+9s
+8s
+3hable
+4ead
+7s
+4orse
+8s
+3ibashi
+9s
+4er
+5st
+4ly
+4ment
+8s
+4ness
+8es
+5g
+4son
+7s
+3k
+4ed
+4ing
+4s
+3less
+4ike
+7ness
+9sses
+5ng
+7s
+4ock
+7ries
+8y
+7s
+5rd
+7ism
+9ms
+7s
+3m
+4aker
+8s
+5n
+4blood
+9ed
+9s
+4ed
+5n
+5r
+6s
+5st
+4hearted
+9edness
+4ing
+7s
+5sh
+4ly
+4ness
+8es
+4onger
+9ing
+9ings
+9s
+5uth
+8s
+4s
+4th
+6s
+4up
+6s
+3n
+4ed
+5r
+6s
+4ing
+7ly
+7s
+4s
+3p
+4age
+7s
+5th
+7s
+4ed
+5r
+6s
+4ing
+7s
+4lane
+8s
+4ower
+8s
+4s
+4wise
+3ragal
+8s
+6le
+8s
+6ul
+8s
+5n
+6d
+7ed
+7ice
+9es
+8ng
+7s
+6ed
+6ing
+6s
+6t
+7ability
+9le
+9leness
+9ly
+7ed
+8e
+9s
+8r
+9s
+7ied
+9s
+8ng
+9gs
+8se
+9es
+7less
+7or
+9s
+7s
+7y
+8ing
+5y
+6ed
+6ing
+6s
+4e
+5d
+5n
+6er
+8s
+6s
+5y
+6ed
+6ing
+6s
+4igal
+8s
+5ng
+5or
+7ess
+9ses
+7s
+5son
+8s
+3s
+4aw
+6s
+4hip
+7s
+4le
+6d
+6r
+7s
+6s
+5ing
+4t
+5le
+7d
+7r
+8s
+7s
+6ing
+3t
+4ed
+4hog
+7s
+4ier
+6st
+5me
+7s
+4less
+5ike
+4s
+4weed
+8s
+5ort
+8s
+4y
+3wolf
+6ves
+5rk
+7s
+6n
+3y
+3zone
+7s
+2s
+3abi
+6s
+3e
+4s
+3h
+4abilities
+9ty
+6le
+8s
+5teria
+9as
+5way
+8s
+4ball
+8s
+6sin
+9s
+5oard
+9s
+6wl
+8s
+4cloth
+9s
+4day
+7s
+4ed
+5n
+5r
+6ed
+6ies
+7ng
+6man
+7en
+6s
+6woman
+9en
+6y
+5s
+5teria
+9as
+4hand
+5ouse
+9s
+4ier
+6st
+5ly
+5n
+6ess
+9es
+6g
+7s
+7tonia
+9nias
+6s
+4land
+8s
+4out
+7s
+4pot
+7s
+4rag
+7s
+5oom
+8s
+4stand
+9s
+4tub
+7s
+4up
+6s
+4wipe
+8s
+5oman
+7en
+4y
+3p
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+5sh
+7ly
+7ness
+9sses
+4like
+4nest
+8s
+4s
+4y
+3sail
+7ed
+8r
+9s
+7ing
+9gs
+7ries
+8y
+7s
+4erman
+7en
+4up
+3t
+4able
+5ge
+7s
+4e
+5basket
+9ets
+5d
+5ful
+8ly
+8ness
+9esses
+5l
+6and
+9s
+6ot
+8s
+6s
+5ness
+9es
+5paper
+9rs
+5r
+6ed
+6ful
+9ly
+9ness
+9nesses
+6ie
+8s
+7ng
+6s
+6y
+5s
+5water
+9rs
+7y
+8s
+6eir
+9s
+4full
+4ing
+7ly
+7s
+4ness
+8es
+4rel
+7s
+5ie
+7s
+6fe
+8s
+5y
+4s
+2t
+3ap
+5e
+6s
+5s
+3ch
+5able
+9s
+5band
+9s
+6ox
+8es
+5case
+9s
+6ries
+7y
+5dog
+8ged
+9ing
+8s
+5ed
+6r
+7s
+6s
+6t
+7s
+6ye
+8s
+5ful
+8ly
+8ness
+9esses
+5glass
+9ses
+6uard
+9ds
+5ing
+5list
+9s
+5maker
+9rs
+8ing
+9ngs
+7n
+6en
+5out
+8s
+5spring
+9ngs
+6trap
+9ps
+5tower
+9rs
+5word
+9s
+3e
+4r
+5age
+8s
+5bed
+8s
+6ird
+9s
+6oarding
+9dings
+7rne
+6rain
+9ns
+6uck
+9s
+7s
+8es
+8ses
+5color
+9rist
+9rists
+9rs
+9ur
+9urist
+9urists
+9urs
+7oler
+9ers
+7urse
+9ses
+6raft
+9ts
+7ess
+9ses
+5dog
+8s
+6rive
+9es
+5ed
+6r
+7s
+5fall
+9s
+6inder
+9ers
+6lood
+9ded
+9ding
+9dings
+9ds
+6owl
+9er
+9ers
+9ing
+9ings
+9s
+6ront
+9ts
+5glass
+9ses
+5head
+9s
+7n
+8s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8s
+6sh
+8ness
+9esses
+5jet
+8s
+5leaf
+9s
+7ss
+9ness
+9nesses
+6ilies
+8y
+7ne
+9s
+6og
+8ged
+9ing
+8s
+7o
+8s
+5man
+8ship
+9hips
+7rk
+9ed
+9ing
+9s
+6elon
+9ns
+7n
+5power
+9rs
+7x
+8es
+6roof
+9fed
+9fer
+9fers
+9fing
+9fings
+9fness
+9fs
+5quake
+9es
+5s
+6cape
+9es
+6hed
+9s
+6ide
+9r
+9rs
+9s
+6ki
+8ing
+9ngs
+8s
+6meet
+9ts
+6pout
+9ts
+5thrush
+9shes
+6ight
+9tness
+5way
+8s
+6eed
+9s
+6heel
+9ls
+6ork
+9s
+8n
+5y
+5zooi
+9s
+3s
+3t
+4age
+7s
+5pe
+7s
+4er
+5st
+4hour
+8s
+4le
+6bark
+9ks
+7ird
+9ds
+6d
+6s
+7s
+6work
+9ks
+5ing
+8s
+4meter
+9s
+4s
+2ucht
+6ed
+6ing
+6s
+3ff
+5ed
+5ing
+5s
+3gh
+5ed
+5ing
+5s
+5t
+6ed
+6ing
+6s
+3k
+4ed
+5r
+6s
+4ing
+4mill
+8s
+4rife
+4s
+3l
+4ed
+4ing
+7s
+4k
+5ed
+6r
+7s
+5ing
+5mill
+9s
+5s
+4s
+3r
+4ed
+4ing
+4s
+5t
+2ve
+4band
+8s
+4d
+4form
+8s
+5ront
+9s
+4guide
+9s
+4length
+9hs
+6ss
+8ly
+6t
+7s
+5ike
+5lite
+9s
+4meter
+9s
+4off
+7s
+4r
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8ly
+8ness
+9esses
+8s
+5ous
+5s
+5y
+4s
+5hape
+9s
+5on
+7s
+4y
+5s
+3icle
+7s
+4er
+5s
+6t
+4ly
+4ness
+8es
+5g
+6s
+3y
+2w
+3a
+4ed
+4ing
+4s
+3e
+4s
+3l
+4ed
+4ing
+7s
+4s
+3s
+2x
+3able
+3berries
+7y
+4ill
+7s
+3cloth
+8s
+3ed
+4n
+4r
+5s
+4s
+4ye
+6s
+3flower
+9s
+3ier
+5st
+4ly
+4ness
+8es
+5g
+6s
+3like
+3plant
+8s
+3weed
+7s
+4ing
+7s
+4ork
+7er
+9s
+7s
+6m
+7s
+3y
+2y
+3bill
+7s
+4oard
+8s
+4read
+8s
+3ed
+3fare
+7d
+7r
+8s
+7s
+6ing
+9s
+3going
+8s
+5ne
+5ose
+8s
+3ing
+3laid
+5y
+6er
+8s
+6ing
+6s
+4eave
+8s
+5ggo
+5ss
+3mark
+7ed
+7ing
+7s
+4ent
+7ed
+7ing
+7s
+3point
+8s
+5st
+7s
+3s
+4ide
+7s
+3ward
+7ly
+7ness
+9sses
+4iser
+8s
+4ode
+7s
+5rn
+3zgoose
+9s
+2zir
+5s
+3oo
+5s
+3zock
+7s
+1e
+2ak
+4en
+6ed
+7r
+8s
+6ing
+6s
+5r
+5st
+4fish
+8es
+4hearted
+4ish
+7ly
+7ness
+9sses
+4lier
+7st
+6ness
+9ses
+7g
+8s
+5y
+4ness
+8es
+4on
+6s
+4side
+8s
+3l
+4d
+5s
+4s
+5man
+6en
+4th
+6ier
+8st
+7ly
+7ness
+9sses
+6less
+6s
+6y
+3mb
+5s
+3n
+4ed
+5l
+6s
+5r
+6s
+4ing
+7s
+4ling
+8s
+4s
+3pon
+6ed
+7er
+9ing
+9ings
+9s
+6ing
+7se
+9d
+9s
+8ing
+7ze
+9d
+9s
+8ing
+6less
+6ries
+7y
+6s
+3r
+4abilities
+9ty
+6le
+8s
+4ed
+5r
+6s
+4ied
+6r
+6s
+7t
+5ful
+8ly
+8ness
+9esses
+5less
+9ly
+6y
+5ness
+9es
+6g
+7ly
+7s
+5sh
+6ome
+9ly
+9ness
+9nesses
+4proof
+4s
+4y
+5ing
+8ly
+3sand
+7s
+4el
+6ed
+7r
+8s
+6ing
+6led
+8r
+9s
+7ing
+7y
+6s
+6y
+4on
+6s
+3ther
+7ability
+9le
+7board
+9arded
+9arding
+9ards
+7cast
+9ster
+9sters
+9sts
+8loth
+9oths
+8ock
+9cked
+9cking
+9cks
+7ed
+8r
+9s
+7girl
+9rls
+8lass
+9asses
+7ing
+9gs
+8sation
+9ations
+9e
+9ed
+9es
+9ing
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7liness
+9nesses
+8y
+7man
+8en
+8ost
+7ometer
+9eters
+7person
+9rsons
+8roof
+9oofed
+9oofing
+9oofs
+7s
+7worn
+3ve
+5d
+5r
+6bird
+9ds
+6s
+5s
+4ing
+7s
+3zand
+7s
+4en
+6ed
+6ing
+6s
+2b
+3bed
+4ie
+6r
+6s
+7t
+5ng
+7s
+4y
+3cam
+6s
+5st
+7ed
+8r
+9s
+7ing
+7s
+3er
+5s
+3fed
+5et
+4oot
+7ed
+3head
+7s
+3ified
+7s
+5y
+6ing
+4nar
+7s
+4sode
+8s
+3less
+4ike
+5sh
+7es
+4og
+6ger
+9s
+6s
+3mail
+7s
+5ster
+9s
+3page
+7s
+3ring
+7s
+3s
+4ite
+7s
+4ter
+7s
+3wheel
+8s
+4ork
+7s
+6m
+7s
+3zine
+7s
+2cht
+5s
+2d
+3ded
+5r
+6ed
+6ing
+6s
+4ing
+7s
+3el
+5ed
+5ing
+5n
+6ed
+6ing
+6s
+5s
+3ge
+5d
+5like
+5s
+5wise
+4ie
+6r
+6s
+7t
+5ng
+7s
+4y
+3lock
+7s
+3s
+2e
+3d
+4ed
+5r
+6ies
+6s
+6y
+4icide
+9s
+5er
+6st
+5ly
+5ness
+9es
+6g
+7s
+4killer
+9rs
+4less
+5ike
+4s
+4y
+3ing
+3k
+4day
+7s
+4e
+5nd
+7ed
+8r
+9s
+7ing
+9gs
+7s
+5s
+4lies
+5ong
+5y
+4night
+9s
+4s
+3l
+4dlesse
+4s
+3m
+4s
+3n
+4ed
+4ie
+6r
+6s
+7t
+5ng
+4s
+5ier
+7st
+5y
+4y
+3p
+4er
+6s
+4hole
+8s
+4ie
+6r
+6s
+7t
+5ly
+5ness
+9es
+6g
+7ly
+7s
+4s
+4y
+3r
+3s
+4t
+3t
+4e
+5d
+5n
+5r
+5st
+4ing
+7ly
+4less
+4s
+3ver
+6s
+4il
+6ed
+6led
+7y
+6s
+6y
+3wee
+6d
+6ing
+6s
+2ft
+4age
+7s
+4e
+5d
+5s
+4ing
+4s
+4wise
+2id
+4s
+3gela
+7s
+6ia
+8s
+4h
+5able
+6ge
+8s
+5board
+9ds
+6ridge
+9ges
+5ed
+6r
+7s
+5ing
+8s
+5man
+6en
+5s
+5t
+6age
+9s
+6ed
+7r
+8s
+6ier
+8st
+7ly
+7ness
+9sses
+8g
+9s
+6less
+9sly
+9sness
+7ifter
+9ters
+9ting
+9tings
+6s
+6y
+3l
+4s
+3maraner
+9rs
+3ner
+6s
+3r
+4d
+5ed
+6r
+6st
+5ie
+7s
+6ng
+5ly
+5ness
+9es
+5o
+6es
+6s
+5s
+5y
+4ed
+4ing
+4s
+3se
+5d
+5nheimer
+9mers
+5s
+4ing
+3ze
+5d
+5s
+4ing
+2ka
+4s
+2laway
+3ch
+5ed
+6r
+7s
+6s
+5ing
+4ome
+7d
+7ly
+7ness
+9sses
+7r
+8s
+7s
+6ing
+9ly
+3d
+4abilities
+9ty
+6le
+4ed
+5r
+6s
+4ing
+7s
+4less
+4ment
+8s
+4or
+6s
+4s
+3fare
+7s
+6ism
+9s
+8t
+9ic
+9s
+3k
+4e
+5d
+5s
+4in
+6g
+6s
+4s
+4t
+3l
+4aday
+8s
+5near
+5way
+8s
+4being
+9s
+5orn
+4curb
+8s
+4doer
+8s
+4ed
+4head
+8s
+5ole
+8s
+6use
+9s
+4ie
+6s
+5ng
+7s
+7ton
+9nia
+9nias
+9ns
+4ness
+8es
+4s
+5ite
+8s
+5pring
+9gs
+4y
+3s
+4h
+5ed
+6r
+7s
+6s
+5ing
+3t
+4anschauung
+9auungs
+4ed
+5r
+6ed
+6ing
+6s
+6weight
+9ghts
+4ing
+7s
+4s
+5chmerz
+9rzes
+3witschia
+9ias
+2m
+3b
+4s
+3s
+2n
+3a
+3ch
+5ed
+6r
+7s
+6s
+5ing
+3d
+4ed
+4igo
+7s
+5ng
+4s
+3ge
+5s
+3nier
+6st
+5sh
+4y
+3s
+4leydale
+9les
+3t
+4letrap
+9ps
+4s
+2pt
+2re
+4gild
+8s
+4wolf
+8eries
+9ry
+8ish
+9sm
+9sms
+7ves
+3geld
+7s
+6t
+7s
+4ild
+7s
+3nerite
+9s
+3o
+4s
+3ris
+6es
+3sh
+5er
+6st
+3t
+3wolf
+7ish
+6ves
+2sand
+6s
+3kit
+6s
+3sand
+7s
+3t
+4about
+4bound
+4ed
+5r
+6ed
+6ing
+9s
+6lies
+8ness
+9esses
+7y
+6n
+7er
+9s
+7isation
+9ations
+9e
+9ed
+9es
+9ing
+9m
+9ms
+8zation
+9ations
+9e
+9ed
+9es
+9ing
+7most
+7s
+6s
+4ie
+6s
+5ng
+7s
+4lin
+7s
+4most
+4s
+4ward
+8ly
+8s
+2t
+3a
+4s
+3her
+6s
+3land
+7s
+4y
+3ness
+7es
+3proof
+3s
+4uit
+7s
+3tabilities
+9ty
+6le
+4ed
+5r
+6s
+5st
+4ie
+6s
+5ng
+7s
+5sh
+3ware
+7s
+2x
+3e
+4d
+4s
+3ing
+2y
+3ard
+3s
+3ward
+2zand
+6s
+1ha
+3ck
+5ed
+6r
+7s
+5ier
+7st
+6ng
+8s
+5o
+6es
+6s
+5s
+5y
+3e
+3ikorero
+9os
+4sle
+7d
+7s
+6ing
+4zle
+7d
+7s
+6ing
+3kairo
+8s
+5papa
+9s
+3le
+5back
+9s
+6oat
+9s
+7ne
+9s
+5d
+5like
+5man
+6en
+5r
+6ies
+6s
+6y
+5s
+4ing
+7s
+4ly
+3m
+4med
+5ies
+6ng
+5o
+6s
+5y
+4o
+4ple
+7s
+4s
+3nau
+6s
+4g
+5am
+7s
+5ed
+6e
+7s
+5ing
+5s
+3p
+4ped
+6r
+7s
+5ing
+4s
+3re
+5nui
+8s
+5puni
+9s
+5s
+4f
+5age
+8s
+5ed
+5ie
+7s
+6ng
+8er
+9rs
+8s
+5master
+9ers
+5s
+4ve
+6s
+3t
+4a
+5bouteries
+9ery
+9s
+5s
+4chamacallit
+4en
+5ver
+4na
+5ess
+8es
+5ot
+7s
+4s
+5hername
+9ames
+6isname
+9ames
+5is
+7es
+6t
+7s
+8name
+9ames
+5o
+6ever
+6mever
+4ten
+3up
+5s
+4r
+5s
+2eal
+5s
+4r
+5e
+4t
+5ear
+8s
+6n
+7s
+5field
+9ds
+5grass
+9ses
+5ier
+7st
+5land
+9s
+6ess
+5meal
+9s
+5s
+5worm
+9s
+5y
+3e
+4ch
+6ed
+6ing
+6s
+4dle
+7d
+7r
+8s
+7s
+8ome
+6ing
+9ly
+9s
+4l
+5barrow
+9owed
+9owing
+9ows
+7se
+9s
+5chair
+9rs
+5ed
+6r
+7s
+5horse
+9es
+7use
+9es
+5ie
+7r
+7s
+8t
+6ng
+8s
+5less
+5man
+6en
+5s
+6man
+7en
+5work
+9s
+6right
+9hts
+5y
+4n
+5ge
+7d
+7s
+6ing
+5s
+4p
+5ed
+5ing
+5le
+7d
+7s
+6ing
+5s
+4sh
+6ed
+7s
+6ing
+6t
+7ed
+7ing
+7s
+4ze
+6d
+6r
+7s
+6s
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+8ly
+8s
+5le
+7d
+7s
+6ing
+5y
+3ft
+5s
+3lk
+5ed
+5ier
+7st
+5s
+5y
+4m
+5ed
+5ing
+5s
+4p
+5ed
+5ing
+5less
+5s
+3mmle
+7d
+7s
+6ing
+3n
+4as
+4ce
+6forth
+6s
+7oever
+6ver
+4ever
+4s
+5oever
+4ua
+6s
+4we
+6s
+3re
+5about
+9ts
+6fter
+6gainst
+6s
+7es
+6t
+5by
+5for
+8e
+9s
+6rom
+5in
+7soever
+7to
+5ness
+9es
+5of
+6n
+6ut
+5s
+6o
+7ever
+5through
+6o
+5under
+7til
+8o
+6pon
+5ver
+5with
+9al
+9als
+9s
+4ret
+7ed
+7ing
+7s
+5ied
+7s
+6t
+7ed
+7ing
+7s
+5y
+6ing
+6man
+7en
+4ve
+6s
+3t
+4her
+4s
+5tone
+9s
+4ted
+6r
+7s
+5ing
+3ugh
+6ed
+6ing
+6s
+3w
+4ed
+5llite
+9es
+4ing
+4s
+3y
+4ey
+4face
+8d
+8s
+4ier
+6st
+5sh
+7ness
+9sses
+4like
+4s
+2ich
+5ever
+5soever
+4ker
+7ed
+7ing
+7s
+3d
+4ah
+6s
+4ded
+6r
+7ed
+7ing
+7s
+5ing
+4s
+3ff
+5ed
+6r
+7s
+6t
+7s
+5ier
+7st
+6ng
+8s
+5le
+7d
+7r
+8ies
+8s
+8y
+7s
+7tree
+9ees
+6ing
+9s
+5s
+5y
+4t
+5s
+3g
+4gamore
+9es
+5ed
+5ing
+4maleerie
+9ries
+9ry
+4s
+3le
+5d
+5re
+5s
+4ing
+4k
+4lied
+7s
+5y
+6ing
+6wha
+9ed
+9ing
+9s
+9w
+9wed
+9wing
+9ws
+4om
+4st
+3m
+4berries
+8y
+5rel
+8s
+4med
+5ier
+7st
+6ng
+5y
+4per
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7s
+5le
+7d
+7s
+6ing
+4s
+5ey
+7s
+5ical
+9ities
+9ity
+9ly
+9ness
+9nesses
+6ed
+7r
+7s
+8t
+6ly
+6ness
+9ses
+5y
+3n
+4berries
+8y
+4chat
+8s
+4e
+5d
+5r
+6s
+5s
+5y
+4gding
+9s
+5e
+6d
+6ing
+9ly
+9s
+6r
+7s
+6s
+5ier
+7st
+6ng
+5y
+4iard
+8s
+5er
+6st
+5ness
+9es
+6g
+7ly
+7s
+4nied
+7r
+7s
+8t
+5y
+6ing
+4s
+5tone
+9s
+4y
+5ard
+8s
+3o
+4s
+3p
+4bird
+8s
+4cat
+7s
+5ord
+8s
+8y
+4jack
+8s
+4lash
+8ed
+9s
+8ing
+5ess
+5ike
+4ped
+6r
+7s
+8napper
+9appers
+6t
+7ing
+9gs
+7s
+5ier
+7st
+6ness
+9ses
+7g
+8s
+5letree
+9ees
+5oorwill
+9ills
+5y
+4ray
+7s
+4s
+5aw
+7ed
+7ing
+7n
+7s
+5nake
+9s
+5taff
+9s
+7ll
+9ed
+9ing
+9s
+6er
+8s
+6itch
+9hed
+9hes
+9hing
+6ock
+9s
+4t
+5ail
+8ed
+8s
+4worm
+8s
+3r
+4l
+5about
+9ts
+5bat
+8s
+6last
+9ts
+5ed
+6r
+7s
+5ier
+7s
+8t
+6gig
+9s
+6ng
+8ly
+8s
+5pool
+9s
+5s
+5wind
+9s
+5y
+6bird
+9ds
+4r
+5ed
+6t
+7ed
+7ing
+7s
+5ied
+7s
+6ng
+8s
+5s
+5y
+6ing
+4s
+4tle
+7s
+3sh
+5ed
+6s
+5ing
+5t
+6ed
+6ing
+6s
+4k
+5ed
+6r
+7ando
+9doed
+9dos
+7ed
+7ier
+9st
+7s
+7y
+6t
+7s
+6y
+7fied
+7s
+5ies
+6fied
+6ng
+5s
+5y
+4per
+7ed
+8r
+9s
+7ing
+9gly
+9gs
+7ously
+7s
+7y
+4s
+5ed
+6s
+5ing
+4t
+5ed
+5ing
+5le
+7able
+7blower
+9owers
+9owing
+9owings
+7d
+7r
+8s
+7s
+6ing
+9ly
+9s
+5s
+3t
+4e
+5bait
+9s
+7ss
+9es
+6eam
+9s
+8rd
+9ds
+6oard
+9ds
+7yism
+9sms
+5cap
+8s
+6oat
+9s
+7mb
+9s
+5d
+6amp
+9s
+5face
+9s
+6ish
+9es
+6lies
+7y
+5head
+9s
+5list
+9ed
+9ing
+9s
+6y
+5n
+6ed
+7r
+8s
+7ss
+9es
+6ing
+9s
+6s
+5out
+8s
+5pot
+8s
+5r
+5s
+6mith
+9hs
+6t
+5tail
+9s
+6horn
+9ns
+7roat
+9ats
+5wall
+9s
+7re
+9s
+7sh
+9ed
+9er
+9ers
+9es
+9ing
+9ings
+7ter
+6ing
+9s
+6ood
+9s
+5y
+6s
+6wood
+9ds
+4her
+7ed
+7ing
+7s
+8oever
+7ward
+9rds
+4ier
+6s
+7t
+5ng
+7s
+5sh
+7ness
+9sses
+4leather
+9ers
+5ing
+8s
+5ow
+7s
+4rack
+8s
+5et
+7s
+5ick
+8s
+4s
+5ter
+8s
+4taw
+7er
+9s
+7s
+5er
+7ed
+7ick
+9ks
+8ng
+7s
+5le
+7d
+7r
+8s
+7s
+6ing
+9s
+5ret
+8s
+4y
+3z
+4bang
+8s
+4z
+5bang
+9s
+5ed
+6r
+7s
+6s
+5ier
+7st
+6ng
+8ly
+8s
+5o
+5y
+2o
+3a
+3dunit
+8ries
+9y
+8s
+6nit
+9ries
+9ry
+9s
+3ever
+3le
+5food
+9s
+5grain
+5hearted
+9tedly
+5meal
+9s
+5ness
+9es
+5s
+6ale
+9d
+9r
+9rs
+9s
+8ing
+6ome
+9ly
+9ness
+9nesses
+9r
+9st
+6titch
+9ches
+5wheat
+4ism
+7s
+6t
+7ic
+7s
+4ly
+4phin
+8s
+3m
+4ble
+7d
+7s
+6ing
+4ever
+4mle
+7d
+7s
+6ing
+4p
+5ed
+5ing
+5s
+4so
+6ever
+3obub
+7s
+4f
+5ed
+5ing
+5s
+4p
+5ed
+6e
+7s
+6r
+7s
+5ie
+7s
+6ng
+8s
+5la
+7s
+5s
+6ie
+8s
+4sh
+6ed
+7s
+6ing
+5is
+7es
+4t
+5ed
+5ing
+5s
+3p
+4ped
+6r
+7s
+5ing
+8s
+4s
+3ring
+5sh
+7ly
+7ness
+9sses
+4l
+5bat
+8s
+5ed
+5s
+4t
+5le
+7berries
+9rry
+7s
+5s
+3se
+5soever
+5ver
+4is
+6es
+4o
+5ever
+3t
+3w
+2ummle
+7d
+7s
+6ing
+4p
+5ed
+5ing
+5s
+3nstane
+9s
+3p
+4ped
+5ing
+8s
+4s
+2y
+3dah
+6s
+4unit
+8s
+6nit
+9s
+3ever
+3s
+1ibble
+6d
+6s
+5ing
+2cca
+5n
+6s
+5s
+3e
+3h
+4es
+3k
+4ape
+7s
+4ed
+6er
+7st
+6ly
+6ness
+9ses
+6s
+5n
+6s
+5r
+6ed
+6s
+6work
+9ks
+5t
+6keeper
+9pers
+6s
+4ies
+5ng
+7s
+5up
+7s
+4less
+4s
+4thing
+9s
+4y
+5up
+7s
+3opies
+5y
+2dder
+6s
+7hins
+4ie
+6s
+4le
+6d
+6s
+5ing
+4y
+3e
+4awake
+9s
+4band
+5odies
+7y
+4chapped
+4ly
+4mouthed
+4n
+5ed
+6r
+7s
+6ss
+8es
+5ing
+5s
+4out
+7s
+4r
+5shins
+4s
+5creen
+5pread
+5t
+3geon
+7s
+5t
+6s
+4ie
+6s
+3ish
+3ow
+5bird
+9s
+5ed
+6r
+7ed
+7hood
+9ods
+7s
+5hood
+9s
+5ing
+5man
+6en
+5s
+3th
+5s
+5way
+8s
+6ise
+2el
+4d
+5able
+5ed
+6r
+7s
+5ier
+7st
+6ness
+9ses
+7g
+5less
+5s
+5y
+4s
+3ner
+6s
+6wurst
+9sts
+4ie
+6s
+2fe
+4d
+5om
+7s
+4hood
+8s
+4less
+5ier
+7st
+6ke
+6ness
+9ses
+5y
+4s
+4y
+5s
+3ie
+5s
+4ng
+3tier
+6st
+4y
+2g
+3an
+5s
+3eon
+6s
+3ga
+5s
+4ed
+5r
+6ies
+6s
+6y
+4ier
+6st
+5ng
+7s
+4le
+6d
+6r
+7s
+6s
+5ier
+7st
+6ng
+5y
+4y
+3ht
+5ed
+5ing
+5ly
+5s
+3less
+5t
+6s
+4ike
+3maker
+8s
+3s
+3wag
+6ged
+8r
+9s
+7ing
+6s
+5m
+6s
+2ki
+4s
+4torial
+9ls
+4up
+6s
+2lco
+3d
+4card
+8s
+6t
+7s
+7ted
+9r
+9rs
+8ing
+9ngs
+4ebeest
+9ts
+5d
+5r
+6ed
+6ing
+6ment
+9ts
+6ness
+9ses
+6s
+5st
+4fire
+8s
+5lower
+9rs
+5owl
+8er
+9rs
+8ing
+9ngs
+8s
+4grave
+9s
+4ing
+7s
+5sh
+4land
+8s
+5ife
+8s
+6ng
+8s
+5y
+4ness
+8es
+4s
+4wood
+8s
+3e
+4d
+4ful
+4s
+3ful
+6ly
+6ness
+9ses
+3ga
+5s
+3i
+4er
+5st
+4ly
+4ness
+8es
+5g
+4s
+3ja
+5s
+3l
+4able
+4ed
+5mite
+9s
+5r
+6s
+5st
+5t
+6s
+5y
+6ed
+6ing
+6s
+4ful
+7ly
+7ness
+9sses
+4iam
+7s
+5e
+6d
+6waught
+9ghts
+5ng
+7er
+8st
+7ly
+7ness
+9sses
+5wau
+8s
+7w
+8s
+4ow
+6ed
+7r
+8s
+6herb
+9bs
+6ier
+8st
+7ng
+7sh
+6like
+6s
+6ware
+9es
+6y
+4power
+9s
+4s
+4yard
+7t
+5ing
+5waw
+8s
+3t
+4ed
+4ing
+4ja
+6s
+4s
+3y
+2mble
+6d
+6s
+5ing
+4rel
+7s
+3min
+3p
+4ed
+4ier
+6st
+5ness
+9es
+6g
+5sh
+7ly
+7ness
+9sses
+4le
+6d
+6s
+5ing
+4s
+4y
+2n
+3ce
+5d
+5r
+6s
+5s
+5y
+6ette
+9es
+6s
+4h
+5ed
+6r
+7s
+6s
+7ter
+9rs
+5ing
+5man
+6en
+4ing
+7s
+4opipe
+9s
+3d
+4able
+5c
+6s
+5ge
+7s
+5s
+6es
+4bag
+7geries
+9ry
+7s
+5ell
+8s
+5ill
+8s
+5last
+9s
+6ow
+8n
+8s
+5orne
+6und
+5reak
+9er
+9ers
+9s
+5urn
+8ed
+8ing
+8s
+8t
+4cheater
+9ers
+6ill
+9s
+4ed
+5r
+6s
+4fall
+8en
+8s
+5law
+8s
+6ower
+9rs
+4gall
+8ed
+8s
+5un
+7s
+4hover
+9s
+4ier
+6st
+5go
+7s
+5ly
+5ness
+9es
+6g
+7ly
+7s
+4jammer
+9rs
+8ing
+9ngs
+4lass
+8ed
+9s
+8ing
+5e
+6d
+6s
+7s
+8ly
+8ness
+9esses
+7trae
+9aes
+9aw
+9aws
+5ing
+8s
+4mill
+8ed
+8ing
+8s
+4ock
+7s
+5re
+7s
+5w
+6ed
+6ing
+9s
+6less
+6pane
+9es
+6s
+7ill
+9ls
+6y
+4pipe
+8s
+5roof
+4ring
+5ow
+7ed
+8r
+9s
+7ing
+7s
+4s
+5ail
+8s
+5creen
+9ns
+5es
+5hake
+9s
+6ield
+9ds
+7p
+8s
+5ock
+8s
+5torm
+9s
+5ucker
+9rs
+6rf
+8ed
+9r
+9rs
+8ing
+9ngs
+8s
+5wept
+4throw
+9s
+5ight
+4up
+6s
+4ward
+8s
+6y
+7s
+4y
+3e
+4berries
+8y
+5ibber
+9rs
+8ing
+9ngs
+4d
+4glass
+9es
+9ful
+9fuls
+5rower
+9rs
+4less
+4maker
+9s
+7ing
+9gs
+4press
+9es
+4ries
+5y
+4s
+5ap
+7s
+5hop
+8s
+5kin
+8s
+5op
+7s
+4y
+3g
+4back
+8s
+5eat
+8s
+5ow
+7s
+4chair
+9s
+4ding
+8s
+4e
+5d
+6ly
+5ing
+5r
+6s
+5s
+4ier
+6st
+5ng
+4less
+8ness
+9esses
+6t
+7s
+5ike
+4man
+5en
+4nut
+7s
+4over
+8s
+4s
+5pan
+8s
+6read
+9ds
+5uit
+8s
+4tip
+7s
+4y
+3ier
+5st
+4ng
+4sh
+3k
+4ed
+5r
+6s
+4ing
+7ly
+7s
+4le
+6d
+6r
+7s
+6s
+5ing
+4s
+3less
+3n
+4a
+5bilities
+9ty
+6le
+5rd
+7s
+4ed
+5r
+6s
+4ing
+7ly
+7ness
+9sses
+7s
+4le
+6s
+4ock
+7s
+5w
+6ed
+7r
+8s
+6ing
+9s
+6s
+4s
+3o
+4es
+4s
+3s
+4ey
+6s
+4ome
+7ly
+7ness
+9sses
+7r
+7st
+3ter
+6berries
+9ry
+7ourne
+9rnes
+6cress
+9sses
+6ed
+7r
+8s
+6fed
+8ed
+9ding
+9ds
+6green
+9ens
+6ier
+8st
+7ness
+9sses
+8g
+7sation
+9tions
+8e
+9d
+9s
+8h
+8ing
+7zation
+9tions
+8e
+9d
+9s
+8ing
+6kill
+9led
+9ling
+9lings
+9ls
+6less
+7iness
+9esses
+7y
+6s
+6tide
+9es
+8me
+9es
+6weight
+6y
+4le
+6d
+6s
+5ing
+4rier
+7st
+6ly
+6ness
+9ses
+5y
+3y
+3ze
+5s
+2pe
+4able
+4d
+4out
+7s
+4r
+5s
+4s
+3ing
+6s
+3pen
+6s
+2rable
+3e
+4d
+5raw
+8er
+9rs
+8ing
+9ngs
+8n
+8s
+6ew
+4frame
+9s
+4grass
+9es
+4hair
+8ed
+8s
+4less
+8ed
+9s
+8ing
+5ike
+4man
+5en
+4photo
+9s
+5uller
+9rs
+8ing
+9ngs
+4r
+5s
+4s
+4tap
+7ped
+9r
+9rs
+8ing
+9ngs
+7s
+4walker
+9rs
+6y
+7s
+5ork
+8er
+9rs
+8ing
+9ngs
+8s
+7m
+8s
+6ve
+3ier
+5st
+4lda
+7s
+5y
+4ness
+8es
+5g
+6s
+3ra
+5h
+6s
+4icow
+8s
+3y
+2s
+3ard
+6s
+3dom
+6s
+3e
+4acre
+8s
+5sses
+4crack
+9ed
+9er
+9ers
+9ing
+9s
+4d
+4guy
+7s
+4lier
+7st
+6ng
+8s
+5y
+4ness
+8es
+5heimer
+9ers
+5t
+6s
+4r
+4s
+5t
+4woman
+7en
+3h
+4a
+4bone
+8s
+4ed
+5r
+6s
+5s
+4ful
+7ly
+7ness
+9sses
+4ing
+7s
+4less
+4t
+5onwish
+9shes
+3ing
+3ket
+6s
+3p
+4ed
+4ier
+6st
+5ly
+5ness
+9es
+6g
+5sh
+4like
+4s
+4y
+3s
+4ed
+5s
+4ing
+3t
+4aria
+8s
+4ed
+5ria
+8s
+4ful
+7ly
+7ness
+9sses
+4ing
+5ti
+7s
+4ly
+4s
+2t
+3an
+5s
+3blits
+8es
+3ch
+5broom
+9ms
+5craft
+9ts
+5ed
+6n
+7s
+6ries
+7y
+6s
+6tties
+8y
+5grass
+9ses
+5hood
+9s
+5ier
+7st
+6ng
+8ly
+8s
+5knot
+9s
+5like
+5weed
+9s
+5y
+3e
+4d
+4less
+4nagemot
+9ote
+9otes
+9ots
+4s
+3gat
+6boom
+9ms
+6s
+3h
+4al
+4draw
+8able
+9l
+9ls
+8er
+9rs
+8ing
+8ment
+9ents
+8n
+9ness
+9nesses
+8s
+6ew
+4e
+5d
+5r
+6ed
+8ness
+9esses
+7r
+8s
+6ing
+9ly
+9s
+7te
+9s
+6od
+8s
+6s
+7hins
+5s
+4hault
+5eld
+5old
+8en
+9r
+9rs
+8ing
+8ment
+9ents
+8s
+4ier
+6s
+7t
+5n
+6doors
+6g
+6s
+4out
+7doors
+7en
+7s
+4s
+5tand
+9er
+9ers
+9ing
+9s
+6ood
+4wind
+8s
+4y
+5wind
+9s
+3ing
+3less
+7ly
+7ness
+9sses
+4ing
+7s
+4oof
+7s
+3ness
+7able
+7ed
+8r
+9s
+8s
+7ing
+5y
+6s
+3s
+3ted
+5r
+6ed
+6ing
+6s
+4icism
+9s
+5er
+6st
+5ly
+5ness
+9es
+6g
+7ly
+7s
+4ol
+6ly
+6s
+4y
+3wall
+7s
+5nton
+9ed
+9ing
+9s
+2ve
+4d
+4hood
+8s
+4r
+5n
+6s
+5s
+4s
+3ing
+2z
+3ard
+6ly
+6ries
+7y
+6s
+3en
+5ed
+5ing
+5s
+4s
+3ier
+6s
+3zen
+6s
+5s
+1o
+2ad
+4ed
+4s
+4wax
+7en
+9s
+8s
+3ld
+5s
+2bbegong
+9s
+4le
+6d
+6r
+7s
+6s
+5ier
+7s
+8t
+6ness
+9ses
+7g
+8s
+5y
+3egone
+2ck
+4s
+2dge
+5s
+2e
+3begone
+9ness
+9nesses
+3ful
+6ler
+8st
+7y
+6ness
+9ses
+3ness
+7es
+3s
+4ome
+2f
+3s
+3ul
+5ler
+7st
+6y
+5ness
+9es
+2g
+3gish
+4le
+6s
+3s
+2iwode
+7s
+2k
+3e
+4n
+3ka
+3s
+2ld
+4s
+3f
+4berries
+8y
+4ed
+5r
+6s
+4fish
+8es
+4hound
+9s
+4ing
+7s
+5sh
+7ly
+7ness
+9sses
+4kin
+7s
+4like
+6ng
+8s
+4ram
+7ite
+9es
+7s
+4s
+5bane
+9s
+5kin
+8s
+3lastonite
+9ites
+4ies
+4y
+3ve
+5d
+5r
+6ene
+9s
+6ine
+9s
+6s
+5s
+4ing
+7s
+5sh
+7ly
+2man
+5ed
+5fully
+5hood
+9s
+5ing
+6se
+8d
+8r
+9s
+8s
+7h
+8ly
+8ness
+9esses
+7ing
+9gs
+7m
+8s
+7t
+8s
+6ze
+8d
+8r
+9s
+8s
+7ing
+9gs
+5kind
+9s
+5less
+6ier
+8st
+7ke
+7ness
+9sses
+6y
+5ness
+9es
+5power
+9rs
+5s
+3b
+4at
+6s
+4ed
+4ier
+6st
+5ng
+4like
+4s
+4y
+3en
+5folk
+9s
+5kind
+9s
+5swear
+9rs
+4ra
+6s
+3mera
+7s
+4it
+6s
+3yn
+2n
+3der
+6ed
+7r
+8s
+6ful
+9ly
+9ness
+9nesses
+6ing
+9ly
+9s
+6kid
+9s
+6land
+9ds
+7ess
+6ment
+9ts
+7onger
+9gering
+9gers
+6ous
+6s
+6work
+9ks
+4red
+5ous
+8ly
+8ness
+9esses
+3ga
+5s
+4i
+5ed
+5ing
+5s
+3ing
+6s
+3k
+4ier
+6st
+4s
+4y
+3ned
+5r
+6s
+4ing
+7s
+3s
+3t
+4ed
+6ly
+6ness
+9ses
+4ing
+4less
+4on
+6s
+4s
+2o
+3but
+6s
+3d
+4bin
+7d
+8s
+7e
+8s
+7s
+5lock
+9s
+5orer
+9s
+6x
+7es
+5urytype
+9ypes
+4carver
+9rs
+8ing
+9ngs
+5hat
+8s
+6ip
+8s
+6op
+8per
+9ers
+8s
+6uck
+9s
+5ock
+8s
+5raft
+9s
+9sman
+9smen
+5ut
+7s
+7ter
+9rs
+8ing
+9ngs
+4ed
+5n
+6ed
+7r
+7st
+6head
+9ded
+9ds
+6ing
+6ly
+6ness
+9ses
+6s
+6top
+9s
+6ware
+9es
+4free
+4grain
+9s
+6ouse
+9es
+4hen
+7s
+5ole
+8s
+6rse
+9s
+6use
+9s
+4ie
+6r
+6s
+7t
+5ness
+9es
+6g
+4land
+8er
+9rs
+8s
+6rk
+8s
+5ess
+8ness
+9esses
+5ice
+5ore
+8s
+6t
+7s
+6use
+4man
+5eal
+8s
+6n
+5ice
+5ouse
+4ness
+8es
+5ote
+8s
+4pecker
+9rs
+5ile
+8s
+5rint
+9s
+4rat
+7s
+5eeve
+9s
+5oof
+8s
+5uff
+8s
+6sh
+8es
+4s
+5crew
+9s
+5hed
+8ded
+9ing
+9ings
+8s
+6ock
+9s
+6rike
+9es
+5ia
+7s
+6er
+7st
+5kin
+8s
+5man
+6en
+5pite
+9s
+5tone
+9s
+7ve
+9s
+5wallow
+9ows
+5y
+4thrush
+9hes
+5one
+8s
+4wale
+8s
+6rd
+8s
+6x
+7en
+9s
+8s
+5ind
+8s
+5ork
+8er
+9rs
+8ing
+9ngs
+8s
+7m
+8s
+6se
+8s
+4y
+5ard
+8s
+3ed
+4r
+5s
+3f
+4ed
+5r
+6s
+4ier
+6st
+5ng
+4s
+4ter
+7s
+4y
+3hoo
+3ing
+6ly
+6s
+3l
+4d
+5ed
+6r
+7s
+5ing
+8s
+5s
+4ed
+5n
+6s
+5r
+6s
+4fat
+7s
+5ell
+8s
+4gatherer
+9rers
+9ring
+9rings
+5rower
+9rs
+8ing
+9ngs
+4hat
+7s
+4ie
+6r
+6s
+7t
+5ness
+9es
+4led
+6n
+7s
+5ier
+7s
+8t
+6ke
+6ly
+6ness
+9ses
+5y
+6back
+9ks
+7utt
+9ts
+6foot
+9ts
+4man
+5en
+4pack
+8s
+4s
+5ack
+8s
+5ey
+7s
+5hed
+8s
+5kin
+8s
+5orter
+9rs
+4ward
+5ork
+8s
+4y
+3mera
+7ng
+9s
+7s
+3n
+4ed
+4ing
+4s
+3pie
+6s
+4s
+5ed
+6s
+5ing
+3rali
+7s
+5ra
+7s
+6i
+7s
+3s
+4e
+5l
+6l
+7s
+6s
+5s
+4h
+5ed
+6s
+5ing
+3t
+4z
+5es
+3zier
+6st
+5ly
+5ness
+9es
+4y
+2p
+3ped
+4ing
+3s
+2rcester
+9berry
+9s
+3d
+4age
+7s
+4book
+8s
+6und
+5reak
+9s
+4ed
+4game
+8s
+4ier
+6st
+5ly
+5ness
+9es
+6g
+7s
+5sh
+7ness
+9sses
+4less
+8ly
+8ness
+9esses
+5ore
+8s
+4monger
+9rs
+4play
+8s
+4s
+5earch
+9hes
+5mith
+9eries
+9ery
+9s
+4y
+3e
+3k
+4abilities
+9ty
+6le
+8ness
+9esses
+7y
+5day
+8s
+5holic
+9cs
+9sm
+9sms
+5round
+9ds
+4bag
+7s
+6sket
+9ts
+5ench
+9es
+5oat
+8s
+6ok
+8s
+6x
+7es
+4day
+7s
+4ed
+5r
+6ist
+9s
+6less
+6s
+4fare
+8s
+5ellow
+9ws
+5low
+8s
+5olk
+8s
+6rce
+9s
+5ul
+4girl
+8s
+5roup
+9s
+4horse
+9s
+6ur
+8s
+7se
+9s
+4ing
+7man
+8en
+7s
+7woman
+9men
+4less
+8ness
+9esses
+5oad
+8s
+4man
+7like
+8y
+7ship
+9ips
+6ster
+9rs
+6te
+8s
+5en
+5istress
+9esses
+4out
+7s
+4people
+5iece
+9s
+5lace
+9s
+5rint
+9s
+4room
+8s
+4s
+5afe
+5heet
+9s
+6op
+8ped
+9ing
+8s
+6y
+5ome
+5pace
+9s
+5tation
+9ons
+6ream
+9ms
+4table
+9s
+5op
+7s
+4up
+6s
+4watcher
+9ers
+5ear
+8s
+6ek
+8s
+5oman
+7en
+3ld
+5beat
+9s
+5ed
+5lier
+8st
+7ness
+9sses
+8g
+9s
+6y
+5s
+6cale
+9es
+5view
+9s
+5wide
+3m
+4cast
+8s
+4ed
+5r
+6ies
+6s
+6y
+4flies
+6y
+4gear
+8s
+4hole
+8d
+8s
+4ier
+6st
+5l
+6s
+5ness
+9es
+6g
+5sh
+4like
+4root
+8s
+4s
+5eed
+8s
+4wood
+8s
+4y
+3n
+4ness
+8es
+3ral
+6s
+4el
+6s
+4icow
+8s
+5ed
+7ly
+6r
+7s
+6s
+5ment
+9s
+5some
+9ly
+9ness
+9nesses
+5t
+6ed
+6ing
+6s
+4y
+5cow
+8s
+5guts
+5ing
+8ly
+8s
+5wart
+9s
+3se
+5d
+5n
+6ed
+7ss
+9es
+6ing
+6s
+5r
+5s
+5t
+6s
+4hip
+7able
+7ed
+8r
+9s
+7ful
+9lly
+9lness
+7ing
+7less
+7ped
+9r
+9rs
+8ing
+7s
+4ing
+4t
+5ed
+7s
+5ing
+5s
+3t
+4h
+5ed
+5ful
+5ied
+7r
+7s
+8t
+6ly
+6ness
+9ses
+7g
+5less
+9ly
+9ness
+9nesses
+5s
+5while
+9eness
+5y
+6ing
+4le
+6s
+4s
+2s
+3bird
+7s
+3t
+2t
+3cha
+5er
+3s
+3ted
+5st
+5th
+4ing
+2ubit
+6s
+3ld
+5est
+5s
+6t
+3nd
+5able
+5ed
+7ly
+6r
+7s
+5ily
+6ng
+8ly
+8s
+5less
+5s
+5wort
+9s
+5y
+3rali
+7s
+2ve
+4n
+5s
+2w
+3ed
+4e
+3f
+4er
+5st
+3ing
+3s
+4er
+6s
+2x
+3en
+1rack
+5ed
+5ful
+5ing
+5s
+3ith
+6like
+6s
+3ng
+5ed
+5ing
+5le
+7d
+7r
+8s
+9hip
+9hips
+7s
+8ome
+6ing
+9s
+5s
+3p
+4around
+9ds
+4over
+8s
+4page
+8s
+5ed
+6r
+7ed
+7ing
+7s
+5ing
+8s
+4round
+9s
+4s
+4t
+3sse
+6s
+5le
+7d
+7s
+6ing
+4t
+5ed
+5ing
+5le
+7d
+7s
+6ing
+5s
+3te
+4h
+5ed
+5ful
+8ly
+8ness
+9esses
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5less
+5s
+5y
+3wl
+5ed
+5ing
+5s
+3xle
+6d
+6s
+5ing
+8s
+2eak
+5ed
+6r
+7s
+5ful
+5ing
+5less
+5s
+4th
+6e
+7d
+7n
+7r
+8s
+7s
+6ier
+8st
+7ng
+6less
+7ike
+6s
+6y
+3ck
+5age
+8s
+5ed
+6r
+7s
+5fish
+9es
+6ul
+5ing
+8s
+5master
+9ers
+5s
+3n
+4ch
+6ed
+7r
+8s
+7s
+6ing
+9ly
+9s
+4s
+3st
+5ed
+6r
+7s
+5ing
+5le
+7d
+7r
+8s
+7s
+6ing
+9s
+5s
+3tch
+6ed
+8er
+9st
+8ly
+8ness
+9esses
+7s
+4he
+6d
+6s
+5ing
+2ick
+5ed
+5ing
+5s
+3ed
+4r
+4s
+5t
+3ggle
+7d
+7r
+8s
+7s
+6ier
+8st
+7ng
+9s
+6y
+4ht
+6s
+3ng
+5ed
+6r
+7s
+5ing
+5s
+4kle
+7d
+7less
+7s
+6ier
+8s
+9t
+7ng
+6y
+3st
+5band
+9s
+5ier
+7st
+5let
+8s
+6ock
+9s
+5s
+5watch
+9hes
+5y
+3t
+4able
+5tive
+4e
+5able
+5r
+6ess
+9es
+6ly
+6s
+7hip
+9ps
+5s
+4he
+6d
+6n
+6r
+7s
+6s
+5ing
+8ly
+8s
+5led
+4ing
+7s
+4s
+4ten
+3zled
+2oath
+6s
+3ke
+5n
+3ng
+5doer
+9s
+7ing
+9gs
+5ed
+6r
+7s
+6st
+5ful
+8ly
+8ness
+9esses
+5headed
+9edly
+9edness
+5ing
+5ly
+5ness
+9es
+5ous
+8ly
+5s
+3ot
+5ed
+5ing
+5s
+3te
+4h
+5ful
+3ught
+2ung
+2y
+3bill
+7s
+3er
+4st
+3ing
+3ly
+3neck
+7s
+5ss
+7es
+3then
+1ud
+3ded
+4ing
+3jula
+7s
+3s
+3u
+4s
+2kkas
+2lfenite
+9s
+3l
+4ed
+4ing
+4s
+2nderkind
+9der
+9ds
+3ner
+6s
+2rley
+6s
+4ie
+6s
+3st
+5s
+3tzite
+8s
+3zel
+6s
+2s
+3es
+3hu
+5s
+3s
+4es
+4ier
+6s
+7t
+4y
+2ther
+6ed
+6ing
+6s
+2xia
+5s
+2zzle
+6d
+6s
+5ing
+1yandotte
+9s
+2ch
+4es
+2e
+3s
+2le
+4d
+4s
+3iecoat
+9s
+4ng
+2n
+3d
+4s
+3n
+4s
+3s
+2te
+4d
+4s
+3ing
+2vern
+6s
+0xantham
+7s
+6n
+7s
+6te
+8s
+7ion
+9ns
+5ein
+8s
+6ne
+8s
+5ic
+6n
+7e
+8s
+7s
+6sm
+8s
+5ochroia
+9oias
+9oic
+9oid
+9oids
+9oism
+9oisms
+9omia
+9omias
+9oous
+6ma
+8s
+8ta
+9ous
+7elanous
+6ne
+8s
+6phyl
+9ll
+9llous
+9lls
+9ls
+7sia
+9as
+7terin
+9rine
+9rines
+9rins
+6us
+6xyl
+9s
+1ebec
+5s
+2narthral
+3ia
+5l
+5s
+4c
+4um
+3obiotic
+9cs
+5last
+9s
+4cryst
+9s
+4diagnoses
+9osis
+9ostic
+5ochium
+9ums
+4gamies
+7ous
+7y
+5eneic
+8ses
+9is
+8tic
+7ic
+8es
+7ous
+7y
+5lossia
+9ias
+9ies
+9y
+5raft
+9s
+4lith
+8ic
+8s
+4mania
+9s
+5enia
+9s
+5orphic
+9ically
+4n
+5s
+4phile
+9s
+6obe
+9s
+8ia
+9as
+9c
+9cally
+9es
+8y
+6ya
+5lastic
+5us
+7es
+4time
+8s
+5ransplant
+9plants
+6opic
+3urine
+2rafin
+7s
+4nses
+6is
+5themum
+9ums
+6ic
+4phin
+8s
+4rch
+4sia
+7s
+3ic
+5ally
+4scape
+9s
+3ochasies
+8y
+4derma
+9e
+9s
+9tic
+9tous
+8ia
+9as
+9c
+4grapher
+9ers
+9ic
+9ically
+9ies
+9y
+4ma
+6s
+6ta
+5orph
+9ic
+9ous
+9s
+4phagies
+8y
+6ile
+9s
+8ies
+8ous
+8y
+6thalmia
+9lmias
+9lmic
+6yte
+9s
+8ic
+9cally
+9sm
+9sms
+4radiography
+4sere
+8s
+6s
+5is
+5toma
+9s
+9ta
+8ia
+9as
+4tes
+5hermic
+5ic
+5ripses
+9is
+4x
+5ed
+6s
+5ing
+3us
+5es
+1i
+2phihumeralis
+5plastra
+9tral
+9trals
+9tron
+5sterna
+9num
+9nums
+4oid
+7al
+7s
+5pagi
+9c
+8ous
+8us
+9ses
+6hyllous
+5suran
+9ns
+2s
+1oana
+4on
+1ray
+4s
+1u
+1ylan
+5s
+3em
+5s
+4ne
+6s
+5ol
+7s
+3ic
+4din
+7e
+8s
+7s
+4tol
+7s
+3obalsamum
+9mums
+4carp
+8ous
+8s
+5hrome
+9es
+4gen
+7ous
+7s
+5raph
+9ed
+9er
+9ers
+9ic
+9ical
+9ies
+9ing
+9s
+9y
+4id
+6in
+8e
+9s
+8s
+4l
+5ogies
+7y
+5s
+4ma
+6s
+6ta
+5eter
+9s
+4nic
+6te
+8s
+4phagan
+9ns
+8e
+9s
+8ous
+6ilous
+6one
+9s
+8ic
+9st
+9sts
+5yrography
+4rimba
+9s
+4se
+6s
+4tomies
+8st
+9ts
+7ous
+7y
+5ypographic
+9raphy
+3yl
+5s
+2ridaceous
+2st
+4er
+6s
+4i
+4oi
+5s
+4s
+4us
+0ya
+2ar
+4s
+2ba
+4s
+3ba
+5s
+4er
+6ed
+6ing
+6s
+4ie
+6d
+6s
+4y
+5ing
+2cca
+5s
+3ht
+5ed
+6r
+7s
+5ie
+7s
+6ng
+8s
+5man
+6en
+5s
+6man
+9ship
+9ships
+7en
+6woman
+9en
+3k
+4a
+5s
+4ed
+5r
+6s
+4ing
+4s
+2d
+3s
+2e
+2ff
+4ed
+4ing
+7ale
+9es
+4le
+6s
+4s
+2g
+3er
+5s
+3ger
+6s
+3i
+4s
+3s
+2h
+3oo
+5ism
+8s
+5s
+3rzeit
+8s
+3s
+2ird
+5s
+2k
+3hdan
+7s
+3imono
+8s
+4tori
+8s
+3ka
+5s
+4ed
+5r
+6s
+4ing
+3ow
+5s
+3s
+3uza
+2ld
+3e
+4s
+2m
+3alka
+7s
+3en
+5s
+3mer
+6ed
+7r
+8s
+6ing
+9s
+6s
+3pies
+4y
+3s
+3ulka
+7s
+4n
+5s
+2ng
+4s
+3k
+4ed
+5e
+6s
+5r
+6s
+4ie
+6s
+5ng
+4s
+3qui
+6s
+3tra
+6s
+2ourt
+6s
+2p
+3ock
+6s
+4k
+5s
+4n
+5s
+3p
+4ed
+5r
+6s
+4ie
+6r
+6s
+7t
+5ng
+7ly
+4s
+4y
+3s
+4ter
+7s
+2qona
+6s
+2r
+3borough
+9hs
+3co
+5s
+3d
+4age
+7s
+5ng
+7s
+5rm
+7s
+4bird
+8s
+4ed
+5r
+6s
+4ing
+7s
+4land
+8s
+4man
+6ster
+9rs
+5en
+4s
+5tick
+9s
+4wand
+8s
+5ork
+8s
+3e
+4ly
+4r
+4st
+3fa
+5s
+3k
+4ed
+4ing
+4s
+3melke
+8s
+4ulka
+8s
+7e
+8s
+3n
+4ed
+5r
+6s
+4ing
+4s
+3pha
+6s
+3r
+4aman
+8s
+6en
+5n
+6s
+4ow
+6s
+4s
+3ta
+5s
+4o
+5s
+2shmac
+7s
+6k
+7s
+3mak
+6s
+2tagan
+7s
+5han
+8s
+3e
+4s
+3ter
+6ed
+6ing
+9ly
+9s
+6s
+2ud
+4s
+3ld
+3p
+4ed
+5r
+6s
+4ing
+4on
+6s
+4s
+3tia
+6s
+2w
+3ed
+4y
+3ing
+3l
+4ed
+4ing
+4s
+3meter
+8s
+3n
+4ed
+5r
+6s
+4ier
+6st
+5ng
+7ly
+7s
+4s
+5ome
+4y
+3p
+4ed
+5r
+6s
+4ing
+7s
+4s
+3s
+3y
+2y
+3s
+1bet
+2lent
+2ore
+3und
+6en
+2rent
+1clad
+3ed
+4epe
+7d
+7s
+6ing
+4ped
+5t
+2ond
+1drad
+3ed
+1e
+2a
+3d
+4ing
+4s
+3h
+4s
+3ldon
+7s
+4ing
+7s
+4m
+5ed
+5ing
+5s
+3n
+4ed
+4ing
+4ling
+8s
+4s
+3r
+4book
+8s
+4d
+5ed
+5ing
+5s
+4end
+7s
+4lies
+6ng
+8s
+5ong
+5y
+4n
+5ed
+6r
+7s
+5ing
+8ly
+8s
+5s
+4s
+3s
+4ayer
+8s
+4t
+5ed
+5ier
+7st
+6ly
+6ness
+9ses
+7g
+5less
+6ike
+5s
+5y
+2bo
+2cch
+5s
+3h
+4ier
+6st
+4s
+4y
+2de
+4s
+3ing
+2ed
+4ing
+4s
+3lin
+6s
+2gg
+4man
+5en
+4s
+2h
+2ld
+4ring
+8s
+5ock
+8s
+3k
+4s
+3l
+4ed
+5r
+6s
+4ing
+7s
+4och
+7ed
+7ing
+7s
+5w
+6back
+9ks
+8rk
+9ks
+7ird
+9ds
+6cake
+9es
+6ed
+7r
+7st
+6fin
+9s
+6hammer
+9mers
+7ead
+9ds
+6ier
+8st
+7ng
+7sh
+9ness
+9nesses
+6legs
+7y
+6ness
+9ses
+6s
+6tail
+9ls
+7hroat
+9oats
+6ware
+9es
+7eed
+9ds
+7ood
+9ds
+8rt
+9ts
+6y
+4s
+3m
+4ed
+4ing
+4s
+3p
+4ed
+5r
+6s
+4ing
+7s
+4s
+3t
+4s
+2mmer
+6s
+2n
+3ned
+4ing
+3s
+3ta
+5s
+4e
+5s
+2oman
+6ly
+6ries
+7y
+4en
+2p
+3s
+2rba
+5s
+3d
+4ed
+4ing
+4s
+3k
+4ed
+4ing
+4s
+3sinia
+8e
+8s
+7oses
+9is
+2s
+3es
+3hiva
+7h
+8s
+7s
+6ot
+8h
+3k
+4ed
+4ing
+4s
+3sed
+5s
+4ing
+3t
+4er
+6day
+9s
+6eve
+9n
+9ning
+9nings
+9ns
+9s
+6morn
+9ning
+9nings
+9ns
+6n
+7ight
+9hts
+6year
+9rs
+4reen
+8s
+4s
+4y
+2t
+3i
+4s
+3t
+4ie
+6s
+4s
+2uk
+4ed
+4ier
+6st
+5ng
+4s
+4y
+2ve
+4n
+4s
+3ing
+2w
+3en
+3s
+2x
+3ed
+4s
+3ing
+1fere
+1glaunst
+2o
+3e
+1ibbles
+2cker
+6ed
+6ing
+6s
+2d
+3aki
+6s
+3s
+2eld
+5able
+9ness
+9nesses
+5ed
+6r
+7s
+5ing
+8ly
+8ness
+9esses
+8s
+5s
+2ke
+4d
+4s
+3ing
+3ker
+6ed
+6ing
+6s
+2ll
+4s
+2n
+3ce
+3die
+6s
+3s
+2p
+3e
+4s
+3ped
+5e
+5r
+6s
+4ie
+6s
+5ng
+4y
+3s
+2rd
+4ed
+4ing
+4s
+3k
+4ed
+4ing
+4s
+3r
+4ed
+4ing
+4s
+3th
+5s
+2te
+4s
+3ie
+5s
+3ten
+1lem
+4s
+2ike
+2ke
+4s
+1molt
+5en
+2pe
+4s
+3ing
+3t
+1nambu
+6s
+1o
+2b
+3beries
+6y
+4ish
+7ly
+6m
+7s
+4o
+5es
+5s
+3s
+2ck
+4ed
+4ing
+4s
+3tosecond
+9nds
+2d
+3e
+4l
+5ed
+6r
+7s
+5ing
+5led
+7r
+8s
+6ing
+5s
+3h
+4s
+3le
+5d
+5r
+6s
+5s
+4ing
+3s
+2ga
+4s
+3ee
+5s
+3h
+4ourt
+8s
+4s
+4urt
+7s
+3i
+4c
+4n
+5i
+6s
+5s
+4s
+5m
+6s
+3urt
+6s
+2himbe
+7s
+6ine
+9s
+2ick
+5ed
+5ing
+5s
+6ed
+7s
+6ing
+2jan
+5a
+6s
+5s
+2k
+3e
+4d
+4fellow
+9ws
+4l
+5ess
+5ish
+5s
+4mate
+8s
+4r
+5ed
+5ing
+5s
+4s
+3ing
+6s
+3ked
+4ing
+3ozuna
+8s
+3s
+3ul
+2ld
+4ring
+8s
+3k
+4ed
+4ier
+6st
+4less
+4s
+4y
+2m
+3im
+3p
+4ed
+4ing
+4s
+2n
+3d
+4er
+6ly
+6s
+3i
+4c
+4s
+3ker
+6s
+4s
+3nie
+6s
+3t
+2of
+4s
+3p
+4s
+2re
+4s
+3k
+4ed
+5r
+6s
+4ie
+6s
+5ng
+4s
+3ling
+7s
+3p
+4ed
+4ing
+4s
+2ttabyte
+9s
+2u
+3k
+4ed
+4ing
+4s
+3ng
+5berries
+9y
+5er
+7s
+6st
+5ish
+5ling
+9s
+6y
+5ness
+9es
+5s
+6ter
+9s
+5th
+7ly
+7s
+4ker
+7s
+3pon
+6s
+3r
+4n
+4s
+5elf
+7ves
+4t
+5s
+3s
+4e
+3th
+5en
+7ed
+7ing
+7s
+5ful
+8ly
+8ness
+9esses
+5head
+9s
+6ood
+9s
+5ier
+7st
+5less
+6y
+5quake
+9es
+5s
+6ome
+5y
+2w
+3e
+4d
+4s
+3ie
+5s
+4ng
+3l
+4ed
+5r
+6s
+5y
+6s
+4ing
+7s
+4s
+3s
+2yo
+1perite
+7s
+2ight
+2last
+3ight
+2siliform
+5oid
+6n
+7s
+1rapt
+3vished
+2ent
+2ivd
+2neh
+5s
+1same
+2hend
+6ing
+6s
+5t
+2laked
+1thundered
+2ost
+2terbia
+8s
+7c
+7te
+9s
+7um
+9s
+6ous
+3ria
+6s
+5c
+5ferous
+5ous
+5um
+7s
+1u
+2an
+4s
+2ca
+4s
+3ca
+5s
+4h
+3h
+3k
+4ed
+5r
+6s
+4ier
+6st
+5ness
+9es
+6g
+4o
+4s
+4y
+2ft
+4s
+2g
+3a
+4rie
+7s
+4s
+3s
+2k
+3ata
+6s
+3e
+4d
+4s
+3ier
+5st
+4ng
+3ked
+4ier
+6st
+5ng
+4y
+3o
+4s
+3s
+3y
+2lan
+5s
+3e
+4s
+4tide
+8s
+2m
+3mier
+6s
+7t
+5ness
+9es
+4o
+4y
+3p
+4ed
+4ie
+6s
+5ng
+4s
+2nx
+4es
+2p
+3on
+5s
+3pie
+6dom
+9s
+6ish
+6s
+5fication
+9tions
+7ed
+8s
+6y
+7ing
+4y
+3s
+4ter
+7s
+2rt
+4a
+5s
+4s
+2s
+2tz
+4es
+2zu
+4s
+1wis
+2roke
+0za
+2baglione
+9es
+4ione
+8s
+4jone
+8s
+3eta
+6s
+3ra
+5s
+3tieh
+7s
+2caton
+7s
+3k
+4s
+2ddick
+5k
+6im
+6s
+2ffar
+6s
+4er
+6s
+4ir
+6s
+4re
+6s
+3tig
+2g
+3ged
+4ing
+3s
+2ibatsu
+3kai
+6s
+3re
+5s
+3tech
+7s
+2kat
+5s
+3ouska
+7i
+3uska
+6i
+2lambdodont
+9onts
+2man
+5g
+6s
+5s
+4rra
+7s
+6o
+7s
+3bo
+5mba
+8s
+5orak
+9s
+5s
+4uck
+7s
+5k
+6s
+3ia
+5s
+4ndar
+8i
+9es
+9s
+8s
+8y
+3ouse
+7s
+3pogna
+8s
+5ne
+6i
+3zawed
+2namivir
+9s
+4na
+6s
+3der
+6s
+3ella
+7s
+3ied
+5r
+5s
+6t
+4ly
+4ness
+8es
+3ja
+5s
+4ero
+7s
+3te
+5deschia
+9hias
+5s
+4hoxyl
+9s
+9um
+9ums
+3y
+4ing
+5sh
+6m
+7s
+3za
+5s
+4e
+5s
+2p
+3ata
+5eado
+9s
+6o
+7s
+3otilla
+9s
+3ped
+5r
+6s
+4ier
+6st
+5ng
+4y
+3s
+3tiah
+7s
+5eh
+7s
+2rape
+6s
+4tite
+8s
+3eba
+6s
+4eba
+7s
+3f
+4s
+3i
+4ba
+6s
+4s
+3nec
+6s
+4ich
+7s
+3zuela
+8s
+2s
+3truga
+7i
+2ti
+4s
+2x
+3es
+2yin
+5s
+2zen
+5s
+1ea
+3l
+4ant
+7s
+4ful
+4less
+4ot
+6ism
+9s
+6ries
+7y
+6s
+5us
+7ly
+7ness
+9sses
+4s
+3s
+3tin
+6s
+2bec
+5k
+6s
+5s
+3ra
+5fish
+9es
+5ic
+5no
+7s
+5s
+6s
+7es
+5wood
+9s
+4ina
+7s
+6e
+7s
+6nies
+7y
+4oid
+4ula
+7s
+6e
+7s
+3u
+4b
+5s
+4s
+2cchin
+7e
+8s
+7i
+7o
+8s
+7s
+3hin
+6s
+2d
+3oaries
+6y
+3s
+2e
+3s
+2in
+4s
+3tgeber
+9s
+6ist
+9s
+9y
+2k
+3s
+2l
+3ant
+6s
+4tor
+7s
+5rice
+9s
+7x
+8es
+3kova
+7s
+3ophobia
+9as
+9c
+9cs
+4so
+4typia
+9s
+3s
+2mindar
+8i
+9es
+9s
+8s
+8y
+3stva
+6o
+7s
+2naida
+7s
+4na
+6s
+3dik
+6s
+3ith
+6al
+6s
+2olite
+7s
+6ic
+7form
+2p
+3hyr
+6s
+3pelin
+8s
+4ole
+7s
+6i
+3s
+3tosecond
+9nds
+2rda
+5s
+3eba
+6s
+3iba
+6s
+3k
+4s
+3o
+4ed
+5s
+4ing
+4s
+4th
+3umbet
+8s
+2st
+4ed
+5r
+6s
+4ful
+7ly
+7ness
+9sses
+4ier
+6st
+5ly
+5ng
+4less
+4s
+4y
+2ta
+4s
+3etic
+7s
+3tabyte
+9s
+2uglodont
+9ts
+4ma
+6s
+6tic
+9ally
+3xite
+7s
+2x
+3es
+2ze
+4s
+1ho
+3mo
+5s
+3s
+1ibeline
+8s
+5line
+9s
+4t
+5h
+6s
+5s
+2dovudine
+9es
+2ff
+4ius
+7es
+4s
+2g
+3an
+5ka
+7s
+5s
+3ged
+4ing
+4urat
+8s
+3s
+3zag
+6ged
+9ness
+9nesses
+8r
+9ies
+9s
+9y
+7ing
+7y
+6s
+2kkurat
+8s
+3urat
+7s
+2la
+4s
+3ch
+5es
+3l
+4a
+5h
+6s
+5s
+4ion
+7aire
+9res
+7s
+7th
+9s
+4s
+2mb
+4i
+5s
+4s
+3occa
+7s
+2n
+3c
+4ate
+7s
+4ed
+4ic
+5er
+6st
+5ferous
+6ication
+9tions
+7ed
+8s
+6y
+7ing
+5ng
+5te
+7s
+4ked
+6nite
+9es
+5ier
+7st
+6fication
+9ations
+8ed
+9s
+7y
+8ing
+6ng
+5y
+4o
+5de
+7s
+5graph
+9her
+9hers
+9hic
+9hical
+9hies
+9hs
+9hy
+5id
+5lyses
+8is
+5s
+5us
+4s
+4y
+3dabad
+3e
+4b
+5s
+4s
+3fandel
+9s
+3g
+4ani
+6o
+5ra
+6e
+6i
+6o
+4ed
+5l
+6s
+5r
+6s
+4iber
+8aceous
+8s
+5er
+6st
+5ng
+4s
+4y
+3janthropi
+9opus
+9opuses
+3ke
+5d
+5nite
+9s
+5s
+4ier
+6st
+5ferous
+6ication
+9tions
+7ed
+8s
+6y
+7ing
+5ng
+4y
+3nia
+6s
+3s
+3ziberaceous
+2p
+3less
+4ock
+7ed
+7ing
+7s
+3ped
+5r
+6ed
+6ing
+6s
+4ier
+6st
+5ng
+4o
+5s
+4y
+3s
+3top
+2ram
+5s
+3calloy
+9s
+6oy
+8s
+4on
+6ia
+8s
+7c
+7um
+9s
+6s
+2t
+3e
+3her
+6ist
+9s
+6n
+7s
+6s
+3i
+4s
+3s
+2z
+3ania
+7s
+3el
+5s
+3it
+5h
+3yphus
+8es
+3z
+4ed
+5s
+4ing
+4le
+6d
+6s
+5ing
+1lote
+4ies
+4y
+5ch
+5s
+1o
+2a
+3ea
+5e
+5s
+3ntharian
+9ans
+6ropic
+9ies
+9y
+3ria
+6l
+5um
+2bo
+4s
+3u
+4s
+2calo
+6s
+3co
+5lo
+7s
+5s
+2diac
+6al
+6s
+2ea
+4e
+4l
+4s
+3chrome
+9s
+4ia
+5um
+3form
+3tic
+4rope
+8s
+7ic
+2ftig
+2iatria
+8s
+7cs
+3c
+3site
+7s
+4m
+5s
+4t
+5s
+2l
+3pidem
+8s
+3s
+2mbi
+5e
+6like
+6s
+5fication
+9tions
+7ed
+8s
+6y
+7ing
+5ism
+8s
+5s
+4oruk
+8s
+2na
+4e
+4l
+5ly
+4ry
+4te
+6d
+5ion
+8s
+3da
+5s
+3e
+4d
+4less
+4r
+5s
+4s
+4time
+8s
+3ing
+6s
+3k
+4ed
+4ing
+4s
+3oid
+3ula
+6e
+6r
+6s
+5e
+6s
+6t
+7s
+4re
+6s
+2o
+3biotic
+4last
+8s
+3cephalic
+4hemical
+8stries
+9try
+5ore
+8s
+7ies
+7ous
+7y
+4ulture
+9es
+4ytia
+7um
+3dendria
+9um
+3ea
+5e
+5l
+5s
+4cia
+6um
+4y
+3gamete
+9s
+6ies
+6ous
+6y
+4enic
+7es
+6ous
+6y
+5ographer
+9phers
+9phic
+9phical
+9phies
+9phy
+4lea
+7e
+7l
+7s
+5oea
+8e
+8l
+8s
+7ic
+7oid
+4onidia
+9um
+7es
+6ous
+6y
+4raft
+8ing
+9ngs
+8s
+6pher
+9rs
+8ic
+9cal
+9es
+9st
+9sts
+8y
+3id
+5al
+5s
+4er
+5st
+3keeper
+9s
+4s
+3later
+8s
+6ria
+9s
+8es
+7ous
+7y
+4ite
+7s
+6h
+7ic
+7s
+6ic
+4ogic
+8al
+9lly
+7es
+7st
+9s
+6y
+3m
+4agnetic
+9ism
+9isms
+5ncies
+7y
+6ia
+8s
+6tic
+4ed
+5tric
+9al
+8es
+7y
+4ing
+4orph
+8ic
+9es
+9sm
+9sms
+8s
+8y
+4s
+3n
+4al
+4ed
+4ic
+5ng
+5te
+7s
+6ic
+4omia
+8s
+7c
+7es
+7st
+9s
+6y
+5ses
+6is
+5tic
+4s
+3pathies
+7ologies
+9ogy
+7y
+4eral
+6ies
+7st
+9s
+6y
+4hagan
+9s
+7ies
+7ous
+7y
+5ilism
+9ms
+9t
+9ts
+7ous
+7y
+5obe
+8s
+7ia
+9s
+7ous
+6ri
+8c
+7us
+5ysiologies
+9logist
+9logy
+6te
+8s
+7ic
+9al
+7oid
+8logical
+9ogies
+9ogist
+9ogists
+9ogy
+4lankter
+9ers
+9on
+9onic
+9ons
+6stic
+9es
+8y
+4sychologies
+9logy
+3s
+4copic
+8es
+7y
+4perm
+8atic
+8ia
+9um
+8s
+5orangia
+9gial
+9gium
+7e
+8s
+7ic
+7ous
+4terol
+9s
+3t
+4axies
+6y
+4echnical
+9cs
+9es
+8y
+4hapses
+8is
+5ecia
+9l
+8um
+6ism
+9s
+8tic
+6rapies
+9y
+5ome
+8s
+4ier
+6st
+4omic
+8al
+9lly
+7es
+7st
+9s
+6y
+5xic
+7n
+8s
+4rope
+8s
+7hic
+9es
+8y
+4suiter
+9rs
+4y
+5pe
+7s
+6ic
+3xanthella
+9llae
+3zoo
+6s
+2pilote
+8s
+3pa
+4o
+2rbing
+7s
+4onaut
+9s
+3gite
+7s
+3i
+4l
+5la
+7s
+6e
+7s
+6o
+7s
+5s
+4no
+6s
+4s
+3ro
+5s
+2s
+3ter
+6s
+2uave
+6s
+3k
+4s
+3nds
+2wie
+2ysia
+6s
+1ucchetti
+8o
+9s
+5ini
+8s
+3hetta
+8s
+7o
+8s
+2ffoli
+6o
+3oli
+5o
+2gzwang
+8ed
+8ing
+8s
+2lu
+4s
+2mbooruk
+9s
+2pa
+4n
+5s
+4s
+2rf
+4s
+2z
+3im
+3zim
+1wanziger
+9s
+2ieback
+8s
+3schenzug
+9ugs
+3tterion
+9nic
+9ns
+1ydeco
+6s
+2ga
+4enid
+6oid
+4l
+4ntra
+7um
+9s
+4pophyseal
+9ses
+9sial
+9sis
+3obranch
+9hiate
+9hiates
+9hs
+4cacti
+8us
+9ses
+6rdiac
+4dactyl
+9lic
+9lism
+9lisms
+9lous
+9ls
+5ont
+4id
+4ma
+6s
+6ta
+7ic
+9s
+5orphic
+9ies
+9ism
+9isms
+9ous
+9y
+5ycete
+9es
+9ous
+4n
+4phyllaceous
+7te
+9s
+5leural
+4se
+6s
+5is
+6ties
+7y
+5perm
+9s
+6hene
+9es
+6ore
+9s
+8ic
+4te
+6ne
+8s
+6s
+5ic
+7ally
+2lonite
+8s
+2mase
+6s
+3e
+4s
+3ic
+4te
+6s
+3ogen
+7e
+8s
+9es
+9is
+7ic
+7s
+5ram
+8s
+4id
+4logic
+9al
+8es
+8st
+9ts
+7y
+5yses
+7is
+6tic
+4me
+6s
+6ter
+9s
+4san
+7s
+5es
+5imeter
+9ers
+6s
+4technic
+9ical
+9ics
+5ic
+7ally
+7s
+3urgies
+6y
+2thum
+6s
+2zzyva
+7s
+1zz
+3s
\ No newline at end of file
diff --git a/core/src/graph/anims.rs b/core/src/graph/anims.rs
new file mode 100644
index 00000000..5bb75071
--- /dev/null
+++ b/core/src/graph/anims.rs
@@ -0,0 +1,406 @@
+//! Animations: keyframes for blocks, as CSS has them. An animation is an entry of the save
+//! (mime `application/x-anend-animation`, its text the animation's JSON), so one animation
+//! is shared by every block that plays it and travels like any entry; a block refers to
+//! it from its placement ([`AnimRef`], with a delay and a speed of its own).
+//!
+//! An animation lasts `duration` seconds and plays once, in a loop, or back and forth
+//! (`repeat`). Its keys are moments (`at`, 0 to 1 of the duration) with any of: a move (units,
+//! added to the block's place), a turn (degrees about x, y and z, after the block's own),
+//! a scale (times the block's sides) and a texture (from that moment on). Between two keys
+//! each value eases along a timing curve, a CSS cubic-bezier (the key's own, or the
+//! animation's); a value a key leaves out is carried between the keys that set it, and
+//! is at rest (no move, no turn, scale 1) where none does. [`sample`] is the reference
+//! the space follows (`space.js` `animPose`).
+
+use serde::{Deserialize, Serialize};
+
+/// how an animation repeats
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "lowercase")]
+pub enum Repeat {
+    /// plays once and stays at its end
+    #[default]
+    Once,
+    /// starts again from the beginning
+    Loop,
+    /// plays forward, then back
+    Alternate,
+}
+
+fn ease() -> [f32; 4] {
+    [0.25, 0.1, 0.25, 1.0]
+}
+fn two() -> f32 {
+    2.0
+}
+
+/// one moment of an animation
+#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
+pub struct Key {
+    /// when, 0 (the start) to 1 (the end)
+    pub at: f32,
+    #[serde(default, rename = "move", skip_serializing_if = "Option::is_none")]
+    pub moved: Option<[f32; 3]>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub turn: Option<[f32; 3]>,
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub scale: Option<[f32; 3]>,
+    /// a texture key (`plain:#rrggbb`, `texture:`, ...) shown from this moment on
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub texture: Option,
+    /// the timing from this key to the next, when not the animation's
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub timing: Option<[f32; 4]>,
+}
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct Animation {
+    #[serde(default)]
+    pub name: String,
+    /// seconds
+    #[serde(default = "two")]
+    pub duration: f32,
+    #[serde(default)]
+    pub repeat: Repeat,
+    /// the timing between keys: a cubic-bezier's two control points (x1, y1, x2, y2)
+    #[serde(default = "ease")]
+    pub timing: [f32; 4],
+    #[serde(default)]
+    pub keys: Vec,
+}
+
+impl Default for Animation {
+    fn default() -> Animation {
+        Animation {
+            name: String::new(),
+            duration: 2.0,
+            repeat: Repeat::Once,
+            timing: ease(),
+            keys: Vec::new(),
+        }
+    }
+}
+
+/// keys an animation has at most
+pub const MAX_KEYS: usize = 64;
+
+fn curve(t: [f32; 4]) -> Result<[f32; 4], String> {
+    if t.iter().any(|v| !v.is_finite()) {
+        return Err("a timing's values are numbers".into());
+    }
+    // x stays in 0..1 so the curve is a function of time; y may overshoot
+    Ok([
+        t[0].clamp(0.0, 1.0),
+        t[1].clamp(-2.0, 3.0),
+        t[2].clamp(0.0, 1.0),
+        t[3].clamp(-2.0, 3.0),
+    ])
+}
+
+fn finite3(v: Option<[f32; 3]>, lo: f32, hi: f32, what: &str) -> Result, String> {
+    match v {
+        Some(a) if a.iter().any(|x| !x.is_finite()) => Err(format!("a {what}'s values are numbers")),
+        Some(a) => Ok(Some(a.map(|x| x.clamp(lo, hi)))),
+        None => Ok(None),
+    }
+}
+
+impl Animation {
+    /// within bounds, its keys in time order (one key a moment: a later one at the same
+    /// moment wins)
+    pub fn checked(mut self) -> Result {
+        if !self.duration.is_finite() {
+            return Err("a duration is a number".into());
+        }
+        self.name = self.name.trim().chars().take(200).collect();
+        self.duration = self.duration.clamp(0.05, 3600.0);
+        self.timing = curve(self.timing)?;
+        if self.keys.len() > MAX_KEYS {
+            return Err(format!("an animation has at most {MAX_KEYS} keys"));
+        }
+        let mut keys: Vec = Vec::with_capacity(self.keys.len());
+        for k in self.keys {
+            if !k.at.is_finite() {
+                return Err("a key's moment is a number".into());
+            }
+            let k = Key {
+                at: (k.at.clamp(0.0, 1.0) * 10_000.0).round() / 10_000.0,
+                moved: finite3(k.moved, -1.0e5, 1.0e5, "move")?,
+                turn: finite3(k.turn, -3600.0, 3600.0, "turn")?,
+                scale: finite3(k.scale, 0.01, 100.0, "scale")?,
+                texture: k.texture.map(|t| t.trim().to_string()).filter(|t| !t.is_empty()),
+                timing: k.timing.map(curve).transpose()?,
+            };
+            match keys.iter_mut().find(|x| x.at == k.at) {
+                Some(x) => *x = k,
+                None => keys.push(k),
+            }
+        }
+        keys.sort_by(|a, b| a.at.total_cmp(&b.at));
+        self.keys = keys;
+        Ok(self)
+    }
+
+    /// where in the animation (0 to 1) the time `t` seconds after it started falls
+    pub fn phase(&self, t: f32) -> f32 {
+        let d = self.duration.max(0.05);
+        let t = t.max(0.0) / d;
+        match self.repeat {
+            Repeat::Once => t.min(1.0),
+            Repeat::Loop => t.fract(),
+            Repeat::Alternate => {
+                let f = t.rem_euclid(2.0);
+                if f <= 1.0 { f } else { 2.0 - f }
+            }
+        }
+    }
+}
+
+/// a cubic-bezier timing at x (time, 0 to 1): the curve's y there, as CSS computes it
+pub fn bezier(t: [f32; 4], x: f32) -> f32 {
+    let [x1, y1, x2, y2] = t;
+    let at = |a: f32, b: f32, s: f32| 3.0 * (1.0 - s) * (1.0 - s) * s * a + 3.0 * (1.0 - s) * s * s * b + s * s * s;
+    // the ends exactly
+    if x <= 0.0 {
+        return 0.0;
+    }
+    if x >= 1.0 {
+        return 1.0;
+    }
+    // the curve's parameter whose x is x: bisection, deterministic and good to 1e-6
+    let (mut lo, mut hi) = (0.0f32, 1.0f32);
+    for _ in 0..40 {
+        let mid = (lo + hi) / 2.0;
+        if at(x1, x2, mid) < x {
+            lo = mid;
+        } else {
+            hi = mid;
+        }
+    }
+    at(y1, y2, (lo + hi) / 2.0)
+}
+
+/// a block's pose at phase `p`: its move, turn (degrees), scale and texture (None: its own)
+#[derive(Clone, Debug, PartialEq)]
+pub struct Pose {
+    pub moved: [f32; 3],
+    pub turn: [f32; 3],
+    pub scale: [f32; 3],
+    pub texture: Option,
+}
+
+/// the pose at phase `p` (0 to 1)
+pub fn sample(a: &Animation, p: f32) -> Pose {
+    let field = |get: &dyn Fn(&Key) -> Option<[f32; 3]>, rest: [f32; 3]| -> [f32; 3] {
+        let set: Vec<(&Key, [f32; 3])> = a.keys.iter().filter_map(|k| get(k).map(|v| (k, v))).collect();
+        if set.is_empty() {
+            return rest;
+        }
+        // before the first key that sets it: from rest at 0 (or its value, when at 0)
+        let first = set[0];
+        if p <= first.0.at {
+            if first.0.at <= 0.0 {
+                return first.1;
+            }
+            let u = bezier(a.timing, p / first.0.at);
+            return [0, 1, 2].map(|i| rest[i] + (first.1[i] - rest[i]) * u);
+        }
+        for w in set.windows(2) {
+            let (k0, v0) = w[0];
+            let (k1, v1) = w[1];
+            if p <= k1.at {
+                let span = (k1.at - k0.at).max(1e-6);
+                let u = bezier(k0.timing.unwrap_or(a.timing), (p - k0.at) / span);
+                return [0, 1, 2].map(|i| v0[i] + (v1[i] - v0[i]) * u);
+            }
+        }
+        set[set.len() - 1].1
+    };
+    let texture = a
+        .keys
+        .iter()
+        .rfind(|k| k.at <= p && k.texture.is_some())
+        .and_then(|k| k.texture.clone());
+    Pose {
+        moved: field(&|k| k.moved, [0.0; 3]),
+        turn: field(&|k| k.turn, [0.0; 3]),
+        scale: field(&|k| k.scale, [1.0; 3]),
+        texture,
+    }
+}
+
+/// a block's animation: the entry, how long after the room opens it starts, how fast
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct AnimRef {
+    pub entry: u64,
+    pub delay: f32,
+    pub speed: f32,
+}
+
+impl AnimRef {
+    pub fn checked(self) -> AnimRef {
+        let f = |v: f32, lo: f32, hi: f32, d: f32| if v.is_finite() { v.clamp(lo, hi) } else { d };
+        AnimRef {
+            entry: self.entry,
+            delay: f(self.delay, 0.0, 3600.0, 0.0),
+            speed: f(self.speed, 0.01, 100.0, 1.0),
+        }
+    }
+
+    /// `A`, version 1, the entry (u64), the delay and the speed (f32s), little endian
+    pub fn write(&self, out: &mut Vec) {
+        out.extend_from_slice(&[b'A', 1]);
+        out.extend_from_slice(&self.entry.to_le_bytes());
+        out.extend_from_slice(&self.delay.to_le_bytes());
+        out.extend_from_slice(&self.speed.to_le_bytes());
+    }
+
+    pub fn read(b: &[u8]) -> Option<(AnimRef, usize)> {
+        if b.len() < 18 || b[0] != b'A' || b[1] != 1 {
+            return None;
+        }
+        let f = |i: usize| f32::from_le_bytes(b[i..i + 4].try_into().unwrap_or([0; 4]));
+        Some((
+            AnimRef {
+                entry: u64::from_le_bytes(b[2..10].try_into().ok()?),
+                delay: f(10),
+                speed: f(14),
+            },
+            18,
+        ))
+    }
+}
+
+impl Serialize for AnimRef {
+    fn serialize(&self, s: S) -> Result {
+        use serde::ser::SerializeMap;
+        let mut m = s.serialize_map(Some(3))?;
+        m.serialize_entry("key", &super::record::label(self.entry))?;
+        m.serialize_entry("delay", &self.delay)?;
+        m.serialize_entry("speed", &self.speed)?;
+        m.end()
+    }
+}
+
+impl<'de> Deserialize<'de> for AnimRef {
+    fn deserialize>(d: D) -> Result {
+        #[derive(Deserialize)]
+        struct Raw {
+            key: String,
+            #[serde(default)]
+            delay: f32,
+            #[serde(default = "one")]
+            speed: f32,
+        }
+        fn one() -> f32 {
+            1.0
+        }
+        let r = Raw::deserialize(d)?;
+        let entry = super::record::parse_label(&r.key)
+            .ok_or_else(|| serde::de::Error::custom(format!("{:?} isn't an animation's key", r.key)))?;
+        Ok(AnimRef {
+            entry,
+            delay: r.delay,
+            speed: r.speed,
+        }
+        .checked())
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    fn bob() -> Animation {
+        Animation {
+            name: " bob ".into(),
+            duration: 4.0,
+            repeat: Repeat::Alternate,
+            timing: [0.0, 0.0, 1.0, 1.0],
+            keys: vec![
+                Key {
+                    at: 1.0,
+                    moved: Some([0.0, 2.0, 0.0]),
+                    texture: Some("plain:#ff0000".into()),
+                    ..Key::default()
+                },
+                Key {
+                    at: 0.0,
+                    moved: Some([0.0, 0.0, 0.0]),
+                    ..Key::default()
+                },
+                Key {
+                    at: 0.5,
+                    turn: Some([0.0, 90.0, 0.0]),
+                    ..Key::default()
+                },
+            ],
+        }
+        .checked()
+        .unwrap()
+    }
+
+    #[test]
+    fn keys_ease_between_moments() {
+        let a = bob();
+        assert_eq!(a.name, "bob");
+        assert_eq!(a.keys.iter().map(|k| k.at).collect::>(), vec![0.0, 0.5, 1.0]);
+        // a linear timing: halfway up at half time
+        let p = sample(&a, 0.5);
+        assert!((p.moved[1] - 1.0).abs() < 1e-4, "{p:?}");
+        // the turn rises from rest to 90 by the middle, then holds
+        assert!((sample(&a, 0.25).turn[1] - 45.0).abs() < 1e-3);
+        assert_eq!(sample(&a, 0.9).turn[1], 90.0);
+        assert_eq!(sample(&a, 0.3).scale, [1.0; 3]);
+        // the texture from its key on
+        assert_eq!(sample(&a, 0.99).texture, None);
+        assert_eq!(sample(&a, 1.0).texture.as_deref(), Some("plain:#ff0000"));
+        // back and forth
+        assert_eq!(a.phase(2.0), 0.5);
+        assert_eq!(a.phase(6.0), 0.5);
+        assert_eq!(a.phase(5.0), 0.75);
+        let once = Animation {
+            repeat: Repeat::Once,
+            ..a.clone()
+        };
+        assert_eq!(once.phase(9.0), 1.0);
+        let l = Animation {
+            repeat: Repeat::Loop,
+            ..a
+        };
+        assert_eq!(l.phase(5.0), 0.25);
+    }
+
+    #[test]
+    fn css_timing() {
+        // ease: slow start, fast middle; linear is the line
+        assert!(bezier([0.25, 0.1, 0.25, 1.0], 0.1) < 0.1 + 0.1);
+        assert!((bezier([0.0, 0.0, 1.0, 1.0], 0.3) - 0.3).abs() < 1e-4);
+        assert!((bezier([0.42, 0.0, 0.58, 1.0], 0.5) - 0.5).abs() < 1e-4);
+        assert_eq!(bezier([0.25, 0.1, 0.25, 1.0], 0.0), 0.0);
+        assert_eq!(bezier([0.25, 0.1, 0.25, 1.0], 1.0), 1.0);
+    }
+
+    #[test]
+    fn refs_are_packed() {
+        let r = AnimRef {
+            entry: 77,
+            delay: 1.5,
+            speed: 2.0,
+        };
+        let mut b = Vec::new();
+        r.write(&mut b);
+        assert_eq!(AnimRef::read(&b), Some((r, 18)));
+        let j = serde_json::to_value(r).unwrap();
+        let back: AnimRef = serde_json::from_value(j).unwrap();
+        assert_eq!(back, r);
+        assert!(
+            Animation {
+                duration: f32::NAN,
+                ..Animation::default()
+            }
+            .checked()
+            .is_err()
+        );
+    }
+}
diff --git a/core/src/graph/assets.rs b/core/src/graph/assets.rs
new file mode 100644
index 00000000..505c0af4
--- /dev/null
+++ b/core/src/graph/assets.rs
@@ -0,0 +1,256 @@
+//! What a save holds besides its entries: its spec models' definitions and its pictures,
+//! each in tables of the save's own database, so they travel with the file (copies,
+//! renames, the hub's share and take) and in its backups and bundles.
+//!
+//! | table | key | holds |
+//! |---|---|---|
+//! | `graph spec models` | model name | the record as JSON (`crate::specs::Record`: the spec's JSON as written, created, modified, version, trainings) |
+//! | `graph pictures` | picture id (content hash, 32 hex digits) | its details as JSON ([`Picture`]) |
+//! | `graph picture bytes` | picture id | the file's bytes (PNG or JPEG, as added) |
+//! | `graph picture lists` | list name → picture ids | which lists a picture is in |
+//!
+//! A picture's list is named, like a list of texts (the text of its head): the pictures
+//! of list "cats" sit beside the texts of the list whose head is "cats". The trained
+//! weights of spec models are large and stay in the save's models file (`crate::specs`).
+
+use redb::{MultimapTableDefinition, ReadableDatabase, ReadableMultimapTable, ReadableTable, TableDefinition};
+use serde::{Deserialize, Serialize};
+
+use super::store::{GResult, Graph, err};
+
+pub const SPECS: TableDefinition<&str, &[u8]> = TableDefinition::new("graph spec models");
+pub const PICTURES: TableDefinition<&str, &[u8]> = TableDefinition::new("graph pictures");
+pub const PICTURE_BYTES: TableDefinition<&str, &[u8]> = TableDefinition::new("graph picture bytes");
+pub const PICTURE_LISTS: MultimapTableDefinition<&str, &str> = MultimapTableDefinition::new("graph picture lists");
+
+pub fn ensure_tables(txn: &redb::WriteTransaction) -> GResult<()> {
+    txn.open_table(SPECS).map_err(err)?;
+    txn.open_table(PICTURES).map_err(err)?;
+    txn.open_table(PICTURE_BYTES).map_err(err)?;
+    txn.open_multimap_table(PICTURE_LISTS).map_err(err)?;
+    Ok(())
+}
+
+/// a picture's details (its bytes are kept apart)
+#[derive(Clone, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
+pub struct Picture {
+    /// the content hash of its bytes ([`picture_id`])
+    pub id: String,
+    /// `image/png` or `image/jpeg`
+    pub mime: String,
+    pub width: u32,
+    pub height: u32,
+    /// what it was called when added (a file name), or what it was named since
+    #[serde(default)]
+    pub name: String,
+    /// when it was added, milliseconds since the Unix epoch
+    pub added: u64,
+    /// its bytes' length
+    pub size: u64,
+}
+
+/// a picture's id: FNV-1a over its bytes, 128 bits as 32 hex digits
+pub fn picture_id(bytes: &[u8]) -> String {
+    let mut h: u128 = 0x6c62_272e_07bb_0142_62b8_2175_6295_c58d;
+    for b in bytes {
+        h ^= *b as u128;
+        h = h.wrapping_mul(0x0000_0000_0100_0000_0000_0000_0000_013b);
+    }
+    format!("{h:032x}")
+}
+
+impl Graph {
+    // ------------------------------------------------------------ spec models
+
+    /// every spec model record, by name (JSON)
+    pub fn spec_records(&self) -> GResult)>> {
+        let txn = self.db().begin_read().map_err(err)?;
+        let t = txn.open_table(SPECS).map_err(err)?;
+        let mut out = Vec::new();
+        for item in t.iter().map_err(err)? {
+            let (k, v) = item.map_err(err)?;
+            out.push((k.value().to_string(), v.value().to_vec()));
+        }
+        Ok(out)
+    }
+
+    pub fn spec_record(&self, name: &str) -> GResult>> {
+        let txn = self.db().begin_read().map_err(err)?;
+        let t = txn.open_table(SPECS).map_err(err)?;
+        Ok(t.get(name).map_err(err)?.map(|v| v.value().to_vec()))
+    }
+
+    /// writes a record under `name`, taking it from `old` when it's renamed
+    pub fn put_spec_record(&self, old: Option<&str>, name: &str, json: &[u8]) -> GResult<()> {
+        let txn = self.db().begin_write().map_err(err)?;
+        {
+            let mut t = txn.open_table(SPECS).map_err(err)?;
+            if let Some(o) = old.filter(|o| *o != name) {
+                t.remove(o).map_err(err)?;
+            }
+            t.insert(name, json).map_err(err)?;
+        }
+        txn.commit().map_err(err)
+    }
+
+    /// whether there was one
+    pub fn delete_spec_record(&self, name: &str) -> GResult {
+        let txn = self.db().begin_write().map_err(err)?;
+        let found = txn.open_table(SPECS).map_err(err)?.remove(name).map_err(err)?.is_some();
+        txn.commit().map_err(err)?;
+        Ok(found)
+    }
+
+    // ------------------------------------------------------------ pictures
+
+    /// every picture's details, oldest first
+    pub fn pictures(&self) -> GResult> {
+        let txn = self.db().begin_read().map_err(err)?;
+        let t = txn.open_table(PICTURES).map_err(err)?;
+        let mut out = Vec::new();
+        for item in t.iter().map_err(err)? {
+            let (_, v) = item.map_err(err)?;
+            out.push(serde_json::from_slice::(v.value()).map_err(err)?);
+        }
+        out.sort_by(|a, b| a.added.cmp(&b.added).then(a.id.cmp(&b.id)));
+        Ok(out)
+    }
+
+    pub fn picture_count(&self) -> GResult {
+        use redb::ReadableTableMetadata;
+        let txn = self.db().begin_read().map_err(err)?;
+        txn.open_table(PICTURES).map_err(err)?.len().map_err(err)
+    }
+
+    pub fn picture(&self, id: &str) -> GResult> {
+        let txn = self.db().begin_read().map_err(err)?;
+        let t = txn.open_table(PICTURES).map_err(err)?;
+        match t.get(id).map_err(err)? {
+            Some(v) => Ok(Some(serde_json::from_slice(v.value()).map_err(err)?)),
+            None => Ok(None),
+        }
+    }
+
+    pub fn picture_bytes(&self, id: &str) -> GResult>> {
+        let txn = self.db().begin_read().map_err(err)?;
+        let t = txn.open_table(PICTURE_BYTES).map_err(err)?;
+        Ok(t.get(id).map_err(err)?.map(|v| v.value().to_vec()))
+    }
+
+    /// stores a picture (its `id` must be its bytes' [`picture_id`]); false when it was
+    /// there already (its details are left as they were)
+    pub fn put_picture(&self, p: &Picture, bytes: &[u8]) -> GResult {
+        if p.id != picture_id(bytes) {
+            return Err("a picture's id is its bytes' hash".into());
+        }
+        let txn = self.db().begin_write().map_err(err)?;
+        let new = {
+            let mut t = txn.open_table(PICTURES).map_err(err)?;
+            if t.get(p.id.as_str()).map_err(err)?.is_some() {
+                false
+            } else {
+                t.insert(p.id.as_str(), serde_json::to_vec(p).map_err(err)?.as_slice())
+                    .map_err(err)?;
+                txn.open_table(PICTURE_BYTES)
+                    .map_err(err)?
+                    .insert(p.id.as_str(), bytes)
+                    .map_err(err)?;
+                true
+            }
+        };
+        txn.commit().map_err(err)?;
+        Ok(new)
+    }
+
+    /// renames a picture
+    pub fn name_picture(&self, id: &str, name: &str) -> GResult<()> {
+        let mut p = self.picture(id)?.ok_or_else(|| format!("no picture {id:?}"))?;
+        p.name = name.to_string();
+        let txn = self.db().begin_write().map_err(err)?;
+        txn.open_table(PICTURES)
+            .map_err(err)?
+            .insert(id, serde_json::to_vec(&p).map_err(err)?.as_slice())
+            .map_err(err)?;
+        txn.commit().map_err(err)
+    }
+
+    /// takes a picture out of the save and its lists; whether it was there
+    pub fn delete_picture(&self, id: &str) -> GResult {
+        let lists = self.lists_of_picture(id)?;
+        let txn = self.db().begin_write().map_err(err)?;
+        let found = {
+            let found = txn
+                .open_table(PICTURES)
+                .map_err(err)?
+                .remove(id)
+                .map_err(err)?
+                .is_some();
+            txn.open_table(PICTURE_BYTES).map_err(err)?.remove(id).map_err(err)?;
+            let mut l = txn.open_multimap_table(PICTURE_LISTS).map_err(err)?;
+            for name in &lists {
+                l.remove(name.as_str(), id).map_err(err)?;
+            }
+            found
+        };
+        txn.commit().map_err(err)?;
+        Ok(found)
+    }
+
+    /// every (list, picture id) row
+    pub fn picture_list_rows(&self) -> GResult> {
+        let txn = self.db().begin_read().map_err(err)?;
+        let t = txn.open_multimap_table(PICTURE_LISTS).map_err(err)?;
+        let mut out = Vec::new();
+        for item in t.iter().map_err(err)? {
+            let (k, vs) = item.map_err(err)?;
+            for v in vs {
+                out.push((k.value().to_string(), v.map_err(err)?.value().to_string()));
+            }
+        }
+        Ok(out)
+    }
+
+    /// the ids of a list's pictures
+    pub fn list_pictures(&self, list: &str) -> GResult> {
+        let txn = self.db().begin_read().map_err(err)?;
+        let t = txn.open_multimap_table(PICTURE_LISTS).map_err(err)?;
+        let mut out = Vec::new();
+        for v in t.get(list).map_err(err)? {
+            out.push(v.map_err(err)?.value().to_string());
+        }
+        Ok(out)
+    }
+
+    /// the lists a picture is in
+    pub fn lists_of_picture(&self, id: &str) -> GResult> {
+        Ok(self
+            .picture_list_rows()?
+            .into_iter()
+            .filter(|(_, p)| p == id)
+            .map(|(l, _)| l)
+            .collect())
+    }
+
+    /// puts a picture into a list (or, with `on` false, takes it out); whether that
+    /// changed anything
+    pub fn tag_picture(&self, id: &str, list: &str, on: bool) -> GResult {
+        let list = list.trim();
+        if list.is_empty() {
+            return Err("which list? (its name)".into());
+        }
+        if on && self.picture(id)?.is_none() {
+            return Err(format!("no picture {id:?}"));
+        }
+        let txn = self.db().begin_write().map_err(err)?;
+        let changed = {
+            let mut t = txn.open_multimap_table(PICTURE_LISTS).map_err(err)?;
+            if on {
+                !t.insert(list, id).map_err(err)?
+            } else {
+                t.remove(list, id).map_err(err)?
+            }
+        };
+        txn.commit().map_err(err)?;
+        Ok(changed)
+    }
+}
diff --git a/core/src/graph/backup.rs b/core/src/graph/backup.rs
new file mode 100644
index 00000000..a298b324
--- /dev/null
+++ b/core/src/graph/backup.rs
@@ -0,0 +1,464 @@
+//! weum's `all-of-it.json` import, and the two-file backup (like weum's `memory.backup`):
+//! all the texts in one JSON, everything else in another.
+//!
+//! **Texts** (`texts.json`): `[[text, [key bytes], created, edited, mime?], ...]`, one row
+//! per entry in id order; `text` is the rendered text, the key is weum's (see
+//! `record::key_of`), the times are milliseconds since the Unix epoch, and `mime` is left
+//! out for `text/plain`. The first two elements are weum's own `[text, key]` rows, so
+//! weum's backup imports through the same reader (with import time for both times).
+//!
+//! **The rest** (`other.json`), an object:
+//! - `format`: `"anend-graph"`, `version`: 1;
+//! - `allocated`: the last allocated key (or null), `free`: the forgotten keys in reuse order;
+//! - `mimes`: `{name: id}` for registered mime types;
+//! - `sources`: `[[key, run], ...]` for entries that aren't plain text (templates,
+//!   functions, transclusions), as a run: a JSON array of strings (text), `{"ref": key}`,
+//!   `{"call": builtin name, "args": [run, ...]}` and `{"fn": key, "args": [run, ...]}`;
+//! - `edges`: `[[from key, relation, to key, payload hex], ...]` (relation by name for the
+//!   known ones, else its number);
+//! - `history`: `[[key, at, mime, text], ...]`, past versions, newest first per entry;
+//! - `settings`: `{name: text}`, or `{name: {"hex": ...}}` for one that isn't UTF-8;
+//! - `specs`: the spec models' records (`crate::specs::Record` as JSON: name, the spec's
+//!   source, created, modified, version, history), without their trained weights;
+//! - `pictures`: `[{id, mime, width, height, name, added, size, data}, ...]`, `data` the
+//!   file's bytes in base64; `picture_lists`: `[[list name, picture id], ...]`.
+//! - `textures`: the texture recipes (`graph::textures::Saved`: id, name, recipe, added).
+//! - `lights`: the room's lights (`graph::lights::Light`), restored with their ids.
+//! - `blocks`: `[{id, kind, texture, x, y, z, w, h, d}, ...]` (`graph::blocks`), restored
+//!   with their ids.
+
+use serde_json::{Value, json};
+
+use super::codec::{Callee, Seg};
+use super::interp::builtin;
+use super::record::{self as rec, Past, mime};
+use super::store::{GResult, Graph, Reader, err, rel};
+
+fn key_json(id: u64) -> Value {
+    json!(rec::key_of(id))
+}
+
+fn key_from(v: &Value) -> Option {
+    match v {
+        Value::Array(a) => {
+            let bytes: Option> = a
+                .iter()
+                .map(|b| b.as_u64().and_then(|b| u8::try_from(b).ok()))
+                .collect();
+            rec::id_of(&bytes?)
+        }
+        Value::String(s) => rec::parse_label(s),
+        _ => None,
+    }
+}
+
+pub fn hex(b: &[u8]) -> String {
+    b.iter().map(|x| format!("{x:02x}")).collect()
+}
+
+pub fn unhex(s: &str) -> Option> {
+    if !s.len().is_multiple_of(2) || !s.is_ascii() {
+        return None;
+    }
+    (0..s.len())
+        .step_by(2)
+        .map(|i| u8::from_str_radix(&s[i..i + 2], 16).ok())
+        .collect()
+}
+
+pub fn run_json(run: &[Seg]) -> Value {
+    Value::Array(
+        run.iter()
+            .map(|s| match s {
+                Seg::Text(t) => json!(t),
+                Seg::Ref(id) => json!({ "ref": key_json(*id) }),
+                Seg::Call { f, args } => {
+                    let args: Vec = args.iter().map(|a| run_json(a)).collect();
+                    match f {
+                        Callee::Builtin(b) => json!({
+                            "call": builtin::NAMES.get(*b as usize).map(|n| n.to_string()).unwrap_or_else(|| b.to_string()),
+                            "args": args
+                        }),
+                        Callee::Entry(id) => json!({ "fn": key_json(*id), "args": args }),
+                    }
+                }
+            })
+            .collect(),
+    )
+}
+
+pub fn run_from(v: &Value) -> GResult> {
+    let Value::Array(items) = v else {
+        return Err("a run is an array".into());
+    };
+    let mut out = Vec::new();
+    for it in items {
+        match it {
+            Value::String(t) => out.push(Seg::Text(t.clone())),
+            Value::Object(o) => {
+                let args = || -> GResult>> {
+                    o.get("args")
+                        .and_then(Value::as_array)
+                        .map(|a| a.iter().map(run_from).collect())
+                        .unwrap_or(Ok(Vec::new()))
+                };
+                if let Some(k) = o.get("ref") {
+                    out.push(Seg::Ref(key_from(k).ok_or("a bad ref key")?));
+                } else if let Some(n) = o.get("call") {
+                    let n = n.as_str().ok_or("a builtin's name is text")?;
+                    let b = builtin::by_name(n)
+                        .or_else(|| n.parse().ok())
+                        .ok_or_else(|| format!("no builtin {n}"))?;
+                    out.push(Seg::call(Callee::Builtin(b), args()?));
+                } else if let Some(k) = o.get("fn") {
+                    out.push(Seg::call(Callee::Entry(key_from(k).ok_or("a bad fn key")?), args()?));
+                } else {
+                    return Err("a run part that isn't text, ref, call or fn".into());
+                }
+            }
+            _ => return Err("a run part that isn't text or an object".into()),
+        }
+    }
+    Ok(super::codec::normalize(out))
+}
+
+/// what an import did
+#[derive(Debug, Clone, Default, PartialEq, Eq)]
+pub struct Imported {
+    pub entries: usize,
+    /// rows that were replaced (their key was taken), keeping the old text as a version
+    pub replaced: usize,
+    /// rows skipped (not `[text, key, ...]`, or a bad key)
+    pub skipped: usize,
+    /// entries stored partly as refs to others
+    pub borrowing: usize,
+}
+
+impl Graph {
+    /// imports texts rows: weum's `all-of-it.json` (`[[text, [key bytes]], ...]`) or this
+    /// store's own `texts.json`. Keys become ids (`record::id_of`); rows without times
+    /// get the import time. One transaction; borrowing applies in key order, so a variant
+    /// borrows from shorter texts imported before it.
+    pub fn import_texts(&self, json: &str) -> GResult {
+        let rows: Value = serde_json::from_str(json).map_err(err)?;
+        let Value::Array(rows) = rows else {
+            return Err("expected an array of [text, key] rows".into());
+        };
+        let mut parsed = Vec::with_capacity(rows.len());
+        let mut out = Imported::default();
+        for row in &rows {
+            let Some(a) = row.as_array() else {
+                out.skipped += 1;
+                continue;
+            };
+            match (a.first().and_then(Value::as_str), a.get(1).and_then(key_from)) {
+                (Some(t), Some(id)) if id <= super::store::MAX_ID => parsed.push((
+                    id,
+                    t.to_string(),
+                    a.get(2).and_then(Value::as_u64),
+                    a.get(3).and_then(Value::as_u64),
+                    a.get(4).and_then(Value::as_str).map(str::to_string),
+                )),
+                _ => out.skipped += 1,
+            }
+        }
+        // shorter texts first within the order keys give, so variants find their sources
+        parsed.sort_by_key(|r| r.0);
+        self.write(|tx| {
+            for (id, text, created, edited, m) in parsed {
+                let now = tx.now;
+                let m = match m {
+                    Some(name) => tx.mime_id(&name)?,
+                    None => mime::TEXT,
+                };
+                let created = created.unwrap_or(now);
+                if tx.exists(id)? {
+                    out.replaced += 1;
+                }
+                tx.put_text_at(id, &text, m, created, edited.unwrap_or(created))?;
+                out.entries += 1;
+                if tx.record(id)?.is_some_and(|r| r.has_refs()) {
+                    out.borrowing += 1;
+                }
+            }
+            Ok(())
+        })?;
+        Ok(out)
+    }
+
+    /// the two backup files: the texts, and everything else
+    pub fn backup(&self) -> GResult<(String, String)> {
+        let v = self.view()?;
+        let all = v.all()?;
+        let ids: Vec = all.iter().map(|e| e.id).collect();
+        let texts = v.render_many(&ids);
+        let mut rows = Vec::with_capacity(all.len());
+        let mut sources = Vec::new();
+        for (e, t) in all.iter().zip(texts) {
+            let t = t.unwrap_or_default();
+            let mut row = vec![
+                json!(t),
+                key_json(e.id),
+                json!(e.record.created),
+                json!(e.record.edited),
+            ];
+            if e.record.mime != mime::TEXT {
+                row.push(json!(v.mime_name(e.record.mime)?));
+            }
+            rows.push(Value::Array(row));
+            if !e.record.plain() {
+                sources.push(json!([key_json(e.id), run_json(&v.source(e.id)?)]));
+            }
+        }
+        let edges: Vec = v
+            .all_edges()?
+            .into_iter()
+            .map(|(f, r, t, p)| json!([key_json(f), rel::name(r), key_json(t), hex(&p)]))
+            .collect();
+        let mut history = Vec::new();
+        for e in &all {
+            if v.history_rows(e.id)?.is_empty() {
+                continue;
+            }
+            for ver in v.versions(e.id)?.into_iter().skip(1) {
+                history.push(json!([key_json(e.id), ver.at, v.mime_name(ver.mime)?, ver.text]));
+            }
+        }
+        let mut settings = serde_json::Map::new();
+        for (k, b) in v.all_settings()? {
+            settings.insert(
+                k,
+                match String::from_utf8(b) {
+                    Ok(s) => json!(s),
+                    Err(e) => json!({ "hex": hex(e.as_bytes()) }),
+                },
+            );
+        }
+        let mimes: serde_json::Map = v.custom_mimes()?.into_iter().map(|(n, i)| (n, json!(i))).collect();
+        let other = json!({
+            "format": "anend-graph",
+            "version": 1,
+            "allocated": v.allocated()?.map(key_json),
+            "free": v.free_ids()?.into_iter().map(key_json).collect::>(),
+            "mimes": mimes,
+            "sources": sources,
+            "edges": edges,
+            "history": history,
+            "settings": settings,
+            "specs": self.spec_records()?.iter()
+                .filter_map(|(_, b)| serde_json::from_slice::(b).ok())
+                .collect::>(),
+            "pictures": self.pictures()?.into_iter().map(|p| {
+                let data = self.picture_bytes(&p.id).ok().flatten().unwrap_or_default();
+                let mut v = json!(p);
+                v["data"] = json!(crate::classifiers::base64(&data));
+                v
+            }).collect::>(),
+            "picture_lists": self.picture_list_rows()?,
+            "sounds": self.sounds()?.into_iter().map(|s| {
+                let data = self.sound_bytes(&s.id).ok().flatten().unwrap_or_default();
+                let mut v = json!(s);
+                v["data"] = json!(crate::classifiers::base64(&data));
+                v
+            }).collect::>(),
+            "textures": self.textures()?,
+            "lights": self.lights()?,
+            "scenes": self.scenes()?,
+            "instances": self.instance_rows()?,
+        });
+        Ok((
+            serde_json::to_string(&Value::Array(rows)).map_err(err)?,
+            serde_json::to_string(&other).map_err(err)?,
+        ))
+    }
+
+    /// restores a backup into this store (meant for an empty one; entries under the same
+    /// keys are replaced)
+    pub fn restore(&self, texts: &str, other: &str) -> GResult {
+        let o: Value = serde_json::from_str(other).map_err(err)?;
+        if o.get("format").and_then(Value::as_str) != Some("anend-graph") {
+            return Err("that isn't an anend graph backup".into());
+        }
+        // mimes first, so the texts' mime names map to the same ids
+        self.write(|tx| {
+            if let Some(m) = o.get("mimes").and_then(Value::as_object) {
+                let mut named: Vec<(&String, u64)> = m.iter().filter_map(|(k, v)| v.as_u64().map(|i| (k, i))).collect();
+                named.sort_by_key(|x| x.1);
+                for (name, _) in named {
+                    tx.mime_id(name)?;
+                }
+            }
+            Ok(())
+        })?;
+        let report = self.import_texts(texts)?;
+        self.write(|tx| {
+            for s in o.get("sources").and_then(Value::as_array).into_iter().flatten() {
+                let (Some(id), Some(run)) = (s.get(0).and_then(key_from), s.get(1)) else {
+                    continue;
+                };
+                let run = run_from(run)?;
+                if tx.exists(id)? {
+                    tx.set_run_quietly(id, &run)?;
+                }
+            }
+            for e in o.get("edges").and_then(Value::as_array).into_iter().flatten() {
+                let from = e.get(0).and_then(key_from);
+                let r = e.get(1).and_then(|r| match r {
+                    Value::String(s) => rel::parse(s),
+                    Value::Number(n) => n.as_u64().and_then(|n| u16::try_from(n).ok()),
+                    _ => None,
+                });
+                let to = e.get(2).and_then(key_from);
+                let p = e.get(3).and_then(Value::as_str).and_then(unhex).unwrap_or_default();
+                if let (Some(f), Some(r), Some(t)) = (from, r, to)
+                    && tx.exists(f)?
+                    && tx.exists(t)?
+                {
+                    tx.link(f, r, t, &p)?;
+                }
+            }
+            // past versions, newest first per entry: each is a delta against the one after
+            let mut newer: Option<(u64, String)> = None;
+            for h in o.get("history").and_then(Value::as_array).into_iter().flatten() {
+                let (Some(id), Some(at), Some(m), Some(text)) = (
+                    h.get(0).and_then(key_from),
+                    h.get(1).and_then(Value::as_u64),
+                    h.get(2).and_then(Value::as_str),
+                    h.get(3).and_then(Value::as_str),
+                ) else {
+                    continue;
+                };
+                if !tx.exists(id)? {
+                    continue;
+                }
+                let base = match &newer {
+                    Some((nid, t)) if *nid == id => t.clone(),
+                    _ => tx.render(id)?,
+                };
+                let m = tx.mime_id(m)?;
+                let (p, s) = rec::common_ends(text, &base);
+                let past = Past::Delta {
+                    mime: m,
+                    prefix: p as u64,
+                    suffix: s as u64,
+                    middle: super::codec::pack_text(&text[p..text.len() - s]),
+                };
+                tx.put_past(id, at, &past)?;
+                newer = Some((id, text.to_string()));
+            }
+            if let Some(a) = o.get("allocated").and_then(key_from) {
+                tx.set_allocated(a)?;
+            }
+            for f in o.get("free").and_then(Value::as_array).into_iter().flatten() {
+                if let Some(id) = key_from(f) {
+                    tx.put_free(id)?;
+                }
+            }
+            if let Some(s) = o.get("settings").and_then(Value::as_object) {
+                for (k, v) in s {
+                    let bytes = match v {
+                        Value::String(t) => t.as_bytes().to_vec(),
+                        other => other
+                            .get("hex")
+                            .and_then(Value::as_str)
+                            .and_then(unhex)
+                            .unwrap_or_default(),
+                    };
+                    tx.set_setting(k, &bytes)?;
+                }
+            }
+            Ok(())
+        })?;
+        self.restore_assets(&o)?;
+        Ok(report)
+    }
+
+    /// a backup's spec model records and pictures (rows that don't read are skipped)
+    pub fn restore_assets(&self, o: &Value) -> GResult<()> {
+        for r in o.get("specs").and_then(Value::as_array).into_iter().flatten() {
+            if let Some(name) = r.get("name").and_then(Value::as_str) {
+                self.put_spec_record(None, name, r.to_string().as_bytes())?;
+            }
+        }
+        for p in o.get("pictures").and_then(Value::as_array).into_iter().flatten() {
+            let Some(data) = p
+                .get("data")
+                .and_then(Value::as_str)
+                .and_then(crate::classifiers::unbase64)
+            else {
+                continue;
+            };
+            let Ok(mut pic) = serde_json::from_value::(p.clone()) else {
+                continue;
+            };
+            pic.id = super::assets::picture_id(&data);
+            pic.size = data.len() as u64;
+            self.put_picture(&pic, &data)?;
+        }
+        for s in o.get("sounds").and_then(Value::as_array).into_iter().flatten() {
+            let Some(data) = s
+                .get("data")
+                .and_then(Value::as_str)
+                .and_then(crate::classifiers::unbase64)
+            else {
+                continue;
+            };
+            let Ok(mut snd) = serde_json::from_value::(s.clone()) else {
+                continue;
+            };
+            snd.id = super::assets::picture_id(&data);
+            snd.size = data.len() as u64;
+            self.put_sound(&snd, &data)?;
+        }
+        for row in o.get("picture_lists").and_then(Value::as_array).into_iter().flatten() {
+            if let (Some(l), Some(id)) = (row.get(0).and_then(Value::as_str), row.get(1).and_then(Value::as_str))
+                && self.picture(id)?.is_some()
+            {
+                self.tag_picture(id, l, true)?;
+            }
+        }
+        for t in o.get("textures").and_then(Value::as_array).into_iter().flatten() {
+            if let Ok(t) = serde_json::from_value::(t.clone()) {
+                self.put_texture(&t.recipe, &t.name, t.added)?;
+            }
+        }
+        let lights: Vec = o
+            .get("lights")
+            .and_then(Value::as_array)
+            .into_iter()
+            .flatten()
+            .filter_map(|l| serde_json::from_value(l.clone()).ok())
+            .collect();
+        self.put_lights(&lights)?;
+        if let Some(scenes) = o.get("scenes").and_then(Value::as_array) {
+            let scenes: Vec = scenes
+                .iter()
+                .filter_map(|s| serde_json::from_value(s.clone()).ok())
+                .collect();
+            let rows: Vec = o
+                .get("instances")
+                .and_then(Value::as_array)
+                .cloned()
+                .unwrap_or_default();
+            self.put_instance_rows(&scenes, &rows)?;
+        }
+        // backups made before scenes: their blocks go into the room, numbered afresh
+        let blocks: Vec = o
+            .get("blocks")
+            .and_then(Value::as_array)
+            .into_iter()
+            .flatten()
+            .filter_map(|b| {
+                let mut b = b.clone();
+                if b.get("id").is_some_and(Value::is_number) {
+                    b["id"] = json!("");
+                }
+                serde_json::from_value(b).ok()
+            })
+            .collect();
+        self.put_blocks(&blocks)?;
+        // a backup made before scenes: its saved scenes (a setting then) become scenes
+        self.migrate_maps()?;
+        Ok(())
+    }
+}
diff --git a/core/src/graph/blocks.rs b/core/src/graph/blocks.rs
new file mode 100644
index 00000000..b25b9f6c
--- /dev/null
+++ b/core/src/graph/blocks.rs
@@ -0,0 +1,1277 @@
+//! Spatial saves: blocks placed in the space, each showing a texture (a text of the save,
+//! one of its pictures, or a plain colour) tiled over its faces.
+//!
+//! Blocks are placements of kind `Block` in the room's scene (`graph::scenes`): the
+//! texture is the definition (an entry, a picture by hash, a plain colour) and each
+//! block a placement under it, its position and its sides (w, h, d) as the scale. A
+//! block's id is its address, `:#` ([`block_id`]): the n-th block
+//! showing that texture. A thousand copies of one text cost about 15 bytes each (format.md).
+//! Saves made before scenes kept blocks in `graph blocks` and `graph block ids`;
+//! [`migrate`] moves them into the room when the save opens. A region query reads the
+//! room's placements once (no spatial index yet).
+//!
+//! A block's size is in the space's units; its texture tiles at one tile per unit
+//! ([`TILE`]), so making a block bigger shows more tiles instead of stretching one.
+
+use redb::{MultimapTableDefinition, MultimapTableHandle, ReadableMultimapTable, TableDefinition};
+use serde::{Deserialize, Serialize};
+
+use super::record;
+use super::scenes::{self, Def, Kind as SKind, Placed, Placement, Scale};
+use super::store::{GResult, Graph, err};
+
+/// the tables blocks were kept in before scenes (read once, by [`migrate`])
+pub const OLD_BLOCKS: MultimapTableDefinition<&str, &[u8]> = MultimapTableDefinition::new("graph blocks");
+pub const OLD_BLOCK_IDS: TableDefinition = TableDefinition::new("graph block ids");
+
+/// the side of one texture tile, in space units
+pub const TILE: f32 = 1.0;
+/// a side at least and at most
+pub const MIN_SIDE: f32 = 0.05;
+pub const MAX_SIDE: f32 = 10_000.0;
+/// how far from the origin a block may be
+pub const MAX_COORD: f32 = 1.0e6;
+
+/// what a block shows
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Serialize, Deserialize)]
+#[serde(rename_all = "lowercase")]
+pub enum Kind {
+    /// a text of the save, by its entry label
+    Text,
+    /// a picture of the save, by its content hash
+    Picture,
+    /// a plain colour, `#rrggbb`
+    Plain,
+    /// a texture recipe (`graph::textures`), by its id
+    Texture,
+}
+
+impl Kind {
+    pub fn name(self) -> &'static str {
+        match self {
+            Kind::Text => "text",
+            Kind::Picture => "picture",
+            Kind::Plain => "plain",
+            Kind::Texture => "texture",
+        }
+    }
+
+    pub fn parse(s: &str) -> Option {
+        match s.trim() {
+            "text" => Some(Kind::Text),
+            "picture" => Some(Kind::Picture),
+            "plain" => Some(Kind::Plain),
+            "texture" => Some(Kind::Texture),
+            _ => None,
+        }
+    }
+}
+
+/// the key a texture is kept under
+pub fn key(kind: Kind, texture: &str) -> String {
+    format!("{}:{}", kind.name(), texture)
+}
+
+/// a key's kind and texture
+pub fn split_key(k: &str) -> Option<(Kind, &str)> {
+    let (a, b) = k.split_once(':')?;
+    Some((Kind::parse(a)?, b))
+}
+
+/// where a block is, how big and how turned: its centre, its sides, its rotation (a unit
+/// quaternion x, y, z, w; the identity costs nothing in the save) and its bend
+#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
+pub struct Transform {
+    pub x: f32,
+    pub y: f32,
+    pub z: f32,
+    pub w: f32,
+    pub h: f32,
+    pub d: f32,
+    #[serde(default = "identity", skip_serializing_if = "is_identity")]
+    pub rot: [f32; 4],
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub bend: Option,
+    /// texture recipes on single faces, in place of the block's own texture there
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub faces: Option,
+    /// a box or a sphere (an ellipsoid with the sides as its diameters)
+    #[serde(default, skip_serializing_if = "Shape::is_box")]
+    pub shape: Shape,
+    /// a staging zone: texts inside it spread among themselves ([`Zone`])
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub zone: Option,
+    /// the animation it plays (`graph::anims`)
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub anim: Option,
+    /// what it does when something happens to it (`graph::wiring`)
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub wire: Option,
+    /// a sound it plays (`graph::sounds`)
+    #[serde(default, skip_serializing_if = "Option::is_none")]
+    pub sound: Option,
+}
+
+/// a block's shape, kept in its placement's flags (bits 3–6, `place::Kind`)
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "lowercase")]
+pub enum Shape {
+    #[default]
+    Box,
+    /// a sphere: one face (faces don't apply) and no bend; regions use its box
+    Sphere,
+}
+
+impl Shape {
+    pub fn is_box(&self) -> bool {
+        *self == Shape::Box
+    }
+
+    fn kind(self) -> super::place::Kind {
+        match self {
+            Shape::Box => super::place::Kind::Cube,
+            Shape::Sphere => super::place::Kind::Sphere,
+        }
+    }
+
+    fn of_flags(flags: Option) -> Shape {
+        match super::place::Kind::from_u8(((flags.unwrap_or(0) >> 3) & 15) as u8) {
+            Some(super::place::Kind::Sphere) => Shape::Sphere,
+            _ => Shape::Box,
+        }
+    }
+}
+
+/// the faces' names, in the order [`Faces`] keeps them (three.js's box order)
+pub const FACE_NAMES: [&str; 6] = ["right", "left", "top", "bottom", "front", "back"];
+
+/// a texture recipe's id (`graph::textures`) on any of a block's six faces: right, left,
+/// top, bottom, front, back ([`FACE_NAMES`]); written as six hex ids or nulls
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
+pub struct Faces(pub [Option<[u8; 16]>; 6]);
+
+fn hex16(t: &str) -> Option<[u8; 16]> {
+    let t = t.trim();
+    if t.len() != 32 {
+        return None;
+    }
+    let v: Option> = (0..16)
+        .map(|i| u8::from_str_radix(t.get(2 * i..2 * i + 2)?, 16).ok())
+        .collect();
+    v?.try_into().ok()
+}
+
+fn hex_of(h: &[u8; 16]) -> String {
+    h.iter().map(|b| format!("{b:02x}")).collect()
+}
+
+impl Faces {
+    pub fn is_empty(&self) -> bool {
+        self.0.iter().all(Option::is_none)
+    }
+
+    /// `F`, version 1, a byte with a bit per face that has a recipe, then their ids
+    fn write(&self, out: &mut Vec) {
+        let mask = (0..6).filter(|&i| self.0[i].is_some()).fold(0u8, |m, i| m | 1 << i);
+        out.extend_from_slice(&[b'F', 1, mask]);
+        for h in self.0.iter().flatten() {
+            out.extend_from_slice(h);
+        }
+    }
+
+    /// reads one from the start of `b`, with how many bytes it took
+    fn read(b: &[u8]) -> Option<(Faces, usize)> {
+        if b.len() < 3 || b[0] != b'F' || b[1] != 1 {
+            return None;
+        }
+        let mask = b[2];
+        let mut f = Faces::default();
+        let mut at = 3;
+        for i in 0..6 {
+            if mask & (1 << i) != 0 {
+                f.0[i] = Some(b.get(at..at + 16)?.try_into().ok()?);
+                at += 16;
+            }
+        }
+        Some((f, at))
+    }
+}
+
+impl Serialize for Faces {
+    fn serialize(&self, s: S) -> Result {
+        let v: Vec> = self.0.iter().map(|h| h.as_ref().map(hex_of)).collect();
+        v.serialize(s)
+    }
+}
+
+impl<'de> Deserialize<'de> for Faces {
+    fn deserialize>(d: D) -> Result {
+        let v: Vec> = Vec::deserialize(d)?;
+        let mut f = Faces::default();
+        for (i, h) in v.iter().take(6).enumerate() {
+            if let Some(h) = h.as_deref().filter(|h| !h.trim().is_empty()) {
+                f.0[i] = Some(hex16(h).ok_or_else(|| serde::de::Error::custom(format!("{h:?} isn't a texture's id")))?);
+            }
+        }
+        Ok(f)
+    }
+}
+
+/// a block placement's extra: its bend, its faces and its zone, each a record of its own
+fn extra_bytes(t: &Transform) -> Option> {
+    let mut out = Vec::new();
+    if let Some(b) = t.bend.filter(|b| !b.straight()) {
+        out.extend(b.to_bytes());
+    }
+    if let Some(f) = t.faces.filter(|f| !f.is_empty()) {
+        f.write(&mut out);
+    }
+    if let Some(z) = t.zone {
+        z.write(&mut out);
+    }
+    if let Some(a) = t.anim {
+        a.write(&mut out);
+    }
+    if let Some(w) = t.wire {
+        w.write(&mut out);
+    }
+    if let Some(s) = t.sound {
+        s.write(&mut out);
+    }
+    (!out.is_empty()).then_some(out)
+}
+
+/// the bend, faces and zone in a block placement's extra (what doesn't read is left out)
+fn read_extra(b: &[u8]) -> Extra {
+    let mut x = Extra::default();
+    let mut at = 0;
+    while at < b.len() {
+        match b[at] {
+            b'B' if b.len() >= at + 38 => {
+                x.bend = Bend::from_bytes(&b[at..at + 38]);
+                at += 38;
+            }
+            b'F' => match Faces::read(&b[at..]) {
+                Some((f, n)) => {
+                    x.faces = Some(f);
+                    at += n;
+                }
+                None => break,
+            },
+            b'Z' => match Zone::read(&b[at..]) {
+                Some((z, n)) => {
+                    x.zone = Some(z);
+                    at += n;
+                }
+                None => break,
+            },
+            b'A' => match super::anims::AnimRef::read(&b[at..]) {
+                Some((a, n)) => {
+                    x.anim = Some(a);
+                    at += n;
+                }
+                None => break,
+            },
+            b'S' => match super::sounds::Emitter::read(&b[at..]) {
+                Some((s, n)) => {
+                    x.sound = Some(s);
+                    at += n;
+                }
+                None => break,
+            },
+            b'W' => match super::wiring::WireRef::read(&b[at..]) {
+                Some((w, n)) => {
+                    x.wire = Some(w);
+                    at += n;
+                }
+                None => break,
+            },
+            _ => break,
+        }
+    }
+    x
+}
+
+/// what a block placement's extra holds
+#[derive(Default)]
+struct Extra {
+    bend: Option,
+    faces: Option,
+    zone: Option,
+    anim: Option,
+    wire: Option,
+    sound: Option,
+}
+
+/// a staging zone: a block whose texts spread among themselves inside it, under physics
+/// of its own (each setting left out follows the room's). Zones nest: a text belongs to
+/// the smallest zone it's in.
+#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
+#[serde(default)]
+pub struct Zone {
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub repel: Option,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub attract: Option,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub link: Option,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub gravity: Option,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub damping: Option,
+}
+
+impl Zone {
+    fn fields(&self) -> [Option; 5] {
+        [self.repel, self.attract, self.link, self.gravity, self.damping]
+    }
+
+    /// within the physics panel's bounds (a value that isn't a number is left out)
+    pub fn checked(self) -> Zone {
+        let c = |v: Option, lo: f32, hi: f32| v.filter(|x| x.is_finite()).map(|x| x.clamp(lo, hi));
+        Zone {
+            repel: c(self.repel, 0.0, 60.0),
+            attract: c(self.attract, 0.0, 5.0),
+            link: c(self.link, 0.5, 30.0),
+            gravity: c(self.gravity, 0.0, 2.0),
+            damping: c(self.damping, 0.1, 10.0),
+        }
+    }
+
+    /// `Z`, version 1, a byte with a bit per setting given, then those as f32s
+    fn write(&self, out: &mut Vec) {
+        let f = self.fields();
+        let mask = (0..5).filter(|&i| f[i].is_some()).fold(0u8, |m, i| m | 1 << i);
+        out.extend_from_slice(&[b'Z', 1, mask]);
+        for v in f.iter().flatten() {
+            out.extend_from_slice(&v.to_le_bytes());
+        }
+    }
+
+    fn read(b: &[u8]) -> Option<(Zone, usize)> {
+        if b.len() < 3 || b[0] != b'Z' || b[1] != 1 {
+            return None;
+        }
+        let mask = b[2];
+        let mut f = [None; 5];
+        let mut at = 3;
+        for (i, slot) in f.iter_mut().enumerate() {
+            if mask & (1 << i) != 0 {
+                *slot = Some(f32::from_le_bytes(b.get(at..at + 4)?.try_into().ok()?));
+                at += 4;
+            }
+        }
+        Some((
+            Zone {
+                repel: f[0],
+                attract: f[1],
+                link: f[2],
+                gravity: f[3],
+                damping: f[4],
+            },
+            at,
+        ))
+    }
+}
+
+fn identity() -> [f32; 4] {
+    super::place::IDENTITY
+}
+
+fn is_identity(q: &[f32; 4]) -> bool {
+    *q == super::place::IDENTITY
+}
+
+impl Default for Transform {
+    fn default() -> Self {
+        Transform {
+            x: 0.0,
+            y: 0.0,
+            z: 0.0,
+            w: 1.0,
+            h: 1.0,
+            d: 1.0,
+            rot: super::place::IDENTITY,
+            bend: None,
+            faces: None,
+            shape: Shape::Box,
+            zone: None,
+            anim: None,
+            wire: None,
+            sound: None,
+        }
+    }
+}
+
+/// how a block bends, in its own frame (x across its width, z through its depth): two
+/// shapes added together, each moving the block's slices along z by an amount that
+/// depends on where across the width they are. Both profiles are cubic bezier curves in
+/// one dimension, with their ends fixed and two control values (c1, c2) shaping them.
+#[derive(Clone, Copy, Debug, Default, PartialEq, Serialize, Deserialize)]
+#[serde(default)]
+pub struct Bend {
+    pub ripple: Ripple,
+    pub fold: Fold,
+}
+
+/// a curtain ripple: a wave across the width, `freq` periods of it, shifted by `phase`
+/// (a fraction of a period); one period's profile is the bezier from 0 through c1, c2
+/// back to 0, scaled so its peak is `amount` units
+#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(default)]
+pub struct Ripple {
+    pub amount: f32,
+    pub freq: f32,
+    pub phase: f32,
+    pub c1: f32,
+    pub c2: f32,
+}
+
+/// a fold across the middle: about the vertical line at `at` (-1 the left edge, 1 the
+/// right), each side bent back by the bezier from 0 at the line through c1, c2 to 1 at the
+/// far edge, times `amount` units
+#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(default)]
+pub struct Fold {
+    pub amount: f32,
+    pub at: f32,
+    pub c1: f32,
+    pub c2: f32,
+}
+
+impl Default for Ripple {
+    fn default() -> Self {
+        Ripple {
+            amount: 0.0,
+            freq: 2.0,
+            phase: 0.0,
+            c1: 1.0,
+            c2: -1.0,
+        }
+    }
+}
+
+impl Default for Fold {
+    fn default() -> Self {
+        Fold {
+            amount: 0.0,
+            at: 0.0,
+            c1: 0.0,
+            c2: 1.0,
+        }
+    }
+}
+
+/// a bezier's control values, an amount and a fold line kept within bounds
+const BEND_MAX: f32 = 50.0;
+
+impl Bend {
+    pub fn straight(&self) -> bool {
+        self.ripple.amount == 0.0 && self.fold.amount == 0.0
+    }
+
+    fn floats(&self) -> [f32; 9] {
+        let (r, f) = (self.ripple, self.fold);
+        [r.amount, r.freq, r.phase, r.c1, r.c2, f.amount, f.at, f.c1, f.c2]
+    }
+
+    /// the bytes a placement keeps: `B`, version 1, nine little endian f32s
+    pub fn to_bytes(&self) -> Vec {
+        let mut out = vec![b'B', 1];
+        for v in self.floats() {
+            out.extend_from_slice(&v.to_le_bytes());
+        }
+        out
+    }
+
+    pub fn from_bytes(b: &[u8]) -> Option {
+        if b.len() != 2 + 36 || b[0] != b'B' || b[1] != 1 {
+            return None;
+        }
+        let f = |i: usize| f32::from_le_bytes(b[2 + i * 4..6 + i * 4].try_into().unwrap_or([0; 4]));
+        Some(Bend {
+            ripple: Ripple {
+                amount: f(0),
+                freq: f(1),
+                phase: f(2),
+                c1: f(3),
+                c2: f(4),
+            },
+            fold: Fold {
+                amount: f(5),
+                at: f(6),
+                c1: f(7),
+                c2: f(8),
+            },
+        })
+    }
+
+    /// finite and within bounds (None when straight)
+    pub fn checked(self) -> Result, String> {
+        if self.floats().iter().any(|v| !v.is_finite()) {
+            return Err("a bend's values are numbers".into());
+        }
+        let c = |v: f32, lo: f32, hi: f32| v.clamp(lo, hi);
+        let b = Bend {
+            ripple: Ripple {
+                amount: c(self.ripple.amount, -BEND_MAX, BEND_MAX),
+                freq: c(self.ripple.freq, 0.0, 64.0),
+                phase: self.ripple.phase.rem_euclid(1.0),
+                c1: c(self.ripple.c1, -3.0, 3.0),
+                c2: c(self.ripple.c2, -3.0, 3.0),
+            },
+            fold: Fold {
+                amount: c(self.fold.amount, -BEND_MAX, BEND_MAX),
+                at: c(self.fold.at, -1.0, 1.0),
+                c1: c(self.fold.c1, -3.0, 3.0),
+                c2: c(self.fold.c2, -3.0, 3.0),
+            },
+        };
+        Ok((!b.straight()).then_some(b))
+    }
+
+    /// how far it moves the block's slice at `u` across its width (0 the left edge, 1 the
+    /// right) along z; the space draws the same (`space.js` `bendAt`)
+    pub fn offset(&self, u: f32) -> f32 {
+        let r = self.ripple;
+        let mut z = 0.0;
+        if r.amount != 0.0 && r.freq > 0.0 {
+            let s = (u * r.freq + r.phase).rem_euclid(1.0);
+            z += r.amount * wave(s, r.c1, r.c2) / wave_peak(r.c1, r.c2);
+        }
+        let f = self.fold;
+        if f.amount != 0.0 {
+            let line = 0.5 + f.at * 0.5;
+            let t = if u >= line {
+                (u - line) / (1.0 - line).max(1e-6)
+            } else {
+                (line - u) / line.max(1e-6)
+            };
+            z += f.amount * rise(t.clamp(0.0, 1.0), f.c1, f.c2);
+        }
+        z
+    }
+
+    /// the most it moves any slice either way (for regions)
+    pub fn reach(&self) -> f32 {
+        self.ripple.amount.abs() + self.fold.amount.abs()
+    }
+}
+
+/// a period's profile: the cubic bezier 0, c1, c2, 0 at s
+fn wave(s: f32, c1: f32, c2: f32) -> f32 {
+    3.0 * (1.0 - s) * (1.0 - s) * s * c1 + 3.0 * (1.0 - s) * s * s * c2
+}
+
+/// the largest |wave| over a period, so `amount` is the peak (1 when it's flat)
+fn wave_peak(c1: f32, c2: f32) -> f32 {
+    let m = (0..=64)
+        .map(|i| wave(i as f32 / 64.0, c1, c2).abs())
+        .fold(0.0, f32::max);
+    if m > 1e-6 { m } else { 1.0 }
+}
+
+/// a fold's profile: the cubic bezier 0, c1, c2, 1 at t
+fn rise(t: f32, c1: f32, c2: f32) -> f32 {
+    3.0 * (1.0 - t) * (1.0 - t) * t * c1 + 3.0 * (1.0 - t) * t * t * c2 + t * t * t
+}
+
+impl Transform {
+    /// the id (big endian, so values sort by it) and six little endian f32s
+    pub fn to_bytes(&self, id: u64) -> [u8; 32] {
+        let mut b = [0u8; 32];
+        b[..8].copy_from_slice(&id.to_be_bytes());
+        for (i, v) in [self.x, self.y, self.z, self.w, self.h, self.d].iter().enumerate() {
+            b[8 + i * 4..12 + i * 4].copy_from_slice(&v.to_le_bytes());
+        }
+        b
+    }
+
+    pub fn from_bytes(b: &[u8]) -> Option<(u64, Transform)> {
+        if b.len() != 32 {
+            return None;
+        }
+        let f = |i: usize| f32::from_le_bytes(b[8 + i * 4..12 + i * 4].try_into().unwrap_or([0; 4]));
+        Some((
+            u64::from_be_bytes(b[..8].try_into().ok()?),
+            Transform {
+                x: f(0),
+                y: f(1),
+                z: f(2),
+                w: f(3),
+                h: f(4),
+                d: f(5),
+                ..Transform::default()
+            },
+        ))
+    }
+
+    /// finite, inside the world, sides within bounds
+    pub fn checked(self) -> Result {
+        let all = [self.x, self.y, self.z, self.w, self.h, self.d];
+        if all.iter().any(|v| !v.is_finite()) {
+            return Err("a block's place and size are numbers".into());
+        }
+        if [self.x, self.y, self.z].iter().any(|v| v.abs() > MAX_COORD) {
+            return Err(format!("a block stays within {MAX_COORD} of the origin"));
+        }
+        let side = |v: f32| v.clamp(MIN_SIDE, MAX_SIDE);
+        // a unit quaternion (a zero or broken one is no turn)
+        let q = self.rot;
+        let n = q.iter().map(|v| v * v).sum::().sqrt();
+        let rot = if !n.is_finite() || n < 1e-6 {
+            super::place::IDENTITY
+        } else {
+            let u = q.map(|v| v / n);
+            // the same turn with w ≥ 0, and the identity exactly when it's no turn
+            let u = if u[3] < 0.0 { u.map(|v| -v) } else { u };
+            if (u[3] - 1.0).abs() < 1e-7 {
+                super::place::IDENTITY
+            } else {
+                u
+            }
+        };
+        // a sphere doesn't bend, and has no faces of its own
+        let bend = match self.bend {
+            Some(b) if self.shape.is_box() => b.checked()?,
+            _ => None,
+        };
+        Ok(Transform {
+            w: side(self.w),
+            h: side(self.h),
+            d: side(self.d),
+            rot,
+            bend,
+            faces: self.faces.filter(|f| !f.is_empty() && self.shape.is_box()),
+            zone: self.zone.map(Zone::checked),
+            anim: self.anim.map(super::anims::AnimRef::checked),
+            wire: self.wire,
+            sound: self.sound.map(super::sounds::Emitter::checked),
+            ..self
+        })
+    }
+
+    /// half the sides of the box around it as it's turned and bent (for regions)
+    pub fn half_extent(&self) -> [f32; 3] {
+        let reach = self.bend.map_or(0.0, |b| b.reach());
+        let half = [self.w / 2.0, self.h / 2.0, self.d / 2.0 + reach];
+        let [x, y, z, w] = self.rot;
+        // the rotation matrix's columns, by absolute value
+        let m = [
+            [
+                1.0 - 2.0 * (y * y + z * z),
+                2.0 * (x * y - z * w),
+                2.0 * (x * z + y * w),
+            ],
+            [
+                2.0 * (x * y + z * w),
+                1.0 - 2.0 * (x * x + z * z),
+                2.0 * (y * z - x * w),
+            ],
+            [
+                2.0 * (x * z - y * w),
+                2.0 * (y * z + x * w),
+                1.0 - 2.0 * (x * x + y * y),
+            ],
+        ];
+        [0, 1, 2].map(|r| (0..3).map(|c| m[r][c].abs() * half[c]).sum())
+    }
+
+    /// whether the block's box meets the box from `lo` to `hi`
+    pub fn meets(&self, lo: [f32; 3], hi: [f32; 3]) -> bool {
+        let c = [self.x, self.y, self.z];
+        let half = self.half_extent();
+        (0..3).all(|i| c[i] + half[i] >= lo[i] && c[i] - half[i] <= hi[i])
+    }
+
+    /// how many times the texture repeats across each face: (w, h) for the front and
+    /// back, (d, h) for the sides, (w, d) for the top and bottom
+    pub fn repeats(&self) -> [[f32; 2]; 3] {
+        [
+            [self.w / TILE, self.h / TILE],
+            [self.d / TILE, self.h / TILE],
+            [self.w / TILE, self.d / TILE],
+        ]
+    }
+}
+
+/// one block
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct Block {
+    /// its address in the room ([`block_id`])
+    pub id: String,
+    pub kind: Kind,
+    pub texture: String,
+    #[serde(flatten)]
+    pub t: Transform,
+}
+
+/// how the blocks table is used: instances and distinct textures
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize)]
+pub struct BlockUse {
+    pub blocks: u64,
+    pub textures: u64,
+}
+
+/// a block's address in the room: `:#`, its texture's key and its
+/// number among that texture's blocks
+pub fn block_id(kind: Kind, texture: &str, n: u64) -> String {
+    format!("{}#{n}", key(kind, texture))
+}
+
+/// an address's texture and number
+pub fn split_id(id: &str) -> Option<(Kind, String, u64)> {
+    let (k, n) = id.rsplit_once('#')?;
+    let (kind, texture) = split_key(k)?;
+    Some((kind, texture.to_string(), n.parse().ok()?))
+}
+
+/// what a texture is as a scene definition
+pub fn def_of(kind: Kind, texture: &str) -> GResult {
+    let t = texture.trim();
+    match kind {
+        Kind::Text => record::parse_label(t.strip_prefix("note:").unwrap_or(t))
+            .map(Def::Entry)
+            .ok_or_else(|| format!("{t:?} isn't a text's key")),
+        Kind::Picture => {
+            let b = (0..16)
+                .map(|i| t.get(2 * i..2 * i + 2).and_then(|h| u8::from_str_radix(h, 16).ok()))
+                .collect::>>()
+                .filter(|_| t.len() == 32)
+                .ok_or_else(|| format!("{t:?} isn't a picture's hash (32 hex digits)"))?;
+            Ok(Def::Picture(b.try_into().expect("16 bytes")))
+        }
+        Kind::Plain => {
+            let ok = t.len() == 7 && t.starts_with('#') && t[1..].chars().all(|c| c.is_ascii_hexdigit());
+            if !ok {
+                return Err(format!("{t:?} isn't a colour (#rrggbb)"));
+            }
+            let v = u32::from_str_radix(&t[1..], 16).map_err(err)?;
+            Ok(Def::Colour([(v >> 16) as u8, (v >> 8) as u8, v as u8]))
+        }
+        Kind::Texture => hex16(t)
+            .map(Def::Texture)
+            .ok_or_else(|| format!("{t:?} isn't a texture's id (32 hex digits)")),
+    }
+}
+
+/// a definition back as a texture
+pub fn texture_of(def: &Def) -> Option<(Kind, String)> {
+    Some(match def {
+        Def::Entry(id) => (Kind::Text, record::label(*id)),
+        Def::Picture(h) => (Kind::Picture, h.iter().map(|b| format!("{b:02x}")).collect()),
+        Def::Colour([r, g, b]) => (Kind::Plain, format!("#{r:02x}{g:02x}{b:02x}")),
+        Def::Texture(h) => (Kind::Texture, hex_of(h)),
+        Def::Scene(_) => return None,
+    })
+}
+
+pub(crate) fn placement(t: &Transform, n: u64) -> Placement {
+    let mut p = Placement::at(n, [t.x, t.y, t.z]);
+    p.scale = Scale::Axes([t.w, t.h, t.d]).canonical();
+    p.rot = (t.rot != super::place::IDENTITY).then(|| super::place::pack_rotation(t.rot));
+    p.extra = extra_bytes(t);
+    // its shape (`place::Kind`) in bits 3–6
+    p.flags = Some((t.shape.kind() as u64) << 3);
+    p
+}
+
+/// a block placement's transform (its place, sides, turn and bend)
+pub fn transform_of(p: &Placement) -> Transform {
+    transform(p)
+}
+
+fn transform(p: &Placement) -> Transform {
+    let Extra {
+        bend,
+        faces,
+        zone,
+        anim,
+        wire,
+        sound,
+    } = p.extra.as_deref().map(read_extra).unwrap_or_default();
+    let [w, h, d] = match p.scale {
+        Scale::One => [1.0; 3],
+        Scale::Uniform(v) => [v; 3],
+        Scale::Axes(a) => a,
+    };
+    Transform {
+        x: p.pos[0],
+        y: p.pos[1],
+        z: p.pos[2],
+        w,
+        h,
+        d,
+        rot: p
+            .rot
+            .map(super::place::unpack_rotation)
+            .unwrap_or(super::place::IDENTITY),
+        bend,
+        faces,
+        shape: Shape::of_flags(p.flags),
+        zone,
+        anim,
+        wire,
+        sound,
+    }
+}
+
+pub(crate) fn block_of(p: &Placed) -> Option {
+    if p.kind != SKind::Block {
+        return None;
+    }
+    let (kind, texture) = texture_of(&p.def)?;
+    Some(Block {
+        id: block_id(kind, &texture, p.place.n),
+        kind,
+        texture,
+        t: transform(&p.place),
+    })
+}
+
+/// the old tables' blocks moved into the room, inside the write that opens the save;
+/// how many moved. Each texture's blocks keep their order (they sorted by id) as their
+/// numbers 1, 2, ...; a texture that doesn't read as a definition is kept as the old
+/// tables had it and the tables stay
+pub(crate) fn migrate(txn: &redb::WriteTransaction) -> GResult {
+    let had = txn
+        .list_multimap_tables()
+        .map_err(err)?
+        .any(|h| h.name() == OLD_BLOCKS.name());
+    if !had {
+        return Ok(0);
+    }
+    let mut groups: Vec<(Def, Vec)> = Vec::new();
+    {
+        let t = txn.open_multimap_table(OLD_BLOCKS).map_err(err)?;
+        for item in t.iter().map_err(err)? {
+            let (k, vs) = item.map_err(err)?;
+            let (kind, texture) = split_key(k.value()).ok_or("an old block's key doesn't read")?;
+            let def = def_of(kind, texture)?;
+            let mut ps = Vec::new();
+            for v in vs {
+                let (_, tr) = Transform::from_bytes(v.map_err(err)?.value()).ok_or("an old block doesn't read")?;
+                ps.push(placement(&tr, 0));
+            }
+            groups.push((def, ps));
+        }
+    }
+    let n: usize = groups.iter().map(|g| g.1.len()).sum();
+    if n > 0 {
+        let room = scenes::room_in(txn)?;
+        for (def, ps) in groups {
+            scenes::place_in(txn, room, false, SKind::Block, def, None, ps, &[])?;
+        }
+    }
+    txn.delete_multimap_table(OLD_BLOCKS).map_err(err)?;
+    txn.delete_table(OLD_BLOCK_IDS).map_err(err)?;
+    Ok(n)
+}
+
+impl Graph {
+    /// the room's placements (none before the room is made)
+    fn room_placements(&self) -> GResult> {
+        match self.room()? {
+            Some(r) => self.placements(r, false),
+            None => Ok(vec![]),
+        }
+    }
+
+    /// places a block in the room; its id
+    pub fn add_block(&self, kind: Kind, texture: &str, t: Transform) -> GResult {
+        Ok(self.add_blocks(&[(kind, texture.to_string(), t)])?.swap_remove(0))
+    }
+
+    /// places several blocks in the room in one write; their ids
+    pub fn add_blocks(&self, blocks: &[(Kind, String, Transform)]) -> GResult> {
+        let mut checked = Vec::with_capacity(blocks.len());
+        for (kind, texture, t) in blocks {
+            checked.push((*kind, texture.trim().to_string(), def_of(*kind, texture)?, t.checked()?));
+        }
+        if checked.is_empty() {
+            return Ok(vec![]);
+        }
+        let txn = self.db().begin_write().map_err(err)?;
+        let mut out = Vec::with_capacity(checked.len());
+        {
+            let room = scenes::room_in(&txn)?;
+            for (kind, texture, def, t) in checked {
+                let n = scenes::place_in(&txn, room, false, SKind::Block, def, None, vec![placement(&t, 0)], &[])?[0];
+                out.push(block_id(kind, &texture_of(&def).map(|x| x.1).unwrap_or(texture), n));
+            }
+        }
+        txn.commit().map_err(err)?;
+        Ok(out)
+    }
+
+    /// one block
+    pub fn block(&self, id: &str) -> GResult> {
+        // a prefab copy's part (`graph::prefabs`)
+        if super::prefabs::is_part(id) {
+            return self.part(id);
+        }
+        let Some((kind, texture, n)) = split_id(id) else {
+            return Ok(None);
+        };
+        let def = def_of(kind, &texture)?;
+        Ok(self
+            .room_placements()?
+            .iter()
+            .find(|p| p.kind == SKind::Block && p.def == def && p.place.n == n)
+            .and_then(block_of))
+    }
+
+    /// moves or resizes blocks (each its whole new transform) in one write; the ones
+    /// that weren't there are skipped, the rest come back as they are now
+    pub fn set_blocks(&self, changes: &[(String, Transform)]) -> GResult> {
+        let mut out = Vec::new();
+        let mut todo = Vec::new();
+        for (id, t) in changes {
+            let t = t.checked()?;
+            // a part changes in its copy only
+            if super::prefabs::is_part(id) {
+                out.extend(self.set_part(id, t)?);
+                continue;
+            }
+            if let Some(mut b) = self.block(id)? {
+                b.t = t;
+                todo.push(b);
+            }
+        }
+        let txn = self.db().begin_write().map_err(err)?;
+        {
+            let room = scenes::room_in(&txn)?;
+            for b in todo {
+                let (_, _, n) = split_id(&b.id).expect("read above");
+                let mut p = placement(&b.t, n);
+                p.n = n;
+                scenes::place_in(
+                    &txn,
+                    room,
+                    false,
+                    SKind::Block,
+                    def_of(b.kind, &b.texture)?,
+                    None,
+                    vec![p],
+                    &[],
+                )?;
+                out.push(b);
+            }
+        }
+        txn.commit().map_err(err)?;
+        Ok(out)
+    }
+
+    /// takes blocks away; the ones that were there, as they were (to put them back)
+    pub fn delete_blocks(&self, ids: &[String]) -> GResult> {
+        let mut out = Vec::new();
+        // a part goes only with its copy
+        for id in ids.iter().filter(|i| !super::prefabs::is_part(i)) {
+            if let Some(b) = self.block(id)? {
+                out.push(b);
+            }
+        }
+        let txn = self.db().begin_write().map_err(err)?;
+        {
+            let room = scenes::room_in(&txn)?;
+            for b in &out {
+                let (_, _, n) = split_id(&b.id).expect("read above");
+                scenes::place_in(
+                    &txn,
+                    room,
+                    false,
+                    SKind::Block,
+                    def_of(b.kind, &b.texture)?,
+                    None,
+                    vec![],
+                    &[n],
+                )?;
+            }
+        }
+        txn.commit().map_err(err)?;
+        Ok(out)
+    }
+
+    /// puts blocks back with their own ids (an undo); the ids already in use are skipped,
+    /// and a block without a number (`#0`, or an old backup's) gets the next free one
+    pub fn put_blocks(&self, blocks: &[Block]) -> GResult {
+        let mut todo = Vec::new();
+        for b in blocks {
+            let n = split_id(&b.id).map(|x| x.2).unwrap_or(0);
+            if n != 0 && self.block(&b.id)?.is_some() {
+                continue;
+            }
+            todo.push((def_of(b.kind, &b.texture)?, b.t.checked()?, n));
+        }
+        if todo.is_empty() {
+            return Ok(0);
+        }
+        let txn = self.db().begin_write().map_err(err)?;
+        {
+            let room = scenes::room_in(&txn)?;
+            for (def, t, n) in &todo {
+                scenes::place_in(&txn, room, false, SKind::Block, *def, None, vec![placement(t, *n)], &[])?;
+            }
+        }
+        txn.commit().map_err(err)?;
+        Ok(todo.len())
+    }
+
+    /// copies of blocks, each moved by `offset`; the new ids
+    pub fn duplicate_blocks(&self, ids: &[String], offset: [f32; 3]) -> GResult> {
+        let mut new = Vec::new();
+        for id in ids {
+            let b = self.block(id)?.ok_or_else(|| format!("no block {id}"))?;
+            let mut t = b.t;
+            t.x += offset[0];
+            t.y += offset[1];
+            t.z += offset[2];
+            new.push((b.kind, b.texture, t));
+        }
+        self.add_blocks(&new)
+    }
+
+    /// every block in the room, or (with a region) those whose boxes meet it
+    pub fn blocks(&self, region: Option<([f32; 3], [f32; 3])>) -> GResult> {
+        Ok(self
+            .room_placements()?
+            .iter()
+            .filter_map(block_of)
+            .filter(|b| region.is_none_or(|(lo, hi)| b.t.meets(lo, hi)))
+            .collect())
+    }
+
+    /// the blocks showing one texture
+    pub fn blocks_of(&self, kind: Kind, texture: &str) -> GResult> {
+        let def = def_of(kind, texture)?;
+        Ok(self
+            .room_placements()?
+            .iter()
+            .filter(|p| p.def == def)
+            .filter_map(block_of)
+            .collect())
+    }
+
+    /// how many blocks and distinct textures
+    pub fn block_use(&self) -> GResult {
+        let bs = self.blocks(None)?;
+        let textures: std::collections::BTreeSet = bs.iter().map(|b| key(b.kind, &b.texture)).collect();
+        Ok(BlockUse {
+            blocks: bs.len() as u64,
+            textures: textures.len() as u64,
+        })
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    fn t(x: f32, w: f32) -> Transform {
+        Transform {
+            x,
+            w,
+            ..Transform::default()
+        }
+    }
+
+    use redb::ReadableDatabase;
+
+    const PIC: &str = "000102030405060708090a0b0c0d0e0f";
+
+    #[test]
+    fn transforms_round_trip_and_sort_by_id() {
+        let a = Transform {
+            x: 1.5,
+            y: -2.0,
+            z: 3.25,
+            w: 4.0,
+            h: 0.5,
+            d: 2.0,
+            ..Transform::default()
+        };
+        assert_eq!(Transform::from_bytes(&a.to_bytes(7)), Some((7, a)));
+        assert!(Transform::from_bytes(&[0; 31]).is_none());
+        assert_eq!(a.repeats(), [[4.0, 0.5], [2.0, 0.5], [4.0, 2.0]]);
+        assert!(t(f32::NAN, 1.0).checked().is_err());
+        assert_eq!(t(0.0, 0.0).checked().unwrap().w, MIN_SIDE);
+        assert_eq!(transform(&placement(&a, 3)), a);
+        assert_eq!(split_id("text:1,2#7"), Some((Kind::Text, "1,2".into(), 7)));
+        assert_eq!(split_id("plain:#a0b0c0#2"), Some((Kind::Plain, "#a0b0c0".into(), 2)));
+        assert!(def_of(Kind::Picture, "ab").is_err());
+    }
+
+    #[test]
+    fn blocks_are_room_placements_numbered_per_texture() {
+        let g = Graph::in_memory().unwrap();
+        let ids = g
+            .add_blocks(&[
+                (Kind::Text, "1,2".into(), t(0.0, 1.0)),
+                (Kind::Text, "1,2".into(), t(5.0, 2.0)),
+                (Kind::Picture, PIC.into(), t(-5.0, 1.0)),
+            ])
+            .unwrap();
+        assert_eq!(ids, ["text:1,2#1", "text:1,2#2", &format!("picture:{PIC}#1")]);
+        assert_eq!(g.block_use().unwrap(), BlockUse { blocks: 3, textures: 2 });
+        assert_eq!(g.blocks_of(Kind::Text, "1,2").unwrap().len(), 2);
+
+        // moving one replaces it under its number
+        let moved = g
+            .set_blocks(&[("text:1,2#2".into(), t(9.0, 3.0)), ("text:1,2#99".into(), t(0.0, 1.0))])
+            .unwrap();
+        assert_eq!(moved.len(), 1);
+        assert_eq!(g.block("text:1,2#2").unwrap().unwrap().t, t(9.0, 3.0));
+        assert_eq!(g.block_use().unwrap().blocks, 3);
+
+        let near: Vec = g
+            .blocks(Some(([-1.0, -1.0, -1.0], [1.0, 1.0, 1.0])))
+            .unwrap()
+            .into_iter()
+            .map(|b| b.id)
+            .collect();
+        assert_eq!(near, ["text:1,2#1"]);
+
+        // duplicate, delete, put back with the same ids
+        let pic = format!("picture:{PIC}#1");
+        let copies = g
+            .duplicate_blocks(&["text:1,2#1".into(), pic.clone()], [0.0, 2.0, 0.0])
+            .unwrap();
+        assert_eq!(copies, ["text:1,2#3", &format!("picture:{PIC}#2")]);
+        assert_eq!(g.block(&copies[1]).unwrap().unwrap().t.y, 2.0);
+        let gone = g.delete_blocks(&["text:1,2#1".into(), "text:1,2#3".into()]).unwrap();
+        assert_eq!(gone.len(), 2);
+        assert_eq!(g.blocks_of(Kind::Text, "1,2").unwrap().len(), 1);
+        assert_eq!(g.put_blocks(&gone).unwrap(), 2);
+        assert_eq!(g.put_blocks(&gone).unwrap(), 0, "their ids are in use again");
+        assert_eq!(g.blocks(None).unwrap().len(), 5);
+        assert_eq!(g.block("text:1,2#1").unwrap().unwrap().t, t(0.0, 1.0));
+        assert_eq!(
+            g.add_block(Kind::Plain, "#FF0000", t(0.0, 1.0)).unwrap(),
+            "plain:#ff0000#1"
+        );
+    }
+
+    #[test]
+    fn old_saves_move_their_blocks_into_the_room() {
+        let db = redb::Database::builder()
+            .create_with_backend(redb::backends::InMemoryBackend::new())
+            .unwrap();
+        // the tables as saves had them before scenes
+        let txn = db.begin_write().unwrap();
+        {
+            let mut b = txn.open_multimap_table(OLD_BLOCKS).unwrap();
+            let mut ids = txn.open_table(OLD_BLOCK_IDS).unwrap();
+            for (id, k, tr) in [
+                (1u64, "text:1,2", t(0.0, 1.0)),
+                (2, "plain:#112233", t(1.0, 2.0)),
+                (3, "text:1,2", t(5.0, 3.0)),
+            ] {
+                b.insert(k, tr.to_bytes(id).as_slice()).unwrap();
+                ids.insert(id, k).unwrap();
+            }
+        }
+        txn.commit().unwrap();
+        let g = Graph::from_db(db).unwrap();
+        let bs = g.blocks(None).unwrap();
+        assert_eq!(bs.len(), 3);
+        // a texture's blocks keep their order as their numbers
+        assert_eq!(g.block("text:1,2#1").unwrap().unwrap().t, t(0.0, 1.0));
+        assert_eq!(g.block("text:1,2#2").unwrap().unwrap().t, t(5.0, 3.0));
+        assert_eq!(g.block("plain:#112233#1").unwrap().unwrap().t, t(1.0, 2.0));
+        // the old tables are gone, so opening again moves nothing twice
+        let txn = g.db().begin_read().unwrap();
+        assert!(!txn.list_multimap_tables().unwrap().any(|h| h.name() == "graph blocks"));
+    }
+}
+
+#[cfg(test)]
+mod turn_and_bend_tests {
+    use super::*;
+
+    #[test]
+    fn rotation_and_bend_are_kept_and_cost_nothing_when_absent() {
+        let g = Graph::in_memory().unwrap();
+        let plain = g.add_block(Kind::Plain, "#123456", Transform::default()).unwrap();
+        let s = (0.3f32).sin();
+        let turned = Transform {
+            x: 1.0,
+            w: 3.0,
+            rot: [0.0, s, 0.0, (0.3f32).cos()],
+            bend: Some(Bend {
+                ripple: Ripple {
+                    amount: 0.4,
+                    freq: 3.0,
+                    phase: 1.25,
+                    ..Ripple::default()
+                },
+                fold: Fold {
+                    amount: -0.5,
+                    at: 0.2,
+                    ..Fold::default()
+                },
+            }),
+            ..Transform::default()
+        };
+        let id = g.add_block(Kind::Plain, "#123456", turned).unwrap();
+        let b = g.block(&id).unwrap().unwrap();
+        // the rotation comes back as packed (smallest three, 32 bits), the bend exactly
+        assert!(
+            (b.t.rot[1] - s).abs() < 1e-3 && b.t.rot[0].abs() < 1e-3,
+            "{:?}",
+            b.t.rot
+        );
+        let bend = b.t.bend.unwrap();
+        assert_eq!(bend.ripple.phase, 0.25, "phase wraps");
+        assert_eq!(bend.fold.at, 0.2);
+        // stored again, the same bytes (canonical)
+        assert_eq!(placement(&b.t, 2), placement(&transform(&placement(&b.t, 2)), 2));
+        // a plain block has no rotation and no extra in its placement
+        let p = g.block(&plain).unwrap().unwrap();
+        let pl = placement(&p.t, 1);
+        assert!(pl.rot.is_none() && pl.extra.is_none());
+        assert_eq!(serde_json::to_value(p.t).unwrap().get("rot"), None);
+        // straightened, the bend goes; a turned block's region grows with its turn
+        let straight = g
+            .set_blocks(&[(
+                id.clone(),
+                Transform {
+                    bend: Some(Bend::default()),
+                    ..b.t
+                },
+            )])
+            .unwrap();
+        assert_eq!(straight[0].t.bend, None);
+        let tall = Transform {
+            w: 4.0,
+            h: 0.1,
+            d: 0.1,
+            rot: [
+                0.0,
+                0.0,
+                (std::f32::consts::FRAC_PI_4).sin(),
+                (std::f32::consts::FRAC_PI_4).cos(),
+            ],
+            ..Transform::default()
+        };
+        assert!(tall.half_extent()[1] > 1.4, "turned 90° about z, its width stands up");
+        // the bend's profile: the fold is 0 at its line and `amount` at the edges
+        let f = Bend {
+            fold: Fold {
+                amount: 2.0,
+                ..Fold::default()
+            },
+            ..Bend::default()
+        };
+        assert_eq!(f.offset(0.5), 0.0);
+        assert!((f.offset(0.0) - 2.0).abs() < 1e-6 && (f.offset(1.0) - 2.0).abs() < 1e-6);
+        let r = Bend {
+            ripple: Ripple {
+                amount: 1.0,
+                ..Ripple::default()
+            },
+            ..Bend::default()
+        };
+        let peak = (0..=200).map(|i| r.offset(i as f32 / 200.0).abs()).fold(0.0, f32::max);
+        assert!((peak - 1.0).abs() < 0.02, "{peak}");
+    }
+}
diff --git a/core/src/graph/chains.rs b/core/src/graph/chains.rs
new file mode 100644
index 00000000..9f57dc8f
--- /dev/null
+++ b/core/src/graph/chains.rs
@@ -0,0 +1,189 @@
+//! Chains (docs/format.md "The model", answer 4): an entry of its own, mime
+//! `application/x-anend-chain`, that is a title plus an ordered run of member entries, such
+//! as the paragraphs of one piece. Its body is a ref to its title entry, so it renders,
+//! searches, lists and opens as its title does (and follows the title's edits); its
+//! members are `MEMBER` edges with order keys, as a list's are. The same text can be a
+//! member of several chains. Notes are not chains; a note placed in a scene is shown as
+//! a chain of two when it is shown, with no chain entry made.
+
+use super::codec::Seg;
+use super::record::{label, mime};
+use super::store::{GResult, Reader, Tx, rel};
+
+/// a chain as read: its entry, its title entry and its members in order
+#[derive(Clone, Debug, PartialEq)]
+pub struct Chain {
+    pub id: u64,
+    pub title: u64,
+    pub members: Vec,
+}
+
+/// the chain an entry is, if it is one
+pub fn chain_of(r: &impl Reader, id: u64) -> GResult> {
+    let Some(rec) = r.record(id)? else { return Ok(None) };
+    if rec.mime != mime::CHAIN {
+        return Ok(None);
+    }
+    let title = match r.source(id)?.as_slice() {
+        [Seg::Ref(t)] => *t,
+        _ => return Err(format!("chain {} isn't a ref to its title", label(id))),
+    };
+    Ok(Some(Chain {
+        id,
+        title,
+        members: r.members(id)?,
+    }))
+}
+
+/// the chains an entry is a member of
+pub fn chains_with(r: &impl Reader, member: u64) -> GResult> {
+    let mut out = Vec::new();
+    for c in r.in_edges(member, rel::MEMBER)? {
+        if r.record(c)?.is_some_and(|x| x.mime == mime::CHAIN) {
+            out.push(c);
+        }
+    }
+    Ok(out)
+}
+
+fn check(tx: &Tx, title: u64, members: &[u64]) -> GResult> {
+    if !tx.exists(title)? {
+        return Err(format!("there's no entry {}", label(title)));
+    }
+    let mut out: Vec = Vec::new();
+    for &m in members {
+        if m == title || out.contains(&m) {
+            continue;
+        }
+        if !tx.exists(m)? {
+            return Err(format!("there's no entry {}", label(m)));
+        }
+        out.push(m);
+    }
+    Ok(out)
+}
+
+impl Tx<'_> {
+    /// a new chain: `title` and then `members` in order (the title and repeats left out of
+    /// the members); its id
+    pub fn make_chain(&mut self, title: u64, members: &[u64]) -> GResult {
+        let members = check(self, title, members)?;
+        let id = self.save_run(&[Seg::Ref(title)], mime::CHAIN)?;
+        self.set_members(id, &members)?;
+        Ok(id)
+    }
+
+    /// a chain's members replaced by these, in this order (make, reorder, add, take out)
+    pub fn set_chain(&mut self, chain: u64, members: &[u64]) -> GResult<()> {
+        let c = chain_of(self, chain)?.ok_or_else(|| format!("{} isn't a chain", label(chain)))?;
+        let members = check(self, c.title, members)?;
+        self.set_members(chain, &members)
+    }
+
+    fn set_members(&mut self, chain: u64, members: &[u64]) -> GResult<()> {
+        for m in self.members(chain)? {
+            self.unlink(chain, rel::MEMBER, m)?;
+        }
+        for (i, m) in members.iter().enumerate() {
+            self.link(chain, rel::MEMBER, *m, &(i as u64).to_be_bytes())?;
+        }
+        Ok(())
+    }
+
+    /// cuts a chain before member `at`: the members before it stay; that member heads a new
+    /// chain of the ones after it (its id; None when `at` is past the end)
+    pub fn cut_chain(&mut self, chain: u64, at: usize) -> GResult> {
+        let c = chain_of(self, chain)?.ok_or_else(|| format!("{} isn't a chain", label(chain)))?;
+        if at >= c.members.len() {
+            return Ok(None);
+        }
+        let (keep, rest) = c.members.split_at(at);
+        self.set_members(chain, keep)?;
+        Ok(Some(self.make_chain(rest[0], &rest[1..])?))
+    }
+
+    /// two chains joined: `b`'s title and members after `a`'s members; `b` goes
+    pub fn join_chains(&mut self, a: u64, b: u64) -> GResult<()> {
+        let ca = chain_of(self, a)?.ok_or_else(|| format!("{} isn't a chain", label(a)))?;
+        let cb = chain_of(self, b)?.ok_or_else(|| format!("{} isn't a chain", label(b)))?;
+        let mut all = ca.members.clone();
+        all.push(cb.title);
+        all.extend(cb.members);
+        self.delete(b)?;
+        self.set_chain(a, &all)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::graph::Graph;
+
+    #[test]
+    fn chains_are_entries_with_a_title_and_ordered_members() {
+        let g = Graph::in_memory().unwrap();
+        let ids: Vec = ["The heron", "It waits.", "It strikes.", "It eats.", "It flies off."]
+            .iter()
+            .map(|t| g.save_text(t, mime::TEXT).unwrap().0)
+            .collect();
+        let c = g
+            .write(|tx| tx.make_chain(ids[0], &[ids[1], ids[2], ids[1], ids[0], ids[3]]))
+            .unwrap();
+        let v = g.view().unwrap();
+        let ch = chain_of(&v, c).unwrap().unwrap();
+        assert_eq!(ch.title, ids[0]);
+        assert_eq!(
+            ch.members,
+            vec![ids[1], ids[2], ids[3]],
+            "repeats and the title left out"
+        );
+        // it reads and searches as its title
+        assert_eq!(v.render(c).unwrap(), "The heron");
+        assert!(chain_of(&v, ids[1]).unwrap().is_none());
+        assert_eq!(chains_with(&v, ids[2]).unwrap(), vec![c]);
+        drop(v);
+        // the title edited: the chain follows
+        g.write(|tx| tx.edit_text(ids[0], "The grey heron")).unwrap();
+        assert_eq!(g.render(c).unwrap(), "The grey heron");
+        // reorder, cut, join
+        g.write(|tx| tx.set_chain(c, &[ids[3], ids[1], ids[2], ids[4]]))
+            .unwrap();
+        let rest = g.write(|tx| tx.cut_chain(c, 2)).unwrap().unwrap();
+        let v = g.view().unwrap();
+        assert_eq!(chain_of(&v, c).unwrap().unwrap().members, vec![ids[3], ids[1]]);
+        let r = chain_of(&v, rest).unwrap().unwrap();
+        assert_eq!((r.title, r.members.clone()), (ids[2], vec![ids[4]]));
+        drop(v);
+        assert_eq!(g.write(|tx| tx.cut_chain(c, 9)).unwrap(), None);
+        g.write(|tx| tx.join_chains(c, rest)).unwrap();
+        let v = g.view().unwrap();
+        assert_eq!(
+            chain_of(&v, c).unwrap().unwrap().members,
+            vec![ids[3], ids[1], ids[2], ids[4]]
+        );
+        assert!(!v.exists(rest).unwrap());
+        // the same text in two chains
+        drop(v);
+        let c2 = g.write(|tx| tx.make_chain(ids[4], &[ids[1]])).unwrap();
+        let mut both = chains_with(&g.view().unwrap(), ids[1]).unwrap();
+        both.sort();
+        assert_eq!(both, {
+            let mut x = vec![c, c2];
+            x.sort();
+            x
+        });
+        // a chain survives a backup
+        let (t, o) = g.backup().unwrap();
+        let back = Graph::in_memory().unwrap();
+        back.restore(&t, &o).unwrap();
+        let bv = back.view().unwrap();
+        let chains: Vec = bv
+            .ids()
+            .unwrap()
+            .into_iter()
+            .filter_map(|i| chain_of(&bv, i).unwrap())
+            .collect();
+        assert_eq!(chains.len(), 2);
+        assert!(chains.iter().any(|ch| ch.members.len() == 4));
+    }
+}
diff --git a/core/src/graph/checkpoints.rs b/core/src/graph/checkpoints.rs
new file mode 100644
index 00000000..6fc25790
--- /dev/null
+++ b/core/src/graph/checkpoints.rs
@@ -0,0 +1,164 @@
+//! Checkpoints: redb's persistent savepoints of a save's whole database, each with a name
+//! and a time, to go back to. The names live in `graph meta` under `checkpoints` (JSON:
+//! id → {name, at}); a savepoint holds the state from before its own name was written, so
+//! going back writes the names of the checkpoints still there again. Going back to one
+//! drops every checkpoint made after it (redb invalidates them) and rebuilds the in-memory
+//! index.
+
+use std::collections::BTreeMap;
+
+use redb::{ReadableDatabase, ReadableTable};
+use serde::{Deserialize, Serialize};
+
+use super::store::{GResult, Graph, META, err};
+
+const KEY: &str = "checkpoints";
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct Checkpoint {
+    pub id: u64,
+    pub name: String,
+    /// when it was made, milliseconds since the Unix epoch
+    pub at: u64,
+}
+
+#[derive(Clone, Debug, Default, Serialize, Deserialize)]
+struct Label {
+    name: String,
+    at: u64,
+}
+
+fn labels_in(meta: &impl ReadableTable<&'static str, &'static [u8]>) -> GResult> {
+    Ok(match meta.get(KEY).map_err(err)? {
+        Some(v) => serde_json::from_slice(v.value()).unwrap_or_default(),
+        None => BTreeMap::new(),
+    })
+}
+
+impl Graph {
+    /// a checkpoint of the save as it is now; its id
+    pub fn checkpoint(&self, name: &str) -> GResult {
+        let txn = self.db().begin_write().map_err(err)?;
+        let id = txn.persistent_savepoint().map_err(err)?;
+        {
+            let mut meta = txn.open_table(META).map_err(err)?;
+            let mut labels = labels_in(&meta)?;
+            labels.insert(
+                id,
+                Label {
+                    name: name.trim().chars().take(120).collect(),
+                    at: self.now(),
+                },
+            );
+            meta.insert(KEY, serde_json::to_vec(&labels).map_err(err)?.as_slice())
+                .map_err(err)?;
+        }
+        txn.commit().map_err(err)?;
+        Ok(id)
+    }
+
+    /// the checkpoints there are, oldest first
+    pub fn checkpoints(&self) -> GResult> {
+        let txn = self.db().begin_write().map_err(err)?;
+        let ids: Vec = txn.list_persistent_savepoints().map_err(err)?.collect();
+        let labels = labels_in(&txn.open_table(META).map_err(err)?)?;
+        txn.abort().map_err(err)?;
+        let mut out: Vec = ids
+            .into_iter()
+            .map(|id| {
+                let l = labels.get(&id).cloned().unwrap_or_default();
+                Checkpoint {
+                    id,
+                    name: l.name,
+                    at: l.at,
+                }
+            })
+            .collect();
+        out.sort_by_key(|c| c.id);
+        Ok(out)
+    }
+
+    /// the save back as it was at a checkpoint (those made after it go)
+    pub fn restore_checkpoint(&self, id: u64) -> GResult<()> {
+        let labels = {
+            let txn = self.db().begin_read().map_err(err)?;
+            labels_in(&txn.open_table(META).map_err(err)?)?
+        };
+        let mut txn = self.db().begin_write().map_err(err)?;
+        let sp = txn
+            .get_persistent_savepoint(id)
+            .map_err(|_| format!("no checkpoint {id}"))?;
+        txn.restore_savepoint(&sp).map_err(err)?;
+        let left: Vec = txn.list_persistent_savepoints().map_err(err)?.collect();
+        {
+            let mut meta = txn.open_table(META).map_err(err)?;
+            let keep: BTreeMap = labels.into_iter().filter(|(k, _)| left.contains(k)).collect();
+            meta.insert(KEY, serde_json::to_vec(&keep).map_err(err)?.as_slice())
+                .map_err(err)?;
+        }
+        txn.commit().map_err(err)?;
+        self.reindex()
+    }
+
+    /// whether there was one
+    pub fn delete_checkpoint(&self, id: u64) -> GResult {
+        let txn = self.db().begin_write().map_err(err)?;
+        let found = txn.delete_persistent_savepoint(id).map_err(err)?;
+        {
+            let mut meta = txn.open_table(META).map_err(err)?;
+            let mut labels = labels_in(&meta)?;
+            labels.remove(&id);
+            meta.insert(KEY, serde_json::to_vec(&labels).map_err(err)?.as_slice())
+                .map_err(err)?;
+        }
+        txn.commit().map_err(err)?;
+        Ok(found)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+    use crate::graph::record::mime;
+
+    #[test]
+    fn back_to_a_checkpoint() {
+        let path = std::env::temp_dir().join(format!("anend-cp-{}.redb", std::process::id()));
+        let _ = std::fs::remove_file(&path);
+        let g = Graph::open(&path).unwrap();
+        g.save_text("listen", mime::TEXT).unwrap();
+        let a = g.checkpoint("one text").unwrap();
+        g.save_text("silent", mime::TEXT).unwrap();
+        let b = g.checkpoint("two texts").unwrap();
+        g.save_text("enlist", mime::TEXT).unwrap();
+        let cps = g.checkpoints().unwrap();
+        assert_eq!(
+            cps.iter().map(|c| c.name.as_str()).collect::>(),
+            ["one text", "two texts"]
+        );
+        assert_eq!(g.entry_count_now(), 3);
+
+        g.restore_checkpoint(b).unwrap();
+        assert_eq!(g.entry_count_now(), 2);
+        // its own name and the older one's are still there
+        assert_eq!(g.checkpoints().unwrap().len(), 2);
+        g.restore_checkpoint(a).unwrap();
+        assert_eq!(g.entry_count_now(), 1);
+        let left = g.checkpoints().unwrap();
+        assert_eq!(left.len(), 1);
+        assert_eq!(left[0].name, "one text");
+        // the index follows: search finds what's there
+        assert!(g.view().unwrap().search_words("silent").unwrap().is_empty());
+        assert!(g.delete_checkpoint(a).unwrap());
+        assert!(g.checkpoints().unwrap().is_empty());
+        assert!(g.restore_checkpoint(a).is_err());
+        drop(g);
+        let _ = std::fs::remove_file(&path);
+    }
+
+    impl Graph {
+        fn entry_count_now(&self) -> u64 {
+            self.view().unwrap().entry_count().unwrap()
+        }
+    }
+}
diff --git a/core/src/graph/codec.rs b/core/src/graph/codec.rs
new file mode 100644
index 00000000..f96de645
--- /dev/null
+++ b/core/src/graph/codec.rs
@@ -0,0 +1,900 @@
+//! The text codec: 5-bit tokens, bit-packed, most significant bit first.
+//!
+//! | token | meaning |
+//! |---|---|
+//! | 0 | space |
+//! | 1–26 | `a`–`z` (`A`–`Z` while caps lock is on) |
+//! | 27 `ESC` | an escape: 8 payload bits follow (see below) |
+//! | 28 `UPPER` | the next letter takes the other case; `UPPER UPPER` toggles caps lock |
+//! | 29 `REF` | an entry id follows as a varint: transclude that entry's rendered text |
+//! | 30 `CALL` | a callee varint, an argument count varint, then each argument as a bit-length varint and that many bits of a nested run |
+//! | 31 | newline |
+//!
+//! A **varint** is 5-bit chunks, least significant group first: bit 4 says another chunk
+//! follows, bits 0–3 are data. Ids under 16 take one chunk, under 256 two, under 65536 four.
+//!
+//! The **escape payload** byte `b`:
+//! - `0x00..=0x7F`: that ASCII byte (letters, space and newline have their own tokens);
+//! - `0xC2..=0xF4`: a UTF-8 lead byte; its continuation bytes follow as 6 bits each (the
+//!   `10` top bits are implied), and it becomes the run's *last lead*;
+//! - `0x80..=0xBF`: `n = b - 0x7F` characters (1–64) that share the last lead byte, each as
+//!   its continuation bits only (Hebrew, Cyrillic and most CJK runs pay 6 or 12 bits per
+//!   character instead of 16 or 24);
+//! - `0xF5`: a digit run: 5 bits holding `n - 2`, then `n` (2–33) digits of 4 bits each;
+//! - `0xF6`: **s mode** for the rest of the run. s, the user's language (`crate::s`), is
+//!   written in lowercase words and a few symbols, which plain packing writes in 13 bits
+//!   each. In s mode the case token is spent on them instead: `UPPER` and 4 bits is one of
+//!   the 16 symbols s uses most ([`S_SYMBOLS`]: its ten suffix characters, the literal
+//!   marks `{ } '`, and `> - =`), 9 bits; `ESC 0` and 4 bits is one of 16 more
+//!   ([`S_MORE`]: the digits and `+ * / < ( )`), 10 bits; `ESC 1` and an 8-bit payload is
+//!   any escape above (capitals are written this way, as ASCII), 14 bits. Caps lock is off
+//!   in s mode. The encoder turns it on for a text when that makes it shorter, so any text
+//!   may use it;
+//! - anything else (`0xC0`, `0xC1`, `0xF7..=0xFF`) is reserved, and fails to decode.
+//!
+//! A **callee** under 32 is a builtin (see `interp`); an entry `id` is written `id + 32`.
+//!
+//! A **run** is a sequence of segments (text, refs and calls). Caps lock and the last lead
+//! start off at the start of every run, so a call's arguments decode on their own.
+//!
+//! A **body** (what an entry stores) is a run with a 3-bit header holding how many padding
+//! bits end its last byte; an empty body is zero bytes.
+
+use std::sync::Arc;
+
+pub const SPACE: u32 = 0;
+pub const ESC: u32 = 27;
+pub const UPPER: u32 = 28;
+pub const REF: u32 = 29;
+pub const CALL: u32 = 30;
+pub const NEWLINE: u32 = 31;
+
+const DIGITS: u8 = 0xF5;
+const S_MODE: u8 = 0xF6;
+
+/// the symbols s mode writes as `UPPER` and 4 bits
+pub const S_SYMBOLS: [char; 16] = [
+    '?', '!', '~', '$', '`', '#', ';', ':', '.', '@', '{', '}', '\'', '>', '-', '=',
+];
+/// the ones it writes as `ESC 0` and 4 bits
+pub const S_MORE: [char; 16] = [
+    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '+', '*', '/', '<', '(', ')',
+];
+/// how deep calls may nest inside a body (decoding recurses per level)
+pub const MAX_NESTING: usize = 64;
+
+/// what a call calls
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+pub enum Callee {
+    /// one of the interpreter's builtins (0–31)
+    Builtin(u8),
+    /// a function (or any) entry, its body evaluated with the arguments
+    Entry(u64),
+}
+
+/// a nested run (a call's argument)
+pub type Run = Arc>;
+
+#[derive(Debug, Clone, PartialEq, Eq, Hash)]
+pub enum Seg {
+    Text(String),
+    Ref(u64),
+    Call { f: Callee, args: Vec },
+}
+
+impl Seg {
+    pub fn text(s: impl Into) -> Seg {
+        Seg::Text(s.into())
+    }
+
+    pub fn call(f: Callee, args: Vec>) -> Seg {
+        Seg::Call {
+            f,
+            args: args.into_iter().map(Arc::new).collect(),
+        }
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum CodecError {
+    /// the bits ran out inside a token
+    Truncated,
+    /// a reserved escape, a bad case token, a run without a lead, a bad digit
+    Invalid(&'static str),
+    /// the bytes don't make UTF-8
+    Utf8,
+    /// calls nested deeper than `MAX_NESTING`
+    TooDeep,
+}
+
+impl std::fmt::Display for CodecError {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        match self {
+            CodecError::Truncated => write!(f, "the packed text ends inside a token"),
+            CodecError::Invalid(why) => write!(f, "the packed text is invalid: {why}"),
+            CodecError::Utf8 => write!(f, "the packed text doesn't decode to UTF-8"),
+            CodecError::TooDeep => write!(f, "calls nest deeper than {MAX_NESTING}"),
+        }
+    }
+}
+
+// ---------------------------------------------------------------- bits
+
+#[derive(Default)]
+pub struct BitWriter {
+    bytes: Vec,
+    bits: usize,
+}
+
+impl BitWriter {
+    pub fn put(&mut self, value: u32, n: u32) {
+        for i in (0..n).rev() {
+            if self.bits.is_multiple_of(8) {
+                self.bytes.push(0);
+            }
+            if (value >> i) & 1 == 1 {
+                let last = self.bytes.len() - 1;
+                self.bytes[last] |= 0x80 >> (self.bits % 8);
+            }
+            self.bits += 1;
+        }
+    }
+
+    pub fn varint(&mut self, mut v: u64) {
+        loop {
+            let data = (v & 0xF) as u32;
+            v >>= 4;
+            if v == 0 {
+                self.put(data, 5);
+                return;
+            }
+            self.put(0x10 | data, 5);
+        }
+    }
+
+    /// appends another writer's bits
+    pub fn append(&mut self, other: &BitWriter) {
+        let mut r = BitReader::new(&other.bytes, 0, other.bits);
+        let mut left = other.bits;
+        while left > 0 {
+            let n = left.min(32) as u32;
+            self.put(r.get(n).unwrap_or(0), n);
+            left -= n as usize;
+        }
+    }
+
+    pub fn bits(&self) -> usize {
+        self.bits
+    }
+
+    /// the bytes, with the count of padding bits in the first three bits (which the
+    /// writer began with three zero bits for)
+    pub fn finish_padded(mut self) -> Vec {
+        let pad = (8 - self.bits % 8) % 8;
+        if let Some(b) = self.bytes.first_mut() {
+            *b |= (pad as u8) << 5;
+        }
+        self.bytes
+    }
+}
+
+pub struct BitReader<'a> {
+    bytes: &'a [u8],
+    pos: usize,
+    end: usize,
+}
+
+impl<'a> BitReader<'a> {
+    pub fn new(bytes: &'a [u8], pos: usize, end: usize) -> BitReader<'a> {
+        BitReader {
+            bytes,
+            pos,
+            end: end.min(bytes.len() * 8),
+        }
+    }
+
+    pub fn left(&self) -> usize {
+        self.end.saturating_sub(self.pos)
+    }
+
+    pub fn get(&mut self, n: u32) -> Result {
+        if self.left() < n as usize {
+            return Err(CodecError::Truncated);
+        }
+        let mut v = 0u32;
+        let mut need = n as usize;
+        while need > 0 {
+            let byte = self.bytes[self.pos / 8];
+            let off = self.pos % 8;
+            let take = need.min(8 - off);
+            let chunk = (byte >> (8 - off - take)) & ((1u16 << take) - 1) as u8;
+            v = (v << take) | chunk as u32;
+            self.pos += take;
+            need -= take;
+        }
+        Ok(v)
+    }
+
+    pub fn varint(&mut self) -> Result {
+        let mut v = 0u64;
+        for shift in (0..64).step_by(4) {
+            let c = self.get(5)? as u64;
+            v |= (c & 0xF) << shift;
+            if c & 0x10 == 0 {
+                return Ok(v);
+            }
+        }
+        Err(CodecError::Invalid("a varint longer than 64 bits"))
+    }
+}
+
+// ---------------------------------------------------------------- encoding
+
+fn letter(c: char) -> Option {
+    c.is_ascii_lowercase().then(|| c as u32 - 'a' as u32 + 1)
+}
+
+fn is_cased(c: char) -> bool {
+    c.is_ascii_alphabetic()
+}
+
+/// how many continuation bytes a UTF-8 lead byte has
+fn continuations(lead: u8) -> Option {
+    match lead {
+        0xC2..=0xDF => Some(1),
+        0xE0..=0xEF => Some(2),
+        0xF0..=0xF4 => Some(3),
+        _ => None,
+    }
+}
+
+#[derive(Clone)]
+struct RunState {
+    caps: bool,
+    lead: Option,
+    /// s mode is on (see the escape payloads above)
+    s: bool,
+}
+
+/// writes `ESC` and an 8-bit payload (with s mode's long-form bit when it's on)
+fn esc(w: &mut BitWriter, st: &RunState, b: u32) {
+    w.put(ESC, 5);
+    if st.s {
+        w.put(1, 1);
+    }
+    w.put(b, 8);
+}
+
+/// a text, turning s mode on first when that makes it shorter
+fn encode_text(w: &mut BitWriter, text: &str, st: &mut RunState) {
+    if !st.s && text.chars().any(|c| S_SYMBOLS.contains(&c)) {
+        let mut plain = BitWriter::default();
+        encode_text_in(&mut plain, text, &mut st.clone());
+        let mut on = st.clone();
+        on.s = true;
+        let mut smode = BitWriter::default();
+        encode_text_in(&mut smode, text, &mut on);
+        if smode.bits() + 13 < plain.bits() {
+            w.put(ESC, 5);
+            w.put(S_MODE as u32, 8);
+            st.s = true;
+            st.caps = false;
+        }
+    }
+    encode_text_in(w, text, st);
+}
+
+fn encode_text_in(w: &mut BitWriter, text: &str, st: &mut RunState) {
+    let chars: Vec = text.chars().collect();
+    let mut i = 0;
+    while i < chars.len() {
+        let c = chars[i];
+        if c == ' ' {
+            w.put(SPACE, 5);
+        } else if c == '\n' {
+            w.put(NEWLINE, 5);
+        } else if st.s {
+            // s mode: lowercase letters as tokens, its symbols short, the rest escaped
+            if c.is_ascii_lowercase() {
+                w.put(letter(c).expect("a letter"), 5);
+            } else if let Some(k) = S_SYMBOLS.iter().position(|&x| x == c) {
+                w.put(UPPER, 5);
+                w.put(k as u32, 4);
+            } else if c.is_ascii_digit() && chars[i..].iter().take(33).take_while(|c| c.is_ascii_digit()).count() >= 4 {
+                let n = chars[i..].iter().take(33).take_while(|c| c.is_ascii_digit()).count();
+                esc(w, st, DIGITS as u32);
+                w.put(n as u32 - 2, 5);
+                for d in &chars[i..i + n] {
+                    w.put(*d as u32 - '0' as u32, 4);
+                }
+                i += n;
+                continue;
+            } else if let Some(k) = S_MORE.iter().position(|&x| x == c) {
+                w.put(ESC, 5);
+                w.put(0, 1);
+                w.put(k as u32, 4);
+            } else if c.is_ascii() {
+                esc(w, st, c as u32);
+            } else {
+                encode_wide(w, &chars, &mut i, st);
+                continue;
+            }
+        } else if is_cased(c) {
+            let upper = c.is_ascii_uppercase();
+            let v = letter(c.to_ascii_lowercase()).unwrap();
+            if upper != st.caps {
+                // switch the lock when the case run ahead is long enough to pay for it
+                let ahead = chars[i..]
+                    .iter()
+                    .filter(|c| c.is_ascii_alphabetic())
+                    .take_while(|c| c.is_ascii_uppercase() == upper)
+                    .take(4)
+                    .count();
+                let switch = if upper { ahead >= 4 } else { ahead >= 2 };
+                if switch {
+                    w.put(UPPER, 5);
+                    w.put(UPPER, 5);
+                    st.caps = upper;
+                } else {
+                    w.put(UPPER, 5);
+                }
+            }
+            w.put(v, 5);
+        } else if c.is_ascii_digit() {
+            let n = chars[i..].iter().take(33).take_while(|c| c.is_ascii_digit()).count();
+            if n >= 3 {
+                esc(w, st, DIGITS as u32);
+                w.put(n as u32 - 2, 5);
+                for d in &chars[i..i + n] {
+                    w.put(*d as u32 - '0' as u32, 4);
+                }
+                i += n;
+                continue;
+            }
+            esc(w, st, c as u32);
+        } else if c.is_ascii() {
+            esc(w, st, c as u32);
+        } else {
+            encode_wide(w, &chars, &mut i, st);
+            continue;
+        }
+        i += 1;
+    }
+}
+
+/// a non-ASCII character at `chars[*i]` (a run of ones sharing the last lead byte, or one
+/// with its lead), moving `i` past what it wrote
+fn encode_wide(w: &mut BitWriter, chars: &[char], i: &mut usize, st: &mut RunState) {
+    let c = chars[*i];
+    let mut buf = [0u8; 4];
+    let lead = c.encode_utf8(&mut buf).as_bytes()[0];
+    if st.lead == Some(lead) {
+        // a run of characters sharing the last lead byte
+        let n = chars[*i..]
+            .iter()
+            .take(64)
+            .take_while(|c| {
+                let mut b = [0u8; 4];
+                !c.is_ascii() && c.encode_utf8(&mut b).as_bytes()[0] == lead
+            })
+            .count();
+        esc(w, st, 0x7F + n as u32);
+        for ch in &chars[*i..*i + n] {
+            let mut b = [0u8; 4];
+            for cont in &ch.encode_utf8(&mut b).as_bytes()[1..] {
+                w.put((cont & 0x3F) as u32, 6);
+            }
+        }
+        *i += n;
+        return;
+    }
+    let bytes = c.encode_utf8(&mut buf).as_bytes();
+    esc(w, st, lead as u32);
+    for cont in &bytes[1..] {
+        w.put((cont & 0x3F) as u32, 6);
+    }
+    st.lead = Some(lead);
+    *i += 1;
+}
+
+fn encode_run(w: &mut BitWriter, segs: &[Seg]) {
+    let mut st = RunState {
+        caps: false,
+        lead: None,
+        s: false,
+    };
+    for s in segs {
+        match s {
+            Seg::Text(t) => encode_text(w, t, &mut st),
+            Seg::Ref(id) => {
+                w.put(REF, 5);
+                w.varint(*id);
+            }
+            Seg::Call { f, args } => {
+                w.put(CALL, 5);
+                w.varint(match f {
+                    Callee::Builtin(b) => (*b & 31) as u64,
+                    Callee::Entry(id) => id.saturating_add(32),
+                });
+                w.varint(args.len() as u64);
+                for a in args {
+                    let mut inner = BitWriter::default();
+                    encode_run(&mut inner, a);
+                    w.varint(inner.bits() as u64);
+                    w.append(&inner);
+                }
+            }
+        }
+    }
+}
+
+/// packs a run into a body
+pub fn pack(segs: &[Seg]) -> Vec {
+    if segs.iter().all(|s| matches!(s, Seg::Text(t) if t.is_empty())) {
+        return Vec::new();
+    }
+    let mut w = BitWriter::default();
+    w.put(0, 3);
+    encode_run(&mut w, segs);
+    let pad = (8 - w.bits % 8) % 8;
+    w.bytes[0] |= (pad as u8) << 5;
+    w.bytes
+}
+
+pub fn pack_text(text: &str) -> Vec {
+    if text.is_empty() {
+        return Vec::new();
+    }
+    pack(&[Seg::Text(text.to_string())])
+}
+
+/// how many bits a text takes inside a run (no body header), for weighing borrowing
+pub fn text_bits(text: &str) -> usize {
+    let mut w = BitWriter::default();
+    encode_text(
+        &mut w,
+        text,
+        &mut RunState {
+            caps: false,
+            lead: None,
+            s: false,
+        },
+    );
+    w.bits()
+}
+
+/// how many bits a ref to this id takes
+pub fn ref_bits(id: u64) -> usize {
+    let mut w = BitWriter::default();
+    w.varint(id);
+    5 + w.bits()
+}
+
+// ---------------------------------------------------------------- decoding
+
+fn push_text(out: &mut Vec, bytes: &mut Vec) -> Result<(), CodecError> {
+    if bytes.is_empty() {
+        return Ok(());
+    }
+    let s = String::from_utf8(std::mem::take(bytes)).map_err(|_| CodecError::Utf8)?;
+    match out.last_mut() {
+        Some(Seg::Text(t)) => t.push_str(&s),
+        _ => out.push(Seg::Text(s)),
+    }
+    Ok(())
+}
+
+fn decode_run(r: &mut BitReader, depth: usize) -> Result, CodecError> {
+    if depth > MAX_NESTING {
+        return Err(CodecError::TooDeep);
+    }
+    let mut out = Vec::new();
+    let mut text: Vec = Vec::new();
+    let mut caps = false;
+    let mut lead: Option = None;
+    let mut smode = false;
+    while r.left() >= 5 {
+        let t = r.get(5)?;
+        match t {
+            SPACE => text.push(b' '),
+            1..=26 => text.push(if caps { b'A' } else { b'a' } + t as u8 - 1),
+            NEWLINE => text.push(b'\n'),
+            UPPER if smode => {
+                let mut buf = [0u8; 4];
+                text.extend_from_slice(S_SYMBOLS[r.get(4)? as usize].encode_utf8(&mut buf).as_bytes());
+            }
+            UPPER => match r.get(5)? {
+                UPPER => caps = !caps,
+                l @ 1..=26 => text.push(if caps { b'a' } else { b'A' } + l as u8 - 1),
+                _ => return Err(CodecError::Invalid("UPPER before a non-letter")),
+            },
+            ESC => {
+                if smode && r.get(1)? == 0 {
+                    text.push(S_MORE[r.get(4)? as usize] as u8);
+                    continue;
+                }
+                let b = r.get(8)? as u8;
+                if b == S_MODE {
+                    smode = true;
+                    caps = false;
+                } else if b < 0x80 {
+                    text.push(b);
+                } else if let Some(k) = continuations(b) {
+                    text.push(b);
+                    for _ in 0..k {
+                        text.push(0x80 | r.get(6)? as u8);
+                    }
+                    lead = Some(b);
+                } else if (0x80..=0xBF).contains(&b) {
+                    let l = lead.ok_or(CodecError::Invalid("a lead run with no lead before it"))?;
+                    let k = continuations(l).unwrap_or(0);
+                    for _ in 0..(b as usize - 0x7F) {
+                        text.push(l);
+                        for _ in 0..k {
+                            text.push(0x80 | r.get(6)? as u8);
+                        }
+                    }
+                } else if b == DIGITS {
+                    let n = r.get(5)? + 2;
+                    for _ in 0..n {
+                        let d = r.get(4)?;
+                        if d > 9 {
+                            return Err(CodecError::Invalid("a digit above 9"));
+                        }
+                        text.push(b'0' + d as u8);
+                    }
+                } else {
+                    return Err(CodecError::Invalid("a reserved escape"));
+                }
+            }
+            REF => {
+                push_text(&mut out, &mut text)?;
+                out.push(Seg::Ref(r.varint()?));
+            }
+            CALL => {
+                push_text(&mut out, &mut text)?;
+                let c = r.varint()?;
+                let f = if c < 32 {
+                    Callee::Builtin(c as u8)
+                } else {
+                    Callee::Entry(c - 32)
+                };
+                let argc = r.varint()?;
+                if argc > 1 << 16 {
+                    return Err(CodecError::Invalid("too many arguments"));
+                }
+                let mut args = Vec::with_capacity(argc as usize);
+                for _ in 0..argc {
+                    let len = r.varint()? as usize;
+                    if len > r.left() {
+                        return Err(CodecError::Truncated);
+                    }
+                    let mut inner = BitReader::new(r.bytes, r.pos, r.pos + len);
+                    args.push(Arc::new(decode_run(&mut inner, depth + 1)?));
+                    if inner.left() != 0 {
+                        return Err(CodecError::Invalid("an argument with stray bits"));
+                    }
+                    r.pos += len;
+                }
+                out.push(Seg::Call { f, args });
+            }
+            _ => unreachable!("5-bit token"),
+        }
+    }
+    if r.left() != 0 {
+        return Err(CodecError::Truncated);
+    }
+    push_text(&mut out, &mut text)?;
+    Ok(out)
+}
+
+/// unpacks a body into its run
+pub fn unpack(body: &[u8]) -> Result, CodecError> {
+    if body.is_empty() {
+        return Ok(Vec::new());
+    }
+    let pad = (body[0] >> 5) as usize;
+    let end = body.len() * 8;
+    if pad > end - 3 {
+        return Err(CodecError::Truncated);
+    }
+    let mut r = BitReader::new(body, 3, end - pad);
+    decode_run(&mut r, 0)
+}
+
+/// the text of a body with no refs or calls in it
+pub fn unpack_text(body: &[u8]) -> Result {
+    let mut out = String::new();
+    for s in unpack(body)? {
+        match s {
+            Seg::Text(t) => out.push_str(&t),
+            _ => return Err(CodecError::Invalid("a ref or call in a plain text")),
+        }
+    }
+    Ok(out)
+}
+
+/// the run's text with refs and calls left out (for a source view or a quick check)
+pub fn plain_parts(segs: &[Seg]) -> String {
+    segs.iter()
+        .filter_map(|s| match s {
+            Seg::Text(t) => Some(t.as_str()),
+            _ => None,
+        })
+        .collect()
+}
+
+/// every entry a run refers to or calls, nested arguments included
+pub fn mentions(segs: &[Seg], out: &mut Vec) {
+    for s in segs {
+        match s {
+            Seg::Ref(id) => out.push(*id),
+            Seg::Call { f, args } => {
+                if let Callee::Entry(id) = f {
+                    out.push(*id);
+                }
+                for a in args {
+                    mentions(a, out);
+                }
+            }
+            Seg::Text(_) => {}
+        }
+    }
+}
+
+/// merges adjacent texts and drops empty ones, so equal runs compare equal
+pub fn normalize(segs: Vec) -> Vec {
+    let mut out: Vec = Vec::with_capacity(segs.len());
+    for s in segs {
+        match s {
+            Seg::Text(t) if t.is_empty() => {}
+            Seg::Text(t) => match out.last_mut() {
+                Some(Seg::Text(prev)) => prev.push_str(&t),
+                _ => out.push(Seg::Text(t)),
+            },
+            Seg::Call { f, args } => out.push(Seg::Call {
+                f,
+                args: args
+                    .into_iter()
+                    .map(|a| Arc::new(normalize(Arc::unwrap_or_clone(a))))
+                    .collect(),
+            }),
+            other => out.push(other),
+        }
+    }
+    out
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    /// xorshift, so failures reproduce
+    pub struct Rng(u64);
+    impl Rng {
+        pub fn new(seed: u64) -> Rng {
+            Rng(seed.wrapping_mul(6364136223846793005).wrapping_add(1442695040888963407) | 1)
+        }
+        pub fn next(&mut self) -> u64 {
+            self.0 ^= self.0 << 13;
+            self.0 ^= self.0 >> 7;
+            self.0 ^= self.0 << 17;
+            self.0
+        }
+        pub fn below(&mut self, n: u64) -> u64 {
+            self.next() % n.max(1)
+        }
+    }
+
+    fn round(text: &str) {
+        let packed = pack_text(text);
+        assert_eq!(unpack_text(&packed).unwrap(), text, "{text:?}");
+    }
+
+    #[test]
+    fn known_layouts() {
+        assert!(pack_text("").is_empty());
+        // "a": header 3 bits (pad 0b000 → pad = 8 - 8 = 0)... 3 + 5 = 8 bits, no padding
+        assert_eq!(pack_text("a"), vec![0b000_00001]);
+        // "ab": 3 + 10 = 13 bits, 3 padding bits
+        assert_eq!(pack_text("ab"), vec![0b0110_0001, 0b0001_0000]);
+        assert_eq!(pack_text("z "), vec![0b0111_1010, 0b0000_0000]);
+        // lowercase prose is 5/8 of its UTF-8 size, plus the header
+        assert_eq!(pack_text(&"abcdefgh".repeat(10)).len(), (3 + 400usize).div_ceil(8));
+        assert_eq!(ref_bits(0), 10);
+        assert_eq!(ref_bits(15), 10);
+        assert_eq!(ref_bits(16), 15);
+        assert_eq!(ref_bits(65535), 25);
+    }
+
+    #[test]
+    fn round_trips() {
+        for t in [
+            "a",
+            " ",
+            "\n",
+            "hello world",
+            "Hello World",
+            "HELLO WORLD and NASA",
+            "McDONALD's",
+            "aBcDeFgHiJ",
+            "ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz",
+            "x = 1234567890123456789012345678901234567890 y",
+            "12 345 6789 0",
+            "# Title\n\n- **bold** _it_ `code` [link](http://x.y/z?q=1&r=2)\n",
+            "tabs\tand\r\nreturns",
+            "שלום עולם",
+            "Λόγος καὶ ἀλήθεια",
+            "привет мир Привет",
+            "日本語のテキスト、漢字とかな",
+            "emoji 🙂🙃 mixed ok 🎉",
+            "é è ê ë",
+            "\u{0}\u{7f}\u{80}\u{7ff}\u{800}\u{ffff}\u{10000}\u{10ffff}",
+        ] {
+            round(t);
+        }
+    }
+
+    #[test]
+    fn fuzz_any_utf8() {
+        let pools: [&[char]; 4] = [
+            &['a', 'e', 't', ' ', 'z', 'q', 'n'],
+            &['a', 'B', 'C', ' ', '\n', '1', '9', '.', '#', '*', 'Z'],
+            &['ש', 'ל', 'ו', 'ם', ' ', 'λ', 'ό', 'я', '日', '🙂', 'a', '0'],
+            &[
+                '\u{0}',
+                '\u{7f}',
+                '\u{80}',
+                '\u{7ff}',
+                '\u{800}',
+                '\u{ffff}',
+                '\u{10000}',
+                '\u{10ffff}',
+                'é',
+                'A',
+            ],
+        ];
+        let mut rng = Rng::new(42);
+        for case in 0..4000 {
+            let len = rng.below(120) as usize;
+            let text: String = if case % 5 == 4 {
+                // any scalar value at all
+                (0..len)
+                    .filter_map(|_| char::from_u32(rng.below(0x11_0000) as u32))
+                    .collect()
+            } else {
+                let pool = pools[case % 4];
+                (0..len).map(|_| pool[rng.below(pool.len() as u64) as usize]).collect()
+            };
+            round(&text);
+        }
+    }
+
+    fn random_run(rng: &mut Rng, depth: usize) -> Vec {
+        let mut out = Vec::new();
+        for _ in 0..rng.below(5) {
+            match rng.below(if depth > 3 { 2 } else { 3 }) {
+                0 => {
+                    let pool = ['a', 'Q', ' ', 'λ', '5', '\n', '日'];
+                    out.push(Seg::Text(
+                        (0..1 + rng.below(9)).map(|_| pool[rng.below(7) as usize]).collect(),
+                    ))
+                }
+                1 => out.push(Seg::Ref(rng.next() >> rng.below(64))),
+                _ => {
+                    let f = if rng.below(2) == 0 {
+                        Callee::Builtin(rng.below(32) as u8)
+                    } else {
+                        Callee::Entry(rng.below(1 << 40))
+                    };
+                    let args = (0..rng.below(4)).map(|_| random_run(rng, depth + 1)).collect();
+                    out.push(Seg::call(f, args));
+                }
+            }
+        }
+        normalize(out)
+    }
+
+    #[test]
+    fn fuzz_runs_with_refs_and_calls() {
+        let mut rng = Rng::new(7);
+        for _ in 0..3000 {
+            let run = random_run(&mut rng, 0);
+            let packed = pack(&run);
+            assert_eq!(unpack(&packed).unwrap(), run);
+        }
+        // u64::MAX as a ref, the largest entry callee
+        let run = vec![Seg::Ref(u64::MAX), Seg::call(Callee::Entry(u64::MAX - 32), vec![])];
+        assert_eq!(unpack(&pack(&run)).unwrap(), run);
+    }
+
+    #[test]
+    fn corrupt_bodies_fail_cleanly() {
+        let mut rng = Rng::new(99);
+        let mut failures = 0;
+        for _ in 0..20_000 {
+            let len = rng.below(24) as usize;
+            let bytes: Vec = (0..len).map(|_| rng.next() as u8).collect();
+            // never a panic; errors are fine
+            if unpack(&bytes).is_err() {
+                failures += 1;
+            }
+        }
+        assert!(failures > 0);
+        // a reserved escape
+        let mut w = BitWriter::default();
+        w.put(0, 3);
+        w.put(ESC, 5);
+        w.put(0xFF, 8);
+        let pad = ((8 - w.bits % 8) % 8) as u8;
+        let mut b = w.bytes.clone();
+        b[0] |= pad << 5;
+        assert!(matches!(unpack(&b), Err(CodecError::Invalid(_))));
+        // deep nesting is refused, not a stack overflow
+        let mut run = vec![Seg::text("x")];
+        for _ in 0..(MAX_NESTING + 2) {
+            run = vec![Seg::call(Callee::Builtin(3), vec![run])];
+        }
+        assert_eq!(unpack(&pack(&run)), Err(CodecError::TooDeep));
+    }
+
+    #[test]
+    fn s_mode_makes_s_programs_shorter() {
+        let prog =
+            "{i: i~ 0 >> loop.?} loop$ 1000 i# loop.. i~ >\n{~x~ y@} f$ a b f.. {n~ >_} p$ 3 p &&& x? y! =~ `prng";
+        let packed = pack_text(prog);
+        assert_eq!(unpack_text(&packed).unwrap(), prog);
+        // the same text with s mode off
+        let mut w = BitWriter::default();
+        w.put(0, 3);
+        encode_text_in(
+            &mut w,
+            prog,
+            &mut RunState {
+                caps: false,
+                lead: None,
+                s: false,
+            },
+        );
+        let plain = w.bits().div_ceil(8);
+        eprintln!("s mode: {} bytes, plain {plain}, utf-8 {}", packed.len(), prog.len());
+        assert!(
+            packed.len() * 100 < plain * 88 && packed.len() < prog.len(),
+            "{} vs {plain}",
+            packed.len()
+        );
+        // prose with a symbol or two doesn't switch
+        let prose = "an ordinary sentence, with a full stop.";
+        let mut w = BitWriter::default();
+        w.put(0, 3);
+        encode_text_in(
+            &mut w,
+            prose,
+            &mut RunState {
+                caps: false,
+                lead: None,
+                s: false,
+            },
+        );
+        assert_eq!(pack_text(prose).len(), w.bits().div_ceil(8));
+        // s mode across segments and in arguments, with other escapes after it
+        let run = vec![
+            Seg::text("x~ y. {a} 'b' é ü 12345"),
+            Seg::Ref(3),
+            Seg::text("z~ 中文"),
+            Seg::call(Callee::Builtin(3), vec![vec![Seg::text("q$ r@ ~~")]]),
+        ];
+        assert_eq!(unpack(&pack(&run)).unwrap(), run);
+    }
+
+    #[test]
+    fn compression_is_better_than_utf8() {
+        let prose = "the quick brown fox jumps over the lazy dog and keeps running far away";
+        let p = pack_text(prose).len() as f64 / prose.len() as f64;
+        assert!(p < 0.66, "{p}");
+        // 2-byte letters cost 6 bits after the first in a run, spaces 5
+        let hebrew = "שלום עולם ומלואו שלום";
+        let h = pack_text(hebrew).len() as f64 / hebrew.len() as f64;
+        assert!(h < 0.65, "{h}");
+    }
+}
diff --git a/core/src/graph/gematria.rs b/core/src/graph/gematria.rs
new file mode 100644
index 00000000..aa84f166
--- /dev/null
+++ b/core/src/graph/gematria.rs
@@ -0,0 +1,74 @@
+//! The measures an entry is filed under: ordinal and reversed sums (from `simd`) and the
+//! letter frequency key.
+
+use crate::simd;
+
+/// which number a text is filed under
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum Mode {
+    /// a = 1 .. z = 26, other characters 0 (`simd::sums`)
+    Ordinal = 0,
+    /// a = 26 .. z = 1 (`simd::sums`)
+    Reversed = 1,
+}
+
+impl Mode {
+    pub const ALL: [Mode; 2] = [Mode::Ordinal, Mode::Reversed];
+
+    pub fn name(self) -> &'static str {
+        match self {
+            Mode::Ordinal => "ordinal",
+            Mode::Reversed => "reversed",
+        }
+    }
+
+    pub fn parse(s: &str) -> Option {
+        Mode::ALL.into_iter().find(|m| m.name() == s.trim())
+    }
+
+    pub fn from_u8(b: u8) -> Option {
+        Mode::ALL.get(b as usize).copied()
+    }
+}
+
+/// everything a text is filed under
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Measure {
+    pub ordinal: i64,
+    pub reversed: i64,
+    pub frequency: String,
+}
+
+impl Measure {
+    pub fn of(text: &str) -> Measure {
+        let s = simd::sums(text.as_bytes());
+        Measure {
+            ordinal: s.ordinal as i64,
+            reversed: s.reversed as i64,
+            frequency: simd::frequency_key(text.as_bytes()),
+        }
+    }
+
+    pub fn get(&self, mode: Mode) -> i64 {
+        match mode {
+            Mode::Ordinal => self.ordinal,
+            Mode::Reversed => self.reversed,
+        }
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn modes() {
+        let m = Measure::of("hello");
+        assert_eq!((m.get(Mode::Ordinal), m.get(Mode::Reversed)), (52, 83));
+        assert_eq!(Mode::parse(" reversed "), Some(Mode::Reversed));
+        assert_eq!(Mode::parse("atbash"), None);
+        assert_eq!(Mode::from_u8(0), Some(Mode::Ordinal));
+        assert_eq!(Mode::from_u8(1), Some(Mode::Reversed));
+        assert_eq!(Mode::from_u8(2), None);
+    }
+}
diff --git a/core/src/graph/interp.rs b/core/src/graph/interp.rs
new file mode 100644
index 00000000..d5b2ff4b
--- /dev/null
+++ b/core/src/graph/interp.rs
@@ -0,0 +1,995 @@
+//! The interpreter: rendering a body means decoding its run, transcluding the entries it
+//! refers to (`REF`) and evaluating its calls (`CALL`).
+//!
+//! Everything is text. A function is any entry (by convention of mime
+//! `application/x-anend-fn`): its body is a template evaluated with the call's arguments,
+//! which it reads with the builtin `arg(n)`. Arguments are evaluated before the call
+//! (call by value), except for `if`, which evaluates only the branch it takes. With
+//! recursion and `if` the language is Turing complete.
+//!
+//! **No native recursion.** Evaluation is a loop over an explicit continuation stack, so a
+//! Rust stack overflow can't happen. A call in **tail position** replaces the frame that
+//! makes it instead of pushing a new one, so tail recursion runs in constant stack,
+//! bounded only by fuel. Tail positions:
+//! - the last segment of a run (a function body, an `if` branch, an argument, an entry's
+//!   body): the text before it has already been emitted into the frame's output, and the
+//!   call's output continues it (`out = prefix ++ call`, which concatenation makes sound);
+//! - the branch `if` takes, when the `if` is itself in tail position;
+//! - the last argument of `concat`, when the `concat` is in tail position (the earlier
+//!   arguments are evaluated and emitted first).
+//!
+//! Anything else (an argument of a call other than those, a call followed by more
+//! segments) is a non-tail call and pushes frames, bounded by `Limits::depth`.
+//!
+//! **Limits**, each an error rather than a panic: fuel (one unit per step, plus the size
+//! of builtin work), the continuation stack depth, the size of any one output, and how
+//! long a text a builtin may be asked to make. `REF` resolution is cycle-safe (an entry
+//! that transcludes itself, directly or not, is an error); calls may recurse freely.
+//! Non-tail calls of entries are memoised by (entry, arguments): evaluation is pure, so
+//! naive recursive Fibonacci runs in linear time.
+//!
+//! **Builtins** (the callee codes under 32; numbers are decimal `i64` text, the empty text
+//! is 0, and truth is non-empty text with `"1"` for true and `""` for false):
+//!
+//! | code | name | does |
+//! |---|---|---|
+//! | 0 | `arg(n)` | the call's `n`th argument, from 0 (`""` when there's none) |
+//! | 1 | `if(c, a, b)` | `a` when `c` is non-empty, else `b` (only that one is evaluated) |
+//! | 2 | `eq(a, b, …)` | whether all are equal |
+//! | 3 | `concat(…)` | the arguments joined |
+//! | 4 | `len(a)` | how many characters |
+//! | 5 | `sum(a, mode)` | `a`'s ordinal (the default) or `reversed` sum |
+//! | 6 | `slice(a, from, to)` | characters `from..to`; negative counts from the end, `to` defaults to the end |
+//! | 7 | `lookup(id)` | the rendered text of the entry with that (decimal) id |
+//! | 8–12 | `add`, `sub`, `mul`, `div`, `mod` | arithmetic over all the arguments, left to right; overflow and division by zero are errors |
+//! | 13 | `lt(a, b)` | whether `a < b`, numerically |
+//! | 14 | `not(a)` | whether `a` is empty |
+//! | 15 | `argc()` | how many arguments the call has |
+//!
+//! Codes 16–31 are reserved (calling one is an error).
+
+use std::collections::{HashMap, HashSet};
+use std::rc::Rc;
+use std::sync::Arc;
+
+use super::codec::{Callee, CodecError, Run, Seg};
+use super::gematria::{Measure, Mode};
+
+pub mod builtin {
+    pub const ARG: u8 = 0;
+    pub const IF: u8 = 1;
+    pub const EQ: u8 = 2;
+    pub const CONCAT: u8 = 3;
+    pub const LEN: u8 = 4;
+    pub const SUM: u8 = 5;
+    pub const SLICE: u8 = 6;
+    pub const LOOKUP: u8 = 7;
+    pub const ADD: u8 = 8;
+    pub const SUB: u8 = 9;
+    pub const MUL: u8 = 10;
+    pub const DIV: u8 = 11;
+    pub const MOD: u8 = 12;
+    pub const LT: u8 = 13;
+    pub const NOT: u8 = 14;
+    pub const ARGC: u8 = 15;
+
+    pub const NAMES: [&str; 16] = [
+        "arg", "if", "eq", "concat", "len", "sum", "slice", "lookup", "add", "sub", "mul", "div", "mod", "lt", "not",
+        "argc",
+    ];
+
+    pub fn by_name(name: &str) -> Option {
+        NAMES.iter().position(|n| *n == name).map(|i| i as u8)
+    }
+}
+
+/// where the interpreter reads entries' bodies from
+pub trait Source {
+    /// an entry's body as a run, `None` when there's no such entry
+    fn body(&self, id: u64) -> Result>, String>;
+}
+
+impl Source for HashMap> {
+    fn body(&self, id: u64) -> Result>, String> {
+        Ok(self.get(&id).cloned())
+    }
+}
+
+#[derive(Debug, Clone, Copy)]
+pub struct Limits {
+    /// steps an evaluation may take
+    pub fuel: u64,
+    /// continuation frames that may be waiting at once (non-tail nesting)
+    pub depth: usize,
+    /// bytes any one output (or argument) may grow to
+    pub output: usize,
+    /// memoised calls kept
+    pub memo: usize,
+}
+
+impl Default for Limits {
+    fn default() -> Limits {
+        Limits {
+            fuel: 10_000_000,
+            depth: 10_000,
+            output: 4 << 20,
+            memo: 4096,
+        }
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum EvalError {
+    /// ran out of fuel
+    Fuel,
+    /// non-tail calls nested deeper than the limit
+    Depth,
+    /// an output grew past the limit
+    Output,
+    /// an entry transcludes itself
+    Cycle(u64),
+    /// a ref or call names an entry that isn't there
+    Missing(u64),
+    /// a builtin was given something it can't use
+    Builtin(&'static str, String),
+    Decode(CodecError),
+    Source(String),
+}
+
+impl std::fmt::Display for EvalError {
+    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
+        match self {
+            EvalError::Fuel => write!(f, "ran out of fuel"),
+            EvalError::Depth => write!(f, "calls nest too deeply"),
+            EvalError::Output => write!(f, "the output grew too large"),
+            EvalError::Cycle(id) => write!(f, "entry {id} transcludes itself"),
+            EvalError::Missing(id) => write!(f, "there is no entry {id}"),
+            EvalError::Builtin(name, why) => write!(f, "{name}: {why}"),
+            EvalError::Decode(e) => write!(f, "{e}"),
+            EvalError::Source(e) => write!(f, "{e}"),
+        }
+    }
+}
+
+type Env = Rc<[String]>;
+
+/// how many calls one memo frame remembers (a tail loop adds one per turn)
+const MEMO_KEYS: usize = 16;
+
+enum Cont {
+    /// a run being evaluated into `out`
+    Run {
+        run: Run,
+        pos: usize,
+        env: Env,
+        out: String,
+    },
+    /// collecting the arguments of the call at `site[at]`
+    Args {
+        site: Run,
+        at: usize,
+        vals: Vec,
+        env: Env,
+        tail: bool,
+    },
+    /// waiting for the condition of the `if` at `site[at]`
+    If { site: Run, at: usize, env: Env, tail: bool },
+    /// a call's value, to remember under these keys
+    Memo { keys: Vec<(u64, Vec)> },
+    /// an entry's rendered text, to cache and unmark
+    RefDone { id: u64 },
+}
+
+/// what evaluating took
+#[derive(Debug, Clone, Copy, Default)]
+pub struct Stats {
+    pub steps: u64,
+    pub max_stack: usize,
+    pub memo_hits: u64,
+}
+
+pub struct Interp<'a, S: Source + ?Sized> {
+    src: &'a S,
+    pub limits: Limits,
+    pub stats: Stats,
+    fuel: u64,
+    bodies: HashMap,
+    rendered: HashMap>,
+    memo: HashMap<(u64, Vec), String>,
+    active: HashSet,
+}
+
+fn num(name: &'static str, s: &str) -> Result {
+    let t = s.trim();
+    if t.is_empty() {
+        return Ok(0);
+    }
+    t.parse::()
+        .map_err(|_| EvalError::Builtin(name, format!("{t:?} isn't a number")))
+}
+
+fn truth(b: bool) -> String {
+    if b { "1".into() } else { String::new() }
+}
+
+impl<'a, S: Source + ?Sized> Interp<'a, S> {
+    pub fn new(src: &'a S) -> Interp<'a, S> {
+        Interp::with_limits(src, Limits::default())
+    }
+
+    pub fn with_limits(src: &'a S, limits: Limits) -> Interp<'a, S> {
+        Interp {
+            src,
+            limits,
+            stats: Stats::default(),
+            fuel: limits.fuel,
+            bodies: HashMap::new(),
+            rendered: HashMap::new(),
+            memo: HashMap::new(),
+            active: HashSet::new(),
+        }
+    }
+
+    /// the rendered text of an entry
+    pub fn render(&mut self, id: u64) -> Result {
+        self.eval(&[Seg::Ref(id)])
+    }
+
+    /// evaluates a run with no arguments
+    pub fn eval(&mut self, run: &[Seg]) -> Result {
+        self.start(Arc::new(run.to_vec()), Rc::from(Vec::new()))
+    }
+
+    /// calls an entry with arguments
+    pub fn call(&mut self, f: u64, args: &[&str]) -> Result {
+        let run = vec![Seg::call(
+            Callee::Entry(f),
+            args.iter().map(|a| vec![Seg::text(*a)]).collect(),
+        )];
+        self.eval(&run)
+    }
+
+    fn body(&mut self, id: u64) -> Result {
+        if let Some(b) = self.bodies.get(&id) {
+            return Ok(b.clone());
+        }
+        let b = Arc::new(
+            self.src
+                .body(id)
+                .map_err(EvalError::Source)?
+                .ok_or(EvalError::Missing(id))?,
+        );
+        if self.bodies.len() < 1 << 16 {
+            self.bodies.insert(id, b.clone());
+        }
+        Ok(b)
+    }
+
+    fn burn(&mut self, n: u64) -> Result<(), EvalError> {
+        self.stats.steps += n;
+        self.fuel = self.fuel.checked_sub(n).ok_or(EvalError::Fuel)?;
+        Ok(())
+    }
+
+    fn grow(&self, out: &mut String, s: &str) -> Result<(), EvalError> {
+        if out.len() + s.len() > self.limits.output {
+            return Err(EvalError::Output);
+        }
+        out.push_str(s);
+        Ok(())
+    }
+
+    fn push(&mut self, stack: &mut Vec, c: Cont) -> Result<(), EvalError> {
+        stack.push(c);
+        if stack.len() > self.limits.depth {
+            return Err(EvalError::Depth);
+        }
+        self.stats.max_stack = self.stats.max_stack.max(stack.len());
+        Ok(())
+    }
+
+    /// runs `run` (in `env`) in the place of the frame on top of the stack, keeping its
+    /// output: a tail call
+    fn replace_top(&mut self, stack: &mut [Cont], new: Run, new_env: Env) {
+        if let Some(Cont::Run { run, pos, env, .. }) = stack.last_mut() {
+            *run = new;
+            *pos = 0;
+            *env = new_env;
+        }
+    }
+
+    fn enter(&mut self, stack: &mut Vec, run: Run, env: Env, tail: bool) -> Result<(), EvalError> {
+        if tail {
+            self.replace_top(stack, run, env);
+            Ok(())
+        } else {
+            self.push(
+                stack,
+                Cont::Run {
+                    run,
+                    pos: 0,
+                    env,
+                    out: String::new(),
+                },
+            )
+        }
+    }
+
+    fn begin_ref(&mut self, stack: &mut Vec, id: u64) -> Result, EvalError> {
+        if let Some(t) = self.rendered.get(&id) {
+            return Ok(Some(t.to_string()));
+        }
+        if !self.active.insert(id) {
+            return Err(EvalError::Cycle(id));
+        }
+        let body = self.body(id)?;
+        self.push(stack, Cont::RefDone { id })?;
+        self.push(
+            stack,
+            Cont::Run {
+                run: body,
+                pos: 0,
+                env: Rc::from(Vec::new()),
+                out: String::new(),
+            },
+        )?;
+        Ok(None)
+    }
+
+    fn start(&mut self, run: Run, env: Env) -> Result {
+        self.active.clear();
+        self.fuel = self.limits.fuel;
+        let mut stack: Vec = Vec::new();
+        self.push(
+            &mut stack,
+            Cont::Run {
+                run,
+                pos: 0,
+                env,
+                out: String::new(),
+            },
+        )?;
+        let mut ret: Option = None;
+        loop {
+            self.burn(1)?;
+            if let Some(v) = ret.take() {
+                let Some(top) = stack.pop() else { return Ok(v) };
+                match top {
+                    Cont::Run { run, pos, env, mut out } => {
+                        self.grow(&mut out, &v)?;
+                        stack.push(Cont::Run { run, pos, env, out });
+                    }
+                    Cont::Args {
+                        site,
+                        at,
+                        mut vals,
+                        env,
+                        tail,
+                    } => {
+                        vals.push(v);
+                        let Seg::Call { f, args } = &site[at] else {
+                            unreachable!()
+                        };
+                        let f = *f;
+                        let next = vals.len();
+                        if next == args.len() {
+                            ret = self.dispatch(&mut stack, f, vals, env, tail)?;
+                        } else if tail && f == Callee::Builtin(builtin::CONCAT) && next == args.len() - 1 {
+                            // the last piece of a concat in tail position continues the frame
+                            let last = args[next].clone();
+                            if let Some(Cont::Run { out, .. }) = stack.last_mut() {
+                                for v in &vals {
+                                    if out.len() + v.len() > self.limits.output {
+                                        return Err(EvalError::Output);
+                                    }
+                                    out.push_str(v);
+                                }
+                            }
+                            self.replace_top(&mut stack, last, env);
+                        } else {
+                            let arg = args[next].clone();
+                            self.push(
+                                &mut stack,
+                                Cont::Args {
+                                    site,
+                                    at,
+                                    vals,
+                                    env: env.clone(),
+                                    tail,
+                                },
+                            )?;
+                            self.push(
+                                &mut stack,
+                                Cont::Run {
+                                    run: arg,
+                                    pos: 0,
+                                    env,
+                                    out: String::new(),
+                                },
+                            )?;
+                        }
+                    }
+                    Cont::If { site, at, env, tail } => {
+                        let Seg::Call { args, .. } = &site[at] else {
+                            unreachable!()
+                        };
+                        let branch = if v.is_empty() { 2 } else { 1 };
+                        match args.get(branch) {
+                            Some(b) => {
+                                let b = b.clone();
+                                self.enter(&mut stack, b, env, tail)?
+                            }
+                            None => ret = Some(String::new()),
+                        }
+                    }
+                    Cont::Memo { keys } => {
+                        for key in keys {
+                            if self.memo.len() < self.limits.memo && v.len() <= 1 << 16 {
+                                self.memo.insert(key, v.clone());
+                            }
+                        }
+                        ret = Some(v);
+                    }
+                    Cont::RefDone { id } => {
+                        self.active.remove(&id);
+                        if self.rendered.len() < 1 << 14 {
+                            self.rendered.insert(id, Arc::from(v.as_str()));
+                        }
+                        ret = Some(v);
+                    }
+                }
+                continue;
+            }
+            let Some(Cont::Run { run, pos, env, mut out }) = stack.pop() else {
+                unreachable!("only a run steps")
+            };
+            if pos >= run.len() {
+                ret = Some(out);
+                continue;
+            }
+            let at = pos;
+            let tail = at + 1 == run.len();
+            match &run[at] {
+                Seg::Text(t) => {
+                    self.grow(&mut out, t)?;
+                    stack.push(Cont::Run {
+                        run,
+                        pos: pos + 1,
+                        env,
+                        out,
+                    });
+                }
+                Seg::Ref(id) => {
+                    let id = *id;
+                    stack.push(Cont::Run {
+                        run,
+                        pos: pos + 1,
+                        env,
+                        out,
+                    });
+                    ret = self.begin_ref(&mut stack, id)?;
+                }
+                Seg::Call { f, args } => {
+                    let f = *f;
+                    let first = args.first().cloned();
+                    let site = run.clone();
+                    stack.push(Cont::Run {
+                        run,
+                        pos: pos + 1,
+                        env: env.clone(),
+                        out,
+                    });
+                    match first {
+                        None => ret = self.dispatch(&mut stack, f, Vec::new(), env, tail)?,
+                        Some(first) => {
+                            let tail_concat = tail && f == Callee::Builtin(builtin::CONCAT);
+                            if tail_concat && site_args(&site, at) == 1 {
+                                // concat(x) in tail position is x in tail position
+                                self.replace_top(&mut stack, first, env);
+                                continue;
+                            }
+                            if f == Callee::Builtin(builtin::IF) {
+                                self.push(
+                                    &mut stack,
+                                    Cont::If {
+                                        site,
+                                        at,
+                                        env: env.clone(),
+                                        tail,
+                                    },
+                                )?;
+                            } else {
+                                self.push(
+                                    &mut stack,
+                                    Cont::Args {
+                                        site,
+                                        at,
+                                        vals: Vec::new(),
+                                        env: env.clone(),
+                                        tail,
+                                    },
+                                )?;
+                            }
+                            self.push(
+                                &mut stack,
+                                Cont::Run {
+                                    run: first,
+                                    pos: 0,
+                                    env,
+                                    out: String::new(),
+                                },
+                            )?;
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    /// a call with its arguments evaluated: a value now, or frames pushed (`None`)
+    fn dispatch(
+        &mut self,
+        stack: &mut Vec,
+        f: Callee,
+        vals: Vec,
+        env: Env,
+        tail: bool,
+    ) -> Result, EvalError> {
+        let id = match f {
+            Callee::Entry(id) => id,
+            Callee::Builtin(b) => return self.builtin(stack, b, vals, env),
+        };
+        let key = (id, vals);
+        if let Some(v) = self.memo.get(&key) {
+            self.stats.memo_hits += 1;
+            return Ok(Some(v.clone()));
+        }
+        let body = self.body(id)?;
+        let env: Env = Rc::from(key.1.clone());
+        if tail {
+            // a tail call from a frame that has emitted nothing has that frame's value:
+            // remember it under the memo just below (up to a few keys, so loops stay
+            // flat), or put one there
+            let n = stack.len();
+            let fresh = matches!(stack.last(), Some(Cont::Run { out, .. }) if out.is_empty());
+            if fresh
+                && n >= 2
+                && let Cont::Memo { keys } = &mut stack[n - 2]
+            {
+                if keys.len() < MEMO_KEYS {
+                    keys.push(key);
+                }
+                self.replace_top(stack, body, env);
+                return Ok(None);
+            }
+            if fresh {
+                stack.pop();
+                self.push(stack, Cont::Memo { keys: vec![key] })?;
+                self.push(
+                    stack,
+                    Cont::Run {
+                        run: body,
+                        pos: 0,
+                        env,
+                        out: String::new(),
+                    },
+                )?;
+            } else {
+                self.replace_top(stack, body, env);
+            }
+        } else {
+            self.push(stack, Cont::Memo { keys: vec![key] })?;
+            self.push(
+                stack,
+                Cont::Run {
+                    run: body,
+                    pos: 0,
+                    env,
+                    out: String::new(),
+                },
+            )?;
+        }
+        Ok(None)
+    }
+
+    fn builtin(
+        &mut self,
+        stack: &mut Vec,
+        b: u8,
+        vals: Vec,
+        env: Env,
+    ) -> Result, EvalError> {
+        use builtin::*;
+        let size: usize = vals.iter().map(|v| v.len()).sum();
+        self.burn(1 + size as u64 / 64)?;
+        let name = NAMES.get(b as usize).copied().unwrap_or("reserved");
+        let arg = |i: usize| vals.get(i).map(String::as_str).unwrap_or("");
+        let v = match b {
+            ARG => {
+                let n = num(name, arg(0))?;
+                usize::try_from(n)
+                    .ok()
+                    .and_then(|n| env.get(n).cloned())
+                    .unwrap_or_default()
+            }
+            ARGC => env.len().to_string(),
+            // reached only when `if` has no arguments
+            IF => String::new(),
+            EQ => truth(vals.windows(2).all(|w| w[0] == w[1])),
+            NOT => truth(arg(0).is_empty()),
+            CONCAT => {
+                if size > self.limits.output {
+                    return Err(EvalError::Output);
+                }
+                vals.concat()
+            }
+            LEN => arg(0).chars().count().to_string(),
+            SUM => {
+                let mode = if arg(1).is_empty() {
+                    Mode::Ordinal
+                } else {
+                    Mode::parse(arg(1)).ok_or_else(|| EvalError::Builtin(name, format!("no sum mode {:?}", arg(1))))?
+                };
+                Measure::of(arg(0)).get(mode).to_string()
+            }
+            SLICE => {
+                let chars: Vec = arg(0).chars().collect();
+                let n = chars.len() as i64;
+                let at = |v: i64| (if v < 0 { n + v } else { v }).clamp(0, n) as usize;
+                let from = at(num(name, arg(1))?);
+                let to = if vals.len() > 2 {
+                    at(num(name, arg(2))?)
+                } else {
+                    n as usize
+                };
+                chars[from..to.max(from)].iter().collect()
+            }
+            LOOKUP => {
+                let id = arg(0)
+                    .trim()
+                    .parse::()
+                    .map_err(|_| EvalError::Builtin(name, format!("{:?} isn't an id", arg(0))))?;
+                return self.begin_ref(stack, id);
+            }
+            ADD | SUB | MUL | DIV | MOD => {
+                let mut acc = num(name, arg(0))?;
+                for v in vals.iter().skip(1) {
+                    let x = num(name, v)?;
+                    let r = match b {
+                        ADD => acc.checked_add(x),
+                        SUB => acc.checked_sub(x),
+                        MUL => acc.checked_mul(x),
+                        DIV if x == 0 => return Err(EvalError::Builtin(name, "division by zero".into())),
+                        DIV => acc.checked_div(x),
+                        _ if x == 0 => return Err(EvalError::Builtin(name, "division by zero".into())),
+                        _ => acc.checked_rem(x),
+                    };
+                    acc = r.ok_or_else(|| EvalError::Builtin(name, "overflow".into()))?;
+                }
+                acc.to_string()
+            }
+            LT => truth(num(name, arg(0))? < num(name, arg(1))?),
+            _ => return Err(EvalError::Builtin(name, format!("builtin {b} is reserved"))),
+        };
+        Ok(Some(v))
+    }
+}
+
+fn site_args(site: &Run, at: usize) -> usize {
+    match &site[at] {
+        Seg::Call { args, .. } => args.len(),
+        _ => 0,
+    }
+}
+
+/// a small way to write runs by hand (tests, examples, the backup's readable form)
+pub mod build {
+    use super::*;
+
+    pub fn t(s: &str) -> Vec {
+        vec![Seg::text(s)]
+    }
+
+    pub fn r(id: u64) -> Vec {
+        vec![Seg::Ref(id)]
+    }
+
+    pub fn b(name: &str, args: Vec>) -> Vec {
+        let code = builtin::by_name(name).unwrap_or_else(|| panic!("no builtin {name}"));
+        vec![Seg::call(Callee::Builtin(code), args)]
+    }
+
+    pub fn f(id: u64, args: Vec>) -> Vec {
+        vec![Seg::call(Callee::Entry(id), args)]
+    }
+
+    pub fn arg(n: usize) -> Vec {
+        b("arg", vec![t(&n.to_string())])
+    }
+
+    pub fn cat(parts: Vec>) -> Vec {
+        parts.into_iter().flatten().collect()
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::build::*;
+    use super::*;
+
+    fn src(entries: Vec<(u64, Vec)>) -> HashMap> {
+        entries.into_iter().collect()
+    }
+
+    #[test]
+    fn refs_and_builtins() {
+        let s = src(vec![
+            (1, t("hello")),
+            (2, cat(vec![r(1), t(" world")])),
+            (3, cat(vec![t("<"), r(2), t(">")])),
+            (4, b("len", vec![r(3)])),
+            (5, b("slice", vec![r(2), t("-5")])),
+            (6, b("sum", vec![t("hello")])),
+            (7, b("sum", vec![t("hello"), t("reversed")])),
+            (8, b("lookup", vec![t("1")])),
+            (9, b("concat", vec![t("a"), t("b"), t("c")])),
+            (10, b("if", vec![t(""), t("yes"), t("no")])),
+            (11, b("div", vec![t("7"), t("0")])),
+            (12, b("add", vec![t("9223372036854775807"), t("1")])),
+            (13, b("mul", vec![t("x"), t("2")])),
+            (14, b("eq", vec![t("a"), t("a"), t("a")])),
+            (15, b("sub", vec![t("10"), t("3"), t("2")])),
+            (16, b("mod", vec![t("-7"), t("3")])),
+            (17, vec![Seg::call(Callee::Builtin(20), vec![])]),
+            (18, b("if", vec![t("x"), t("only")])),
+            (19, b("if", vec![t(""), t("only")])),
+            (20, b("sum", vec![t("hello"), t("atbash")])),
+        ]);
+        let mut i = Interp::new(&s);
+        assert_eq!(i.render(2).unwrap(), "hello world");
+        assert_eq!(i.render(3).unwrap(), "");
+        assert_eq!(i.render(4).unwrap(), "13");
+        assert_eq!(i.render(5).unwrap(), "world");
+        assert_eq!(i.render(6).unwrap(), "52");
+        assert_eq!(i.render(7).unwrap(), "83");
+        assert_eq!(i.render(8).unwrap(), "hello");
+        assert_eq!(i.render(9).unwrap(), "abc");
+        assert_eq!(i.render(10).unwrap(), "no");
+        assert!(matches!(i.render(11), Err(EvalError::Builtin("div", _))));
+        assert!(matches!(i.render(12), Err(EvalError::Builtin("add", _))));
+        assert!(matches!(i.render(13), Err(EvalError::Builtin("mul", _))));
+        assert_eq!(i.render(14).unwrap(), "1");
+        assert_eq!(i.render(15).unwrap(), "5");
+        assert_eq!(i.render(16).unwrap(), "-1");
+        assert!(matches!(i.render(17), Err(EvalError::Builtin(..))));
+        assert_eq!(i.render(18).unwrap(), "only");
+        assert_eq!(i.render(19).unwrap(), "");
+        assert!(matches!(i.render(20), Err(EvalError::Builtin("sum", _))));
+        assert_eq!(i.render(99), Err(EvalError::Missing(99)));
+    }
+
+    #[test]
+    fn ref_cycles_are_errors() {
+        let s = src(vec![
+            (1, cat(vec![t("a"), r(2)])),
+            (2, cat(vec![t("b"), r(1)])),
+            (3, r(3)),
+            (4, b("lookup", vec![t("4")])),
+            // the same entry twice, not nested, is fine
+            (5, cat(vec![r(6), r(6)])),
+            (6, t("x")),
+        ]);
+        let mut i = Interp::new(&s);
+        assert_eq!(i.render(1), Err(EvalError::Cycle(1)));
+        assert_eq!(i.render(3), Err(EvalError::Cycle(3)));
+        assert_eq!(i.render(4), Err(EvalError::Cycle(4)));
+        assert_eq!(i.render(5).unwrap(), "xx");
+    }
+
+    /// fact(n) = if(eq(n, 0), 1, mul(n, fact(sub(n, 1))))
+    fn fact() -> Vec {
+        b(
+            "if",
+            vec![
+                b("eq", vec![arg(0), t("0")]),
+                t("1"),
+                b("mul", vec![arg(0), f(100, vec![b("sub", vec![arg(0), t("1")])])]),
+            ],
+        )
+    }
+
+    /// fib(n) = if(lt(n, 2), n, add(fib(n - 1), fib(n - 2)))
+    fn fib() -> Vec {
+        b(
+            "if",
+            vec![
+                b("lt", vec![arg(0), t("2")]),
+                arg(0),
+                b(
+                    "add",
+                    vec![
+                        f(101, vec![b("sub", vec![arg(0), t("1")])]),
+                        f(101, vec![b("sub", vec![arg(0), t("2")])]),
+                    ],
+                ),
+            ],
+        )
+    }
+
+    #[test]
+    fn recursion_factorial_fibonacci() {
+        let s = src(vec![(100, fact()), (101, fib())]);
+        let mut i = Interp::new(&s);
+        assert_eq!(i.call(100, &["10"]).unwrap(), "3628800");
+        assert_eq!(i.call(100, &["20"]).unwrap(), "2432902008176640000");
+        assert!(matches!(i.call(100, &["21"]), Err(EvalError::Builtin("mul", _))));
+        // naive Fibonacci, linear thanks to the memo
+        assert_eq!(i.call(101, &["80"]).unwrap(), "23416728348467685");
+        assert!(i.stats.memo_hits > 70);
+        // the same through a REF to an entry that calls it
+        let mut s2 = s.clone();
+        s2.insert(5, cat(vec![t("fib(30) = "), f(101, vec![t("30")])]));
+        assert_eq!(Interp::new(&s2).render(5).unwrap(), "fib(30) = 832040");
+    }
+
+    /// count(n, limit) = if(eq(n, limit), n, count(add(n, 1), limit)): a tail call
+    fn counter() -> Vec {
+        b(
+            "if",
+            vec![
+                b("eq", vec![arg(0), arg(1)]),
+                arg(0),
+                f(200, vec![b("add", vec![arg(0), t("1")]), arg(1)]),
+            ],
+        )
+    }
+
+    #[test]
+    fn counter_to_a_thousand() {
+        let s = src(vec![(200, counter())]);
+        let mut i = Interp::new(&s);
+        assert_eq!(i.call(200, &["0", "1000"]).unwrap(), "1000");
+    }
+
+    #[test]
+    fn tail_recursion_runs_in_constant_stack() {
+        let s = src(vec![(200, counter())]);
+        let mut i = Interp::with_limits(
+            &s,
+            Limits {
+                fuel: 100_000_000,
+                ..Limits::default()
+            },
+        );
+        assert_eq!(i.call(200, &["0", "1000000"]).unwrap(), "1000000");
+        assert!(i.stats.max_stack <= 8, "{:?}", i.stats);
+        // nor is the memo filled by a tail loop
+        assert!(i.memo.len() <= MEMO_KEYS);
+        // too little fuel is an error, not a hang
+        let mut i = Interp::with_limits(
+            &s,
+            Limits {
+                fuel: 10_000,
+                ..Limits::default()
+            },
+        );
+        assert_eq!(i.call(200, &["0", "1000000"]), Err(EvalError::Fuel));
+    }
+
+    #[test]
+    fn mutual_tail_recursion() {
+        // even(n) = if(eq(n, 0), 1, odd(n - 1)); odd(n) = if(eq(n, 0), "", even(n - 1))
+        let s = src(vec![
+            (
+                300,
+                b(
+                    "if",
+                    vec![
+                        b("eq", vec![arg(0), t("0")]),
+                        t("1"),
+                        f(301, vec![b("sub", vec![arg(0), t("1")])]),
+                    ],
+                ),
+            ),
+            (
+                301,
+                b(
+                    "if",
+                    vec![
+                        b("eq", vec![arg(0), t("0")]),
+                        t(""),
+                        f(300, vec![b("sub", vec![arg(0), t("1")])]),
+                    ],
+                ),
+            ),
+        ]);
+        let mut i = Interp::with_limits(
+            &s,
+            Limits {
+                fuel: 100_000_000,
+                ..Limits::default()
+            },
+        );
+        assert_eq!(i.call(300, &["200001"]).unwrap(), "");
+        assert_eq!(i.call(301, &["200001"]).unwrap(), "1");
+        assert!(i.stats.max_stack <= 8);
+    }
+
+    #[test]
+    fn tail_calls_after_text_and_in_concat() {
+        // rep(n) = if(eq(n, 0), "", concat("x", rep(n - 1)))
+        // bang(n) = "!" rep(n): text before a tail call
+        let s = src(vec![
+            (
+                400,
+                b(
+                    "if",
+                    vec![
+                        b("eq", vec![arg(0), t("0")]),
+                        t(""),
+                        b("concat", vec![t("x"), f(400, vec![b("sub", vec![arg(0), t("1")])])]),
+                    ],
+                ),
+            ),
+            (401, cat(vec![t("!"), f(400, vec![arg(0)])])),
+            (
+                402,
+                b(
+                    "if",
+                    vec![
+                        b("eq", vec![arg(0), t("0")]),
+                        t(""),
+                        cat(vec![t("y"), f(402, vec![b("sub", vec![arg(0), t("1")])])]),
+                    ],
+                ),
+            ),
+        ]);
+        let mut i = Interp::new(&s);
+        let out = i.call(400, &["100000"]).unwrap();
+        assert_eq!(out.len(), 100_000);
+        assert!(i.stats.max_stack <= 8, "{:?}", i.stats);
+        assert_eq!(i.call(401, &["3"]).unwrap(), "!xxx");
+        let out = i.call(402, &["50000"]).unwrap();
+        assert_eq!(out, "y".repeat(50_000));
+        assert!(i.stats.max_stack <= 8);
+        // the output limit stops a runaway
+        let mut i = Interp::with_limits(
+            &s,
+            Limits {
+                output: 1000,
+                ..Limits::default()
+            },
+        );
+        assert_eq!(i.call(400, &["5000"]), Err(EvalError::Output));
+    }
+
+    #[test]
+    fn non_tail_recursion_hits_the_depth_limit() {
+        // down(n) = if(eq(n, 0), 0, add(1, down(n - 1))): the call is an argument
+        let s = src(vec![(
+            500,
+            b(
+                "if",
+                vec![
+                    b("eq", vec![arg(0), t("0")]),
+                    t("0"),
+                    b("add", vec![t("1"), f(500, vec![b("sub", vec![arg(0), t("1")])])]),
+                ],
+            ),
+        )]);
+        let mut i = Interp::new(&s);
+        assert_eq!(i.call(500, &["1000"]).unwrap(), "1000");
+        let mut i = Interp::new(&s);
+        assert_eq!(i.call(500, &["1000000"]), Err(EvalError::Depth));
+        // a body calling itself forever through a non-tail position
+        let s = src(vec![(501, cat(vec![f(501, vec![]), t("x")]))]);
+        assert_eq!(Interp::new(&s).render(501), Err(EvalError::Depth));
+        // ... and through a tail position: fuel
+        let s = src(vec![(502, f(502, vec![]))]);
+        let few = Limits {
+            fuel: 100_000,
+            ..Limits::default()
+        };
+        assert_eq!(Interp::with_limits(&s, few).render(502), Err(EvalError::Fuel));
+    }
+}
diff --git a/core/src/graph/lights.rs b/core/src/graph/lights.rs
new file mode 100644
index 00000000..46046cb4
--- /dev/null
+++ b/core/src/graph/lights.rs
@@ -0,0 +1,286 @@
+//! The room's lights: what lights its blocks. A light is flat (ambient, from everywhere;
+//! or directional, from one way), a point, or a cone (spot). Each has a colour and an
+//! intensity; a point and a cone reach `range` units (fading to nothing there) from where
+//! they are; a directional light and a cone point along `dir`; a cone opens `angle`
+//! degrees from its axis with a `softness` at its edge.
+//!
+//! The light is baked: the space computes it onto the blocks' vertices (each face cut
+//! into cells about a unit across) when a light or a block changes, not every frame, and
+//! nothing about it is stored but the lights themselves (the bake follows from them and
+//! the blocks, the same every time). No shadows: a block doesn't shade another.
+//!
+//! | table | key | holds |
+//! |---|---|---|
+//! | `graph lights` | light id (u64) | the light as JSON ([`Light`]) |
+
+use redb::{ReadableDatabase, ReadableTable, TableDefinition};
+use serde::{Deserialize, Serialize};
+
+use super::store::{GResult, Graph, err};
+
+pub const LIGHTS: TableDefinition = TableDefinition::new("graph lights");
+
+/// lights a save holds at most
+pub const MAX_LIGHTS: usize = 64;
+
+pub fn ensure_tables(txn: &redb::WriteTransaction) -> GResult<()> {
+    txn.open_table(LIGHTS).map_err(err)?;
+    Ok(())
+}
+
+#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Serialize, Deserialize)]
+#[serde(rename_all = "lowercase")]
+pub enum LightKind {
+    /// from everywhere at once
+    #[default]
+    Ambient,
+    /// from one way, as the sun
+    Directional,
+    /// from a point, all round
+    Point,
+    /// from a point, in a cone
+    Spot,
+}
+
+fn white() -> String {
+    "#ffffff".into()
+}
+fn one() -> f32 {
+    1.0
+}
+fn down() -> [f32; 3] {
+    [0.0, -1.0, 0.0]
+}
+fn ten() -> f32 {
+    10.0
+}
+fn thirty() -> f32 {
+    30.0
+}
+fn soft() -> f32 {
+    0.3
+}
+
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct Light {
+    #[serde(default)]
+    pub id: u64,
+    #[serde(default)]
+    pub kind: LightKind,
+    #[serde(default = "white")]
+    pub colour: String,
+    /// how bright, 0–10 (1 is a face lit square on at full strength)
+    #[serde(default = "one")]
+    pub intensity: f32,
+    #[serde(default)]
+    pub x: f32,
+    #[serde(default)]
+    pub y: f32,
+    #[serde(default)]
+    pub z: f32,
+    /// the way it shines (a unit vector), for a directional light and a cone
+    #[serde(default = "down")]
+    pub dir: [f32; 3],
+    /// how far a point or a cone reaches, in units
+    #[serde(default = "ten")]
+    pub range: f32,
+    /// a cone's half angle, in degrees
+    #[serde(default = "thirty")]
+    pub angle: f32,
+    /// how soft a cone's edge is, 0 (sharp) to 1
+    #[serde(default = "soft")]
+    pub softness: f32,
+}
+
+impl Default for Light {
+    fn default() -> Light {
+        Light {
+            id: 0,
+            kind: LightKind::Ambient,
+            colour: white(),
+            intensity: 1.0,
+            x: 0.0,
+            y: 0.0,
+            z: 0.0,
+            dir: down(),
+            range: 10.0,
+            angle: 30.0,
+            softness: 0.3,
+        }
+    }
+}
+
+impl Light {
+    /// within bounds: a colour, finite numbers, a unit direction
+    pub fn checked(mut self) -> Result {
+        if !super::textures::is_colour(&self.colour) {
+            return Err(format!("{:?} isn't a colour (#rrggbb)", self.colour));
+        }
+        self.colour = self.colour.to_lowercase();
+        let all = [
+            self.intensity,
+            self.x,
+            self.y,
+            self.z,
+            self.range,
+            self.angle,
+            self.softness,
+        ];
+        if all.iter().chain(&self.dir).any(|v| !v.is_finite()) {
+            return Err("a light's values are numbers".into());
+        }
+        let m = super::blocks::MAX_COORD;
+        if [self.x, self.y, self.z].iter().any(|v| v.abs() > m) {
+            return Err(format!("a light stays within {m} of the origin"));
+        }
+        self.intensity = self.intensity.clamp(0.0, 10.0);
+        self.range = self.range.clamp(0.1, 10_000.0);
+        self.angle = self.angle.clamp(1.0, 89.0);
+        self.softness = self.softness.clamp(0.0, 1.0);
+        let n = self.dir.iter().map(|v| v * v).sum::().sqrt();
+        // a unit already stays as it is, so checking twice changes nothing
+        self.dir = if n < 1e-6 {
+            down()
+        } else if (n - 1.0).abs() < 1e-5 {
+            self.dir
+        } else {
+            self.dir.map(|v| v / n)
+        };
+        Ok(self)
+    }
+}
+
+impl Graph {
+    /// the lights, by id
+    pub fn lights(&self) -> GResult> {
+        let txn = self.db().begin_read().map_err(err)?;
+        let t = txn.open_table(LIGHTS).map_err(err)?;
+        let mut out = Vec::new();
+        for item in t.iter().map_err(err)? {
+            let (k, v) = item.map_err(err)?;
+            if let Ok(mut l) = serde_json::from_slice::(v.value()) {
+                l.id = k.value();
+                out.push(l);
+            }
+        }
+        Ok(out)
+    }
+
+    /// adds a light (a new id) and answers it
+    pub fn add_light(&self, l: Light) -> GResult {
+        let mut l = l.checked()?;
+        let txn = self.db().begin_write().map_err(err)?;
+        {
+            let mut t = txn.open_table(LIGHTS).map_err(err)?;
+            use redb::ReadableTableMetadata;
+            if t.len().map_err(err)? as usize >= MAX_LIGHTS {
+                return Err(format!("a save has at most {MAX_LIGHTS} lights"));
+            }
+            l.id = t.last().map_err(err)?.map_or(1, |(k, _)| k.value() + 1);
+            t.insert(l.id, serde_json::to_vec(&l).map_err(err)?.as_slice())
+                .map_err(err)?;
+        }
+        txn.commit().map_err(err)?;
+        Ok(l)
+    }
+
+    /// changes a light that's there
+    pub fn set_light(&self, l: Light) -> GResult {
+        let l = l.checked()?;
+        let txn = self.db().begin_write().map_err(err)?;
+        {
+            let mut t = txn.open_table(LIGHTS).map_err(err)?;
+            if t.get(l.id).map_err(err)?.is_none() {
+                return Err(format!("no light {}", l.id));
+            }
+            t.insert(l.id, serde_json::to_vec(&l).map_err(err)?.as_slice())
+                .map_err(err)?;
+        }
+        txn.commit().map_err(err)?;
+        Ok(l)
+    }
+
+    /// takes a light out, answering it
+    pub fn delete_light(&self, id: u64) -> GResult> {
+        let txn = self.db().begin_write().map_err(err)?;
+        let gone = txn
+            .open_table(LIGHTS)
+            .map_err(err)?
+            .remove(id)
+            .map_err(err)?
+            .and_then(|v| serde_json::from_slice::(v.value()).ok());
+        txn.commit().map_err(err)?;
+        Ok(gone.map(|mut l| {
+            l.id = id;
+            l
+        }))
+    }
+
+    /// puts lights back with their ids (an undo, a restore)
+    pub fn put_lights(&self, lights: &[Light]) -> GResult {
+        let txn = self.db().begin_write().map_err(err)?;
+        let mut n = 0;
+        {
+            let mut t = txn.open_table(LIGHTS).map_err(err)?;
+            for l in lights {
+                let Ok(l) = l.clone().checked() else { continue };
+                if l.id == 0 || t.get(l.id).map_err(err)?.is_some() {
+                    continue;
+                }
+                t.insert(l.id, serde_json::to_vec(&l).map_err(err)?.as_slice())
+                    .map_err(err)?;
+                n += 1;
+            }
+        }
+        txn.commit().map_err(err)?;
+        Ok(n)
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn lights_are_kept_checked() {
+        let g = Graph::in_memory().unwrap();
+        let a = g
+            .add_light(Light {
+                kind: LightKind::Spot,
+                colour: "#FFAA00".into(),
+                intensity: 40.0,
+                dir: [0.0, 0.0, -2.0],
+                angle: 120.0,
+                ..Light::default()
+            })
+            .unwrap();
+        assert_eq!(
+            (a.id, a.colour.as_str(), a.intensity, a.dir, a.angle),
+            (1, "#ffaa00", 10.0, [0.0, 0.0, -1.0], 89.0)
+        );
+        let b = g.add_light(Light::default()).unwrap();
+        assert_eq!(b.id, 2);
+        assert!(
+            g.add_light(Light {
+                colour: "red".into(),
+                ..Light::default()
+            })
+            .is_err()
+        );
+        let moved = g.set_light(Light { x: 3.0, ..a.clone() }).unwrap();
+        assert_eq!(g.lights().unwrap(), vec![moved.clone(), b.clone()]);
+        assert!(
+            g.set_light(Light {
+                id: 9,
+                ..Light::default()
+            })
+            .is_err()
+        );
+        let gone = g.delete_light(1).unwrap().unwrap();
+        assert_eq!(g.lights().unwrap(), vec![b]);
+        assert_eq!(g.put_lights(&[gone]).unwrap(), 1);
+        assert_eq!(g.lights().unwrap().len(), 2);
+        // the next id is after the last
+        assert_eq!(g.add_light(Light::default()).unwrap().id, 3);
+    }
+}
diff --git a/core/src/graph/mod.rs b/core/src/graph/mod.rs
new file mode 100644
index 00000000..211ba4d2
--- /dev/null
+++ b/core/src/graph/mod.rs
@@ -0,0 +1,28 @@
+//! The entry graph (work in progress).
+
+pub mod anims;
+pub mod assets;
+pub mod backup;
+pub mod blocks;
+pub mod chains;
+pub mod checkpoints;
+pub mod codec;
+pub mod gematria;
+pub mod interp;
+pub mod lights;
+pub mod place;
+pub mod postings;
+pub mod prefabs;
+pub mod query;
+pub mod record;
+pub mod scenes;
+pub mod settle;
+pub mod sounds;
+pub mod store;
+pub mod textures;
+pub mod wiring;
+
+pub use store::{GResult, Graph, Reader, Tx, View};
+
+#[cfg(test)]
+mod tests;
diff --git a/core/src/graph/place.rs b/core/src/graph/place.rs
new file mode 100644
index 00000000..213ec42c
--- /dev/null
+++ b/core/src/graph/place.rs
@@ -0,0 +1,513 @@
+//! Placements: the payload of a `PLACE` edge (from a map entry to the entry placed in it),
+//! a transform bit-packed into a small fixed value. The same entry can stand in several
+//! places and several maps; identical placements collapse into one edge.
+//!
+//! **The packed value** (`PACKED` = 34 bytes, little endian, version 2):
+//!
+//! | bytes | field |
+//! |---|---|
+//! | 0 | version, 2 (an unknown version doesn't unpack) |
+//! | 1 | kind: 0 text, 1 cube, 2 long block, 3 brick, 4 model (glTF; reserved), 5 sphere |
+//! | 2 | flags: 1 pinned, 2 hidden, 4 spread (laid out by its sums when not pinned); the rest kept as they are |
+//! | 3 | reserved, 0 |
+//! | 4–15 | position, 3 × f32 |
+//! | 16–19 | rotation, smallest three: bits 30–31 the index of the largest component of the unit quaternion (x y z w), made positive and left out; the other three in order, 10 bits each (bits 20–29, 10–19, 0–9), each `round(v·√2·511) + 511` |
+//! | 20–25 | scale, 3 × f16 (a text uses x as its em size) |
+//! | 26–29 | colour, RGBA8 |
+//! | 30–33 | asset, u32: 0 none (reserved for models) |
+//!
+//! The map isn't in the value: it's the edge's `from`.
+//!
+//! **Packing is canonical**, so the same placement always gives the same bytes and
+//! `pack(unpack(b)) == b` for anything `pack` made: −0 is +0, a NaN position is 0 (a NaN
+//! scale is 1), infinities clamp to ±f32::MAX, scales clamp to ±65504 and round to nearest
+//! even, and a rotation is normalised first (a zero or broken one is the identity).
+//!
+//! The fix over the first version (docs/wip): smallest-three quantisation alone isn't
+//! idempotent. When two components are nearly equal, the decoded largest can come out
+//! smaller than another decoded component, so re-packing picks another index (or rounds a
+//! component one step off after normalising). `pack_rotation` therefore iterates
+//! `quantise ∘ dequantise` until it reaches a value that maps to itself, and if the
+//! sequence ends in a cycle instead, takes the smallest value of the cycle. Both ends of a
+//! round trip land on the same cycle, so they agree, and the chosen value maps to itself.
+
+/// the layout version
+pub const VERSION: u8 = 2;
+pub const PACKED: usize = 34;
+
+pub const PINNED: u8 = 1;
+pub const HIDDEN: u8 = 2;
+pub const SPREAD: u8 = 4;
+
+pub const IDENTITY: [f32; 4] = [0.0, 0.0, 0.0, 1.0];
+
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Default)]
+#[repr(u8)]
+pub enum Kind {
+    #[default]
+    Text = 0,
+    Cube = 1,
+    LongBlock = 2,
+    Brick = 3,
+    /// a glTF model (reserved)
+    Model = 4,
+    /// a sphere (an ellipsoid when its sides differ)
+    Sphere = 5,
+}
+
+impl Kind {
+    pub fn from_u8(b: u8) -> Option {
+        Some(match b {
+            0 => Kind::Text,
+            1 => Kind::Cube,
+            2 => Kind::LongBlock,
+            3 => Kind::Brick,
+            4 => Kind::Model,
+            5 => Kind::Sphere,
+            _ => return None,
+        })
+    }
+}
+
+/// one placement of an entry in a map
+#[derive(Clone, Copy, Debug, PartialEq)]
+pub struct Place {
+    pub kind: Kind,
+    pub flags: u8,
+    pub pos: [f32; 3],
+    /// a quaternion, x y z w
+    pub rot: [f32; 4],
+    pub scale: [f32; 3],
+    pub color: [u8; 4],
+    pub asset: u32,
+}
+
+impl Place {
+    /// a text of em size `size`, facing the camera
+    pub fn text(pos: [f32; 3], size: f32, color: [u8; 4], flags: u8) -> Place {
+        Place {
+            kind: Kind::Text,
+            flags,
+            pos,
+            rot: IDENTITY,
+            scale: [size; 3],
+            color,
+            asset: 0,
+        }
+    }
+
+    pub fn pinned(&self) -> bool {
+        self.flags & PINNED != 0
+    }
+
+    pub fn hidden(&self) -> bool {
+        self.flags & HIDDEN != 0
+    }
+
+    pub fn spread(&self) -> bool {
+        self.flags & SPREAD != 0
+    }
+
+    pub fn pack(&self) -> [u8; PACKED] {
+        let mut b = [0u8; PACKED];
+        b[0] = VERSION;
+        b[1] = self.kind as u8;
+        b[2] = self.flags;
+        for (i, v) in self.pos.iter().enumerate() {
+            b[4 + i * 4..8 + i * 4].copy_from_slice(&canon_f32(*v).to_le_bytes());
+        }
+        b[16..20].copy_from_slice(&pack_rotation(self.rot).to_le_bytes());
+        for (i, v) in self.scale.iter().enumerate() {
+            // a scale that rounds to -0 is +0, like one that was -0 to begin with
+            let h = match f32_to_f16(canon_scale(*v)) {
+                0x8000 => 0,
+                h => h,
+            };
+            b[20 + i * 2..22 + i * 2].copy_from_slice(&h.to_le_bytes());
+        }
+        b[26..30].copy_from_slice(&self.color);
+        b[30..34].copy_from_slice(&self.asset.to_le_bytes());
+        b
+    }
+
+    /// `None` for a value of another size, version or kind
+    pub fn unpack(b: &[u8]) -> Option {
+        if b.len() != PACKED || b[0] != VERSION {
+            return None;
+        }
+        let f32_at = |i: usize| f32::from_le_bytes([b[i], b[i + 1], b[i + 2], b[i + 3]]);
+        let f16_at = |i: usize| f16_to_f32(u16::from_le_bytes([b[i], b[i + 1]]));
+        Some(Place {
+            kind: Kind::from_u8(b[1])?,
+            flags: b[2],
+            pos: [f32_at(4), f32_at(8), f32_at(12)],
+            rot: unpack_rotation(u32::from_le_bytes([b[16], b[17], b[18], b[19]])),
+            scale: [f16_at(20), f16_at(22), f16_at(24)],
+            color: [b[26], b[27], b[28], b[29]],
+            asset: u32::from_le_bytes([b[30], b[31], b[32], b[33]]),
+        })
+    }
+}
+
+fn canon_f32(v: f32) -> f32 {
+    if v.is_nan() || v == 0.0 {
+        0.0
+    } else {
+        v.clamp(f32::MIN, f32::MAX)
+    }
+}
+
+fn canon_scale(v: f32) -> f32 {
+    if v.is_nan() {
+        1.0
+    } else if v == 0.0 {
+        0.0
+    } else {
+        v.clamp(-65504.0, 65504.0)
+    }
+}
+
+// ---------------------------------------------------------------- f16
+
+/// IEEE half precision, rounded to nearest even
+pub fn f32_to_f16(v: f32) -> u16 {
+    let x = v.to_bits();
+    let sign = ((x >> 16) & 0x8000) as u16;
+    let exp = ((x >> 23) & 0xff) as i32;
+    let man = x & 0x7f_ffff;
+    if exp == 0xff {
+        return sign | 0x7c00 | if man != 0 { 0x200 } else { 0 };
+    }
+    let e = exp - 127 + 15;
+    if e >= 0x1f {
+        return sign | 0x7c00;
+    }
+    if e <= 0 {
+        let shift = (14 - e) as u32;
+        if shift > 24 {
+            return sign;
+        }
+        let full = man | 0x80_0000;
+        let half = 1u32 << (shift - 1);
+        let rest = full & ((1u32 << shift) - 1);
+        let mut m = full >> shift;
+        if rest > half || (rest == half && m & 1 == 1) {
+            m += 1;
+        }
+        return sign | m as u16;
+    }
+    let mut h = ((e as u32) << 10) | (man >> 13);
+    let rest = man & 0x1fff;
+    if rest > 0x1000 || (rest == 0x1000 && h & 1 == 1) {
+        h += 1;
+    }
+    sign | h as u16
+}
+
+pub fn f16_to_f32(h: u16) -> f32 {
+    let sign = ((h & 0x8000) as u32) << 16;
+    let e = ((h >> 10) & 0x1f) as u32;
+    let m = (h & 0x3ff) as u32;
+    let bits = match (e, m) {
+        (0, 0) => sign,
+        (0, m) => {
+            let v = m as f32 * (1.0 / 16_777_216.0);
+            return if sign != 0 { -v } else { v };
+        }
+        (0x1f, 0) => sign | 0x7f80_0000,
+        (0x1f, m) => sign | 0x7fc0_0000 | (m << 13),
+        (e, m) => sign | ((e + 112) << 23) | (m << 13),
+    };
+    f32::from_bits(bits)
+}
+
+// ---------------------------------------------------------------- rotation
+
+const STEPS: f32 = 511.0;
+
+/// one smallest-three quantisation, without the fixed point search
+fn quantise(q: [f32; 4]) -> u32 {
+    let len = q.iter().map(|v| v * v).sum::().sqrt();
+    let q = if len.is_finite() && len > 1e-6 {
+        q.map(|v| v / len)
+    } else {
+        IDENTITY
+    };
+    let mut big = 0;
+    for i in 1..4 {
+        if q[i].abs() > q[big].abs() {
+            big = i;
+        }
+    }
+    let q = if q[big] < 0.0 { q.map(|v| -v) } else { q };
+    let mut out = (big as u32) << 30;
+    let mut shift = 20;
+    for (i, v) in q.iter().enumerate() {
+        if i == big {
+            continue;
+        }
+        let s = (v * std::f32::consts::SQRT_2 * STEPS).round().clamp(-STEPS, STEPS) as i32 + 511;
+        out |= (s as u32) << shift;
+        shift -= 10;
+    }
+    out
+}
+
+/// a unit quaternion (x y z w) in 32 bits, canonically: the result `r` always has
+/// `pack_rotation(unpack_rotation(r)) == r`
+pub fn pack_rotation(q: [f32; 4]) -> u32 {
+    let mut seen: Vec = vec![quantise(q)];
+    loop {
+        let last = *seen.last().unwrap();
+        let next = quantise(unpack_rotation(last));
+        if next == last {
+            return last;
+        }
+        if let Some(at) = seen.iter().position(|&s| s == next) {
+            return *seen[at..].iter().min().unwrap();
+        }
+        seen.push(next);
+        if seen.len() > 64 {
+            // never seen in practice; still a value both ends agree on
+            return *seen.iter().min().unwrap();
+        }
+    }
+}
+
+pub fn unpack_rotation(r: u32) -> [f32; 4] {
+    let big = (r >> 30) as usize;
+    let mut q = [0f32; 4];
+    let mut shift = 20;
+    let mut sum = 0.0;
+    for (i, slot) in q.iter_mut().enumerate() {
+        if i == big {
+            continue;
+        }
+        let s = ((r >> shift) & 0x3ff).min(1022) as i32 - 511;
+        *slot = s as f32 / STEPS * std::f32::consts::FRAC_1_SQRT_2;
+        sum += *slot * *slot;
+        shift -= 10;
+    }
+    q[big] = (1.0 - sum).max(0.0).sqrt();
+    q
+}
+
+// ---------------------------------------------------------------- colours
+
+/// `#rgb`, `#rgba`, `#rrggbb` or `#rrggbbaa`
+pub fn parse_hex_color(s: &str) -> Option<[u8; 4]> {
+    let h = s.trim().trim_start_matches('#');
+    if !h.is_ascii() {
+        return None;
+    }
+    let nib = |c: u8| (c as char).to_digit(16).map(|d| d as u8);
+    let b = h.as_bytes();
+    let mut out = [255u8; 4];
+    match b.len() {
+        3 | 4 => {
+            for (i, c) in b.iter().enumerate() {
+                out[i] = nib(*c)? * 17;
+            }
+        }
+        6 | 8 => {
+            for i in 0..b.len() / 2 {
+                out[i] = nib(b[i * 2])? * 16 + nib(b[i * 2 + 1])?;
+            }
+        }
+        _ => return None,
+    }
+    Some(out)
+}
+
+/// `#rrggbb`, with `aa` when it isn't opaque
+pub fn hex_color(c: [u8; 4]) -> String {
+    if c[3] == 255 {
+        format!("#{:02x}{:02x}{:02x}", c[0], c[1], c[2])
+    } else {
+        format!("#{:02x}{:02x}{:02x}{:02x}", c[0], c[1], c[2], c[3])
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    struct Lcg(u64);
+    impl Lcg {
+        fn next(&mut self) -> u32 {
+            self.0 = self
+                .0
+                .wrapping_mul(6364136223846793005)
+                .wrapping_add(1442695040888963407);
+            (self.0 >> 32) as u32
+        }
+        fn unit(&mut self) -> f32 {
+            self.next() as f32 / u32::MAX as f32 * 2.0 - 1.0
+        }
+    }
+
+    const INK: [u8; 4] = [0x3b, 0x2a, 0x1c, 255];
+
+    fn sample() -> Place {
+        Place {
+            kind: Kind::Brick,
+            flags: PINNED | SPREAD | 0x80,
+            pos: [1.25, -3.5e7, 0.1],
+            rot: [0.1, -0.7, 0.2, 0.68],
+            scale: [0.5, 2.0, -1.5],
+            color: [1, 2, 3, 4],
+            asset: 0xdead_beef,
+        }
+    }
+
+    #[test]
+    fn layout_is_fixed() {
+        let b = sample().pack();
+        assert_eq!(b.len(), PACKED);
+        assert_eq!((b[0], b[1], b[2], b[3]), (2, 3, 0x85, 0));
+        assert_eq!(&b[4..8], &1.25f32.to_le_bytes());
+        assert_eq!(&b[20..22], &0x3800u16.to_le_bytes()); // 0.5 in f16
+        assert_eq!(&b[24..26], &0xbe00u16.to_le_bytes()); // -1.5
+        assert_eq!(&b[26..30], &[1, 2, 3, 4]);
+        assert_eq!(&b[30..34], &0xdead_beefu32.to_le_bytes());
+        let id = pack_rotation(IDENTITY);
+        assert_eq!(id, (3 << 30) | (511 << 20) | (511 << 10) | 511);
+        assert_eq!(unpack_rotation(id), IDENTITY);
+    }
+
+    #[test]
+    fn round_trip_and_idempotence() {
+        let p = sample();
+        let q = Place::unpack(&p.pack()).unwrap();
+        assert_eq!(
+            (q.kind, q.flags, q.pos, q.color, q.asset),
+            (p.kind, p.flags, p.pos, p.color, p.asset)
+        );
+        assert_eq!(q.scale, [0.5, 2.0, -1.5]);
+        assert_eq!(q.pack(), p.pack());
+        let mut b = p.pack();
+        assert!(Place::unpack(&b[..33]).is_none());
+        b[0] = 1;
+        assert!(Place::unpack(&b).is_none());
+        let mut b = p.pack();
+        b[1] = 9;
+        assert!(Place::unpack(&b).is_none());
+
+        let mut g = Lcg(7);
+        for _ in 0..20_000 {
+            let p = Place {
+                kind: Kind::from_u8((g.next() % 5) as u8).unwrap(),
+                flags: g.next() as u8,
+                pos: [g.unit() * 1e4, g.unit(), g.unit() * 1e-3],
+                rot: [g.unit(), g.unit(), g.unit(), g.unit()],
+                scale: [g.unit() * 100.0, g.unit(), g.unit() * 1e-3],
+                color: g.next().to_le_bytes(),
+                asset: g.next(),
+            };
+            let b = p.pack();
+            let q = Place::unpack(&b).unwrap();
+            assert_eq!(q.pack(), b, "{p:?}");
+            assert_eq!(q.pos, p.pos);
+            for i in 0..3 {
+                let tol = (p.scale[i].abs() * (1.0 / 2048.0)).max(1.0 / 33_554_432.0);
+                assert!((q.scale[i] - p.scale[i]).abs() <= tol);
+            }
+            let len = p.rot.iter().map(|v| v * v).sum::().sqrt();
+            if len > 1e-6 {
+                let dot: f32 = p.rot.iter().zip(q.rot).map(|(a, b)| a / len * b).sum();
+                let angle = 2.0 * dot.abs().min(1.0).acos();
+                assert!(angle.to_degrees() < 0.3, "{angle} for {:?}", p.rot);
+            }
+        }
+    }
+
+    #[test]
+    fn near_ties_repack_identically() {
+        // the cases the first version got wrong: two or more components nearly equal
+        let h = std::f32::consts::FRAC_1_SQRT_2;
+        let mut g = Lcg(11);
+        let mut cases = vec![
+            [0.0, 0.0, h, h],
+            [h, 0.0, 0.0, h],
+            [0.5, 0.5, 0.5, 0.5],
+            [-0.5, 0.5, -0.5, 0.5],
+        ];
+        for _ in 0..50_000 {
+            let e = g.unit() * 2e-3;
+            let a = g.unit();
+            let c = g.unit() * 0.3;
+            let mut q = [c, a, a + e, -c * 0.5];
+            let k = (g.next() % 4) as usize;
+            q.swap(k, 3);
+            cases.push(q);
+            let s = 0.5 + g.unit() * 1e-3;
+            cases.push([s, -s, s + e, 0.5]);
+        }
+        for q in cases {
+            let r = pack_rotation(q);
+            assert_eq!(pack_rotation(unpack_rotation(r)), r, "{q:?}");
+            // and again from the decoded value, any number of times
+            let again = pack_rotation(unpack_rotation(pack_rotation(unpack_rotation(r))));
+            assert_eq!(again, r);
+        }
+        // every 32-bit pattern a corrupt value might hold re-packs to a fixed point
+        for _ in 0..50_000 {
+            let r = g.next();
+            let once = pack_rotation(unpack_rotation(r));
+            assert_eq!(pack_rotation(unpack_rotation(once)), once);
+        }
+    }
+
+    #[test]
+    fn canonical_values() {
+        let base = Place::text([0.0; 3], 0.5, INK, 0);
+        let with = |f: &dyn Fn(&mut Place)| {
+            let mut p = base;
+            f(&mut p);
+            p.pack()
+        };
+        assert_eq!(with(&|p| p.pos = [-0.0, -0.0, -0.0]), base.pack());
+        assert_eq!(with(&|p| p.pos[0] = f32::NAN), base.pack());
+        let inf = Place::unpack(&with(&|p| p.pos = [f32::INFINITY, f32::NEG_INFINITY, 1.0])).unwrap();
+        assert_eq!(inf.pos, [f32::MAX, f32::MIN, 1.0]);
+        assert_eq!(with(&|p| p.scale[0] = -0.0), with(&|p| p.scale[0] = 0.0));
+        assert_eq!(
+            Place::unpack(&with(&|p| p.scale = [f32::NAN; 3])).unwrap().scale,
+            [1.0; 3]
+        );
+        let r = [0.3, -0.5, 0.1, -0.8];
+        assert_eq!(pack_rotation(r), pack_rotation(r.map(|v: f32| -v)));
+        assert_eq!(pack_rotation(r), pack_rotation(r.map(|v: f32| v * 9.0)));
+        assert_eq!(pack_rotation([0.0; 4]), pack_rotation(IDENTITY));
+        assert_eq!(pack_rotation([f32::NAN, 0.0, 0.0, 1.0]), pack_rotation(IDENTITY));
+        for big in 0..4 {
+            let mut q = [0.1f32, -0.2, 0.15, 0.05];
+            q[big] = -0.9;
+            let b = pack_rotation(q);
+            assert_eq!((b >> 30) as usize, big);
+            assert!(unpack_rotation(b)[big] > 0.0);
+        }
+    }
+
+    #[test]
+    fn f16_every_value() {
+        for h in 0..=u16::MAX {
+            let v = f16_to_f32(h);
+            if v.is_nan() {
+                continue;
+            }
+            assert_eq!(f32_to_f16(v), h, "{h:#06x} {v}");
+        }
+        assert_eq!(f32_to_f16(1.0 + 1.0 / 2048.0), 0x3c00);
+        assert_eq!(f32_to_f16(1.0 + 3.0 / 2048.0), 0x3c02);
+    }
+
+    #[test]
+    fn colours() {
+        assert_eq!(parse_hex_color("#3b2a1c"), Some(INK));
+        assert_eq!(parse_hex_color("fff"), Some([255; 4]));
+        assert_eq!(parse_hex_color("#10203040"), Some([0x10, 0x20, 0x30, 0x40]));
+        assert_eq!(parse_hex_color("#12"), None);
+        assert_eq!(hex_color([1, 2, 3, 4]), "#01020304");
+    }
+}
diff --git a/core/src/graph/postings.rs b/core/src/graph/postings.rs
new file mode 100644
index 00000000..e131b371
--- /dev/null
+++ b/core/src/graph/postings.rs
@@ -0,0 +1,297 @@
+//! Posting lists: the derived indexes keep one row per (term, id chunk) whose value is the
+//! set of ids under that term, rather than one multimap row per (term, id) pair, because
+//! redb's per-row cost dwarfs a 2–3 byte id.
+//!
+//! **An id set** covers the ids of one chunk (`id >> CHUNK_BITS`), as their low 16 bits:
+//! - byte 0 = 0: the offsets in ascending order as LEB128 varints of their differences
+//!   (the first from 0);
+//! - byte 0 = 1: a 65536-bit bitmap (8192 bytes), used when it's smaller (dense sets).
+//!
+//! **The content hash index** is keyed by the hash's top 14 bits; its value is a list of
+//! `(the next 32 bits of the hash, little endian u32; the id, LEB128)` pairs sorted by
+//! check then id. A probe returns every id whose check matches; callers compare texts.
+
+use std::collections::{BTreeMap, HashMap};
+
+use super::record::{get_varint, put_varint};
+
+pub const CHUNK_BITS: u32 = 16;
+pub const BITMAP: usize = 8192;
+/// the content hash's bucket bits
+pub const HASH_BUCKET_BITS: u32 = 14;
+
+pub fn chunk_of(id: u64) -> u32 {
+    (id >> CHUNK_BITS) as u32
+}
+
+fn low(id: u64) -> u16 {
+    id as u16
+}
+
+/// the ids of a chunk's set, ascending
+pub fn decode_ids(b: &[u8], chunk: u32) -> Vec {
+    let base = (chunk as u64) << CHUNK_BITS;
+    match b.first() {
+        Some(1) if b.len() == 1 + BITMAP => {
+            let mut out = Vec::new();
+            for (i, byte) in b[1..].iter().enumerate() {
+                let mut bits = *byte;
+                while bits != 0 {
+                    let j = bits.trailing_zeros() as u64;
+                    out.push(base + i as u64 * 8 + j);
+                    bits &= bits - 1;
+                }
+            }
+            out
+        }
+        Some(0) => {
+            let mut out = Vec::new();
+            let mut at = 1;
+            let mut v = 0u64;
+            while at < b.len() {
+                let Some(d) = get_varint(b, &mut at) else { break };
+                v += d;
+                if v > 0xFFFF {
+                    break;
+                }
+                out.push(base + v);
+            }
+            out
+        }
+        _ => Vec::new(),
+    }
+}
+
+/// encodes ascending, distinct ids of one chunk
+pub fn encode_ids(ids: &[u64]) -> Vec {
+    let mut list = vec![0u8];
+    let mut prev = 0u64;
+    for &id in ids {
+        let o = low(id) as u64;
+        put_varint(&mut list, o - prev);
+        prev = o;
+    }
+    if list.len() <= 1 + BITMAP {
+        return list;
+    }
+    let mut bm = vec![0u8; 1 + BITMAP];
+    bm[0] = 1;
+    for &id in ids {
+        let o = low(id) as usize;
+        bm[1 + o / 8] |= 1 << (o % 8);
+    }
+    bm
+}
+
+/// adds and removes ids (all of one chunk) in an encoded set; `None` when it ends empty
+pub fn update_ids(old: Option<&[u8]>, chunk: u32, add: &[u64], remove: &[u64]) -> Option> {
+    let mut ids = old.map(|b| decode_ids(b, chunk)).unwrap_or_default();
+    if !remove.is_empty() {
+        ids.retain(|i| !remove.contains(i));
+    }
+    for &a in add {
+        if let Err(at) = ids.binary_search(&a) {
+            ids.insert(at, a);
+        }
+    }
+    (!ids.is_empty()).then(|| encode_ids(&ids))
+}
+
+pub fn hash_bucket(hash: u64) -> u64 {
+    hash >> (64 - HASH_BUCKET_BITS)
+}
+
+pub fn hash_check(hash: u64) -> u32 {
+    (hash >> (64 - HASH_BUCKET_BITS - 32)) as u32
+}
+
+pub fn decode_pairs(b: &[u8]) -> Vec<(u32, u64)> {
+    let mut out = Vec::new();
+    let mut at = 0;
+    while at + 4 <= b.len() {
+        let check = u32::from_le_bytes([b[at], b[at + 1], b[at + 2], b[at + 3]]);
+        at += 4;
+        let Some(id) = get_varint(b, &mut at) else { break };
+        out.push((check, id));
+    }
+    out
+}
+
+pub fn encode_pairs(pairs: &[(u32, u64)]) -> Vec {
+    let mut out = Vec::with_capacity(pairs.len() * 7);
+    for &(c, id) in pairs {
+        out.extend_from_slice(&c.to_le_bytes());
+        put_varint(&mut out, id);
+    }
+    out
+}
+
+pub fn update_pairs(old: Option<&[u8]>, add: &[(u32, u64)], remove: &[(u32, u64)]) -> Option> {
+    let mut pairs = old.map(decode_pairs).unwrap_or_default();
+    pairs.retain(|p| !remove.contains(p));
+    for &p in add {
+        if let Err(at) = pairs.binary_search(&p) {
+            pairs.insert(at, p);
+        }
+    }
+    (!pairs.is_empty()).then(|| encode_pairs(&pairs))
+}
+
+/// the letter frequency term of a frequency key: its hash's top 14 bits, so a row holds
+/// a few anagram classes and readers check the key (most texts are alone in their class,
+/// and a row per class would be a row per entry)
+pub fn freq_term(key: &str) -> Term {
+    Term::Freq(super::record::content_hash(key) >> (64 - HASH_BUCKET_BITS))
+}
+
+/// what an entry is filed under in the derived indexes
+#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum Term {
+    /// a sum mode (`gematria::Mode as u8`) and value
+    Sum(u8, i64),
+    /// the bucket of a letter frequency key (see `freq_term`)
+    Freq(u64),
+    /// a word (a token from `simd::tokenize`)
+    Word(Vec),
+    /// the content hash of a plain entry's text
+    Hash(u64),
+    /// the creation time bucket (`created >> TIME_BUCKET_BITS` ms)
+    Created(u64),
+    /// an entry this one refers to or calls (what editing that entry must look after)
+    Mention(u64),
+}
+
+/// how many milliseconds of creation time share a bucket (2^22 ms, about 70 minutes)
+pub const TIME_BUCKET_BITS: u32 = 22;
+
+/// the derived indexes held in memory (the `memory` index mode)
+#[derive(Default)]
+pub struct MemIndex {
+    pub map: HashMap>,
+    /// words again, ordered, for prefix search
+    pub words: BTreeMap, Vec>,
+    /// creation buckets, ordered, for time ranges
+    pub created: BTreeMap>,
+}
+
+fn add_sorted(v: &mut Vec, id: u64) {
+    if let Err(at) = v.binary_search(&id) {
+        v.insert(at, id);
+    }
+}
+
+fn remove_sorted(v: &mut Vec, id: u64) {
+    if let Ok(at) = v.binary_search(&id) {
+        v.remove(at);
+    }
+}
+
+impl MemIndex {
+    pub fn add(&mut self, t: &Term, id: u64) {
+        match t {
+            Term::Word(w) => add_sorted(self.words.entry(w.clone()).or_default(), id),
+            Term::Created(b) => add_sorted(self.created.entry(*b).or_default(), id),
+            _ => add_sorted(self.map.entry(t.clone()).or_default(), id),
+        }
+    }
+
+    pub fn remove(&mut self, t: &Term, id: u64) {
+        let gone = match t {
+            Term::Word(w) => self.words.get_mut(w).map(|v| {
+                remove_sorted(v, id);
+                v.is_empty()
+            }),
+            Term::Created(b) => self.created.get_mut(b).map(|v| {
+                remove_sorted(v, id);
+                v.is_empty()
+            }),
+            _ => self.map.get_mut(t).map(|v| {
+                remove_sorted(v, id);
+                v.is_empty()
+            }),
+        };
+        if gone == Some(true) {
+            match t {
+                Term::Word(w) => {
+                    self.words.remove(w);
+                }
+                Term::Created(b) => {
+                    self.created.remove(b);
+                }
+                _ => {
+                    self.map.remove(t);
+                }
+            }
+        }
+    }
+
+    pub fn get(&self, t: &Term) -> &[u64] {
+        match t {
+            Term::Word(w) => self.words.get(w),
+            Term::Created(b) => self.created.get(b),
+            _ => self.map.get(t),
+        }
+        .map(Vec::as_slice)
+        .unwrap_or(&[])
+    }
+
+    /// bytes the index takes, roughly (ids and keys, not the maps' own overhead)
+    pub fn approx_bytes(&self) -> usize {
+        let ids: usize = self.map.values().map(|v| v.len()).sum::()
+            + self.words.values().map(|v| v.len()).sum::()
+            + self.created.values().map(|v| v.len()).sum::();
+        ids * 8 + self.words.keys().map(|k| k.len() + 24).sum::() + self.map.len() * 40
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn id_sets() {
+        let ids: Vec = vec![65536, 65537, 65600, 131071];
+        let b = encode_ids(&ids);
+        assert_eq!(b[0], 0);
+        assert_eq!(decode_ids(&b, 1), ids);
+        // dense sets become bitmaps, and stay exact
+        let dense: Vec = (0..60_000).map(|i| i + (i / 7)).filter(|&i| i < 65536).collect();
+        let b = encode_ids(&dense);
+        assert_eq!(b.len(), 1 + BITMAP);
+        assert_eq!(decode_ids(&b, 0), dense);
+        let u = update_ids(Some(&b), 0, &[6], &[0, 1]).unwrap();
+        let mut want: Vec = dense.iter().copied().filter(|&i| i > 1).collect();
+        want.push(6);
+        want.sort();
+        want.dedup();
+        assert_eq!(decode_ids(&u, 0), want);
+        assert_eq!(update_ids(Some(&encode_ids(&[5])), 0, &[], &[5]), None);
+        assert_eq!(
+            decode_ids(&update_ids(None, 3, &[3 << 16 | 9, 3 << 16 | 2], &[]).unwrap(), 3),
+            vec![3 << 16 | 2, 3 << 16 | 9]
+        );
+        // a small set is about a byte an id
+        let b = encode_ids(&(100..200).collect::>());
+        assert_eq!(b.len(), 1 + 1 + 99);
+    }
+
+    #[test]
+    fn hash_pairs_and_memory() {
+        let p = update_pairs(None, &[(5, 300), (1, 2), (5, 1)], &[]).unwrap();
+        assert_eq!(decode_pairs(&p), vec![(1, 2), (5, 1), (5, 300)]);
+        assert_eq!(
+            decode_pairs(&update_pairs(Some(&p), &[], &[(5, 1)]).unwrap()),
+            vec![(1, 2), (5, 300)]
+        );
+        assert_eq!(hash_bucket(u64::MAX), (1 << HASH_BUCKET_BITS) - 1);
+        let mut m = MemIndex::default();
+        m.add(&Term::Word(b"x".to_vec()), 3);
+        m.add(&Term::Word(b"x".to_vec()), 1);
+        m.add(&Term::Sum(0, 5), 2);
+        assert_eq!(m.get(&Term::Word(b"x".to_vec())), &[1, 3]);
+        m.remove(&Term::Word(b"x".to_vec()), 1);
+        m.remove(&Term::Word(b"x".to_vec()), 3);
+        assert!(m.words.is_empty());
+        assert_eq!(m.get(&Term::Sum(0, 5)), &[2]);
+    }
+}
diff --git a/core/src/graph/prefabs.rs b/core/src/graph/prefabs.rs
new file mode 100644
index 00000000..6403bd27
--- /dev/null
+++ b/core/src/graph/prefabs.rs
@@ -0,0 +1,739 @@
+//! Prefabs (queued request #19; docs/format.md, "One model for a definition and its
+//! placed instances"): blocks grouped into a subassembly, kept as a scene of their own
+//! (its setting `prefab` true), and placed in the room as copies: one prefab placement
+//! each (kind 2, the scene as its definition), a place, a turn and a size.
+//!
+//! A copy's parts are the prefab's blocks, turned, sized and moved with the copy. A part
+//! is addressed as `prefab:#/`, so a link inside the
+//! group (a sticky ray's target) names the inner address and works in every copy. Copies
+//! inherit, as prototypes do in JavaScript: changing the prefab changes every copy, and a
+//! copy's own changes to a part (its place, turn, size, texture or wiring state) are kept
+//! in the copy's placement as overrides that shadow the prefab's values for it alone.
+
+use serde::{Deserialize, Serialize};
+use serde_json::{Map, Value, json};
+
+use super::blocks::{self, Block, Kind, Transform};
+use super::place::{IDENTITY, pack_rotation, unpack_rotation};
+use super::scenes::{self, Def, Kind as SKind, Placed, Placement, SCENES, Scale, Scene};
+use super::store::{GResult, Graph, err};
+use super::wiring::rotate;
+
+/// a placed copy of a prefab
+#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
+pub struct Copy {
+    /// `prefab:#`
+    pub id: String,
+    pub scene: u64,
+    pub name: String,
+    pub x: f32,
+    pub y: f32,
+    pub z: f32,
+    pub rot: [f32; 4],
+    pub scale: f32,
+    /// how many of its parts have their own values
+    pub own: usize,
+}
+
+/// a copy's address
+pub fn copy_id(scene: u64, n: u64) -> String {
+    format!("prefab:{scene}#{n}")
+}
+
+/// a copy's scene and number
+pub fn split_copy(id: &str) -> Option<(u64, u64)> {
+    let rest = id.strip_prefix("prefab:")?;
+    let (s, n) = rest.split_once('#')?;
+    Some((s.parse().ok()?, n.parse().ok()?))
+}
+
+/// a part's copy and inner address
+pub fn split_part(id: &str) -> Option<(&str, &str)> {
+    if !id.starts_with("prefab:") {
+        return None;
+    }
+    id.split_once('/')
+}
+
+pub fn is_part(id: &str) -> bool {
+    split_part(id).is_some()
+}
+
+fn qmul(a: [f32; 4], b: [f32; 4]) -> [f32; 4] {
+    let [ax, ay, az, aw] = a;
+    let [bx, by, bz, bw] = b;
+    let q = [
+        aw * bx + ax * bw + ay * bz - az * by,
+        aw * by - ax * bz + ay * bw + az * bx,
+        aw * bz + ax * by - ay * bx + az * bw,
+        aw * bw - ax * bx - ay * by - az * bz,
+    ];
+    let n = q.iter().map(|x| x * x).sum::().sqrt().max(1e-9);
+    q.map(|x| x / n)
+}
+
+fn conj(q: [f32; 4]) -> [f32; 4] {
+    [-q[0], -q[1], -q[2], q[3]]
+}
+
+/// a part's transform in the room from its transform in the prefab
+fn to_world(c: &Copy, t: &Transform) -> Transform {
+    let p = rotate(c.rot, [t.x * c.scale, t.y * c.scale, t.z * c.scale]);
+    Transform {
+        x: c.x + p[0],
+        y: c.y + p[1],
+        z: c.z + p[2],
+        w: t.w * c.scale,
+        h: t.h * c.scale,
+        d: t.d * c.scale,
+        rot: qmul(c.rot, t.rot),
+        ..*t
+    }
+}
+
+/// a part's transform in the prefab from its transform in the room
+fn to_local(c: &Copy, t: &Transform) -> Transform {
+    let qi = conj(c.rot);
+    let s = c.scale.max(1e-6);
+    let p = rotate(qi, [t.x - c.x, t.y - c.y, t.z - c.z]);
+    Transform {
+        x: p[0] / s,
+        y: p[1] / s,
+        z: p[2] / s,
+        w: t.w / s,
+        h: t.h / s,
+        d: t.d / s,
+        rot: qmul(qi, t.rot),
+        ..*t
+    }
+}
+
+/// each block's address in a new prefab holding them, in this order: its number among
+/// its texture's blocks there, counted from 1
+pub fn inner_ids(parts: &[(Kind, String)]) -> Vec {
+    let mut seen: std::collections::HashMap = Default::default();
+    parts
+        .iter()
+        .map(|(k, t)| {
+            let n = seen.entry(blocks::key(*k, t)).or_insert(0);
+            *n += 1;
+            blocks::block_id(*k, t, *n)
+        })
+        .collect()
+}
+
+fn copy_of(p: &Placed, names: &std::collections::HashMap) -> Option {
+    let (SKind::Prefab, Def::Scene(scene)) = (p.kind, p.def) else {
+        return None;
+    };
+    let q = &p.place;
+    Some(Copy {
+        id: copy_id(scene, q.n),
+        scene,
+        name: names.get(&scene).cloned().unwrap_or_default(),
+        x: q.pos[0],
+        y: q.pos[1],
+        z: q.pos[2],
+        rot: q.rot.map(unpack_rotation).unwrap_or(IDENTITY),
+        scale: match q.scale {
+            Scale::One => 1.0,
+            Scale::Uniform(v) => v,
+            Scale::Axes(a) => (a[0] + a[1] + a[2]) / 3.0,
+        },
+        own: q
+            .own()
+            .and_then(|m| m.get("parts").and_then(Value::as_object).map(|p| p.len()))
+            .unwrap_or(0),
+    })
+}
+
+/// a copy's overrides: inner address → its own values
+fn overrides(p: &Placement) -> Map {
+    p.own()
+        .and_then(|m| m.get("parts").and_then(Value::as_object).cloned())
+        .unwrap_or_default()
+}
+
+/// a part with a copy's own values applied
+fn shadowed(mut b: Block, own: Option<&Value>) -> Block {
+    let Some(o) = own else { return b };
+    if let Some(t) = o
+        .get("t")
+        .and_then(|t| serde_json::from_value::(t.clone()).ok())
+    {
+        let wire = b.t.wire;
+        b.t = t;
+        b.t.wire = wire;
+    }
+    if let (Some(k), Some(tex)) = (
+        o.get("kind")
+            .and_then(|k| serde_json::from_value::(k.clone()).ok()),
+        o.get("texture").and_then(Value::as_str),
+    ) {
+        b.kind = k;
+        b.texture = tex.to_string();
+    }
+    b
+}
+
+impl Graph {
+    /// the save's prefabs (scenes whose setting `prefab` is true)
+    pub fn prefabs(&self) -> GResult> {
+        Ok(self
+            .scenes()?
+            .into_iter()
+            .filter(|s| s.settings.get("prefab") == Some(&Value::Bool(true)))
+            .collect())
+    }
+
+    /// a prefab's blocks, as placed in it (relative to its origin)
+    pub fn prefab_parts(&self, scene: u64) -> GResult> {
+        Ok(self
+            .placements(scene, false)?
+            .iter()
+            .filter_map(blocks::block_of)
+            .collect())
+    }
+
+    fn room_prefab_placements(&self) -> GResult> {
+        Ok(match self.room()? {
+            Some(r) => self
+                .placements(r, false)?
+                .into_iter()
+                .filter(|p| p.kind == SKind::Prefab)
+                .collect(),
+            None => vec![],
+        })
+    }
+
+    fn names(&self) -> GResult> {
+        Ok(self.prefabs()?.into_iter().map(|s| (s.id, s.name)).collect())
+    }
+
+    /// the copies placed in the room
+    pub fn copies(&self) -> GResult> {
+        let names = self.names()?;
+        Ok(self
+            .room_prefab_placements()?
+            .iter()
+            .filter_map(|p| copy_of(p, &names))
+            .collect())
+    }
+
+    fn copy_placement(&self, id: &str) -> GResult<(Copy, Placed)> {
+        let (scene, n) = split_copy(id).ok_or_else(|| format!("{id:?} isn't a prefab's copy"))?;
+        let names = self.names()?;
+        let p = self
+            .room_prefab_placements()?
+            .into_iter()
+            .find(|p| p.def == Def::Scene(scene) && p.place.n == n)
+            .ok_or_else(|| format!("no copy {id}"))?;
+        let c = copy_of(&p, &names).ok_or("not a copy")?;
+        Ok((c, p))
+    }
+
+    /// a copy's parts in the room, each under its part address
+    pub fn copy_parts(&self, id: &str) -> GResult> {
+        let (c, p) = self.copy_placement(id)?;
+        let own = overrides(&p.place);
+        Ok(self
+            .prefab_parts(c.scene)?
+            .into_iter()
+            .map(|b| {
+                let inner = b.id.clone();
+                let mut b = shadowed(b, own.get(&inner));
+                b.t = to_world(&c, &b.t);
+                b.id = format!("{}/{inner}", c.id);
+                b
+            })
+            .collect())
+    }
+
+    /// every copy's parts in the room
+    pub fn parts(&self) -> GResult> {
+        let mut out = Vec::new();
+        for c in self.copies()? {
+            out.extend(self.copy_parts(&c.id)?);
+        }
+        Ok(out)
+    }
+
+    /// the room's blocks and every copy's parts
+    pub fn world_blocks(&self) -> GResult> {
+        let mut all = self.blocks(None)?;
+        all.extend(self.parts()?);
+        Ok(all)
+    }
+
+    /// one part, as it is in the room
+    pub fn part(&self, id: &str) -> GResult> {
+        let Some((copy, _)) = split_part(id) else {
+            return Ok(None);
+        };
+        if self.copy_placement(copy).is_err() {
+            return Ok(None);
+        }
+        Ok(self.copy_parts(copy)?.into_iter().find(|b| b.id == id))
+    }
+
+    /// a copy's own values for one part: what's given replaces them (`Null` drops one)
+    fn set_own(&self, copy: &str, inner: &str, f: impl FnOnce(&mut Map)) -> GResult<()> {
+        let (_, mut p) = self.copy_placement(copy)?;
+        let mut own = p.place.own().unwrap_or_default();
+        let mut parts = own.get("parts").and_then(Value::as_object).cloned().unwrap_or_default();
+        let mut mine = parts.get(inner).and_then(Value::as_object).cloned().unwrap_or_default();
+        f(&mut mine);
+        mine.retain(|_, v| !v.is_null());
+        if mine.is_empty() {
+            parts.remove(inner);
+        } else {
+            parts.insert(inner.to_string(), Value::Object(mine));
+        }
+        if parts.is_empty() {
+            own.remove("parts");
+        } else {
+            own.insert("parts".into(), Value::Object(parts));
+        }
+        p.place.set_own(Some(own));
+        let room = self.room()?.ok_or("no room")?;
+        self.place(room, false, SKind::Prefab, p.def, None, vec![p.place])?;
+        Ok(())
+    }
+
+    /// moves, turns or resizes a part in its copy only (an override); the part as it is now
+    pub fn set_part(&self, id: &str, t: Transform) -> GResult> {
+        let Some((copy, inner)) = split_part(id) else {
+            return Ok(None);
+        };
+        let Ok((c, _)) = self.copy_placement(copy) else {
+            return Ok(None);
+        };
+        let mut local = to_local(&c, &t.checked()?);
+        local.wire = None;
+        let v = serde_json::to_value(local).map_err(err)?;
+        self.set_own(copy, inner, |m| {
+            m.insert("t".into(), v);
+        })?;
+        self.part(id)
+    }
+
+    /// shows another texture on a part, in its copy only
+    pub fn retexture_part(&self, id: &str, kind: Kind, texture: &str) -> GResult> {
+        let Some((copy, inner)) = split_part(id) else {
+            return Ok(None);
+        };
+        blocks::def_of(kind, texture)?;
+        self.set_own(copy, inner, |m| {
+            m.insert("kind".into(), json!(kind));
+            m.insert("texture".into(), json!(texture));
+        })?;
+        self.part(id)
+    }
+
+    /// a part's wiring as its copy has it (its own, when the copy changed it)
+    pub fn part_wiring(&self, id: &str) -> GResult> {
+        let Some((copy, inner)) = split_part(id) else {
+            return Ok(None);
+        };
+        let (_, p) = self.copy_placement(copy)?;
+        Ok(overrides(&p.place).get(inner).and_then(|o| o.get("wiring")).cloned())
+    }
+
+    /// keeps a part's wiring (its state, a ray that stuck) in its copy only
+    pub fn set_part_wiring(&self, id: &str, w: Option) -> GResult<()> {
+        let Some((copy, inner)) = split_part(id) else {
+            return Err(format!("{id:?} isn't a part"));
+        };
+        self.set_own(copy, inner, |m| {
+            m.insert("wiring".into(), w.unwrap_or(Value::Null));
+        })
+    }
+
+    /// groups room blocks into a new prefab named `name` and puts one copy where they
+    /// were: the prefab's id and the copy's. `wires` gives each block's wiring entry as
+    /// the prefab should keep it (links inside the group already naming inner addresses)
+    pub fn make_prefab(&self, name: &str, ids: &[String], wires: &[Option]) -> GResult<(u64, String)> {
+        let mut bs = Vec::new();
+        for id in ids {
+            if is_part(id) || split_copy(id).is_some() {
+                return Err("a prefab can't hold another prefab's parts yet".into());
+            }
+            bs.push(self.block(id)?.ok_or_else(|| format!("no block {id}"))?);
+        }
+        if bs.is_empty() {
+            return Err("which blocks? (select some first)".into());
+        }
+        // the origin: the middle of their boxes
+        let (mut lo, mut hi) = ([f32::INFINITY; 3], [f32::NEG_INFINITY; 3]);
+        for b in &bs {
+            let h = b.t.half_extent();
+            let c = [b.t.x, b.t.y, b.t.z];
+            for i in 0..3 {
+                lo[i] = lo[i].min(c[i] - h[i]);
+                hi[i] = hi[i].max(c[i] + h[i]);
+            }
+        }
+        let o = [0, 1, 2].map(|i| (lo[i] + hi[i]) / 2.0);
+        let txn = self.db().begin_write().map_err(err)?;
+        let copy = {
+            let scene = scenes::add_scene_in(&txn, name, 0)?;
+            mark(&txn, scene)?;
+            let room = scenes::room_in(&txn)?;
+            for (i, b) in bs.iter().enumerate() {
+                let mut t = b.t;
+                (t.x, t.y, t.z) = (t.x - o[0], t.y - o[1], t.z - o[2]);
+                t.wire = wires
+                    .get(i)
+                    .copied()
+                    .flatten()
+                    .map(|entry| super::wiring::WireRef { entry });
+                let def = blocks::def_of(b.kind, &b.texture)?;
+                scenes::place_in(
+                    &txn,
+                    scene,
+                    false,
+                    SKind::Block,
+                    def,
+                    None,
+                    vec![blocks::placement(&t, 0)],
+                    &[],
+                )?;
+                let (_, _, n) = blocks::split_id(&b.id).ok_or("an address")?;
+                scenes::place_in(&txn, room, false, SKind::Block, def, None, vec![], &[n])?;
+            }
+            let n = scenes::place_in(
+                &txn,
+                room,
+                false,
+                SKind::Prefab,
+                Def::Scene(scene),
+                None,
+                vec![Placement::at(0, o).for_kind(SKind::Prefab)],
+                &[],
+            )?[0];
+            (scene, copy_id(scene, n))
+        };
+        txn.commit().map_err(err)?;
+        Ok(copy)
+    }
+
+    /// a new prefab from blocks given relative to its origin (a merge brings them); its id
+    pub fn put_prefab(&self, name: &str, parts: &[(Kind, String, Transform)]) -> GResult {
+        let txn = self.db().begin_write().map_err(err)?;
+        let scene = scenes::add_scene_in(&txn, name, 0)?;
+        mark(&txn, scene)?;
+        for (k, tex, t) in parts {
+            let def = blocks::def_of(*k, tex)?;
+            scenes::place_in(
+                &txn,
+                scene,
+                false,
+                SKind::Block,
+                def,
+                None,
+                vec![blocks::placement(&t.checked()?, 0)],
+                &[],
+            )?;
+        }
+        txn.commit().map_err(err)?;
+        Ok(scene)
+    }
+
+    /// places a copy of a prefab in the room; its id
+    pub fn add_copy(&self, scene: u64, at: [f32; 3], rot: [f32; 4], scale: f32) -> GResult {
+        if !self.prefabs()?.iter().any(|s| s.id == scene) {
+            return Err(format!("no prefab {scene}"));
+        }
+        let room = match self.room()? {
+            Some(r) => r,
+            None => {
+                let txn = self.db().begin_write().map_err(err)?;
+                let r = scenes::room_in(&txn)?;
+                txn.commit().map_err(err)?;
+                r
+            }
+        };
+        let n = self.place(
+            room,
+            false,
+            SKind::Prefab,
+            Def::Scene(scene),
+            None,
+            vec![copy_placement(0, at, rot, scale, None)?],
+        )?[0];
+        Ok(copy_id(scene, n))
+    }
+
+    /// a new copy with its own values (`own`, as a copy keeps them): a copy of a copy, or a
+    /// removed copy put back
+    pub fn add_copy_with(
+        &self,
+        scene: u64,
+        at: [f32; 3],
+        rot: [f32; 4],
+        scale: f32,
+        own: Option>,
+    ) -> GResult {
+        let id = self.add_copy(scene, at, rot, scale)?;
+        if own.as_ref().is_some_and(|m| !m.is_empty()) {
+            let (_, mut p) = self.copy_placement(&id)?;
+            p.place.set_own(own);
+            let room = self.room()?.ok_or("no room")?;
+            self.place(room, false, SKind::Prefab, p.def, None, vec![p.place])?;
+        }
+        Ok(id)
+    }
+
+    /// a copy's own values (overrides of its parts), as it keeps them
+    pub fn copy_own(&self, id: &str) -> GResult>> {
+        Ok(self.copy_placement(id)?.1.place.own())
+    }
+
+    /// moves, turns or sizes a copy (its own values stay)
+    pub fn set_copy(&self, id: &str, at: [f32; 3], rot: [f32; 4], scale: f32) -> GResult {
+        let (_, p) = self.copy_placement(id)?;
+        let own = p.place.own();
+        let room = self.room()?.ok_or("no room")?;
+        self.place(
+            room,
+            false,
+            SKind::Prefab,
+            p.def,
+            None,
+            vec![copy_placement(p.place.n, at, rot, scale, own)?],
+        )?;
+        Ok(self.copy_placement(id)?.0)
+    }
+
+    /// takes a copy away; its placement (to put back)
+    pub fn delete_copy(&self, id: &str) -> GResult {
+        let (_, p) = self.copy_placement(id)?;
+        let room = self.room()?.ok_or("no room")?;
+        self.unplace(room, false, SKind::Prefab, p.def, None, &[p.place.n])?;
+        Ok(p)
+    }
+
+    /// puts a copy back as it was (an undo of [`Graph::delete_copy`])
+    pub fn put_copy(&self, p: Placed) -> GResult<()> {
+        let room = self.room()?.ok_or("no room")?;
+        self.place(room, false, SKind::Prefab, p.def, None, vec![p.place])?;
+        Ok(())
+    }
+
+    /// drops a copy's own values: it shows the prefab as it is again
+    pub fn reset_copy(&self, id: &str) -> GResult<()> {
+        let (_, mut p) = self.copy_placement(id)?;
+        p.place.set_own(None);
+        let room = self.room()?.ok_or("no room")?;
+        self.place(room, false, SKind::Prefab, p.def, None, vec![p.place])?;
+        Ok(())
+    }
+
+    /// makes a copy's own values the prefab's. With `others_follow`, every other copy
+    /// shows the change (their own values still shadow it); without, the other copies
+    /// keep the prefab as it was, as a prefab of its own (` (before)`). The prefab
+    /// the other copies now show, when it's another
+    pub fn apply_copy(&self, id: &str, others_follow: bool) -> GResult> {
+        let (c, p) = self.copy_placement(id)?;
+        let own = overrides(&p.place);
+        let parts = self.prefab_parts(c.scene)?;
+        let mut kept = None;
+        if !others_follow && self.copies()?.iter().any(|o| o.scene == c.scene && o.id != c.id) {
+            let name = format!("{} (before)", c.name);
+            let old: Vec<(Kind, String, Transform)> = parts.iter().map(|b| (b.kind, b.texture.clone(), b.t)).collect();
+            let s = self.put_prefab(&name, &old)?;
+            let room = self.room()?.ok_or("no room")?;
+            for o in self.room_prefab_placements()? {
+                if o.def == Def::Scene(c.scene) && o.place.n != p.place.n {
+                    self.unplace(room, false, SKind::Prefab, o.def, None, &[o.place.n])?;
+                    let mut q = o.place.clone();
+                    q.n = 0;
+                    self.place(room, false, SKind::Prefab, Def::Scene(s), None, vec![q])?;
+                }
+            }
+            kept = Some(s);
+        }
+        // the parts as this copy shows them, written into the prefab
+        let txn = self.db().begin_write().map_err(err)?;
+        for b in parts {
+            let Some(o) = own.get(&b.id) else { continue };
+            let (_, _, n) = blocks::split_id(&b.id).ok_or("an address")?;
+            let def = blocks::def_of(b.kind, &b.texture)?;
+            let mut nb = shadowed(b.clone(), Some(o));
+            // a wiring of its own becomes the prefab's (an entry, as wirings are)
+            if let Some(w) = o.get("wiring") {
+                let text = serde_json::to_string(w).map_err(err)?;
+                nb.t.wire = Some(super::wiring::WireRef {
+                    entry: self.save_text(&text, super::record::mime::WIRING)?.0,
+                });
+            }
+            scenes::place_in(&txn, c.scene, false, SKind::Block, def, None, vec![], &[n])?;
+            let mut pl = blocks::placement(&nb.t, n);
+            pl.n = if nb.kind == b.kind && nb.texture == b.texture {
+                n
+            } else {
+                0
+            };
+            scenes::place_in(
+                &txn,
+                c.scene,
+                false,
+                SKind::Block,
+                blocks::def_of(nb.kind, &nb.texture)?,
+                None,
+                vec![pl],
+                &[],
+            )?;
+        }
+        txn.commit().map_err(err)?;
+        self.reset_copy(id)?;
+        Ok(kept)
+    }
+
+    /// turns a copy into ordinary blocks where its parts are (it stops following the
+    /// prefab); the new blocks' ids, each with the part it was
+    pub fn detach_copy(&self, id: &str) -> GResult> {
+        let parts = self.copy_parts(id)?;
+        let made = self.add_blocks(
+            &parts
+                .iter()
+                .map(|b| (b.kind, b.texture.clone(), b.t))
+                .collect::>(),
+        )?;
+        self.delete_copy(id)?;
+        Ok(parts.into_iter().map(|b| b.id).zip(made).collect())
+    }
+
+    /// removes a prefab with its copies in the room; how many copies went
+    pub fn delete_prefab(&self, scene: u64) -> GResult {
+        if !self.prefabs()?.iter().any(|s| s.id == scene) {
+            return Err(format!("no prefab {scene}"));
+        }
+        let gone: Vec = self
+            .copies()?
+            .into_iter()
+            .filter(|c| c.scene == scene)
+            .map(|c| c.id)
+            .collect();
+        for c in &gone {
+            self.delete_copy(c)?;
+        }
+        self.delete_scene(scene)?;
+        Ok(gone.len())
+    }
+}
+
+/// marks a scene as a prefab, inside a write
+fn mark(txn: &redb::WriteTransaction, scene: u64) -> GResult<()> {
+    use redb::ReadableTable;
+    let mut t = txn.open_table(SCENES).map_err(err)?;
+    let mut s: Scene = match t.get(scene).map_err(err)? {
+        Some(v) => serde_json::from_slice(v.value()).map_err(err)?,
+        None => return Err(format!("no scene {scene}")),
+    };
+    s.settings = json!({ "prefab": true });
+    t.insert(scene, serde_json::to_vec(&s).map_err(err)?.as_slice())
+        .map_err(err)?;
+    Ok(())
+}
+
+fn copy_placement(
+    n: u64,
+    at: [f32; 3],
+    rot: [f32; 4],
+    scale: f32,
+    own: Option>,
+) -> GResult {
+    if !at.iter().all(|v| v.is_finite()) || !scale.is_finite() || scale <= 0.0 {
+        return Err("a copy's place and size are numbers (its size above 0)".into());
+    }
+    let mut p = Placement::at(n, at).for_kind(SKind::Prefab);
+    let len = rot.iter().map(|x| x * x).sum::().sqrt();
+    if len.is_finite() && len > 1e-6 && rot != IDENTITY {
+        p.rot = Some(pack_rotation(rot.map(|x| x / len)));
+    }
+    p.scale = Scale::Uniform(scale.clamp(0.01, 100.0)).canonical();
+    p.set_own(own);
+    Ok(p)
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    fn at(x: f32, z: f32) -> Transform {
+        Transform {
+            x,
+            z,
+            ..Transform::default()
+        }
+    }
+
+    #[test]
+    fn prefabs_group_copy_and_inherit() {
+        let g = Graph::in_memory().unwrap();
+        let ids = g
+            .add_blocks(&[
+                (Kind::Plain, "#ff0000".into(), at(0.0, 0.0)),
+                (Kind::Plain, "#00ff00".into(), at(2.0, 0.0)),
+                (Kind::Plain, "#0000ff".into(), at(9.0, 9.0)),
+            ])
+            .unwrap();
+        let (scene, copy) = g.make_prefab("pair", &ids[..2], &[None, None]).unwrap();
+        // the two went into the prefab; one copy stands where they were
+        assert_eq!(g.blocks(None).unwrap().len(), 1);
+        assert_eq!(g.prefabs().unwrap()[0].name, "pair");
+        let parts = g.copy_parts(©).unwrap();
+        assert_eq!(parts.len(), 2);
+        assert_eq!(parts[0].id, format!("{copy}/plain:#00ff00#1"));
+        let x: Vec = g.prefab_parts(scene).unwrap().iter().map(|b| b.t.x).collect();
+        assert_eq!(x, [1.0, -1.0]);
+        assert_eq!(g.world_blocks().unwrap().len(), 3);
+
+        // a second copy, a quarter turn about y, twice the size, at 20
+        let s = std::f32::consts::FRAC_1_SQRT_2;
+        let two = g.add_copy(scene, [20.0, 0.0, 0.0], [0.0, s, 0.0, s], 2.0).unwrap();
+        let red = g.part(&format!("{two}/plain:#ff0000#1")).unwrap().unwrap();
+        // -1 along x, turned a quarter about y, is +2 along z at twice the size
+        assert!(
+            (red.t.x - 20.0).abs() < 1e-3 && (red.t.z - 2.0).abs() < 1e-3,
+            "{:?}",
+            red.t
+        );
+        assert!((red.t.w - 2.0).abs() < 1e-6);
+
+        // moving a part in one copy is that copy's own
+        let mut t = red.t;
+        t.y = 5.0;
+        g.set_part(&red.id, t).unwrap();
+        assert!((g.part(&red.id).unwrap().unwrap().t.y - 5.0).abs() < 1e-4);
+        let first_red = g.part(&format!("{copy}/plain:#ff0000#1")).unwrap().unwrap();
+        assert_eq!(first_red.t.y, 0.0);
+        g.retexture_part(&red.id, Kind::Plain, "#123456").unwrap();
+        assert_eq!(g.part(&red.id).unwrap().unwrap().texture, "#123456");
+
+        // applying it to the prefab while keeping the first copy as it was
+        let kept = g.apply_copy(&two, false).unwrap().unwrap();
+        assert_eq!(g.prefabs().unwrap().len(), 2);
+        assert!(g.copies().unwrap().iter().any(|c| c.scene == kept));
+        let now: Vec = g
+            .prefab_parts(scene)
+            .unwrap()
+            .iter()
+            .map(|b| b.texture.clone())
+            .collect();
+        assert!(now.contains(&"#123456".to_string()));
+        assert_eq!(g.copies().unwrap().iter().find(|c| c.scene == scene).unwrap().own, 0);
+
+        // detaching makes ordinary blocks
+        let made = g.detach_copy(&two).unwrap();
+        assert_eq!(made.len(), 2);
+        assert_eq!(g.blocks(None).unwrap().len(), 3);
+        assert_eq!(g.delete_prefab(kept).unwrap(), 1);
+        assert!(g.copies().unwrap().is_empty());
+        assert_eq!(
+            inner_ids(&[(Kind::Plain, "#aaaaaa".into()), (Kind::Plain, "#aaaaaa".into())])[1],
+            "plain:#aaaaaa#2"
+        );
+    }
+}
diff --git a/core/src/graph/query.rs b/core/src/graph/query.rs
new file mode 100644
index 00000000..cb05e5b2
--- /dev/null
+++ b/core/src/graph/query.rs
@@ -0,0 +1,307 @@
+//! The query model the lenses read through: filters by words, sums, letters, tags, time,
+//! mime and relations, intersected, then ordered and paged; and the figures for a stats
+//! view.
+
+use std::collections::{BTreeMap, HashMap};
+
+use super::gematria::{Measure, Mode};
+use super::postings::{TIME_BUCKET_BITS, Term};
+use super::record::mime;
+use super::store::{GResult, Reader, View, rel};
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub struct Page {
+    pub offset: usize,
+    pub limit: usize,
+}
+
+impl Page {
+    pub fn first(limit: usize) -> Page {
+        Page { offset: 0, limit }
+    }
+
+    pub fn all() -> Page {
+        Page {
+            offset: 0,
+            limit: usize::MAX,
+        }
+    }
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq)]
+pub enum Dir {
+    /// the entries `id` has edges to (a list's members, what a note is on, an entry's tags,
+    /// what a map places)
+    From,
+    /// the entries with edges to `id` (notes on it, lists holding it, entries with a tag)
+    To,
+}
+
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
+pub enum Order {
+    /// ascending ids (weum's key order)
+    #[default]
+    Id,
+    /// oldest first
+    Created,
+    /// newest first
+    CreatedDesc,
+    /// most recently edited first
+    EditedDesc,
+    /// the relation's own order (a list's member order, notes oldest first), when the
+    /// query has a relation; else by id
+    Relation,
+}
+
+/// what to find; every filter given must hold
+#[derive(Debug, Clone, Default)]
+pub struct Query {
+    /// weum's token search: entries with at least three quarters of the query's words
+    pub words: Option,
+    /// entries filed under a sum
+    pub sum: Option<(Mode, i64)>,
+    /// entries with a sum in an inclusive range
+    pub sum_range: Option<(Mode, i64, i64)>,
+    /// anagrams of a text (the same letter frequencies)
+    pub letters_of: Option,
+    /// entries carrying a tag entry
+    pub tag: Option,
+    /// created between these times (ms, inclusive)
+    pub created: Option<(u64, u64)>,
+    /// last edited between these times (ms, inclusive)
+    pub edited: Option<(u64, u64)>,
+    pub mime: Option,
+    /// entries related to an entry
+    pub related: Option<(u16, u64, Dir)>,
+    pub order: Order,
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Found {
+    /// the page of ids
+    pub ids: Vec,
+    /// how many matched in all
+    pub total: usize,
+}
+
+fn intersect(a: Vec, b: &[u64]) -> Vec {
+    let set: std::collections::HashSet = b.iter().copied().collect();
+    a.into_iter().filter(|x| set.contains(x)).collect()
+}
+
+impl View<'_> {
+    /// weum's search: ids found under at least three quarters of the query's tokens, in
+    /// the order they turn up
+    pub fn search_words(&self, query: &str) -> GResult> {
+        let tokens = crate::simd::unique_tokens(query.as_bytes());
+        if tokens.is_empty() {
+            return Ok(Vec::new());
+        }
+        let threshold = ((tokens.len() as f32 * 0.75).ceil() as usize).max(1);
+        let mut scores: HashMap = HashMap::new();
+        let mut order = Vec::new();
+        for tk in tokens {
+            for id in self.postings(&Term::Word(tk.to_vec()))? {
+                let n = scores.entry(id).or_insert(0);
+                if *n == 0 {
+                    order.push(id);
+                }
+                *n += 1;
+            }
+        }
+        Ok(order.into_iter().filter(|id| scores[id] >= threshold).collect())
+    }
+
+    /// entries filed under a sum
+    pub fn by_sum(&self, mode: Mode, value: i64) -> GResult> {
+        self.postings(&Term::Sum(mode as u8, value))
+    }
+
+    /// anagrams of a text; candidates by the frequency key's hash, checked
+    pub fn by_letters(&self, text: &str) -> GResult> {
+        let key = crate::simd::frequency_key(text.as_bytes());
+        if key.is_empty() {
+            return Ok(Vec::new());
+        }
+        let ids = self.postings(&super::postings::freq_term(&key))?;
+        let texts = self.render_many(&ids);
+        Ok(ids
+            .into_iter()
+            .zip(texts)
+            .filter(|(_, t)| {
+                t.as_ref()
+                    .is_ok_and(|t| crate::simd::frequency_key(t.as_bytes()) == key)
+            })
+            .map(|(id, _)| id)
+            .collect())
+    }
+
+    /// entries created in a time range (ms, inclusive), oldest first
+    pub fn created_between(&self, from: u64, to: u64) -> GResult> {
+        let mut out = Vec::new();
+        for id in self.created_buckets(from >> TIME_BUCKET_BITS, to >> TIME_BUCKET_BITS)? {
+            if let Some(r) = self.record(id)?
+                && r.created >= from
+                && r.created <= to
+            {
+                out.push((r.created, id));
+            }
+        }
+        out.sort();
+        out.dedup();
+        Ok(out.into_iter().map(|(_, id)| id).collect())
+    }
+
+    fn related(&self, r: u16, id: u64, dir: Dir) -> GResult> {
+        Ok(match (r, dir) {
+            (rel::MEMBER, Dir::From) => self.members(id)?,
+            (rel::NOTE, Dir::To) => self.notes_on(id)?,
+            (_, Dir::From) => {
+                let mut v: Vec = self.out_edges(id, r)?.into_iter().map(|(t, _)| t).collect();
+                v.dedup();
+                v
+            }
+            (_, Dir::To) => self.in_edges(id, r)?,
+        })
+    }
+
+    pub fn query(&self, q: &Query, page: Page) -> GResult {
+        let mut sets: Vec> = Vec::new();
+        let mut rel_order: Option> = None;
+        if let Some((r, id, dir)) = q.related {
+            let v = self.related(r, id, dir)?;
+            rel_order = Some(v.clone());
+            sets.push(v);
+        }
+        if let Some(w) = &q.words {
+            sets.push(self.search_words(w)?);
+        }
+        if let Some((m, v)) = q.sum {
+            sets.push(self.by_sum(m, v)?);
+        }
+        if let Some((m, lo, hi)) = q.sum_range {
+            let mut v = Vec::new();
+            for (value, _) in self.sum_counts(m)? {
+                if value >= lo && value <= hi {
+                    v.extend(self.by_sum(m, value)?);
+                }
+            }
+            sets.push(v);
+        }
+        if let Some(t) = &q.letters_of {
+            sets.push(self.by_letters(t)?);
+        }
+        if let Some(t) = q.tag {
+            sets.push(self.in_edges(t, rel::TAG)?);
+        }
+        if let Some((a, b)) = q.created {
+            sets.push(self.created_between(a, b)?);
+        }
+        let mut ids = match sets.len() {
+            0 => self.ids()?,
+            _ => {
+                // the first set keeps its order (relation order, search order)
+                let mut it = sets.into_iter();
+                let first = it.next().unwrap();
+                it.fold(first, |acc, s| intersect(acc, &s))
+            }
+        };
+        let mut seen = std::collections::HashSet::new();
+        ids.retain(|id| seen.insert(*id));
+        let needs_records = q.mime.is_some()
+            || q.edited.is_some()
+            || matches!(q.order, Order::Created | Order::CreatedDesc | Order::EditedDesc);
+        let mut rows: Vec<(u64, u64, u64)> = Vec::with_capacity(ids.len());
+        for id in ids {
+            if needs_records {
+                let Some(r) = self.record(id)? else { continue };
+                if q.mime.is_some_and(|m| m != r.mime) {
+                    continue;
+                }
+                if q.edited.is_some_and(|(a, b)| r.edited < a || r.edited > b) {
+                    continue;
+                }
+                rows.push((id, r.created, r.edited));
+            } else {
+                rows.push((id, 0, 0));
+            }
+        }
+        match q.order {
+            Order::Id => rows.sort_by_key(|r| r.0),
+            Order::Created => rows.sort_by_key(|r| (r.1, r.0)),
+            Order::CreatedDesc => rows.sort_by_key(|r| std::cmp::Reverse((r.1, r.0))),
+            Order::EditedDesc => rows.sort_by_key(|r| std::cmp::Reverse((r.2, r.0))),
+            Order::Relation => {
+                if rel_order.is_none() {
+                    rows.sort_by_key(|r| r.0);
+                }
+            }
+        }
+        let total = rows.len();
+        let ids = rows
+            .into_iter()
+            .skip(page.offset)
+            .take(page.limit)
+            .map(|r| r.0)
+            .collect();
+        Ok(Found { ids, total })
+    }
+
+    /// the figures of a stats view
+    pub fn stats(&self) -> GResult {
+        let all = self.all()?;
+        let mut by_mime: BTreeMap = BTreeMap::new();
+        let mut oldest = u64::MAX;
+        let mut newest = 0;
+        let mut body_bytes = 0u64;
+        let mut borrowing = 0u64;
+        for e in &all {
+            *by_mime.entry(e.record.mime).or_default() += 1;
+            oldest = oldest.min(e.record.created);
+            newest = newest.max(e.record.created);
+            body_bytes += e.record.body.len() as u64;
+            if e.record.plain() && e.record.has_refs() {
+                borrowing += 1;
+            }
+        }
+        let mut edges: BTreeMap = BTreeMap::new();
+        for (_, r, _, _) in self.all_edges()? {
+            *edges.entry(r).or_default() += 1;
+        }
+        let mut mimes = Vec::new();
+        for (m, n) in by_mime {
+            mimes.push((self.mime_name(m)?, n));
+        }
+        Ok(Stats {
+            entries: all.len() as u64,
+            by_mime: mimes,
+            edges: edges.into_iter().map(|(r, n)| (rel::name(r), n)).collect(),
+            versions: self.history_count()?,
+            oldest: (oldest != u64::MAX).then_some(oldest),
+            newest: (!all.is_empty()).then_some(newest),
+            body_bytes,
+            borrowing,
+            notes: all.iter().filter(|e| e.record.mime == mime::MARKDOWN).count() as u64,
+        })
+    }
+
+    /// what a text measures (for a sidecar)
+    pub fn measure(text: &str) -> Measure {
+        Measure::of(text)
+    }
+}
+
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Stats {
+    pub entries: u64,
+    pub by_mime: Vec<(String, u64)>,
+    pub edges: Vec<(String, u64)>,
+    pub versions: u64,
+    pub oldest: Option,
+    pub newest: Option,
+    /// packed body bytes of every entry
+    pub body_bytes: u64,
+    /// entries stored partly as refs to others
+    pub borrowing: u64,
+    pub notes: u64,
+}
diff --git a/core/src/graph/record.rs b/core/src/graph/record.rs
new file mode 100644
index 00000000..32830775
--- /dev/null
+++ b/core/src/graph/record.rs
@@ -0,0 +1,568 @@
+//! The bytes an entry, a past version and an edge are stored as; ids and weum keys; the
+//! content hash. Pure functions, no database.
+
+/// the record layout version
+pub const VERSION: u8 = 1;
+
+/// the body holds only text and refs that borrow (its rendered text never changes unless
+/// the entry itself is edited); such entries are in the content hash index
+pub const PLAIN: u8 = 1;
+/// the body has refs (borrowed parts for a plain entry, transclusions or calls otherwise)
+pub const HAS_REFS: u8 = 2;
+/// flag bits 4–7: how many borrow hops rendering may take (a hint for borrowing)
+pub const DEPTH_SHIFT: u8 = 4;
+
+/// mime types every store knows; others are registered in the `graph mimes` table from
+/// `FIRST_CUSTOM_MIME` on
+pub mod mime {
+    pub const TEXT: u16 = 0;
+    pub const MARKDOWN: u16 = 1;
+    pub const FN: u16 = 2;
+    pub const TAG: u16 = 3;
+    pub const LIST: u16 = 4;
+    pub const MAP: u16 = 5;
+    pub const CLASSIFIER: u16 = 6;
+    pub const JSON: u16 = 7;
+    /// a chain: a ref to its title, members as ordered `MEMBER` edges (`graph::chains`)
+    pub const CHAIN: u16 = 8;
+    /// an animation: its text the animation's JSON (`graph::anims`)
+    pub const ANIMATION: u16 = 9;
+    /// a block's wiring: its text the wiring's JSON (`graph::wiring`)
+    pub const WIRING: u16 = 10;
+    /// a taxonomy: its text the taxonomy's JSON, classifiers in a tree (`ops::taxonomy`)
+    pub const TAXONOMY: u16 = 11;
+    /// a pipe: its text the pipe's JSON, a filter and its effects (`ops::pipes`)
+    pub const PIPE: u16 = 12;
+    /// a tag set: its text the set's JSON, word types of one's own (`ops::tagsets`)
+    pub const TAGSET: u16 = 13;
+    /// a group of things in the room: its text the group's JSON (`ops::groups`)
+    pub const GROUP: u16 = 14;
+
+    /// entries that are a block's data rather than texts: left out of search and counts
+    pub fn hidden(m: u16) -> bool {
+        m == ANIMATION || m == WIRING || m == TAXONOMY || m == PIPE || m == TAGSET || m == GROUP
+    }
+
+    pub const NAMES: [&str; 15] = [
+        "text/plain",
+        "text/markdown",
+        "application/x-anend-fn",
+        "application/x-anend-tag",
+        "application/x-anend-list",
+        "application/x-anend-map",
+        "application/x-anend-classifier",
+        "application/json",
+        "application/x-anend-chain",
+        "application/x-anend-animation",
+        "application/x-anend-wiring",
+        "application/x-anend-taxonomy",
+        "application/x-anend-pipe",
+        "application/x-anend-tagset",
+        "application/x-anend-group",
+    ];
+
+    pub fn builtin(name: &str) -> Option {
+        NAMES.iter().position(|n| *n == name).map(|i| i as u16)
+    }
+}
+
+pub const FIRST_CUSTOM_MIME: u16 = 64;
+
+// ---------------------------------------------------------------- varints (bytes)
+
+pub fn put_varint(out: &mut Vec, mut v: u64) {
+    loop {
+        let b = (v & 0x7F) as u8;
+        v >>= 7;
+        if v == 0 {
+            out.push(b);
+            return;
+        }
+        out.push(b | 0x80);
+    }
+}
+
+pub fn get_varint(b: &[u8], at: &mut usize) -> Option {
+    let mut v = 0u64;
+    for shift in (0..64).step_by(7) {
+        let byte = *b.get(*at)?;
+        *at += 1;
+        v |= ((byte & 0x7F) as u64) << shift;
+        if byte & 0x80 == 0 {
+            return Some(v);
+        }
+    }
+    None
+}
+
+// ---------------------------------------------------------------- entries
+
+/// an entry as stored
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub struct Record {
+    pub flags: u8,
+    /// milliseconds since the Unix epoch
+    pub created: u64,
+    pub edited: u64,
+    pub mime: u16,
+    /// the packed run (see `codec`)
+    pub body: Vec,
+}
+
+impl Record {
+    pub fn plain(&self) -> bool {
+        self.flags & PLAIN != 0
+    }
+
+    pub fn has_refs(&self) -> bool {
+        self.flags & HAS_REFS != 0
+    }
+
+    pub fn depth(&self) -> u8 {
+        self.flags >> DEPTH_SHIFT
+    }
+
+    /// `version, flags, varint created, varint (edited - created), varint mime, body`
+    pub fn encode(&self) -> Vec {
+        let mut out = Vec::with_capacity(self.body.len() + 12);
+        out.push(VERSION);
+        out.push(self.flags);
+        put_varint(&mut out, self.created);
+        put_varint(&mut out, self.edited.saturating_sub(self.created));
+        put_varint(&mut out, self.mime as u64);
+        out.extend_from_slice(&self.body);
+        out
+    }
+
+    pub fn decode(b: &[u8]) -> Option {
+        if b.len() < 2 || b[0] != VERSION {
+            return None;
+        }
+        let mut at = 2;
+        let created = get_varint(b, &mut at)?;
+        let edited = created.checked_add(get_varint(b, &mut at)?)?;
+        let mime = u16::try_from(get_varint(b, &mut at)?).ok()?;
+        Some(Record {
+            flags: b[1],
+            created,
+            edited,
+            mime,
+            body: b[at..].to_vec(),
+        })
+    }
+}
+
+// ---------------------------------------------------------------- past versions
+
+/// a past version: either whole, or the text of the version after it with a middle part
+/// swapped (`prefix` bytes kept from the start, `suffix` from the end)
+#[derive(Debug, Clone, PartialEq, Eq)]
+pub enum Past {
+    Whole(Record),
+    Delta {
+        mime: u16,
+        prefix: u64,
+        suffix: u64,
+        /// the packed middle text
+        middle: Vec,
+    },
+}
+
+impl Past {
+    /// byte 0 the version, byte 1 the kind (0 whole: a record follows; 1 delta: varint
+    /// mime, prefix and suffix, then the packed middle)
+    pub fn encode(&self) -> Vec {
+        match self {
+            Past::Whole(r) => [vec![VERSION, 0], r.encode()].concat(),
+            Past::Delta {
+                mime,
+                prefix,
+                suffix,
+                middle,
+            } => {
+                let mut out = vec![VERSION, 1];
+                put_varint(&mut out, *mime as u64);
+                put_varint(&mut out, *prefix);
+                put_varint(&mut out, *suffix);
+                out.extend_from_slice(middle);
+                out
+            }
+        }
+    }
+
+    pub fn decode(b: &[u8]) -> Option {
+        if b.len() < 2 || b[0] != VERSION {
+            return None;
+        }
+        match b[1] {
+            0 => Record::decode(&b[2..]).map(Past::Whole),
+            1 => {
+                let mut at = 2;
+                let mime = u16::try_from(get_varint(b, &mut at)?).ok()?;
+                let prefix = get_varint(b, &mut at)?;
+                let suffix = get_varint(b, &mut at)?;
+                Some(Past::Delta {
+                    mime,
+                    prefix,
+                    suffix,
+                    middle: b[at..].to_vec(),
+                })
+            }
+            _ => None,
+        }
+    }
+}
+
+/// how many bytes `old` shares with `new` at the start and the end (on char boundaries,
+/// not overlapping)
+pub fn common_ends(old: &str, new: &str) -> (usize, usize) {
+    let mut p = old.bytes().zip(new.bytes()).take_while(|(a, b)| a == b).count();
+    while !old.is_char_boundary(p) || !new.is_char_boundary(p) {
+        p -= 1;
+    }
+    let max_s = old.len().min(new.len()) - p;
+    let mut s = old
+        .bytes()
+        .rev()
+        .zip(new.bytes().rev())
+        .take(max_s)
+        .take_while(|(a, b)| a == b)
+        .count();
+    while !old.is_char_boundary(old.len() - s) || !new.is_char_boundary(new.len() - s) {
+        s -= 1;
+    }
+    (p, s)
+}
+
+// ---------------------------------------------------------------- edges
+
+/// a forward edge value: the target id (big endian) then the payload
+pub fn edge_value(to: u64, payload: &[u8]) -> Vec {
+    [&to.to_be_bytes()[..], payload].concat()
+}
+
+pub fn split_edge(v: &[u8]) -> Option<(u64, &[u8])> {
+    let to = u64::from_be_bytes(v.get(..8)?.try_into().ok()?);
+    Some((to, &v[8..]))
+}
+
+// ---------------------------------------------------------------- ids
+
+/// where each weum key length starts among the ids
+const SPANS: [u64; 4] = [0, 256, 256 + 65_536, 256 + 65_536 + 16_777_216];
+/// the first id with no weum key
+pub const PAST_WEUM: u64 = 256 + 65_536 + 16_777_216 + 4_294_967_296;
+
+/// weum's key for an id: ids count weum's allocation order (`[0]..[255]`, `[0,0]..`,
+/// three bytes, four bytes), so id `n + 1` is weum's `next_key` of id `n`. Ids past the
+/// four byte keys are their 8 big endian bytes.
+pub fn key_of(id: u64) -> Vec {
+    for len in (1..=4).rev() {
+        if id >= SPANS[len - 1] && id < PAST_WEUM {
+            let v = id - SPANS[len - 1];
+            return v.to_be_bytes()[8 - len..].to_vec();
+        }
+    }
+    id.to_be_bytes().to_vec()
+}
+
+pub fn id_of(key: &[u8]) -> Option {
+    match key.len() {
+        1..=4 => {
+            let mut b = [0u8; 8];
+            b[8 - key.len()..].copy_from_slice(key);
+            Some(SPANS[key.len() - 1] + u64::from_be_bytes(b))
+        }
+        8 => {
+            let id = u64::from_be_bytes(key.try_into().ok()?);
+            (id >= PAST_WEUM).then_some(id)
+        }
+        _ => None,
+    }
+}
+
+/// how weum shows a key: its bytes, comma separated ("3,14")
+pub fn label(id: u64) -> String {
+    key_of(id).iter().map(|b| b.to_string()).collect::>().join(",")
+}
+
+pub fn parse_label(s: &str) -> Option {
+    let bytes: Option> = s.trim().split(',').map(|p| p.trim().parse::().ok()).collect();
+    id_of(&bytes?)
+}
+
+// ---------------------------------------------------------------- hashing
+
+const BASE: u64 = 0x100_0000_01b3;
+
+/// a polynomial hash over bytes, so any prefix or suffix hash comes from prefix hashes
+pub fn poly(bytes: &[u8]) -> u64 {
+    bytes
+        .iter()
+        .fold(0u64, |h, &b| h.wrapping_mul(BASE).wrapping_add(b as u64 + 1))
+}
+
+/// the poly hash of every prefix: `p[k]` hashes `bytes[..k]`
+pub fn prefix_polys(bytes: &[u8]) -> Vec {
+    let mut out = Vec::with_capacity(bytes.len() + 1);
+    let mut h = 0u64;
+    out.push(h);
+    for &b in bytes {
+        h = h.wrapping_mul(BASE).wrapping_add(b as u64 + 1);
+        out.push(h);
+    }
+    out
+}
+
+pub fn pow(n: usize) -> u64 {
+    let (mut r, mut b, mut e) = (1u64, BASE, n);
+    while e > 0 {
+        if e & 1 == 1 {
+            r = r.wrapping_mul(b);
+        }
+        b = b.wrapping_mul(b);
+        e >>= 1;
+    }
+    r
+}
+
+/// the poly hash of `bytes[a..b]` from the prefix hashes
+pub fn slice_poly(prefix: &[u64], a: usize, b: usize) -> u64 {
+    prefix[b].wrapping_sub(prefix[a].wrapping_mul(pow(b - a)))
+}
+
+/// the content hash the dedup index is keyed by, from a poly hash and a length
+pub fn finish(poly: u64, len: usize) -> u64 {
+    let mut x = poly ^ (len as u64).wrapping_mul(0x9E37_79B9_7F4A_7C15);
+    x ^= x >> 33;
+    x = x.wrapping_mul(0xff51_afd7_ed55_8ccd);
+    x ^= x >> 33;
+    x = x.wrapping_mul(0xc4ce_b9fe_1a85_ec53);
+    x ^ (x >> 33)
+}
+
+pub fn content_hash(text: &str) -> u64 {
+    finish(poly(text.as_bytes()), text.len())
+}
+
+#[cfg(test)]
+mod tests {
+    use super::*;
+
+    #[test]
+    fn records_round_trip() {
+        let r = Record {
+            flags: PLAIN | HAS_REFS | (3 << DEPTH_SHIFT),
+            created: 1_791_000_000_000,
+            edited: 1_791_000_000_500,
+            mime: 300,
+            body: vec![1, 2, 3],
+        };
+        let b = r.encode();
+        assert_eq!(b.len(), 2 + 6 + 2 + 2 + 3);
+        assert_eq!(Record::decode(&b), Some(r.clone()));
+        assert_eq!(r.depth(), 3);
+        assert!(Record::decode(&[2, 0, 0, 0, 0]).is_none());
+        assert!(Record::decode(&[1]).is_none());
+        let p = Past::Delta {
+            mime: 1,
+            prefix: 10,
+            suffix: 200,
+            middle: vec![9, 9],
+        };
+        assert_eq!(Past::decode(&p.encode()), Some(p));
+        let w = Past::Whole(r);
+        assert_eq!(Past::decode(&w.encode()), Some(w));
+    }
+
+    #[test]
+    fn weum_keys() {
+        assert_eq!(key_of(0), vec![0]);
+        assert_eq!(key_of(255), vec![255]);
+        assert_eq!(key_of(256), vec![0, 0]);
+        assert_eq!(key_of(256 + 0x0102), vec![1, 2]);
+        assert_eq!(key_of(256 + 65_536), vec![0, 0, 0]);
+        assert_eq!(key_of(PAST_WEUM - 1), vec![255, 255, 255, 255]);
+        assert_eq!(key_of(PAST_WEUM).len(), 8);
+        for id in [
+            0,
+            1,
+            255,
+            256,
+            257,
+            65_791,
+            65_792,
+            70_000,
+            16_843_007,
+            16_843_008,
+            PAST_WEUM - 1,
+            PAST_WEUM,
+            u64::MAX,
+        ] {
+            assert_eq!(id_of(&key_of(id)), Some(id), "{id}");
+            assert_eq!(parse_label(&label(id)), Some(id));
+        }
+        assert_eq!(label(256 + 3 * 256 + 14), "3,14");
+        assert_eq!(parse_label(" 3, 14 "), Some(256 + 3 * 256 + 14));
+        assert_eq!(parse_label("hello"), None);
+        assert_eq!(id_of(&[]), None);
+        assert_eq!(id_of(&[0; 8]), None, "8 byte keys are only for ids past weum's");
+        // id n + 1 is weum's next key after id n
+        let next = |b: &[u8]| id_of(b).map(|i| key_of(i + 1));
+        assert_eq!(next(&[255]), Some(vec![0, 0]));
+        assert_eq!(next(&[0, 255]), Some(vec![1, 0]));
+        assert_eq!(next(&[255, 255]), Some(vec![0, 0, 0]));
+        assert_eq!(next(&[0, 0, 1, 255]), Some(vec![0, 0, 2, 0]));
+    }
+
+    #[test]
+    fn hashes_compose() {
+        let t = "the quick brown fox";
+        let p = prefix_polys(t.as_bytes());
+        assert_eq!(p[t.len()], poly(t.as_bytes()));
+        assert_eq!(slice_poly(&p, 4, 9), poly(b"quick"));
+        assert_eq!(slice_poly(&p, 10, t.len()), poly(b"brown fox"));
+        assert_ne!(content_hash("a"), content_hash("a "));
+        assert_ne!(content_hash(""), content_hash("\0"));
+        assert_eq!(common_ends("hello world", "hello there world"), (6, 5));
+        assert_eq!(common_ends("aaa", "aaaa"), (3, 0));
+        assert_eq!(common_ends("ab", "ab"), (2, 0));
+        assert_eq!(common_ends("xé", "yé"), (0, 2));
+        assert_eq!(common_ends("éa", "èa"), (0, 1));
+    }
+}
+
+// ---------------------------------------------------------------- blocks
+
+/// the first byte of a long record's stub (never a record's version)
+pub const LONG_STUB: u8 = 0xF5;
+
+/// a stub for a record kept in `graph long`: its length in bytes and how many pieces
+pub fn make_long_stub(total: usize, pieces: u32) -> Vec {
+    let mut out = vec![LONG_STUB];
+    put_varint(&mut out, total as u64);
+    put_varint(&mut out, pieces as u64);
+    out
+}
+
+/// a stub's (length, pieces), when a slot holds one
+pub fn long_stub(b: &[u8]) -> Option<(usize, u32)> {
+    if b.first() != Some(&LONG_STUB) {
+        return None;
+    }
+    let mut at = 1;
+    let total = get_varint(b, &mut at)? as usize;
+    let pieces = u32::try_from(get_varint(b, &mut at)?).ok()?;
+    Some((total, pieces))
+}
+
+/// entries are stored 32 to a row: block `id >> BLOCK_BITS`, slot `id & 31`
+pub const BLOCK_BITS: u32 = 5;
+pub const SLOTS: usize = 1 << BLOCK_BITS;
+
+pub fn block_of(id: u64) -> u64 {
+    id >> BLOCK_BITS
+}
+
+pub fn slot_of(id: u64) -> usize {
+    (id as usize) & (SLOTS - 1)
+}
+
+/// a block row: a u32 (little endian) with a bit per occupied slot, a varint length per
+/// occupied slot in slot order, then the records in slot order
+#[derive(Debug, Clone, Default, PartialEq, Eq)]
+pub struct Block {
+    pub slots: [Option>; SLOTS],
+}
+
+impl Block {
+    pub fn decode(b: &[u8]) -> Block {
+        let mut out = Block::default();
+        if b.len() < 4 {
+            return out;
+        }
+        let bits = u32::from_le_bytes([b[0], b[1], b[2], b[3]]);
+        let mut at = 4;
+        let mut lens = Vec::new();
+        for i in 0..SLOTS {
+            if bits >> i & 1 == 1 {
+                let Some(l) = get_varint(b, &mut at) else { return out };
+                lens.push((i, l as usize));
+            }
+        }
+        for (i, l) in lens {
+            let Some(rec) = b.get(at..at + l) else { return out };
+            out.slots[i] = Some(rec.to_vec());
+            at += l;
+        }
+        out
+    }
+
+    pub fn encode(&self) -> Vec {
+        let mut bits = 0u32;
+        let mut out = vec![0; 4];
+        for (i, s) in self.slots.iter().enumerate() {
+            if let Some(r) = s {
+                bits |= 1 << i;
+                put_varint(&mut out, r.len() as u64);
+            }
+        }
+        out[..4].copy_from_slice(&bits.to_le_bytes());
+        for r in self.slots.iter().flatten() {
+            out.extend_from_slice(r);
+        }
+        out
+    }
+
+    pub fn is_empty(&self) -> bool {
+        self.slots.iter().all(Option::is_none)
+    }
+}
+
+/// one slot's record straight from a block row, without decoding the rest
+pub fn block_slot(b: &[u8], slot: usize) -> Option<&[u8]> {
+    if b.len() < 4 {
+        return None;
+    }
+    let bits = u32::from_le_bytes([b[0], b[1], b[2], b[3]]);
+    if bits >> slot & 1 == 0 {
+        return None;
+    }
+    let mut at = 4;
+    let mut skip = 0usize;
+    let mut len = 0usize;
+    for i in 0..SLOTS {
+        if bits >> i & 1 == 1 {
+            let l = get_varint(b, &mut at)? as usize;
+            if i < slot {
+                skip += l;
+            } else if i == slot {
+                len = l;
+            }
+        }
+    }
+    b.get(at + skip..at + skip + len)
+}
+
+#[cfg(test)]
+mod block_tests {
+    use super::*;
+
+    #[test]
+    fn blocks() {
+        let mut b = Block::default();
+        b.slots[0] = Some(vec![1, 2, 3]);
+        b.slots[7] = Some(vec![]);
+        b.slots[31] = Some(vec![9; 200]);
+        let e = b.encode();
+        assert_eq!(e.len(), 4 + 1 + 1 + 2 + 3 + 200);
+        assert_eq!(Block::decode(&e), b);
+        assert_eq!(block_slot(&e, 0), Some(&[1u8, 2, 3][..]));
+        assert_eq!(block_slot(&e, 7), Some(&[][..]));
+        assert_eq!(block_slot(&e, 31).map(|r| r.len()), Some(200));
+        assert_eq!(block_slot(&e, 8), None);
+        assert_eq!(block_slot(&e[..10], 31), None);
+        assert!(Block::default().is_empty());
+        assert_eq!((block_of(70), slot_of(70)), (2, 6));
+    }
+}
diff --git a/core/src/graph/scenes.rs b/core/src/graph/scenes.rs
new file mode 100644
index 00000000..b7c7590d
--- /dev/null
+++ b/core/src/graph/scenes.rs
@@ -0,0 +1,1466 @@
+//! Scenes and their placements (docs/format.md, "One model for a definition and its
+//! placed instances"): a save holds many scenes; a scene holds placements of texts
+//! (billboards), blocks and prefabs (scenes placed inside scenes).
+//!
+//! | table | key | value |
+//! |---|---|---|
+//! | `graph scenes` | scene id | its record as JSON: name, parent, created, edited, settings |
+//! | `graph scene instances` (multimap) | scene id | inheriting placements: per (kind, definition, chunk of 64 numbers) one value, [`Chunk`] |
+//! | `graph scene detached` (multimap) | scene id | detached placements, the same layout with the entry's version after the definition |
+//! | `graph placed` (multimap) | definition ref | the scenes placing it |
+//!
+//! The room (the space's own scene, holding its blocks) is the scene the setting
+//! `scenes.room` names. `graph::blocks` keeps its block API over the room's placements,
+//! and `ops::scenes` reads and writes the saved scenes.
+
+use redb::{MultimapTableDefinition, ReadableDatabase, ReadableMultimapTable, ReadableTable, TableDefinition};
+use serde::{Deserialize, Serialize};
+
+use super::codec::{BitReader, BitWriter};
+use super::store::{GResult, Graph, err};
+
+pub const SCENES: TableDefinition = TableDefinition::new("graph scenes");
+pub const INSTANCES: MultimapTableDefinition = MultimapTableDefinition::new("graph scene instances");
+pub const DETACHED: MultimapTableDefinition = MultimapTableDefinition::new("graph scene detached");
+pub const PLACED: MultimapTableDefinition<&[u8], u64> = MultimapTableDefinition::new("graph placed");
+
+/// placements a chunk holds at most (numbers `64c .. 64c + 63`)
+pub const CHUNK: u64 = 64;
+
+pub fn ensure_tables(txn: &redb::WriteTransaction) -> GResult<()> {
+    txn.open_table(SCENES).map_err(err)?;
+    txn.open_multimap_table(INSTANCES).map_err(err)?;
+    txn.open_multimap_table(DETACHED).map_err(err)?;
+    txn.open_multimap_table(PLACED).map_err(err)?;
+    Ok(())
+}
+
+// ---------------------------------------------------------------- sized ids
+
+/// one length byte (0–8), then that many big-endian bytes with no leading zero byte, so
+/// comparing the bytes compares the numbers
+pub fn put_sized(out: &mut Vec, v: u64) {
+    let n = 8 - (v.leading_zeros() / 8) as usize;
+    out.push(n as u8);
+    out.extend_from_slice(&v.to_be_bytes()[8 - n..]);
+}
+
+pub fn get_sized(b: &[u8]) -> Option<(u64, usize)> {
+    let n = *b.first()? as usize;
+    if n > 8 || b.len() < 1 + n || (n > 0 && b[1] == 0) {
+        return None;
+    }
+    let mut v = 0u64;
+    for &x in &b[1..1 + n] {
+        v = (v << 8) | x as u64;
+    }
+    Some((v, 1 + n))
+}
+
+// ---------------------------------------------------------------- definitions
+
+/// what is placed; the byte order of [`Def::bytes`] is its sort order
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)]
+pub enum Def {
+    /// an entry: a text, a chain, or a block's text texture
+    Entry(u64),
+    /// a picture, by its 128-bit content hash
+    Picture([u8; 16]),
+    /// a plain colour
+    Colour([u8; 3]),
+    /// a scene, placed as a prefab
+    Scene(u64),
+    /// a texture recipe (`graph::textures`), by its 128-bit content hash
+    Texture([u8; 16]),
+}
+
+impl Def {
+    pub fn write(&self, out: &mut Vec) {
+        match self {
+            Def::Entry(id) => {
+                out.push(0);
+                put_sized(out, *id);
+            }
+            Def::Picture(h) => {
+                out.push(1);
+                out.extend_from_slice(h);
+            }
+            Def::Colour(c) => {
+                out.push(2);
+                out.extend_from_slice(c);
+            }
+            Def::Scene(id) => {
+                out.push(3);
+                put_sized(out, *id);
+            }
+            Def::Texture(h) => {
+                out.push(4);
+                out.extend_from_slice(h);
+            }
+        }
+    }
+
+    pub fn bytes(&self) -> Vec {
+        let mut v = Vec::new();
+        self.write(&mut v);
+        v
+    }
+
+    pub fn read(b: &[u8]) -> Option<(Def, usize)> {
+        let rest = b.get(1..)?;
+        Some(match b.first()? {
+            0 => {
+                let (id, n) = get_sized(rest)?;
+                (Def::Entry(id), 1 + n)
+            }
+            1 => (Def::Picture(rest.get(..16)?.try_into().ok()?), 17),
+            2 => (Def::Colour(rest.get(..3)?.try_into().ok()?), 4),
+            3 => {
+                let (id, n) = get_sized(rest)?;
+                (Def::Scene(id), 1 + n)
+            }
+            4 => (Def::Texture(rest.get(..16)?.try_into().ok()?), 17),
+            _ => return None,
+        })
+    }
+}
+
+/// how a definition is placed
+#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
+#[serde(rename_all = "lowercase")]
+#[repr(u8)]
+pub enum Kind {
+    /// a billboard: a position and a font size
+    Text = 0,
+    /// a block with a rotation, a scale, a colour and a shape
+    Block = 1,
+    /// a scene placed inside another, with a rotation and a scale
+    Prefab = 2,
+}
+
+impl Kind {
+    fn from_u8(b: u8) -> Option {
+        Some(match b {
+            0 => Kind::Text,
+            1 => Kind::Block,
+            2 => Kind::Prefab,
+            _ => return None,
+        })
+    }
+
+    /// whether `def` can be placed this way
+    pub fn takes(self, def: &Def) -> bool {
+        match self {
+            Kind::Text => matches!(def, Def::Entry(_)),
+            Kind::Block => !matches!(def, Def::Scene(_)),
+            Kind::Prefab => matches!(def, Def::Scene(_)),
+        }
+    }
+}
+
+// ---------------------------------------------------------------- placements
+
+#[derive(Clone, Copy, Debug, PartialEq, Serialize, Deserialize)]
+#[serde(untagged)]
+pub enum Scale {
+    One,
+    Uniform(f32),
+    Axes([f32; 3]),
+}
+
+impl Scale {
+    /// the same scale in its canonical form: one when every axis is 1, uniform when the
+    /// three are the same bits
+    pub fn canonical(self) -> Scale {
+        let one = 1f32.to_bits();
+        match self {
+            Scale::Uniform(v) if v.to_bits() == one => Scale::One,
+            Scale::Axes([a, b, c]) if a.to_bits() == b.to_bits() && b.to_bits() == c.to_bits() => {
+                Scale::Uniform(a).canonical()
+            }
+            s => s,
+        }
+    }
+
+    fn same(&self, o: &Scale) -> bool {
+        match (self, o) {
+            (Scale::One, Scale::One) => true,
+            (Scale::Uniform(a), Scale::Uniform(b)) => a.to_bits() == b.to_bits(),
+            (Scale::Axes(a), Scale::Axes(b)) => a.iter().zip(b).all(|(x, y)| x.to_bits() == y.to_bits()),
+            _ => false,
+        }
+    }
+}
+
+/// one placement; the fields a kind doesn't have stay at their defaults
+#[derive(Clone, Debug, PartialEq)]
+pub struct Placement {
+    /// its number among its definition's placements of its kind in its scene, from 1
+    pub n: u64,
+    /// free coordinates, stored as the exact f32 bits
+    pub pos: [f32; 3],
+    /// a text's font size: 0 the default (a setting), 1–255 explicit
+    pub font: u8,
+    /// a block's or prefab's rotation, packed as `place::pack_rotation` (None: identity)
+    pub rot: Option,
+    pub scale: Scale,
+    /// a block's RGBA8 colour
+    pub colour: Option,
+    /// 1 pinned, 2 hidden, 4 spread, 8–64 a block's shape (`place::Kind`), the rest kept
+    pub flags: Option,
+    /// an asset id, a prefab copy's overrides, later a program; kept as it is
+    pub extra: Option>,
+}
+
+/// the flag saying a placement's extra holds its own values, which shadow its
+/// definition's (an inheriting copy's overrides, as a JSON object: `text` for a text)
+pub const OWN: u64 = 128;
+
+impl Placement {
+    /// an inheriting copy's own values (overrides), when it has any
+    pub fn own(&self) -> Option> {
+        if self.flags.unwrap_or(0) & OWN == 0 {
+            return None;
+        }
+        serde_json::from_slice(self.extra.as_deref()?).ok()
+    }
+
+    /// sets or clears its own values; an empty map clears them
+    pub fn set_own(&mut self, own: Option>) {
+        let rest = self.flags.unwrap_or(0) & !OWN;
+        match own.filter(|m| !m.is_empty()) {
+            Some(m) => {
+                self.flags = Some(rest | OWN);
+                self.extra = Some(serde_json::to_vec(&m).expect("a JSON map"));
+            }
+            None => {
+                if self.flags.unwrap_or(0) & OWN != 0 {
+                    self.extra = None;
+                }
+                self.flags = Some(rest).filter(|f| *f != 0);
+            }
+        }
+    }
+
+    /// its own text, shadowing its entry's
+    pub fn own_text(&self) -> Option {
+        self.own()?.get("text")?.as_str().map(str::to_string)
+    }
+
+    pub fn at(n: u64, pos: [f32; 3]) -> Placement {
+        Placement {
+            n,
+            pos,
+            font: 0,
+            rot: None,
+            scale: Scale::One,
+            colour: None,
+            flags: None,
+            extra: None,
+        }
+    }
+
+    /// the fields `kind` keeps, the rest at their defaults, the scale canonical
+    pub fn for_kind(mut self, kind: Kind) -> Placement {
+        self.scale = self.scale.canonical();
+        match kind {
+            Kind::Text => {
+                self.rot = None;
+                self.scale = Scale::One;
+                self.colour = None;
+            }
+            Kind::Block => self.font = 0,
+            Kind::Prefab => {
+                self.font = 0;
+                self.colour = None;
+            }
+        }
+        self
+    }
+}
+
+fn put_f32(w: &mut BitWriter, v: f32) {
+    w.put(v.to_bits(), 32);
+}
+
+fn get_f32(r: &mut BitReader) -> GResult {
+    Ok(f32::from_bits(r.get(32).map_err(err)?))
+}
+
+/// the bits a varint takes
+fn varint_bits(v: u64) -> usize {
+    5 * (64 - v.leading_zeros() as usize).div_ceil(4).max(1)
+}
+
+fn scale_bits(s: &Scale) -> usize {
+    match s {
+        Scale::One => 0,
+        Scale::Uniform(_) => 32,
+        Scale::Axes(_) => 96,
+    }
+}
+
+/// one value of a scene's multimap: the prefix (kind, definition, the detached version,
+/// the chunk number) and its placements in number order
+#[derive(Clone, Debug, PartialEq)]
+pub struct Chunk {
+    pub kind: Kind,
+    pub def: Def,
+    /// a detached placement's entry version (the `edited` ms it was detached at)
+    pub version: Option,
+    pub c: u64,
+    pub places: Vec,
+}
+
+impl Chunk {
+    /// the bytes every value of this (kind, definition, version, chunk) starts with
+    pub fn prefix(kind: Kind, def: &Def, version: Option, c: u64) -> Vec {
+        let mut out = vec![kind as u8];
+        def.write(&mut out);
+        if let Some(v) = version {
+            put_sized(&mut out, v);
+        }
+        put_sized(&mut out, c);
+        out
+    }
+
+    /// the canonical bytes: the prefix, then a 3-bit padding count and one record per
+    /// placement (gap, position, flags, extra, then the kind's own fields)
+    pub fn encode(&self) -> GResult> {
+        let mut out = Chunk::prefix(self.kind, &self.def, self.version, self.c);
+        let mut w = BitWriter::default();
+        w.put(0, 3);
+        let mut prev: Option = None;
+        let places: Vec = self.places.iter().cloned().map(|p| p.for_kind(self.kind)).collect();
+        for (i, p) in places.iter().enumerate() {
+            if p.n / CHUNK != self.c {
+                return Err(format!("placement {} isn't in chunk {}", p.n, self.c));
+            }
+            let gap = match prev {
+                None => p.n - CHUNK * self.c,
+                Some(q) if p.n > q => p.n - q - 1,
+                Some(_) => return Err("placements out of number order".into()),
+            };
+            prev = Some(p.n);
+            w.varint(gap);
+            for v in p.pos {
+                put_f32(&mut w, v);
+            }
+            w.put(p.flags.is_some() as u32, 1);
+            w.put(p.extra.is_some() as u32, 1);
+            if let Some(f) = p.flags {
+                w.varint(f);
+            }
+            if let Some(x) = &p.extra {
+                w.varint(x.len() as u64);
+                for b in x {
+                    w.put(*b as u32, 8);
+                }
+            }
+            match self.kind {
+                Kind::Text => w.varint(p.font as u64),
+                Kind::Block | Kind::Prefab => {
+                    // the nearest earlier placement with the same bits, when that's smaller
+                    let back = |same: &dyn Fn(&Placement) -> bool| {
+                        (0..i).rev().find(|&j| same(&places[j])).map(|j| p.n - places[j].n)
+                    };
+                    match p.rot {
+                        None => w.put(0, 2),
+                        Some(r) => match back(&|q: &Placement| q.rot == Some(r)) {
+                            Some(d) if varint_bits(d) < 32 => {
+                                w.put(2, 2);
+                                w.varint(d);
+                            }
+                            _ => {
+                                w.put(1, 2);
+                                w.put(r, 32);
+                            }
+                        },
+                    }
+                    let own = scale_bits(&p.scale);
+                    match back(&|q: &Placement| q.scale.same(&p.scale)) {
+                        Some(d) if own > 0 && varint_bits(d) < own => {
+                            w.put(3, 2);
+                            w.varint(d);
+                        }
+                        _ => match p.scale {
+                            Scale::One => w.put(0, 2),
+                            Scale::Uniform(v) => {
+                                w.put(1, 2);
+                                put_f32(&mut w, v);
+                            }
+                            Scale::Axes(a) => {
+                                w.put(2, 2);
+                                for v in a {
+                                    put_f32(&mut w, v);
+                                }
+                            }
+                        },
+                    }
+                    if self.kind == Kind::Block {
+                        w.put(p.colour.is_some() as u32, 1);
+                        if let Some(c) = p.colour {
+                            w.put(c, 32);
+                        }
+                    }
+                }
+            }
+        }
+        out.extend(w.finish_padded());
+        Ok(out)
+    }
+
+    /// reads a value back; `detached` says whether a version follows the definition
+    pub fn decode(b: &[u8], detached: bool) -> GResult {
+        let bad = || "a scene value that doesn't read".to_string();
+        let kind = Kind::from_u8(*b.first().ok_or_else(bad)?).ok_or_else(bad)?;
+        let (def, n) = Def::read(&b[1..]).ok_or_else(bad)?;
+        let mut at = 1 + n;
+        let version = if detached {
+            let (v, n) = get_sized(&b[at..]).ok_or_else(bad)?;
+            at += n;
+            Some(v)
+        } else {
+            None
+        };
+        let (c, n) = get_sized(&b[at..]).ok_or_else(bad)?;
+        at += n;
+        let body = &b[at..];
+        let mut places: Vec = Vec::new();
+        if !body.is_empty() {
+            let pad = (body[0] >> 5) as usize;
+            let mut r = BitReader::new(body, 3, body.len() * 8 - pad);
+            let mut prev: Option = None;
+            while r.left() > 0 {
+                let gap = r.varint().map_err(err)?;
+                let n = match prev {
+                    None => CHUNK * c + gap,
+                    Some(q) => q + 1 + gap,
+                };
+                prev = Some(n);
+                let mut p = Placement::at(n, [get_f32(&mut r)?, get_f32(&mut r)?, get_f32(&mut r)?]);
+                let has_flags = r.get(1).map_err(err)? == 1;
+                let has_extra = r.get(1).map_err(err)? == 1;
+                if has_flags {
+                    p.flags = Some(r.varint().map_err(err)?);
+                }
+                if has_extra {
+                    let len = r.varint().map_err(err)? as usize;
+                    let mut x = Vec::with_capacity(len);
+                    for _ in 0..len {
+                        x.push(r.get(8).map_err(err)? as u8);
+                    }
+                    p.extra = Some(x);
+                }
+                let find = |d: u64, places: &Vec| -> GResult {
+                    places
+                        .iter()
+                        .find(|q| q.n + d == n)
+                        .cloned()
+                        .ok_or_else(|| "a reference to a placement that isn't there".to_string())
+                };
+                match kind {
+                    Kind::Text => p.font = u8::try_from(r.varint().map_err(err)?).map_err(|_| bad())?,
+                    Kind::Block | Kind::Prefab => {
+                        p.rot = match r.get(2).map_err(err)? {
+                            0 => None,
+                            1 => Some(r.get(32).map_err(err)?),
+                            2 => find(r.varint().map_err(err)?, &places)?.rot,
+                            _ => return Err(bad()),
+                        };
+                        p.scale = match r.get(2).map_err(err)? {
+                            0 => Scale::One,
+                            1 => Scale::Uniform(get_f32(&mut r)?),
+                            2 => Scale::Axes([get_f32(&mut r)?, get_f32(&mut r)?, get_f32(&mut r)?]),
+                            _ => find(r.varint().map_err(err)?, &places)?.scale,
+                        };
+                        if kind == Kind::Block && r.get(1).map_err(err)? == 1 {
+                            p.colour = Some(r.get(32).map_err(err)?);
+                        }
+                    }
+                }
+                places.push(p);
+            }
+        }
+        Ok(Chunk {
+            kind,
+            def,
+            version,
+            c,
+            places,
+        })
+    }
+}
+
+// ---------------------------------------------------------------- scenes
+
+/// a scene's record
+#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
+pub struct Scene {
+    pub id: u64,
+    pub name: String,
+    /// the scene it sits in (0: none)
+    #[serde(default)]
+    pub parent: u64,
+    pub created: u64,
+    pub edited: u64,
+    #[serde(default)]
+    pub settings: serde_json::Value,
+}
+
+/// a placement with where it is
+#[derive(Clone, Debug, PartialEq)]
+pub struct Placed {
+    pub kind: Kind,
+    pub def: Def,
+    pub version: Option,
+    pub place: Placement,
+}
+
+pub(crate) fn now_ms() -> u64 {
+    std::time::SystemTime::now()
+        .duration_since(std::time::UNIX_EPOCH)
+        .map(|d| d.as_millis() as u64)
+        .unwrap_or(0)
+}
+
+fn table(detached: bool) -> MultimapTableDefinition<'static, u64, &'static [u8]> {
+    if detached { DETACHED } else { INSTANCES }
+}
+
+/// the setting naming the room's scene (its id, in decimal)
+pub const ROOM: &str = "scenes.room";
+
+fn room_id(b: &[u8]) -> Option {
+    std::str::from_utf8(b).ok()?.trim().parse().ok()
+}
+
+/// a scene's values in one table, decoded, with their bytes
+fn values(
+    t: &impl ReadableMultimapTable,
+    scene: u64,
+    detached: bool,
+) -> GResult, Chunk)>> {
+    let mut out = Vec::new();
+    for v in t.get(scene).map_err(err)? {
+        let b = v.map_err(err)?.value().to_vec();
+        let ch = Chunk::decode(&b, detached)?;
+        out.push((b, ch));
+    }
+    Ok(out)
+}
+
+/// splits placements into chunks of 64 numbers and writes them
+fn write_chunks(
+    t: &mut redb::MultimapTable,
+    scene: u64,
+    kind: Kind,
+    def: Def,
+    version: Option,
+    mut places: Vec,
+) -> GResult<()> {
+    places.sort_by_key(|p| p.n);
+    let mut i = 0;
+    while i < places.len() {
+        let c = places[i].n / CHUNK;
+        let j = places[i..]
+            .iter()
+            .position(|p| p.n / CHUNK != c)
+            .map_or(places.len(), |k| i + k);
+        let ch = Chunk {
+            kind,
+            def,
+            version,
+            c,
+            places: places[i..j].to_vec(),
+        };
+        t.insert(scene, ch.encode()?.as_slice()).map_err(err)?;
+        i = j;
+    }
+    Ok(())
+}
+
+/// `graph placed` made to agree with what the scene holds now
+fn sync_placed(txn: &redb::WriteTransaction, scene: u64) -> GResult<()> {
+    let mut now: std::collections::BTreeSet> = Default::default();
+    for d in [false, true] {
+        let t = txn.open_multimap_table(table(d)).map_err(err)?;
+        for (_, ch) in values(&t, scene, d)? {
+            now.insert(ch.def.bytes());
+        }
+    }
+    let mut placed = txn.open_multimap_table(PLACED).map_err(err)?;
+    let mut stale = Vec::new();
+    for item in placed.iter().map_err(err)? {
+        let (k, vs) = item.map_err(err)?;
+        for v in vs {
+            if v.map_err(err)?.value() == scene && !now.contains(k.value()) {
+                stale.push(k.value().to_vec());
+            }
+        }
+    }
+    for k in stale {
+        placed.remove(k.as_slice(), scene).map_err(err)?;
+    }
+    for k in now {
+        placed.insert(k.as_slice(), scene).map_err(err)?;
+    }
+    Ok(())
+}
+
+/// writes placements of one (kind, definition, version) into a scene inside a write:
+/// each replaces the one with its number, or takes the next free number when its `n` is
+/// 0; `drop` takes numbers out. Their numbers.
+#[allow(clippy::too_many_arguments)]
+pub(crate) fn place_in(
+    txn: &redb::WriteTransaction,
+    scene: u64,
+    detached: bool,
+    kind: Kind,
+    def: Def,
+    version: Option,
+    places: Vec,
+    drop: &[u64],
+) -> GResult> {
+    if !kind.takes(&def) {
+        return Err(format!("a {kind:?} can't place {def:?}"));
+    }
+    if detached != version.is_some() {
+        return Err("a detached placement has the version it was detached at, and only it".into());
+    }
+    if txn.open_table(SCENES).map_err(err)?.get(scene).map_err(err)?.is_none() {
+        return Err(format!("no scene {scene}"));
+    }
+    let numbers = {
+        let mut t = txn.open_multimap_table(table(detached)).map_err(err)?;
+        let mut mine: Vec = Vec::new();
+        for (b, ch) in values(&t, scene, detached)? {
+            if ch.kind == kind && ch.def == def && ch.version == version {
+                mine.extend(ch.places);
+                t.remove(scene, b.as_slice()).map_err(err)?;
+            }
+        }
+        mine.retain(|p| !drop.contains(&p.n));
+        let mut next = mine.iter().map(|p| p.n).max().unwrap_or(0) + 1;
+        let mut numbers = Vec::new();
+        for mut p in places {
+            if p.n == 0 {
+                p.n = next;
+                next += 1;
+            }
+            numbers.push(p.n);
+            mine.retain(|q| q.n != p.n);
+            mine.push(p);
+        }
+        write_chunks(&mut t, scene, kind, def, version, mine)?;
+        numbers
+    };
+    sync_placed(txn, scene)?;
+    Ok(numbers)
+}
+
+/// a new scene inside a write; its id
+pub(crate) fn add_scene_in(txn: &redb::WriteTransaction, name: &str, parent: u64) -> GResult {
+    let name = name.trim();
+    if name.is_empty() {
+        return Err("a scene needs a name".into());
+    }
+    let mut t = txn.open_table(SCENES).map_err(err)?;
+    if parent != 0 && t.get(parent).map_err(err)?.is_none() {
+        return Err(format!("no scene {parent}"));
+    }
+    let id = t.last().map_err(err)?.map(|(k, _)| k.value() + 1).unwrap_or(1);
+    let now = now_ms();
+    let s = Scene {
+        id,
+        name: name.to_string(),
+        parent,
+        created: now,
+        edited: now,
+        settings: serde_json::Value::Null,
+    };
+    t.insert(id, serde_json::to_vec(&s).map_err(err)?.as_slice())
+        .map_err(err)?;
+    Ok(id)
+}
+
+/// the room's scene inside a write, made when there's none
+pub(crate) fn room_in(txn: &redb::WriteTransaction) -> GResult {
+    let kept = {
+        let s = txn.open_table(super::store::SETTINGS).map_err(err)?;
+        s.get(ROOM).map_err(err)?.and_then(|v| room_id(v.value()))
+    };
+    if let Some(id) = kept
+        && txn.open_table(SCENES).map_err(err)?.get(id).map_err(err)?.is_some()
+    {
+        return Ok(id);
+    }
+    let id = add_scene_in(txn, "room", 0)?;
+    txn.open_table(super::store::SETTINGS)
+        .map_err(err)?
+        .insert(ROOM, id.to_string().as_bytes())
+        .map_err(err)?;
+    Ok(id)
+}
+
+impl Graph {
+    /// a new scene; its id
+    pub fn add_scene(&self, name: &str, parent: u64) -> GResult {
+        let txn = self.db().begin_write().map_err(err)?;
+        let id = add_scene_in(&txn, name, parent)?;
+        txn.commit().map_err(err)?;
+        Ok(id)
+    }
+
+    /// the room's scene (the space's own, holding its blocks), if it has been made
+    pub fn room(&self) -> GResult> {
+        let txn = self.db().begin_read().map_err(err)?;
+        let s = txn.open_table(super::store::SETTINGS).map_err(err)?;
+        let kept = s.get(ROOM).map_err(err)?.and_then(|v| room_id(v.value()));
+        match kept {
+            Some(id) if txn.open_table(SCENES).map_err(err)?.get(id).map_err(err)?.is_some() => Ok(Some(id)),
+            _ => Ok(None),
+        }
+    }
+
+    pub fn scenes(&self) -> GResult> {
+        let txn = self.db().begin_read().map_err(err)?;
+        let t = txn.open_table(SCENES).map_err(err)?;
+        let mut out = Vec::new();
+        for item in t.iter().map_err(err)? {
+            let (_, v) = item.map_err(err)?;
+            out.push(serde_json::from_slice(v.value()).map_err(err)?);
+        }
+        Ok(out)
+    }
+
+    pub fn scene(&self, id: u64) -> GResult> {
+        let txn = self.db().begin_read().map_err(err)?;
+        let t = txn.open_table(SCENES).map_err(err)?;
+        match t.get(id).map_err(err)? {
+            Some(v) => Ok(Some(serde_json::from_slice(v.value()).map_err(err)?)),
+            None => Ok(None),
+        }
+    }
+
+    /// the first scene with this name (prefabs aside: `graph::prefabs`)
+    pub fn scene_named(&self, name: &str) -> GResult> {
+        Ok(self
+            .scenes()?
+            .into_iter()
+            .find(|s| s.name == name && s.settings.get("prefab") != Some(&serde_json::Value::Bool(true))))
+    }
+
+    pub fn rename_scene(&self, id: u64, name: &str) -> GResult<()> {
+        let name = name.trim();
+        if name.is_empty() {
+            return Err("a scene needs a name".into());
+        }
+        let txn = self.db().begin_write().map_err(err)?;
+        {
+            let mut t = txn.open_table(SCENES).map_err(err)?;
+            let mut s: Scene = match t.get(id).map_err(err)? {
+                Some(v) => serde_json::from_slice(v.value()).map_err(err)?,
+                None => return Err(format!("no scene {id}")),
+            };
+            s.name = name.to_string();
+            s.edited = now_ms();
+            t.insert(id, serde_json::to_vec(&s).map_err(err)?.as_slice())
+                .map_err(err)?;
+        }
+        txn.commit().map_err(err)
+    }
+
+    /// removes a scene with its placements; what it held (to put back)
+    pub fn delete_scene(&self, id: u64) -> GResult<(Scene, Vec)> {
+        let s = self.scene(id)?.ok_or_else(|| format!("no scene {id}"))?;
+        let held = [self.placements(id, false)?, self.placements(id, true)?].concat();
+        let txn = self.db().begin_write().map_err(err)?;
+        {
+            for d in [false, true] {
+                txn.open_multimap_table(table(d))
+                    .map_err(err)?
+                    .remove_all(id)
+                    .map_err(err)?;
+            }
+            txn.open_table(SCENES).map_err(err)?.remove(id).map_err(err)?;
+            sync_placed(&txn, id)?;
+        }
+        txn.commit().map_err(err)?;
+        Ok((s, held))
+    }
+
+    /// every placement in a scene, inheriting or detached, in (kind, definition, number)
+    /// order
+    pub fn placements(&self, scene: u64, detached: bool) -> GResult> {
+        let txn = self.db().begin_read().map_err(err)?;
+        let t = txn.open_multimap_table(table(detached)).map_err(err)?;
+        let mut out = Vec::new();
+        for (_, ch) in values(&t, scene, detached)? {
+            out.extend(ch.places.into_iter().map(|place| Placed {
+                kind: ch.kind,
+                def: ch.def,
+                version: ch.version,
+                place,
+            }));
+        }
+        Ok(out)
+    }
+
+    /// writes placements into a scene: each replaces the one with its number (its
+    /// `n`), or is added under the next free number when `n` is 0; their numbers
+    pub fn place(
+        &self,
+        scene: u64,
+        detached: bool,
+        kind: Kind,
+        def: Def,
+        version: Option,
+        places: Vec,
+    ) -> GResult> {
+        let txn = self.db().begin_write().map_err(err)?;
+        let numbers = place_in(&txn, scene, detached, kind, def, version, places, &[])?;
+        txn.commit().map_err(err)?;
+        Ok(numbers)
+    }
+
+    /// takes placements out by number; how many went
+    pub fn unplace(
+        &self,
+        scene: u64,
+        detached: bool,
+        kind: Kind,
+        def: Def,
+        version: Option,
+        numbers: &[u64],
+    ) -> GResult {
+        let before = self.placements(scene, detached)?.len();
+        let txn = self.db().begin_write().map_err(err)?;
+        place_in(&txn, scene, detached, kind, def, version, vec![], numbers)?;
+        txn.commit().map_err(err)?;
+        Ok(before - self.placements(scene, detached)?.len())
+    }
+
+    /// replaces every text placement of a scene, inheriting and detached, with these, in
+    /// one write: per entry, the version it was detached at (None: inheriting) and its
+    /// placements
+    pub fn set_texts(&self, scene: u64, texts: Vec) -> GResult<()> {
+        let txn = self.db().begin_write().map_err(err)?;
+        {
+            if txn.open_table(SCENES).map_err(err)?.get(scene).map_err(err)?.is_none() {
+                return Err(format!("no scene {scene}"));
+            }
+            for d in [false, true] {
+                let mut t = txn.open_multimap_table(table(d)).map_err(err)?;
+                for (b, ch) in values(&t, scene, d)? {
+                    if ch.kind == Kind::Text {
+                        t.remove(scene, b.as_slice()).map_err(err)?;
+                    }
+                }
+                for st in texts.iter().filter(|st| st.version.is_some() == d) {
+                    write_chunks(
+                        &mut t,
+                        scene,
+                        Kind::Text,
+                        Def::Entry(st.id),
+                        st.version,
+                        st.places.clone(),
+                    )?;
+                }
+            }
+            let mut st = txn.open_table(SCENES).map_err(err)?;
+            let mut s: Scene =
+                serde_json::from_slice(st.get(scene).map_err(err)?.expect("checked").value()).map_err(err)?;
+            s.edited = now_ms();
+            st.insert(scene, serde_json::to_vec(&s).map_err(err)?.as_slice())
+                .map_err(err)?;
+        }
+        sync_placed(&txn, scene)?;
+        txn.commit().map_err(err)
+    }
+
+    /// the scenes placing a definition, and how many placements each holds
+    pub fn placed_in(&self, def: Def) -> GResult> {
+        let scenes: Vec = {
+            let txn = self.db().begin_read().map_err(err)?;
+            let t = txn.open_multimap_table(PLACED).map_err(err)?;
+            t.get(def.bytes().as_slice())
+                .map_err(err)?
+                .map(|v| v.map(|v| v.value()).map_err(err))
+                .collect::>()?
+        };
+        let mut out = Vec::new();
+        for s in scenes {
+            let n = [false, true]
+                .iter()
+                .map(|&d| {
+                    self.placements(s, d)
+                        .map(|ps| ps.iter().filter(|p| p.def == def).count())
+                })
+                .sum::>()?;
+            out.push((s, n));
+        }
+        Ok(out)
+    }
+}
+
+// ---------------------------------------------------------------- migration
+
+/// a space text's size (world units per em) as a placement's font size: steps of 1/50,
+/// so the space's default 0.5 is 25 (docs/wip/questions.md, 1)
+pub fn font_of(size: f64) -> u8 {
+    (size * 50.0).round().clamp(1.0, 255.0) as u8
+}
+
+/// a font size back as a space text's size (None: the default)
+pub fn size_of(font: u8) -> Option {
+    (font != 0).then(|| font as f64 / 50.0)
+}
+
+/// where the old saved scenes' JSON is kept after it moved into scenes
+pub const MAPS_BEFORE: &str = "space.maps (before scenes)";
+
+impl Graph {
+    /// a saved scene's rows as the space keeps them, `[text, x, y, z, {key?, size?,
+    /// detached?, own?}]`, into a scene's text placements: a row with a key places that
+    /// entry (a note's key is `note: