diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index c3370fa4..bc2e0930 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -45,11 +45,12 @@ build:
     stage: build
     script:
         - npm run build
+        - mv dist ds4
     cache:
         <<: *global_cache
     artifacts:
         paths:
-            - dist
+            - ds4
         expire_in: 1 week
 
 deploy:
@@ -58,7 +59,7 @@ deploy:
     dependencies:
         - build
     script:
-        - rsync --delete -az ./dist/ rsync://${DEPLOYMENT_USER}@${DEPLOYMENT_SERVER}:${DEPLOYMENT_PATH}
+        - rsync --delete -az ./ds4/ rsync://${DEPLOYMENT_USER}@${DEPLOYMENT_SERVER}:${DEPLOYMENT_PATH}
     environment:
         name: production
         url: https://vtt.f3l.de/
diff --git a/.gitlab/issue_templates/Bug Report.md b/.gitlab/issue_templates/Bug Report.md
new file mode 100644
index 00000000..c209b177
--- /dev/null
+++ b/.gitlab/issue_templates/Bug Report.md	
@@ -0,0 +1,29 @@
+# Description
+
+Please describe the issue.
+
+# Steps to Reproduce
+
+1. ...
+2. ...
+3. ...
+
+# Expected Behavior
+
+Please describe the expected behavior.
+
+# Actual Behavior
+
+Please describe the actual behavior.
+
+# Additional Details
+
+These are optional, please add them if it makes sense.
+
+- ![Screenshot]()
+- [Logfile]()
+- ...
+
+# Possible Solutions
+
+If you have any suggestions on how to solve the issue, please add them here.
diff --git a/.gitlab/issue_templates/Feature Request.md b/.gitlab/issue_templates/Feature Request.md
index f60644d2..d6dbe30b 100644
--- a/.gitlab/issue_templates/Feature Request.md	
+++ b/.gitlab/issue_templates/Feature Request.md	
@@ -1,9 +1,13 @@
-# Description
+# Story
 
 As a …, I want … so that …
 
+# Description
+
+Please add a more detailed description of the feature here.
+
 # Acceptance criteria
 
-* Criterion 1
-* Criterion 2
-* …
+1. Criterion 1
+2. Criterion 2
+3. …
diff --git a/README.md b/README.md
index 8119bbdb..9b502a47 100644
--- a/README.md
+++ b/README.md
@@ -3,50 +3,89 @@
 An implementation of the Dungeonslayers 4 game system for [Foundry Virtual
 Tabletop](http://foundryvtt.com).
 
-## Prerequisites
+This system provides character sheet support for Actors and Items and mechanical
+support for dice and rules necessary to
+play games of Dungeponslayers 4.
 
-In order to build this system, a recent version of `npm` is required.
+## Installation
 
-## Building
+To install and use the Dungeonslayers 4 system for Foundry Virtual Tabletop,
+simply paste the following URL into the **Install System** dialog on the Setup
+menu of the application.
 
-To build the system, first install all required dependencies:
+https://git.f3l.de/dungeonslayers/ds4/-/raw/master/src/system.json?inline=false
+
+## Development
+
+### Prerequisits
+
+In order to build this system, recent versions of `node` and `npm` are required.
+We recommend using the latest lts version of `node`, which is `v14.15.4` at the
+time of writing. If you use `nvm` to manage your `node` versions, you can simply
+run
+```
+nvm install
+```
+
+in the project's root directory.
+
+You also need to install the the project's dependencies. To do so, run
 
 ```
 npm install
 ```
 
-Then build the project by running
+### Building
+
+You can build the project by running
 
 ```
 npm run build
 ```
 
-If you'd like the built system to be automatically linked to your local Foundry
-VTT installation's data folder, add a file called `foundryconfig.json` to the
-project root with the following contents:
+Alternatively, you can run
+
+```
+npm run build:watch
+```
+
+to watch for changes and automatically build as necessary.
+
+### Linking the built system to Foundry VTT
+
+In order to provide a fluent development experience, it is recommended to link
+the built system to your local Foundry VTT installation's data folder. In order
+to do so, first add a file called `foundryconfig.json` to the project root with
+the following content:
 
 ```
 {
-    "dataPath": "/<absolute path to your home>/.local/share/FoundryVTT",
-    "repository": "",
-    "rawURL": ""
+    "dataPath": "<path to your home directory>/.local/share/FoundryVTT"
 }
 ```
 
+On platforms other than Linux you need to adjust the path accordingly.
+
 Then run
 
 ```
 npm run link
 ```
 
-If you want the system to be continuously build upon every saved change, just
-run
+### Running the tests
+
+You can run the tests with the following command:
 
 ```
-npm run build:watch
+npm test
 ```
 
-# Licensing
+## Contributing
+
+Code and content contributions are accepted. Please feel free to submit issues
+to the issue tracker or submit merge requests for code changes. To create an issue send a mail to [git+dungeonslayers-ds4-155-issue-@git.f3l.de](mailto:git+dungeonslayers-ds4-155-issue-@git.f3l.de).
+
+## Licensing
 
 Dungeonslayers (© Christian Kennig) is licensed under [CC BY-NC-SA 3.0](https://creativecommons.org/licenses/by-nc-sa/3.0/de/deed.en).
 
@@ -56,5 +95,5 @@ CC BY-NC-SA 3.0.  Hence the modified icons are also published under this
 license. A copy of this license can be found under
 [src/assets/official/LICENSE](src/assets/official/LICENSE).
 
-The rest of this project is licensed under the MIT License, a copy of which can
-be found under [LICENSE](LICENSE).
+The software component of this project is licensed under the MIT License, a copy
+of which can be found under [LICENSE](LICENSE).
diff --git a/gulpfile.js b/gulpfile.js
index 83aa3820..dc62e8b7 100644
--- a/gulpfile.js
+++ b/gulpfile.js
@@ -1,429 +1,429 @@
-const gulp = require("gulp");
-const fs = require("fs-extra");
-const path = require("path");
-const chalk = require("chalk");
-const archiver = require("archiver");
-const stringify = require("json-stringify-pretty-compact");
-const typescript = require("typescript");
-
-const ts = require("gulp-typescript");
-const less = require("gulp-less");
-const sass = require("gulp-sass");
-const git = require("gulp-git");
-
-const argv = require("yargs").argv;
-
-sass.compiler = require("sass");
-
-function getConfig() {
-    const configPath = path.resolve(process.cwd(), "foundryconfig.json");
-    let config;
-
-    if (fs.existsSync(configPath)) {
-        config = fs.readJSONSync(configPath);
-        return config;
-    } else {
-        return;
-    }
-}
-
-function getManifest() {
-    const json = {};
-
-    if (fs.existsSync("src")) {
-        json.root = "src";
-    } else {
-        json.root = "dist";
-    }
-
-    const modulePath = path.join(json.root, "module.json");
-    const systemPath = path.join(json.root, "system.json");
-
-    if (fs.existsSync(modulePath)) {
-        json.file = fs.readJSONSync(modulePath);
-        json.name = "module.json";
-    } else if (fs.existsSync(systemPath)) {
-        json.file = fs.readJSONSync(systemPath);
-        json.name = "system.json";
-    } else {
-        return;
-    }
-
-    return json;
-}
-
-/**
- * TypeScript transformers
- * @returns {typescript.TransformerFactory<typescript.SourceFile>}
- */
-function createTransformer() {
-    /**
-     * @param {typescript.Node} node
-     */
-    function shouldMutateModuleSpecifier(node) {
-        if (!typescript.isImportDeclaration(node) && !typescript.isExportDeclaration(node)) return false;
-        if (node.moduleSpecifier === undefined) return false;
-        if (!typescript.isStringLiteral(node.moduleSpecifier)) return false;
-        if (!node.moduleSpecifier.text.startsWith("./") && !node.moduleSpecifier.text.startsWith("../")) return false;
-        if (path.extname(node.moduleSpecifier.text) !== "") return false;
-        return true;
-    }
-
-    /**
-     * Transforms import/export declarations to append `.js` extension
-     * @param {typescript.TransformationContext} context
-     */
-    function importTransformer(context) {
-        return (node) => {
-            /**
-             * @param {typescript.Node} node
-             */
-            function visitor(node) {
-                if (shouldMutateModuleSpecifier(node)) {
-                    if (typescript.isImportDeclaration(node)) {
-                        const newModuleSpecifier = typescript.createLiteral(`${node.moduleSpecifier.text}.js`);
-                        return typescript.updateImportDeclaration(
-                            node,
-                            node.decorators,
-                            node.modifiers,
-                            node.importClause,
-                            newModuleSpecifier
-                        );
-                    } else if (typescript.isExportDeclaration(node)) {
-                        const newModuleSpecifier = typescript.createLiteral(`${node.moduleSpecifier.text}.js`);
-                        return typescript.updateExportDeclaration(
-                            node,
-                            node.decorators,
-                            node.modifiers,
-                            node.exportClause,
-                            newModuleSpecifier
-                        );
-                    }
-                }
-                return typescript.visitEachChild(node, visitor, context);
-            }
-
-            return typescript.visitNode(node, visitor);
-        };
-    }
-
-    return importTransformer;
-}
-
-const tsConfig = ts.createProject("tsconfig.json", {
-    getCustomTransformers: (_program) => ({
-        after: [createTransformer()],
-    }),
-});
-
-/********************/
-/*		BUILD		*/
-/********************/
-
-/**
- * Build TypeScript
- */
-function buildTS() {
-    return gulp.src("src/**/*.ts").pipe(tsConfig()).pipe(gulp.dest("dist"));
-}
-
-/**
- * Build Less
- */
-function buildLess() {
-    return gulp.src("src/*.less").pipe(less()).pipe(gulp.dest("dist"));
-}
-
-/**
- * Build SASS
- */
-function buildSASS() {
-    return gulp.src("src/*.scss").pipe(sass().on("error", sass.logError)).pipe(gulp.dest("dist"));
-}
-
-/**
- * Copy static files
- */
-async function copyFiles() {
-    const statics = ["lang", "fonts", "assets", "templates", "module.json", "system.json", "template.json"];
-    try {
-        for (const file of statics) {
-            if (fs.existsSync(path.join("src", file))) {
-                await fs.copy(path.join("src", file), path.join("dist", file));
-            }
-        }
-        return Promise.resolve();
-    } catch (err) {
-        Promise.reject(err);
-    }
-}
-
-/**
- * Watch for changes for each build step
- */
-function buildWatch() {
-    gulp.watch("src/**/*.ts", { ignoreInitial: false }, buildTS);
-    gulp.watch("src/**/*.less", { ignoreInitial: false }, buildLess);
-    gulp.watch("src/**/*.scss", { ignoreInitial: false }, buildSASS);
-    gulp.watch(["src/fonts", "src/lang", "src/templates", "src/*.json"], { ignoreInitial: false }, copyFiles);
-}
-
-/********************/
-/*		CLEAN		*/
-/********************/
-
-/**
- * Remove built files from `dist` folder
- * while ignoring source files
- */
-async function clean() {
-    const name = path.basename(path.resolve("."));
-    const files = [];
-
-    // If the project uses TypeScript
-    if (fs.existsSync(path.join("src", `${name}.ts`))) {
-        files.push(
-            "lang",
-            "templates",
-            "assets",
-            "module",
-            `${name}.js`,
-            "module.json",
-            "system.json",
-            "template.json"
-        );
-    }
-
-    // If the project uses Less or SASS
-    if (fs.existsSync(path.join("src", `${name}.less`)) || fs.existsSync(path.join("src", `${name}.scss`))) {
-        files.push("fonts", `${name}.css`);
-    }
-
-    console.log(" ", chalk.yellow("Files to clean:"));
-    console.log("   ", chalk.blueBright(files.join("\n    ")));
-
-    // Attempt to remove the files
-    try {
-        for (const filePath of files) {
-            await fs.remove(path.join("dist", filePath));
-        }
-        return Promise.resolve();
-    } catch (err) {
-        Promise.reject(err);
-    }
-}
-
-/********************/
-/*		LINK		*/
-/********************/
-
-/**
- * Link build to User Data folder
- */
-async function linkUserData() {
-    const name = path.basename(path.resolve("."));
-    const config = fs.readJSONSync("foundryconfig.json");
-
-    let destDir;
-    try {
-        if (
-            fs.existsSync(path.resolve(".", "dist", "module.json")) ||
-            fs.existsSync(path.resolve(".", "src", "module.json"))
-        ) {
-            destDir = "modules";
-        } else if (
-            fs.existsSync(path.resolve(".", "dist", "system.json")) ||
-            fs.existsSync(path.resolve(".", "src", "system.json"))
-        ) {
-            destDir = "systems";
-        } else {
-            throw Error(`Could not find ${chalk.blueBright("module.json")} or ${chalk.blueBright("system.json")}`);
-        }
-
-        let linkDir;
-        if (config.dataPath) {
-            if (!fs.existsSync(path.join(config.dataPath, "Data")))
-                throw Error("User Data path invalid, no Data directory found");
-
-            linkDir = path.join(config.dataPath, "Data", destDir, name);
-        } else {
-            throw Error("No User Data path defined in foundryconfig.json");
-        }
-
-        if (argv.clean || argv.c) {
-            console.log(chalk.yellow(`Removing build in ${chalk.blueBright(linkDir)}`));
-
-            await fs.remove(linkDir);
-        } else if (!fs.existsSync(linkDir)) {
-            console.log(chalk.green(`Copying build to ${chalk.blueBright(linkDir)}`));
-            await fs.symlink(path.resolve("./dist"), linkDir);
-        }
-        return Promise.resolve();
-    } catch (err) {
-        Promise.reject(err);
-    }
-}
-
-/*********************/
-/*		PACKAGE		 */
-/*********************/
-
-/**
- * Package build
- */
-async function packageBuild() {
-    const manifest = getManifest();
-
-    return new Promise((resolve, reject) => {
-        try {
-            // Remove the package dir without doing anything else
-            if (argv.clean || argv.c) {
-                console.log(chalk.yellow("Removing all packaged files"));
-                fs.removeSync("package");
-                return;
-            }
-
-            // Ensure there is a directory to hold all the packaged versions
-            fs.ensureDirSync("package");
-
-            // Initialize the zip file
-            const zipName = `${manifest.file.name}-v${manifest.file.version}.zip`;
-            const zipFile = fs.createWriteStream(path.join("package", zipName));
-            const zip = archiver("zip", { zlib: { level: 9 } });
-
-            zipFile.on("close", () => {
-                console.log(chalk.green(zip.pointer() + " total bytes"));
-                console.log(chalk.green(`Zip file ${zipName} has been written`));
-                return resolve();
-            });
-
-            zip.on("error", (err) => {
-                throw err;
-            });
-
-            zip.pipe(zipFile);
-
-            // Add the directory with the final code
-            zip.directory("dist/", manifest.file.name);
-
-            zip.finalize();
-        } catch (err) {
-            return reject(err);
-        }
-    });
-}
-
-/*********************/
-/*		PACKAGE		 */
-/*********************/
-
-/**
- * Update version and URLs in the manifest JSON
- */
-function updateManifest(cb) {
-    const packageJson = fs.readJSONSync("package.json");
-    const config = getConfig(),
-        manifest = getManifest(),
-        rawURL = config.rawURL,
-        repoURL = config.repository,
-        manifestRoot = manifest.root;
-
-    if (!config) cb(Error(chalk.red("foundryconfig.json not found")));
-    if (!manifest) cb(Error(chalk.red("Manifest JSON not found")));
-    if (!rawURL || !repoURL) cb(Error(chalk.red("Repository URLs not configured in foundryconfig.json")));
-
-    try {
-        const version = argv.update || argv.u;
-
-        /* Update version */
-
-        const versionMatch = /^(\d{1,}).(\d{1,}).(\d{1,})$/;
-        const currentVersion = manifest.file.version;
-        let targetVersion = "";
-
-        if (!version) {
-            cb(Error("Missing version number"));
-        }
-
-        if (versionMatch.test(version)) {
-            targetVersion = version;
-        } else {
-            targetVersion = currentVersion.replace(versionMatch, (substring, major, minor, patch) => {
-                console.log(substring, Number(major) + 1, Number(minor) + 1, Number(patch) + 1);
-                if (version === "major") {
-                    return `${Number(major) + 1}.0.0`;
-                } else if (version === "minor") {
-                    return `${major}.${Number(minor) + 1}.0`;
-                } else if (version === "patch") {
-                    return `${major}.${minor}.${Number(patch) + 1}`;
-                } else {
-                    return "";
-                }
-            });
-        }
-
-        if (targetVersion === "") {
-            return cb(Error(chalk.red("Error: Incorrect version arguments.")));
-        }
-
-        if (targetVersion === currentVersion) {
-            return cb(Error(chalk.red("Error: Target version is identical to current version.")));
-        }
-        console.log(`Updating version number to '${targetVersion}'`);
-
-        packageJson.version = targetVersion;
-        manifest.file.version = targetVersion;
-
-        /* Update URLs */
-
-        const result = `${rawURL}/v${manifest.file.version}/package/${manifest.file.name}-v${manifest.file.version}.zip`;
-
-        manifest.file.url = repoURL;
-        manifest.file.manifest = `${rawURL}/master/${manifestRoot}/${manifest.name}`;
-        manifest.file.download = result;
-
-        const prettyProjectJson = stringify(manifest.file, {
-            maxLength: 35,
-            indent: "\t",
-        });
-
-        fs.writeJSONSync("package.json", packageJson, { spaces: "\t" });
-        fs.writeFileSync(path.join(manifest.root, manifest.name), prettyProjectJson, "utf8");
-
-        return cb();
-    } catch (err) {
-        cb(err);
-    }
-}
-
-function gitAdd() {
-    return gulp.src("package").pipe(git.add({ args: "--no-all" }));
-}
-
-function gitCommit() {
-    return gulp.src("./*").pipe(
-        git.commit(`v${getManifest().file.version}`, {
-            args: "-a",
-            disableAppendPaths: true,
-        })
-    );
-}
-
-function gitTag() {
-    const manifest = getManifest();
-    return git.tag(`v${manifest.file.version}`, `Updated to ${manifest.file.version}`, (err) => {
-        if (err) throw err;
-    });
-}
-
-const execGit = gulp.series(gitAdd, gitCommit, gitTag);
-
-const execBuild = gulp.parallel(buildTS, buildLess, buildSASS, copyFiles);
-
-exports.build = gulp.series(clean, execBuild);
-exports.watch = buildWatch;
-exports.clean = clean;
-exports.link = linkUserData;
-exports.package = packageBuild;
-exports.update = updateManifest;
-exports.publish = gulp.series(clean, updateManifest, execBuild, packageBuild, execGit);
+const gulp = require("gulp");
+const fs = require("fs-extra");
+const path = require("path");
+const chalk = require("chalk");
+const archiver = require("archiver");
+const stringify = require("json-stringify-pretty-compact");
+const typescript = require("typescript");
+
+const ts = require("gulp-typescript");
+const less = require("gulp-less");
+const sass = require("gulp-sass");
+const git = require("gulp-git");
+
+const argv = require("yargs").argv;
+
+sass.compiler = require("sass");
+
+function getConfig() {
+    const configPath = path.resolve(process.cwd(), "foundryconfig.json");
+    let config;
+
+    if (fs.existsSync(configPath)) {
+        config = fs.readJSONSync(configPath);
+        return config;
+    } else {
+        return;
+    }
+}
+
+function getManifest() {
+    const json = {};
+
+    if (fs.existsSync("src")) {
+        json.root = "src";
+    } else {
+        json.root = "dist";
+    }
+
+    const modulePath = path.join(json.root, "module.json");
+    const systemPath = path.join(json.root, "system.json");
+
+    if (fs.existsSync(modulePath)) {
+        json.file = fs.readJSONSync(modulePath);
+        json.name = "module.json";
+    } else if (fs.existsSync(systemPath)) {
+        json.file = fs.readJSONSync(systemPath);
+        json.name = "system.json";
+    } else {
+        return;
+    }
+
+    return json;
+}
+
+/**
+ * TypeScript transformers
+ * @returns {typescript.TransformerFactory<typescript.SourceFile>}
+ */
+function createTransformer() {
+    /**
+     * @param {typescript.Node} node
+     */
+    function shouldMutateModuleSpecifier(node) {
+        if (!typescript.isImportDeclaration(node) && !typescript.isExportDeclaration(node)) return false;
+        if (node.moduleSpecifier === undefined) return false;
+        if (!typescript.isStringLiteral(node.moduleSpecifier)) return false;
+        if (!node.moduleSpecifier.text.startsWith("./") && !node.moduleSpecifier.text.startsWith("../")) return false;
+        if (path.extname(node.moduleSpecifier.text) !== "") return false;
+        return true;
+    }
+
+    /**
+     * Transforms import/export declarations to append `.js` extension
+     * @param {typescript.TransformationContext} context
+     */
+    function importTransformer(context) {
+        return (node) => {
+            /**
+             * @param {typescript.Node} node
+             */
+            function visitor(node) {
+                if (shouldMutateModuleSpecifier(node)) {
+                    if (typescript.isImportDeclaration(node)) {
+                        const newModuleSpecifier = typescript.createLiteral(`${node.moduleSpecifier.text}.js`);
+                        return typescript.updateImportDeclaration(
+                            node,
+                            node.decorators,
+                            node.modifiers,
+                            node.importClause,
+                            newModuleSpecifier,
+                        );
+                    } else if (typescript.isExportDeclaration(node)) {
+                        const newModuleSpecifier = typescript.createLiteral(`${node.moduleSpecifier.text}.js`);
+                        return typescript.updateExportDeclaration(
+                            node,
+                            node.decorators,
+                            node.modifiers,
+                            node.exportClause,
+                            newModuleSpecifier,
+                        );
+                    }
+                }
+                return typescript.visitEachChild(node, visitor, context);
+            }
+
+            return typescript.visitNode(node, visitor);
+        };
+    }
+
+    return importTransformer;
+}
+
+const tsConfig = ts.createProject("tsconfig.json", {
+    getCustomTransformers: (_program) => ({
+        after: [createTransformer()],
+    }),
+});
+
+/********************/
+/*		BUILD		*/
+/********************/
+
+/**
+ * Build TypeScript
+ */
+function buildTS() {
+    return gulp.src("src/**/*.ts").pipe(tsConfig()).pipe(gulp.dest("dist"));
+}
+
+/**
+ * Build Less
+ */
+function buildLess() {
+    return gulp.src("src/*.less").pipe(less()).pipe(gulp.dest("dist"));
+}
+
+/**
+ * Build SASS
+ */
+function buildSASS() {
+    return gulp.src("src/*.scss").pipe(sass().on("error", sass.logError)).pipe(gulp.dest("dist"));
+}
+
+/**
+ * Copy static files
+ */
+async function copyFiles() {
+    const statics = ["lang", "fonts", "assets", "templates", "module.json", "system.json", "template.json"];
+    try {
+        for (const file of statics) {
+            if (fs.existsSync(path.join("src", file))) {
+                await fs.copy(path.join("src", file), path.join("dist", file));
+            }
+        }
+        return Promise.resolve();
+    } catch (err) {
+        Promise.reject(err);
+    }
+}
+
+/**
+ * Watch for changes for each build step
+ */
+function buildWatch() {
+    gulp.watch("src/**/*.ts", { ignoreInitial: false }, buildTS);
+    gulp.watch("src/**/*.less", { ignoreInitial: false }, buildLess);
+    gulp.watch("src/**/*.scss", { ignoreInitial: false }, buildSASS);
+    gulp.watch(["src/fonts", "src/lang", "src/templates", "src/*.json"], { ignoreInitial: false }, copyFiles);
+}
+
+/********************/
+/*		CLEAN		*/
+/********************/
+
+/**
+ * Remove built files from `dist` folder
+ * while ignoring source files
+ */
+async function clean() {
+    const name = path.basename(path.resolve("."));
+    const files = [];
+
+    // If the project uses TypeScript
+    if (fs.existsSync(path.join("src", `${name}.ts`))) {
+        files.push(
+            "lang",
+            "templates",
+            "assets",
+            "module",
+            `${name}.js`,
+            "module.json",
+            "system.json",
+            "template.json",
+        );
+    }
+
+    // If the project uses Less or SASS
+    if (fs.existsSync(path.join("src", `${name}.less`)) || fs.existsSync(path.join("src", `${name}.scss`))) {
+        files.push("fonts", `${name}.css`);
+    }
+
+    console.log(" ", chalk.yellow("Files to clean:"));
+    console.log("   ", chalk.blueBright(files.join("\n    ")));
+
+    // Attempt to remove the files
+    try {
+        for (const filePath of files) {
+            await fs.remove(path.join("dist", filePath));
+        }
+        return Promise.resolve();
+    } catch (err) {
+        Promise.reject(err);
+    }
+}
+
+/********************/
+/*		LINK		*/
+/********************/
+
+/**
+ * Link build to User Data folder
+ */
+async function linkUserData() {
+    const name = path.basename(path.resolve("."));
+    const config = fs.readJSONSync("foundryconfig.json");
+
+    let destDir;
+    try {
+        if (
+            fs.existsSync(path.resolve(".", "dist", "module.json")) ||
+            fs.existsSync(path.resolve(".", "src", "module.json"))
+        ) {
+            destDir = "modules";
+        } else if (
+            fs.existsSync(path.resolve(".", "dist", "system.json")) ||
+            fs.existsSync(path.resolve(".", "src", "system.json"))
+        ) {
+            destDir = "systems";
+        } else {
+            throw Error(`Could not find ${chalk.blueBright("module.json")} or ${chalk.blueBright("system.json")}`);
+        }
+
+        let linkDir;
+        if (config.dataPath) {
+            if (!fs.existsSync(path.join(config.dataPath, "Data")))
+                throw Error("User Data path invalid, no Data directory found");
+
+            linkDir = path.join(config.dataPath, "Data", destDir, name);
+        } else {
+            throw Error("No User Data path defined in foundryconfig.json");
+        }
+
+        if (argv.clean || argv.c) {
+            console.log(chalk.yellow(`Removing build in ${chalk.blueBright(linkDir)}`));
+
+            await fs.remove(linkDir);
+        } else if (!fs.existsSync(linkDir)) {
+            console.log(chalk.green(`Copying build to ${chalk.blueBright(linkDir)}`));
+            await fs.symlink(path.resolve("./dist"), linkDir);
+        }
+        return Promise.resolve();
+    } catch (err) {
+        Promise.reject(err);
+    }
+}
+
+/*********************/
+/*		PACKAGE		 */
+/*********************/
+
+/**
+ * Package build
+ */
+async function packageBuild() {
+    const manifest = getManifest();
+
+    return new Promise((resolve, reject) => {
+        try {
+            // Remove the package dir without doing anything else
+            if (argv.clean || argv.c) {
+                console.log(chalk.yellow("Removing all packaged files"));
+                fs.removeSync("package");
+                return;
+            }
+
+            // Ensure there is a directory to hold all the packaged versions
+            fs.ensureDirSync("package");
+
+            // Initialize the zip file
+            const zipName = `${manifest.file.name}-v${manifest.file.version}.zip`;
+            const zipFile = fs.createWriteStream(path.join("package", zipName));
+            const zip = archiver("zip", { zlib: { level: 9 } });
+
+            zipFile.on("close", () => {
+                console.log(chalk.green(zip.pointer() + " total bytes"));
+                console.log(chalk.green(`Zip file ${zipName} has been written`));
+                return resolve();
+            });
+
+            zip.on("error", (err) => {
+                throw err;
+            });
+
+            zip.pipe(zipFile);
+
+            // Add the directory with the final code
+            zip.directory("dist/", manifest.file.name);
+
+            zip.finalize();
+        } catch (err) {
+            return reject(err);
+        }
+    });
+}
+
+/*********************/
+/*		PACKAGE		 */
+/*********************/
+
+/**
+ * Update version and URLs in the manifest JSON
+ */
+function updateManifest(cb) {
+    const packageJson = fs.readJSONSync("package.json");
+    const config = getConfig(),
+        manifest = getManifest(),
+        rawURL = config.rawURL,
+        repoURL = config.repository,
+        manifestRoot = manifest.root;
+
+    if (!config) cb(Error(chalk.red("foundryconfig.json not found")));
+    if (!manifest) cb(Error(chalk.red("Manifest JSON not found")));
+    if (!rawURL || !repoURL) cb(Error(chalk.red("Repository URLs not configured in foundryconfig.json")));
+
+    try {
+        const version = argv.update || argv.u;
+
+        /* Update version */
+
+        const versionMatch = /^(\d{1,}).(\d{1,}).(\d{1,})$/;
+        const currentVersion = manifest.file.version;
+        let targetVersion = "";
+
+        if (!version) {
+            cb(Error("Missing version number"));
+        }
+
+        if (versionMatch.test(version)) {
+            targetVersion = version;
+        } else {
+            targetVersion = currentVersion.replace(versionMatch, (substring, major, minor, patch) => {
+                console.log(substring, Number(major) + 1, Number(minor) + 1, Number(patch) + 1);
+                if (version === "major") {
+                    return `${Number(major) + 1}.0.0`;
+                } else if (version === "minor") {
+                    return `${major}.${Number(minor) + 1}.0`;
+                } else if (version === "patch") {
+                    return `${major}.${minor}.${Number(patch) + 1}`;
+                } else {
+                    return "";
+                }
+            });
+        }
+
+        if (targetVersion === "") {
+            return cb(Error(chalk.red("Error: Incorrect version arguments.")));
+        }
+
+        if (targetVersion === currentVersion) {
+            return cb(Error(chalk.red("Error: Target version is identical to current version.")));
+        }
+        console.log(`Updating version number to '${targetVersion}'`);
+
+        packageJson.version = targetVersion;
+        manifest.file.version = targetVersion;
+
+        /* Update URLs */
+
+        const result = `${rawURL}/v${manifest.file.version}/package/${manifest.file.name}-v${manifest.file.version}.zip`;
+
+        manifest.file.url = repoURL;
+        manifest.file.manifest = `${rawURL}/master/${manifestRoot}/${manifest.name}`;
+        manifest.file.download = result;
+
+        const prettyProjectJson = stringify(manifest.file, {
+            maxLength: 35,
+            indent: "\t",
+        });
+
+        fs.writeJSONSync("package.json", packageJson, { spaces: "\t" });
+        fs.writeFileSync(path.join(manifest.root, manifest.name), prettyProjectJson, "utf8");
+
+        return cb();
+    } catch (err) {
+        cb(err);
+    }
+}
+
+function gitAdd() {
+    return gulp.src("package").pipe(git.add({ args: "--no-all" }));
+}
+
+function gitCommit() {
+    return gulp.src("./*").pipe(
+        git.commit(`v${getManifest().file.version}`, {
+            args: "-a",
+            disableAppendPaths: true,
+        }),
+    );
+}
+
+function gitTag() {
+    const manifest = getManifest();
+    return git.tag(`v${manifest.file.version}`, `Updated to ${manifest.file.version}`, (err) => {
+        if (err) throw err;
+    });
+}
+
+const execGit = gulp.series(gitAdd, gitCommit, gitTag);
+
+const execBuild = gulp.parallel(buildTS, buildLess, buildSASS, copyFiles);
+
+exports.build = gulp.series(clean, execBuild);
+exports.watch = buildWatch;
+exports.clean = clean;
+exports.link = linkUserData;
+exports.package = packageBuild;
+exports.update = updateManifest;
+exports.publish = gulp.series(clean, updateManifest, execBuild, packageBuild, execGit);
diff --git a/src/ds4.scss b/src/ds4.scss
index 2fedca1f..db46a09a 100644
--- a/src/ds4.scss
+++ b/src/ds4.scss
@@ -16,8 +16,10 @@
     @import "scss/components/basic_property";
     @import "scss/components/tabs";
     @import "scss/components/items";
+    @import "scss/components/talents";
     @import "scss/components/description";
     @import "scss/components/character_values";
     @import "scss/components/attributes_traits";
     @import "scss/components/combat_values";
+    @import "scss/components/character_progression";
 }
diff --git a/src/lang/en.json b/src/lang/en.json
index de17c09b..267e0b2c 100644
--- a/src/lang/en.json
+++ b/src/lang/en.json
@@ -1,10 +1,12 @@
 {
     "DS4.UserInteractionAddItem": "Add item",
     "DS4.NotOwned": "No owner",
-    "DS4.Description": "Description",
-    "DS4.DescriptionAbbr": "Desc",
-    "DS4.Details": "Details",
-    "DS4.Effects": "Effects",
+    "DS4.HeadingDescription": "Description",
+    "DS4.HeadingDetails": "Details",
+    "DS4.HeadingEffects": "Effects",
+    "DS4.HeadingInventory": "Inventory",
+    "DS4.HeadingProfile": "Profile",
+    "DS4.HeadingTalents": "Talents & Abilities",
     "DS4.AttackType": "Attack Type",
     "DS4.AttackTypeAbbr": "AT",
     "DS4.WeaponBonus": "Weapon Bonus",
@@ -29,10 +31,19 @@
     "DS4.ItemAvailabilityNowhere": "Nowhere",
     "DS4.ItemName": "Name",
     "DS4.ItemTypeWeapon": "Weapon",
+    "DS4.ItemTypeWeaponPlural": "Weapons",
     "DS4.ItemTypeArmor": "Armor",
+    "DS4.ItemTypeArmorPlural": "Armor",
     "DS4.ItemTypeShield": "Shield",
+    "DS4.ItemTypeShieldPlural": "Shields",
     "DS4.ItemTypeTrinket": "Trinket",
+    "DS4.ItemTypeTrinketPlural": "Trinkets",
     "DS4.ItemTypeEquipment": "Equipment",
+    "DS4.ItemTypeEquipmentPlural": "Equipment",
+    "DS4.ItemTypeTalent": "Talent",
+    "DS4.ItemTypeTalentPlural": "Talents",
+    "DS4.ItemTypeRacialAbility": "Racial Ability",
+    "DS4.ItemTypeRacialAbilityPlural": "Racial Abilities",
     "DS4.ArmorType": "Armor Type",
     "DS4.ArmorTypeAbbr": "AT",
     "DS4.ArmorMaterialType": "Material Type",
@@ -78,8 +89,26 @@
     "DS4.BaseInfoClass": "Class",
     "DS4.BaseInfoHeroClass": "Hero Class",
     "DS4.BaseInfoRacialAbilities": "Racial Abilites",
+    "DS4.BaseInfoCulture": "Culture",
     "DS4.ProgressionLevel": "Level",
     "DS4.ProgressionExperiencePoints": "Experience Points",
     "DS4.ProgressionTalentPoints": "Talent Points",
-    "DS4.ProgressionProgressPoints": "Progress Points"
+    "DS4.ProgressionProgressPoints": "Progress Points",
+    "DS4.TalentRank": "Rank",
+    "DS4.TalentRankBase": "Acquired Ranks",
+    "DS4.TalentRankMax": "Maximum Ranks",
+    "DS4.TalentRankMod": "Additional Ranks",
+    "DS4.TalentRankTotal": "Total Ranks",
+    "DS4.LanguageLanguages": "Languages",
+    "DS4.LanguageAlphabets": "Alphabets",
+    "DS4.ProfileGender": "Gender",
+    "DS4.ProfileBirthday": "Birthday",
+    "DS4.ProfileBirthplace": "Birthplace",
+    "DS4.ProfileAge": "Age",
+    "DS4.ProfileHeight": "Height",
+    "DS4.ProfilHairColor": "Hair Color",
+    "DS4.ProfileWeight": "Weight",
+    "DS4.ProfileEyeColor": "Eye Color",
+    "DS4.ProfileSpecialCharacteristics": "Special Characteristics",
+    "DS4.WarningManageActiveEffectOnOwnedItem": "Managing Active Effects within an Owned Item is not currently supported and will be added in a subsequent update."
 }
diff --git a/src/module/actor/actor-data.ts b/src/module/actor/actor-data.ts
index 93385b65..4269bce0 100644
--- a/src/module/actor/actor-data.ts
+++ b/src/module/actor/actor-data.ts
@@ -4,6 +4,8 @@ export interface DS4ActorDataType {
     combatValues: DS4ActorDataCombatValues;
     baseInfo: DS4ActorDataBaseInfo;
     progression: DS4ActorDataProgression;
+    language: DS4ActorDataLanguage;
+    profile: DS4ActorDataProfile;
 }
 
 interface DS4ActorDataAttributes {
@@ -23,8 +25,9 @@ interface UsableResource<T> {
     used: T;
 }
 
-interface CurrentData<T> extends ModifiableData<T> {
-    current: T;
+interface ResourceData<T> extends ModifiableData<T> {
+    value: T;
+    max?: T;
 }
 
 // Blueprint in case we need more detailed differentiation
@@ -40,7 +43,7 @@ interface DS4ActorDataTraits {
 }
 
 interface DS4ActorDataCombatValues {
-    hitPoints: CurrentData<number>;
+    hitPoints: ResourceData<number>;
     defense: ModifiableData<number>;
     initiative: ModifiableData<number>;
     movement: ModifiableData<number>;
@@ -55,6 +58,7 @@ interface DS4ActorDataBaseInfo {
     class: string;
     heroClass: string;
     racialAbilities: string;
+    culture: string;
 }
 
 interface DS4ActorDataProgression {
@@ -63,3 +67,20 @@ interface DS4ActorDataProgression {
     talentPoints: UsableResource<number>;
     progressPoints: UsableResource<number>;
 }
+
+interface DS4ActorDataLanguage {
+    languages: string;
+    alphabets: string;
+}
+
+interface DS4ActorDataProfile {
+    gender: string;
+    birthday: string;
+    birthplace: string;
+    age: number;
+    height: number;
+    hairColor: string;
+    weight: number;
+    eyeColor: string;
+    specialCharacteristics: string;
+}
diff --git a/src/module/actor/actor.ts b/src/module/actor/actor.ts
index c17d6843..7f2f8209 100644
--- a/src/module/actor/actor.ts
+++ b/src/module/actor/actor.ts
@@ -18,5 +18,7 @@ export class DS4Actor extends Actor<DS4ActorDataType, DS4ItemDataType, DS4Item>
         Object.values(combatValues).forEach(
             (combatValue: ModifiableData<number>) => (combatValue.total = combatValue.base + combatValue.mod),
         );
+
+        combatValues.hitPoints.max = combatValues.hitPoints.total;
     }
 }
diff --git a/src/module/config.ts b/src/module/config.ts
index 89d285cf..28e0a655 100644
--- a/src/module/config.ts
+++ b/src/module/config.ts
@@ -48,6 +48,8 @@ export const DS4 = {
         shield: "DS4.ItemTypeShield",
         trinket: "DS4.ItemTypeTrinket",
         equipment: "DS4.ItemTypeEquipment",
+        talent: "DS4.ItemTypeTalent",
+        racialAbility: "DS4.ItemTypeRacialAbility",
     },
 
     /**
@@ -135,10 +137,11 @@ export const DS4 = {
         class: "DS4.BaseInfoClass",
         heroClass: "DS4.BaseInfoHeroClass",
         racialAbilities: "DS4.BaseInfoRacialAbilities",
+        culture: "DS4.BaseInfoCulture",
     },
 
     /**
-     * Definme the progression info of a character
+     * Define the progression info of a character
      */
     progression: {
         level: "DS4.ProgressionLevel",
@@ -146,4 +149,42 @@ export const DS4 = {
         talentPoints: "DS4.ProgressionTalentPoints",
         progressPoints: "DS4.ProgressionProgressPoints",
     },
+
+    /**
+     * Define the language info of a character
+     */
+    language: {
+        languages: "DS4.LanguageLanguages",
+        alphabets: "DS4.LanguageAlphabets",
+    },
+
+    /**
+     * Define the profile info of a character
+     */
+    profile: {
+        gender: "DS4.ProfileGender",
+        birthday: "DS4.ProfileBirthday",
+        birthplace: "DS4.ProfileBirthplace",
+        age: "DS4.ProfileAge",
+        height: "DS4.ProfileHeight",
+        hairColor: "DS4.ProfilHairColor",
+        weight: "DS4.ProfileWeight",
+        eyeColor: "DS4.ProfileEyeColor",
+        specialCharacteristics: "DS4.ProfileSpecialCharacteristics",
+    },
+
+    /**
+     * Define the profile info types for hanndlebars of a character
+     */
+    profileDTypes: {
+        gender: "String",
+        birthday: "String",
+        birthplace: "String",
+        age: "Number",
+        height: "Number",
+        hairColor: "String",
+        weight: "Number",
+        eyeColor: "String",
+        specialCharacteristics: "String",
+    },
 };
diff --git a/src/module/ds4.ts b/src/module/ds4.ts
index ddc135ae..1c593ff6 100644
--- a/src/module/ds4.ts
+++ b/src/module/ds4.ts
@@ -46,8 +46,13 @@ async function registerHandlebarsPartials() {
         "systems/ds4/templates/item/partials/effects.hbs",
         "systems/ds4/templates/item/partials/body.hbs",
         "systems/ds4/templates/actor/partials/items-overview.hbs",
+        "systems/ds4/templates/actor/partials/talents-overview.hbs",
+        "systems/ds4/templates/actor/partials/overview-add-button.hbs",
+        "systems/ds4/templates/actor/partials/overview-control-buttons.hbs",
         "systems/ds4/templates/actor/partials/attributes-traits.hbs",
         "systems/ds4/templates/actor/partials/combat-values.hbs",
+        "systems/ds4/templates/actor/partials/profile.hbs",
+        "systems/ds4/templates/actor/partials/character-progression.hbs",
     ];
     return loadTemplates(templatePaths);
 }
@@ -75,6 +80,8 @@ Hooks.once("setup", function () {
         "combatValues",
         "baseInfo",
         "progression",
+        "language",
+        "profile",
     ];
 
     // Exclude some from sorting where the default order matters
diff --git a/src/module/item/item-data.ts b/src/module/item/item-data.ts
index 58f4dc90..76b90e78 100644
--- a/src/module/item/item-data.ts
+++ b/src/module/item/item-data.ts
@@ -1,5 +1,13 @@
-// TODO: Actually add a type for data
-export type DS4ItemDataType = DS4Weapon | DS4Armor | DS4Shield | DS4Trinket | DS4Equipment;
+import { ModifiableData } from "../actor/actor-data";
+
+export type DS4ItemDataType =
+    | DS4Weapon
+    | DS4Armor
+    | DS4Shield
+    | DS4Trinket
+    | DS4Equipment
+    | DS4Talent
+    | DS4RacialAbility;
 
 // types
 
@@ -14,9 +22,18 @@ interface DS4Armor extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable, DS4It
     armorType: "body" | "helmet" | "vambrace" | "greaves" | "vambraceGreaves";
 }
 
+export interface DS4Talent extends DS4ItemBase {
+    rank: DS4TalentRank;
+}
+
+interface DS4TalentRank extends ModifiableData<number> {
+    max: number;
+}
+
 interface DS4Shield extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable, DS4ItemProtective {}
 interface DS4Trinket extends DS4ItemBase, DS4ItemPhysical, DS4ItemEquipable {}
 interface DS4Equipment extends DS4ItemBase, DS4ItemPhysical {}
+type DS4RacialAbility = DS4ItemBase;
 
 // templates
 
@@ -30,6 +47,10 @@ interface DS4ItemPhysical {
     storageLocation: string;
 }
 
+export function isDS4ItemDataTypePhysical(input: DS4ItemDataType): boolean {
+    return "quantity" in input && "price" in input && "availability" in input && "storageLocation" in input;
+}
+
 interface DS4ItemEquipable {
     equipped: boolean;
 }
diff --git a/src/module/item/item-sheet.ts b/src/module/item/item-sheet.ts
index ac8197aa..8d8df70f 100644
--- a/src/module/item/item-sheet.ts
+++ b/src/module/item/item-sheet.ts
@@ -1,5 +1,5 @@
 import { DS4Item } from "./item";
-import { DS4ItemDataType } from "./item-data";
+import { DS4ItemDataType, isDS4ItemDataTypePhysical } from "./item-data";
 
 /**
  * Extend the basic ItemSheet with some very simple modifications
@@ -26,7 +26,13 @@ export class DS4ItemSheet extends ItemSheet<DS4ItemDataType, DS4Item> {
 
     /** @override */
     getData(): ItemSheetData<DS4ItemDataType, DS4Item> {
-        const data = { ...super.getData(), config: CONFIG.DS4, isOwned: this.item.isOwned, actor: this.item.actor };
+        const data = {
+            ...super.getData(),
+            config: CONFIG.DS4,
+            isOwned: this.item.isOwned,
+            actor: this.item.actor,
+            isPhysical: isDS4ItemDataTypePhysical(this.item.data.data),
+        };
         console.log(data);
         return data;
     }
@@ -54,29 +60,38 @@ export class DS4ItemSheet extends ItemSheet<DS4ItemDataType, DS4Item> {
 
         if (!this.options.editable) return;
 
-        html.find(".effect-create").on("click", this._onEffectCreate.bind(this));
-
-        html.find(".effect-edit").on("click", (ev) => {
-            const li = $(ev.currentTarget).parents(".effect");
-            console.log(li.data("effectId"));
-            const effect = this.item.effects.get(li.data("effectId"));
-            effect.sheet.render(true);
-        });
-
-        html.find(".effect-delete").on("click", async (ev) => {
-            const li = $(ev.currentTarget).parents(".effect");
-            await this.item.deleteEmbeddedEntity("ActiveEffect", li.data("effectId"));
-        });
+        html.find(".effect-control").on("click", this._onManageActiveEffect.bind(this));
     }
 
     /**
-     * Handle creating a new ActiveEffect for the item using initial data defined in the HTML dataset
+     * Handle management of ActiveEffects.
      * @param {Event} event   The originating click event
-     * @private
      */
-    private async _onEffectCreate(event: JQuery.ClickEvent): Promise<unknown> {
+    private async _onManageActiveEffect(event: JQuery.ClickEvent): Promise<unknown> {
         event.preventDefault();
 
+        if (this.item.isOwned) {
+            return ui.notifications.warn(game.i18n.localize("DS4.WarningManageActiveEffectOnOwnedItem"));
+        }
+        const a = event.currentTarget;
+        const li = $(a).parents(".effect");
+
+        switch (a.dataset["action"]) {
+            case "create":
+                return this._createActiveEffect();
+            case "edit":
+                const effect = this.item.effects.get(li.data("effectId"));
+                return effect.sheet.render(true);
+            case "delete": {
+                return this.item.deleteEmbeddedEntity("ActiveEffect", li.data("effectId"));
+            }
+        }
+    }
+
+    /**
+     * Create a new ActiveEffect for the item using default data.
+     */
+    private async _createActiveEffect(): Promise<unknown> {
         const label = `New Effect`;
 
         const createData = {
diff --git a/src/module/item/item.ts b/src/module/item/item.ts
index c32f0cfe..e9a1aa3e 100644
--- a/src/module/item/item.ts
+++ b/src/module/item/item.ts
@@ -1,6 +1,6 @@
 import { DS4Actor } from "../actor/actor";
 import { DS4ActorDataType } from "../actor/actor-data";
-import { DS4ItemDataType } from "./item-data";
+import { DS4ItemDataType, DS4Talent } from "./item-data";
 
 /**
  * Extend the basic Item with some very simple modifications.
@@ -12,10 +12,18 @@ export class DS4Item extends Item<DS4ItemDataType, DS4ActorDataType, DS4Actor> {
      */
     prepareData(): void {
         super.prepareData();
+        this.prepareDerivedData();
 
         // Get the Item's data
         // const itemData = this.data;
         // const actorData = this.actor ? this.actor.data : {};
         // const data = itemData.data;
     }
+
+    prepareDerivedData(): void {
+        if (this.type === "talent") {
+            const data = this.data.data as DS4Talent;
+            data.rank.total = data.rank.base + data.rank.mod;
+        }
+    }
 }
diff --git a/src/scss/components/_attributes_traits.scss b/src/scss/components/_attributes_traits.scss
index 19cef982..09cb469b 100644
--- a/src/scss/components/_attributes_traits.scss
+++ b/src/scss/components/_attributes_traits.scss
@@ -8,7 +8,6 @@
         }
         .attribute-value {
             border: 2px groove $c-border-groove;
-            line-height: $default-input-height;
             font-size: 1.5em;
             text-align: center;
             padding-left: 2px;
@@ -17,6 +16,7 @@
             input,
             .attribute-value-total {
                 grid-column: span 2;
+                line-height: $default-input-height;
             }
         }
     }
@@ -32,7 +32,6 @@
         .trait-value {
             border: 2px groove $c-border-groove;
             font-size: 1.5em;
-            line-height: $default-input-height;
             text-align: center;
             padding-left: 2px;
             padding-right: 2px;
@@ -40,6 +39,7 @@
             input,
             .trait-value-total {
                 grid-column: span 2;
+                line-height: $default-input-height;
             }
         }
     }
diff --git a/src/scss/components/_basic_property.scss b/src/scss/components/_basic_property.scss
index 6f725dad..40978da4 100644
--- a/src/scss/components/_basic_property.scss
+++ b/src/scss/components/_basic_property.scss
@@ -1,13 +1,25 @@
 .basic-properties {
     flex: 0 0 100%;
+    gap: 2px;
     .basic-property {
-        .basic-property-label {
+        display: grid;
+        align-content: end;
+        padding-left: 1px;
+        padding-right: 1px;
+
+        & > label {
             font-weight: bold;
         }
 
-        .basic-property-select {
+        & > select {
             display: block;
             width: 100%;
         }
+
+        .input-divider {
+            text-align: center;
+        }
+
+        @include mark-invalid-or-disabled-input;
     }
 }
diff --git a/src/scss/components/_character_progression.scss b/src/scss/components/_character_progression.scss
new file mode 100644
index 00000000..c2b3fdcd
--- /dev/null
+++ b/src/scss/components/_character_progression.scss
@@ -0,0 +1,28 @@
+.progression {
+    .progression-entry {
+        display: flex;
+        flex-direction: row;
+        flex-wrap: wrap;
+        justify-content: flex-end;
+        align-items: center;
+
+        padding-right: 3px;
+        h2.progression-label {
+            font-family: $font-heading;
+            display: block;
+            height: 50px;
+            padding: 0px;
+            color: $c-light-grey;
+            border: none;
+            line-height: 50px;
+            margin: $header-top-margin 0;
+            text-align: right;
+            //flex: 0;
+        }
+        input.progression-value {
+            margin-left: 5px;
+            flex: 0 0 40px;
+            text-align: left;
+        }
+    }
+}
diff --git a/src/scss/components/_description.scss b/src/scss/components/_description.scss
index 8bd3b18b..cc4c1322 100644
--- a/src/scss/components/_description.scss
+++ b/src/scss/components/_description.scss
@@ -9,7 +9,7 @@
     .side-property {
         margin: 2px 0;
         display: grid;
-        grid-template-columns: 40% auto;
+        grid-template-columns: minmax(30%, auto) auto;
         justify-content: left;
 
         label {
@@ -23,6 +23,8 @@
             width: calc(100% - 2px);
         }
 
+        @include mark-invalid-or-disabled-input;
+
         input[type="checkbox"] {
             width: auto;
             height: 100%;
@@ -31,6 +33,10 @@
     }
 }
 
+.description {
+    height: 100%;
+}
+
 .sheet-body .tab .editor {
     height: 100%;
 }
diff --git a/src/scss/components/_forms.scss b/src/scss/components/_forms.scss
index 2a992d7b..4c99b156 100644
--- a/src/scss/components/_forms.scss
+++ b/src/scss/components/_forms.scss
@@ -43,7 +43,7 @@ header.sheet-header {
         display: block;
         height: 50px;
         padding: 0px;
-        flex: 0 0 0;
+        flex: 0 0 auto;
         color: $c-light-grey;
         border: none;
         line-height: 50px;
diff --git a/src/scss/components/_items.scss b/src/scss/components/_items.scss
index 4dd97f78..6382c587 100644
--- a/src/scss/components/_items.scss
+++ b/src/scss/components/_items.scss
@@ -31,6 +31,7 @@
         input {
             border: 0;
             padding: 0;
+            background-color: transparent;
         }
 
         input[type="checkbox"] {
@@ -38,6 +39,8 @@
             height: 100%;
             margin: 0px;
         }
+
+        @include mark-invalid-or-disabled-input;
     }
 
     .item-name {
@@ -54,9 +57,6 @@
         width: 2.5em;
         padding: 0;
     }
-    .item-num-val:invalid {
-        background-color: color.mix(lightcoral, $c-light-grey, 25%);
-    }
 
     .item-description {
         font-size: 75%;
diff --git a/src/scss/components/_talents.scss b/src/scss/components/_talents.scss
new file mode 100644
index 00000000..2f8db41b
--- /dev/null
+++ b/src/scss/components/_talents.scss
@@ -0,0 +1,3 @@
+.talent-ranks-equation {
+    text-align: center;
+}
diff --git a/src/scss/global/_flex.scss b/src/scss/global/_flex.scss
index 271c64b3..3f23d105 100644
--- a/src/scss/global/_flex.scss
+++ b/src/scss/global/_flex.scss
@@ -18,6 +18,9 @@
     .flex1 {
         flex: 1;
     }
+    .flex125 {
+        flex: 1.25;
+    }
     .flex15 {
         flex: 1.5;
     }
@@ -51,6 +54,9 @@
     .flex1 {
         flex: 1;
     }
+    .flex125 {
+        flex: 1.25;
+    }
     .flex15 {
         flex: 1.5;
     }
diff --git a/src/scss/global/_grid.scss b/src/scss/global/_grid.scss
index 8498a314..b8903f70 100644
--- a/src/scss/global/_grid.scss
+++ b/src/scss/global/_grid.scss
@@ -28,8 +28,8 @@
 }
 
 .grid-6col {
-    grid-column: span 5 / span 5;
-    grid-template-columns: repeat(5, minmax(0, 1fr));
+    grid-column: span 6 / span 6;
+    grid-template-columns: repeat(6, minmax(0, 1fr));
 }
 
 .grid-7col {
diff --git a/src/scss/global/_window.scss b/src/scss/global/_window.scss
index bbe12083..36985d71 100644
--- a/src/scss/global/_window.scss
+++ b/src/scss/global/_window.scss
@@ -1,5 +1,12 @@
 .window-app {
     font-family: $font-primary;
+    input[type="text"],
+    input[type="number"],
+    input[type="password"],
+    input[type="date"],
+    input[type="time"] {
+        width: 100%;
+    }
 }
 
 .rollable {
diff --git a/src/scss/utils/_colors.scss b/src/scss/utils/_colors.scss
index 7a2200d1..55fb8c0a 100644
--- a/src/scss/utils/_colors.scss
+++ b/src/scss/utils/_colors.scss
@@ -2,3 +2,4 @@ $c-white: #fff;
 $c-black: #000;
 $c-light-grey: #777;
 $c-border-groove: #eeede0;
+$c-invalid-input: rgba(lightcoral, 50%);
diff --git a/src/scss/utils/_mixins.scss b/src/scss/utils/_mixins.scss
index 7e028c29..adc2e69a 100644
--- a/src/scss/utils/_mixins.scss
+++ b/src/scss/utils/_mixins.scss
@@ -19,3 +19,12 @@
     display: grid;
     place-items: center;
 }
+
+@mixin mark-invalid-or-disabled-input {
+    input:invalid {
+        background-color: $c-invalid-input;
+    }
+    input:disabled {
+        background-color: transparent;
+    }
+}
diff --git a/src/system.json b/src/system.json
index 3929e3ab..a64a1a8c 100644
--- a/src/system.json
+++ b/src/system.json
@@ -20,9 +20,9 @@
     ],
     "gridDistance": 1,
     "gridUnits": "m",
-    "primaryTokenAttribute": "combatValues.hitPoints.current",
+    "primaryTokenAttribute": "combatValues.hitPoints",
     "url": "https://git.f3l.de/dungeonslayers/ds4",
-    "manifest": "https://git.f3l.de/dungeonslayers/ds4/-/blob/master/src/system.json",
-    "download": "https://git.f3l.de/dungeonslayers/ds4/-/archive/master/ds4-master.zip",
+    "manifest": "https://git.f3l.de/dungeonslayers/ds4/-/raw/master/src/system.json?inline=false",
+    "download": "https://git.f3l.de/dungeonslayers/ds4/-/jobs/artifacts/0.1.0/download?job=build",
     "license": "MIT"
 }
diff --git a/src/template.json b/src/template.json
index b78fd3e1..6e8d6354 100644
--- a/src/template.json
+++ b/src/template.json
@@ -48,7 +48,7 @@
                 "hitPoints": {
                     "base": 0,
                     "mod": 0,
-                    "current": 0
+                    "value": 0
                 },
                 "defense": {
                     "base": 0,
@@ -83,7 +83,8 @@
                 "race": "",
                 "class": "",
                 "heroClass": "",
-                "racialAbilities": ""
+                "racialAbilities": "",
+                "culture": ""
             },
             "progression": {
                 "level": 0,
@@ -96,11 +97,26 @@
                     "total": 0,
                     "used": 0
                 }
+            },
+            "language": {
+                "languages": "",
+                "alphabets": ""
+            },
+            "profile": {
+                "gender": "",
+                "birthday": "",
+                "birthplace": "",
+                "age": 0,
+                "height": 0,
+                "hairColor": "",
+                "weight": 0,
+                "eyeColor": "",
+                "specialCharacteristics": ""
             }
         }
     },
     "Item": {
-        "types": ["weapon", "armor", "shield", "trinket", "equipment"],
+        "types": ["weapon", "armor", "shield", "trinket", "equipment", "talent", "racialAbility"],
         "templates": {
             "base": {
                 "description": ""
@@ -137,6 +153,17 @@
         },
         "equipment": {
             "templates": ["base", "physical"]
+        },
+        "talent": {
+            "templates": ["base"],
+            "rank": {
+                "base": 0,
+                "max": 0,
+                "mod": 0
+            }
+        },
+        "racialAbility": {
+            "templates": ["base"]
         }
     }
 }
diff --git a/src/templates/actor/actor-sheet.hbs b/src/templates/actor/actor-sheet.hbs
index 475ce2fd..8e3e5f54 100644
--- a/src/templates/actor/actor-sheet.hbs
+++ b/src/templates/actor/actor-sheet.hbs
@@ -2,96 +2,66 @@
     {{!-- Sheet Header --}}
     <header class="sheet-header">
         <img class="profile-img" src="{{actor.img}}" data-edit="img" title="{{actor.name}}" height="100" width="100" />
-        <div class="header-fields">
+        <div class="header-fields flexrow">
             <h1 class="charname"><input name="name" type="text" value="{{actor.name}}" placeholder="Name" /></h1>
-        </div>
-        <div class="character-values">
-            {{!-- The grid classes are defined in scss/global/_grid.scss. To use, use both the "grid" and "grid-Ncol"
-            class where "N" can be any number from 1 to 12 and will create that number of columns. --}}
-            <div class="base-infos grid grid-3col">
-                {{!-- "flex-group-center" is also defined in the _grid.scss file and it will add a small amount of
-                padding, a border, and will center all of its child elements content and text. --}}
-                <div class="base-info flex-group-center">
-                    <label for="data.baseInfo.race" class="base-info-label">{{config.baseInfo.race}}</label>
-                    <div class="base-info-content flexrow flex-center flex-between">
-                        <input type="text" name="data.baseInfo.race" value="{{data.baseInfo.race}}"
-                            data-dtype="String" />
+            {{> systems/ds4/templates/actor/partials/character-progression.hbs}}
+
+            <div class="flexrow basic-properties">
+                <div class="basic-property">
+                    <label class="basic-property-label" for="data.baseInfo.race">{{config.baseInfo.race}}</label>
+                    <input type="text" name="data.baseInfo.race" value="{{data.baseInfo.race}}" data-dtype="String" />
+                </div>
+                <div class="basic-property">
+                    <label class="basic-property-label" for="data.baseInfo.culture">{{config.baseInfo.culture}}</label>
+                    <input type="text" name="data.baseInfo.culture" value="{{data.baseInfo.culture}}"
+                        data-dtype="String" />
+                </div>
+                <div class="basic-property flex125">
+                    <label class="basic-property-label"
+                        for="data.progression.progressPoints.used">{{config.progression.progressPoints}}</label>
+                    <div class="flexrow">
+                        <input type="number" name="data.progression.progressPoints.used"
+                            value="{{data.progression.progressPoints.used}}" data-dtype="Number" /><span
+                            class="input-divider"> /
+                        </span><input type="number" name="data.progression.progressPoints.total"
+                            value="{{data.progression.progressPoints.total}}" data-dtype="Number" />
                     </div>
                 </div>
-                <div class="base-info flex-group-center">
-                    <div class="grid grid-3col">
-                        <div class="base-info flex-group-center">
-                            <label for="data.progression.level"
-                                class="base-info-label">{{config.progression.level}}</label>
-                            <div class="base-info-content flexrow flex-center flex-between">
-                                <input type="text" name="data.progression.level" value="{{data.progression.level}}"
-                                    data-dtype="Number" />
-                            </div>
-                        </div>
-                        <div class="base-info flex-group-center">
-                            <label for="data.progression.progressPoints"
-                                class="base-info-label">{{config.progression.progressPoints}}</label>
-                            <div class="base-info-content flexrow flex-center flex-between">
-                                <input type="text" name="data.progression.progressPoints.used"
-                                    value="{{data.progression.progressPoints.used}}" data-dtype="Number" /><span> /
-                                </span><input type="text" name="data.progression.progressPoints.total"
-                                    value="{{data.progression.progressPoints.total}}" data-dtype="Number" />
-                            </div>
-                        </div>
-                        <div class="base-info flex-group-center">
-                            <label for="data.progression.talentPoints"
-                                class="base-info-label">{{config.progression.talentPoints}}</label>
-                            <div class="base-info-content flexrow flex-center flex-between">
-                                <input type="text" name="data.progression.talentPoints.used"
-                                    value="{{data.progression.talentPoints.used}}" data-dtype="Number" /><span> /
-                                </span><input type="text" name="data.progression.talentPoints.total"
-                                    value="{{data.progression.talentPoints.total}}" data-dtype="Number" />
-                            </div>
-                        </div>
+                <div class="basic-property flex125">
+                    <label class="basic-property-label"
+                        for="data.progression.talentPoints.used">{{config.progression.talentPoints}}</label>
+                    <div class="flexrow">
+                        <input type="number" name="data.progression.talentPoints.used"
+                            value="{{data.progression.talentPoints.used}}" data-dtype="Number" /><span
+                            class="input-divider"> /
+                        </span><input type="number" name="data.progression.talentPoints.total"
+                            value="{{data.progression.talentPoints.total}}" data-dtype="Number" />
                     </div>
                 </div>
-                <div class="base-info flex-group-center">
-                    <label for="data.baseInfo.class" class="base-info-label">{{config.baseInfo.class}}</label>
-                    <div class="base-info-content flexrow flex-center flex-between">
-                        <input type="text" name="data.baseInfo.class" value="{{data.baseInfo.class}}"
-                            data-dtype="String" />
-                    </div>
+                <div class="basic-property">
+                    <label class="basic-property-label" for="data.baseInfo.class">{{config.baseInfo.class}}</label>
+                    <input type="text" name="data.baseInfo.class" value="{{data.baseInfo.class}}" data-dtype="String" />
                 </div>
-                <div class="base-info flex-group-center">
-                    <label for="data.baseInfo.racialAbilities"
-                        class="base-info-label">{{config.baseInfo.racialAbilities}}</label>
-                    <div class="base-info-content flexrow flex-center flex-between">
-                        <input type="text" name="data.baseInfo.racialAbilities"
-                            value="{{data.baseInfo.racialAbilities}}" data-dtype="String" />
-                    </div>
-                </div>
-                <div class="base-info flex-group-center">
-                    <label for="data.progression.experiencePoints"
-                        class="base-info-label">{{config.progression.experiencePoints}}</label>
-                    <div class="base-info-content flexrow flex-center flex-between">
-                        <input type="text" name="data.progression.experiencePoints"
-                            value="{{data.progression.experiencePoints}}" data-dtype="Number" />
-                    </div>
-                </div>
-                <div class="base-info flex-group-center">
-                    <label for="data.baseInfo.heroClass" class="base-info-label">{{config.baseInfo.heroClass}}</label>
-                    <div class="base-info-content flexrow flex-center flex-between">
-                        <input type="text" name="data.baseInfo.heroClass" value="{{data.baseInfo.heroClass}}"
-                            data-dtype="String" />
-                    </div>
+                <div class="basic-property">
+                    <label class="basic-property-label"
+                        for="data.baseInfo.heroClass">{{config.baseInfo.heroClass}}</label>
+                    <input type="text" name="data.baseInfo.heroClass" value="{{data.baseInfo.heroClass}}"
+                        data-dtype="String" />
                 </div>
             </div>
-
+        </div>
+        <div class="character-values">
             {{> systems/ds4/templates/actor/partials/attributes-traits.hbs}}
             {{> systems/ds4/templates/actor/partials/combat-values.hbs}}
-
         </div>
     </header>
 
     {{!-- Sheet Tab Navigation --}}
     <nav class="sheet-tabs tabs" data-group="primary">
-        <a class="item" data-tab="description">Description</a>
-        <a class="item" data-tab="items">Items</a>
+        <a class="item" data-tab="description">{{localize 'DS4.HeadingDescription'}}</a>
+        <a class="item" data-tab="talents">{{localize 'DS4.HeadingTalents'}}</a>
+        <a class="item" data-tab="profile">{{localize "DS4.HeadingProfile"}}</a>
+        <a class="item" data-tab="inventory">{{localize 'DS4.HeadingInventory'}}</a>
     </nav>
 
     {{!-- Sheet Body --}}
@@ -101,6 +71,12 @@
             {{editor content=data.biography target="data.biography" button=true owner=owner editable=editable}}
         </div>
 
+        {{! Profile Tab --}}
+        {{> systems/ds4/templates/actor/partials/profile.hbs}}
+
+        {{!-- Talents Tab --}}
+        {{> systems/ds4/templates/actor/partials/talents-overview.hbs}}
+
         {{!-- Items Tab --}}
         {{> systems/ds4/templates/actor/partials/items-overview.hbs}}
     </section>
diff --git a/src/templates/actor/partials/character-progression.hbs b/src/templates/actor/partials/character-progression.hbs
new file mode 100644
index 00000000..f22376f0
--- /dev/null
+++ b/src/templates/actor/partials/character-progression.hbs
@@ -0,0 +1,15 @@
+<div class="progression flexrow">
+    <div class="progression-entry">
+        <h2 class="progression-label"><label for="data.progression.level">{{config.progression.level}}</label>
+        </h2>
+        <input class="progression-value" type="number" name="data.progression.level" value="{{data.progression.level}}"
+            data-dtype="Number" />
+    </div>
+    <div class="progression-entry">
+        <h2 class="progression-label"><label
+                for="data.progression.experiencePoints">{{config.progression.experiencePoints}}</label>
+        </h2>
+        <input class="progression-value" type="number" name="data.progression.experiencePoints"
+            value="{{data.progression.experiencePoints}}" data-dtype="Number" />
+    </div>
+</div>
diff --git a/src/templates/actor/partials/items-overview.hbs b/src/templates/actor/partials/items-overview.hbs
index 0cc57faf..e41d6f98 100644
--- a/src/templates/actor/partials/items-overview.hbs
+++ b/src/templates/actor/partials/items-overview.hbs
@@ -5,29 +5,6 @@
 {{!-- INLINE PARTIAL DEFINITIONS --}}
 {{!-- ======================================================================== --}}
 
-{{!--
-!-- Render an "add" button for a given data type.
-!--
-!-- @param datType: hand over the dataType to the partial as hash parameter
---}}
-{{#*inline "addItemButton"}}
-    <div class="item-controls">
-        <a class="item-control item-create" title="Create item" data-type="{{dataType}}">
-            <i class="fas fa-plus"></i>
-            {{localize 'DS4.UserInteractionAddItem'}}</a>
-    </div>
-{{/inline}}
-{{!--
-!-- Render a group of an "edit" and a "delete" button for the current item.
-!-- The current item is defined by the data-item-id HTML property of the parent li element.
---}}
-{{#*inline "itemControlButtons"}}
-    <div class="item-controls">
-        <a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
-        <a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
-    </div>
-{{/inline}}
-
 
 {{!--
 !-- Render a header row for a given data type.
@@ -55,9 +32,9 @@
         {{!-- item type specifics --}}
         {{> @partial-block }}
         {{!-- description --}}
-        <div class="flex4">{{localize 'DS4.Description'}}</div>
+        <div class="flex4">{{localize 'DS4.HeadingDescription'}}</div>
         {{!-- add button --}}
-        {{> addItemButton dataType=dataType }}
+        {{> systems/ds4/templates/actor/partials/overview-add-button.hbs dataType=dataType }}
     </li>
 {{/inline}}
 
@@ -94,7 +71,7 @@
         {{!-- description --}}
         <div class="flex4 item-description">{{{item.data.data.description}}}</div>
         {{!-- control buttons --}}
-        {{> itemControlButtons}}
+        {{> systems/ds4/templates/actor/partials/overview-control-buttons.hbs }}
     </li>
 {{/inline}}
 
@@ -102,10 +79,10 @@
 {{!-- ======================================================================== --}}
 
 
-<div class="tab items" data-group="primary" data-tab="items">
+<div class="tab inventory" data-group="primary" data-tab="inventory">
 
     {{!-- WEAPONS --}}
-    <h4 class="items-list-title">{{localize 'DS4.ItemTypeWeapon'}}</h4>
+    <h4 class="items-list-title">{{localize 'DS4.ItemTypeWeaponPlural'}}</h4>
     <ol class="items-list">
         {{#> itemListHeader dataType='weapon'}}
             <div class="flex05 item-image" title="{{localize 'DS4.AttackType'}}">{{localize 'DS4.AttackTypeAbbr'}}</div>
@@ -129,7 +106,7 @@
     </ol>
 
     {{!-- ARMOR --}}
-    <h4 class="items-list-title">{{localize 'DS4.ItemTypeArmor'}}</h4>
+    <h4 class="items-list-title">{{localize 'DS4.ItemTypeArmorPlural'}}</h4>
     <ol class="items-list">
         {{#> itemListHeader dataType='armor'}}
             <div title="{{localize 'DS4.ArmorMaterialType'}}">{{localize 'DS4.ArmorMaterialTypeAbbr'}}</div>
@@ -153,7 +130,7 @@
 
 
     {{!-- SHIELD --}}
-    <h4 class="items-list-title">{{localize 'DS4.ItemTypeShield'}}</h4> {{!-- SPECIFIC --}}
+    <h4 class="items-list-title">{{localize 'DS4.ItemTypeShieldPlural'}}</h4> {{!-- SPECIFIC --}}
     <ol class="items-list">
         {{#> itemListHeader dataType='shield' }}
             <div class="flex05 item-num-val" title="{{localize 'DS4.ArmorValue'}}">
@@ -168,7 +145,7 @@
     </ol>
 
     {{!-- TRINKET --}}
-    <h4 class="items-list-title">{{localize 'DS4.ItemTypeTrinket'}}</h4>
+    <h4 class="items-list-title">{{localize 'DS4.ItemTypeTrinketPlural'}}</h4>
     <ol class="items-list">
         {{#> itemListHeader dataType='trinket'}}
             <div class="flex2">{{localize 'DS4.StorageLocation'}}</div>
@@ -182,7 +159,7 @@
     </ol>
 
     {{!-- EQUIPMENT --}}
-    <h4 class="items-list-title">{{localize 'DS4.ItemTypeEquipment'}}</h4>
+    <h4 class="items-list-title">{{localize 'DS4.ItemTypeEquipmentPlural'}}</h4>
     <ol class="items-list">
         {{#> itemListHeader dataType='equipment'}}
             <div class="flex2">{{localize 'DS4.StorageLocation'}}</div>
diff --git a/src/templates/actor/partials/overview-add-button.hbs b/src/templates/actor/partials/overview-add-button.hbs
new file mode 100644
index 00000000..86e5d774
--- /dev/null
+++ b/src/templates/actor/partials/overview-add-button.hbs
@@ -0,0 +1,11 @@
+{{!
+!-- Render an "add" button for adding an item of given data type.
+!--
+!-- @param datType: hand over the dataType to the partial as hash parameter
+}}
+<div class="item-controls">
+    <a class="item-control item-create" title="Create item" data-type="{{dataType}}">
+        <i class="fas fa-plus"></i>
+        {{localize "DS4.UserInteractionAddItem"}}
+    </a>
+</div>
\ No newline at end of file
diff --git a/src/templates/actor/partials/overview-control-buttons.hbs b/src/templates/actor/partials/overview-control-buttons.hbs
new file mode 100644
index 00000000..d10dbc3f
--- /dev/null
+++ b/src/templates/actor/partials/overview-control-buttons.hbs
@@ -0,0 +1,8 @@
+{{!--
+!-- Render a group of an "edit" and a "delete" button for the current item.
+!-- The current item is defined by the data-item-id HTML property of the parent li element.
+--}}
+<div class="item-controls">
+    <a class="item-control item-edit" title="Edit Item"><i class="fas fa-edit"></i></a>
+    <a class="item-control item-delete" title="Delete Item"><i class="fas fa-trash"></i></a>
+</div>
diff --git a/src/templates/actor/partials/profile.hbs b/src/templates/actor/partials/profile.hbs
new file mode 100644
index 00000000..b0034128
--- /dev/null
+++ b/src/templates/actor/partials/profile.hbs
@@ -0,0 +1,13 @@
+<div class="tab profile" data-group="primary" data-tab="profile">
+    <div class="grid grid-2col">
+        {{#each data.profile as |profile-data-value profile-data-key|}}
+        <div class="profile-entry">
+            <label for="data.profile.{{profile-data-key}}">
+                {{lookup ../config.profile profile-data-key}}
+            </label>
+            <input type="text" name="data.profile.{{profile-data-key}}" value="{{profile-data-value}}"
+                data-dtype="{{lookup ../config/profileDTypes profile-data-key}}" />
+        </div>
+        {{/each}}
+    </div>
+</div>
\ No newline at end of file
diff --git a/src/templates/actor/partials/talents-overview.hbs b/src/templates/actor/partials/talents-overview.hbs
new file mode 100644
index 00000000..179703e2
--- /dev/null
+++ b/src/templates/actor/partials/talents-overview.hbs
@@ -0,0 +1,123 @@
+{{!-- ======================================================================== --}}
+{{!-- INLINE PARTIAL DEFINITIONS --}}
+{{!-- ======================================================================== --}}
+{{!-- TODO: remove duplicate add and delete button definition --}}
+
+
+{{!--
+!-- Render an input element for a rank value property of an item.
+!--
+!-- @param item: the item
+!-- @param property: the key of the property in item.data.data (if 'base', the max value is set automatically)
+!-- @param disabled: if given, is placed plainly into the input as HTML property;
+!-- meant to be set to "disabled" to disable the input element
+--}}
+{{#*inline "talentRankValue"}}
+<input class="item-num-val item-change" data-dtype="Number" type="number" min="0" step="1" {{#if (eq property 'base' )
+    }}max="{{item.data.data.rank.max}}" {{/if}} {{disabled}} data-property="data.rank.{{property}}"
+    value="{{lookup item.data.data.rank property}}" title="{{localize localizeString}}" />
+{{/inline}}
+
+
+{{!--
+!-- Render a talent list row from a given item.
+!-- It is a flexbox with a child for each item value of interest.
+!-- The partial assumes a variable item to be given in the context.
+!--
+!-- @param item: hand over the item to the partial as hash parameter
+!-- @param partial-block: hand over custom children of the flexbox in the partial block.
+--}}
+{{#*inline "talentListEntry"}}
+<li class="item flexrow" data-item-id="{{item._id}}">
+    {{!-- image --}}
+    <div class="flex05 item-image">
+        <img src="{{item.img}}" title="{{item.name}}" width="24" height="24" />
+    </div>
+    {{!-- name --}}
+    <input class="flex2 item-name item-change" type="text" value="{{item.name}}" data-dtype="String"
+        data-property="name" title="{{localize 'DS4.ItemName'}}">
+    <div class="flex3 flexrow talent-ranks-equation">
+        {{!-- acquired rank --}}
+        {{> talentRankValue item=item property='base' localizeString='DS4.TalentRankBase'}}
+        <span> ( of </span>
+        {{!-- maximum acquirable rank --}}
+        {{> talentRankValue item=item property='max' localizeString='DS4.TalentRankMax'}}
+        <span>) + </span>
+        {{!-- additional ranks --}}
+        {{> talentRankValue item=item property='mod' localizeString='DS4.TalentRankMod'}}
+        <span> = </span>
+        {{!-- derived total rank --}}
+        {{> talentRankValue item=item property='total' localizeString='DS4.TalentRankTotal' disabled='disabled'}}
+    </div>
+    {{!-- description --}}
+    <div class="flex4 item-description">{{{item.data.data.description}}}</div>
+    {{!-- control buttons --}}
+    {{> systems/ds4/templates/actor/partials/overview-control-buttons.hbs }}
+</li>
+{{/inline}}
+
+
+{{!--
+!-- Render a racial ability list row from a given item.
+!-- It is a flexbox with a child for each item value of interest.
+!-- The partial assumes a variable item to be given in the context.
+!--
+!-- @param item: hand over the item to the partial as hash parameter
+!-- @param partial-block: hand over custom children of the flexbox in the partial block.
+--}}
+{{#*inline "racialAbilityListEntry"}}
+<li class="item flexrow" data-item-id="{{item._id}}">
+    {{!-- image --}}
+    <div class="flex05 item-image">
+        <img src="{{item.img}}" title="{{item.name}}" width="24" height="24" />
+    </div>
+    {{!-- name --}}
+    <input class="flex1 item-name item-change" type="text" value="{{item.name}}" data-dtype="String"
+        data-property="name" title="{{localize 'DS4.ItemName'}}">
+    {{!-- description --}}
+    <div class="flex3 item-description">{{{item.data.data.description}}}</div>
+    {{!-- control buttons --}}
+    {{> systems/ds4/templates/actor/partials/overview-control-buttons.hbs }}
+</li>
+{{/inline}}
+
+{{!-- ======================================================================== --}}
+
+
+<div class="tab items" data-group="primary" data-tab="talents">
+    <h4 class="items-list-title">{{localize 'DS4.ItemTypeTalentPlural'}}</h4>
+    <ol class="items-list">
+        <li class="item flexrow item-header">
+            {{!-- image --}}
+            <div class="flex05 item-image"></div>
+            {{!-- name --}}
+            <div class="flex2 item-name">{{localize 'DS4.ItemName'}}</div>
+            {{!-- rank info --}}
+            <div class="flex3">{{localize 'DS4.TalentRank'}}</div>
+            {{!-- description --}}
+            <div class="flex4">{{localize 'DS4.HeadingDescription'}}</div>
+            {{!-- add button --}}
+            {{> systems/ds4/templates/actor/partials/overview-add-button.hbs dataType='talent' }}
+        </li>
+        {{#each itemsByType.talent as |item id|}}
+        {{> talentListEntry item=item}}
+        {{/each}}
+    </ol>
+
+    <h4 class="items-list-title">{{localize 'DS4.ItemTypeRacialAbilityPlural'}}</h4>
+    <ol class="items-list">
+        <li class="item flexrow item-header">
+            {{!-- image --}}
+            <div class="flex05 item-image"></div>
+            {{!-- name --}}
+            <div class="flex1 item-name">{{localize 'DS4.ItemName'}}</div>
+            {{!-- description --}}
+            <div class="flex3">{{localize 'DS4.HeadingDescription'}}</div>
+            {{!-- add button --}}
+            {{> systems/ds4/templates/actor/partials/overview-add-button.hbs dataType='racialAbility' }}
+        </li>
+        {{#each itemsByType.racialAbility as |item id|}}
+        {{> racialAbilityListEntry item=item}}
+        {{/each}}
+    </ol>
+</div>
\ No newline at end of file
diff --git a/src/templates/item/armor-sheet.hbs b/src/templates/item/armor-sheet.hbs
index a0a671dc..b7887131 100644
--- a/src/templates/item/armor-sheet.hbs
+++ b/src/templates/item/armor-sheet.hbs
@@ -6,8 +6,8 @@
             <h2 class="item-type">{{localize (lookup config.itemTypes item.type)}}</h2>
             <div class="grid grid-3col basic-properties">
                 <div class="basic-property">
-                    <label class="basic-property-label">{{localize "DS4.ArmorType"}}</label>
-                    <select class="basic-property-select" name="data.armorType" data-type="String">
+                    <label>{{localize "DS4.ArmorType"}}</label>
+                    <select name="data.armorType" data-type="String">
                         {{#select data.armorType}}
                         {{#each config.armorTypes as |value key|}}
                         <option value="{{key}}">{{value}}</option>
@@ -16,8 +16,8 @@
                     </select>
                 </div>
                 <div class="basic-property">
-                    <label class="basic-property-label">{{localize "DS4.ArmorMaterialType"}}</label>
-                    <select class="basic-property-select" name="data.armorMaterialType" data-type="String">
+                    <label>{{localize "DS4.ArmorMaterialType"}}</label>
+                    <select name="data.armorMaterialType" data-type="String">
                         {{#select data.armorMaterialType}}
                         {{#each config.armorMaterialTypes as |value key|}}
                         <option value="{{key}}">{{value}}</option>
@@ -26,8 +26,8 @@
                     </select>
                 </div>
                 <div class="basic-property">
-                    <label class="basic-property-label">{{localize "DS4.ArmorValue"}}</label>
-                    <input class="basic-property-input" type="text" name="data.armorValue" value="{{data.armorValue}}"
+                    <label>{{localize "DS4.ArmorValue"}}</label>
+                    <input type="text" name="data.armorValue" value="{{data.armorValue}}"
                         placeholder="0" data-dtype="Number" />
                 </div>
             </div>
diff --git a/src/templates/item/partials/body.hbs b/src/templates/item/partials/body.hbs
index 9b5cde20..1f465d9f 100644
--- a/src/templates/item/partials/body.hbs
+++ b/src/templates/item/partials/body.hbs
@@ -2,9 +2,11 @@
 
 {{!-- Sheet Tab Navigation --}}
 <nav class="sheet-tabs tabs" data-group="primary">
-    <a class="item" data-tab="description">{{localize "DS4.Description"}}</a>
-    <a class="item" data-tab="effects">{{localize "DS4.Effects"}}</a>
-    <a class="item" data-tab="details">{{localize "DS4.Details"}}</a>
+    <a class="item" data-tab="description">{{localize "DS4.HeadingDescription"}}</a>
+    <a class="item" data-tab="effects">{{localize "DS4.HeadingEffects"}}</a>
+    {{#if isPhysical}}
+    <a class="item" data-tab="details">{{localize "DS4.HeadingDetails"}}</a>
+    {{/if}}
 </nav>
 
 {{!-- Sheet Body --}}
@@ -13,10 +15,12 @@
     {{!-- Description Tab --}}
     {{> systems/ds4/templates/item/partials/description.hbs}}
 
-    {{!-- Details Tab --}}
-    {{> systems/ds4/templates/item/partials/details.hbs}}
-
     {{!-- Effects Tab --}}
     {{> systems/ds4/templates/item/partials/effects.hbs}}
     
+    {{#if isPhysical}}
+    {{!-- Details Tab --}}
+    {{> systems/ds4/templates/item/partials/details.hbs}}
+    {{/if}}
+    
 </section>
\ No newline at end of file
diff --git a/src/templates/item/partials/description.hbs b/src/templates/item/partials/description.hbs
index 1776f1f2..d7088a30 100644
--- a/src/templates/item/partials/description.hbs
+++ b/src/templates/item/partials/description.hbs
@@ -11,19 +11,21 @@
             <a class="entity-link" draggable="true" data-entity="Actor" data-id="{{actor._id}}"><i
                     class="fas fa-user"></i>{{actor.name}}</a>
         </div>
-        <div class="side-property">
-            <label for="data.quantity">{{localize 'DS4.Quantity'}}</label>
-            <input type="number" min="0" step="1" data-dtype="Number" name="data.quantity" value="{{data.quantity}}" />
-        </div>
-        <div class="side-property">
-            <label for="data.storageLocation">{{localize 'DS4.StorageLocation'}}</label>
-            <input type="text" data-dtype="String" name="data.storageLocation" value="{{data.storageLocation}}" />
-        </div>
+        {{#if isPhysical}}
+            <div class="side-property">
+                <label for="data.quantity">{{localize 'DS4.Quantity'}}</label>
+                <input type="number" min="0" step="1" data-dtype="Number" name="data.quantity" value="{{data.quantity}}" />
+            </div>
+            <div class="side-property">
+                <label for="data.storageLocation">{{localize 'DS4.StorageLocation'}}</label>
+                <input type="text" data-dtype="String" name="data.storageLocation" value="{{data.storageLocation}}" />
+            </div>
+        {{/if}}
         {{else}}
-        {{localize "DS4.NotOwned"}}
+        <span>{{localize "DS4.NotOwned"}}</span>
         {{/if}}
     </div>
-    <div class="description">
+    <div class="description" title="{{localize 'DS4.HeadingDescription'}}">
         {{editor content=data.description target="data.description" button=true owner=owner editable=editable}}
     </div>
 </div>
\ No newline at end of file
diff --git a/src/templates/item/partials/effects.hbs b/src/templates/item/partials/effects.hbs
index 819290d6..b829bfac 100644
--- a/src/templates/item/partials/effects.hbs
+++ b/src/templates/item/partials/effects.hbs
@@ -5,16 +5,16 @@
             <div class="effect-image"></div>
             <div class="effect-name">Name</div>
             <div class="effect-controls">
-                <a class="effect-control effect-create" title="Create Effect"><i
-                        class="fas fa-plus"></i> Add effect</a>
+                <a class="effect-control" data-action="create" title="Create Effect"><i class="fas fa-plus"></i> Add
+                    effect</a>
             </div>
         </li>
         {{#each item.effects as |effect id|}}
         <li class="effect flexrow" data-effect-id="{{effect._id}}">
             <h4 class="effect-name">{{effect.label}}</h4>
             <div class="effect-controls">
-                <a class="effect-control effect-edit" title="Edit Effect"><i class="fas fa-edit"></i></a>
-                <a class="effect-control effect-delete" title="Delete Effect"><i class="fas fa-trash"></i></a>
+                <a class="effect-control" data-action="edit" title="Edit Effect"><i class="fas fa-edit"></i></a>
+                <a class="effect-control" data-action="delete" title="Delete Effect"><i class="fas fa-trash"></i></a>
             </div>
         </li>
         {{/each}}
diff --git a/src/templates/item/racialAbility-sheet.hbs b/src/templates/item/racialAbility-sheet.hbs
new file mode 100644
index 00000000..46dcf476
--- /dev/null
+++ b/src/templates/item/racialAbility-sheet.hbs
@@ -0,0 +1,13 @@
+<form class="{{cssClass}}" autocomplete="off">
+    <header class="sheet-header">
+        <img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}" />
+        <div class="header-fields flexrow">
+            <h1 class="charname"><input name="name" type="text" value="{{item.name}}" placeholder="Name" /></h1>
+            <h2 class="item-type">{{localize (lookup config.itemTypes item.type)}}</h2>
+        </div>
+    </header>
+
+    {{!-- Common Item body --}}
+    {{> systems/ds4/templates/item/partials/body.hbs}}
+
+</form>
diff --git a/src/templates/item/shield-sheet.hbs b/src/templates/item/shield-sheet.hbs
index 1e893d2a..ede89655 100644
--- a/src/templates/item/shield-sheet.hbs
+++ b/src/templates/item/shield-sheet.hbs
@@ -6,8 +6,8 @@
             <h2 class="item-type">{{localize (lookup config.itemTypes item.type)}}</h2>
             <div class="grid grid-1col basic-properties">
                 <div class="basic-property">
-                    <label class="basic-property-label">{{localize "DS4.ArmorValue"}}</label>
-                    <input class="basic-property-input" type="text" name="data.armorValue" value="{{data.armorValue}}"
+                    <label>{{localize "DS4.ArmorValue"}}</label>
+                    <input type="text" name="data.armorValue" value="{{data.armorValue}}"
                         placeholder="0" data-dtype="Number" />
                 </div>
             </div>
diff --git a/src/templates/item/talent-sheet.hbs b/src/templates/item/talent-sheet.hbs
new file mode 100644
index 00000000..a4be9b03
--- /dev/null
+++ b/src/templates/item/talent-sheet.hbs
@@ -0,0 +1,37 @@
+{{!-- ======================================================================== --}}
+{{!-- INLINE PARTIAL DEFINITIONS --}}
+{{!-- ======================================================================== --}}
+
+
+{{#*inline "talentRankBasicProperty" }}
+<div class="basic-property">
+    <label for="data.rank.{{property}}">{{localize localizeString}}</label>
+    <input type="number" min="0" step="1" data-dtype="Number" {{disabled}}
+        {{#if (eq property 'base') }}max="{{data.rank.max}}"{{/if}}
+        name="data.rank.{{property}}" value="{{lookup data.rank property}}" />
+</div>
+{{/inline}}
+
+
+{{!-- ======================================================================== --}}
+
+
+<form class="{{cssClass}}" autocomplete="off">
+    <header class="sheet-header">
+        <img class="profile-img" src="{{item.img}}" data-edit="img" title="{{item.name}}" />
+        <div class="header-fields flexrow">
+            <h1 class="charname"><input name="name" type="text" value="{{item.name}}" placeholder="Name" /></h1>
+            <h2 class="item-type">{{localize (lookup config.itemTypes item.type)}}</h2>
+            <div class="grid grid-4col basic-properties">
+                {{> talentRankBasicProperty data=data property='base' localizeString='DS4.TalentRankBase' }}
+                {{> talentRankBasicProperty data=data property='max' localizeString='DS4.TalentRankMax'}}
+                {{> talentRankBasicProperty data=data property='mod' localizeString='DS4.TalentRankMod'}}
+                {{> talentRankBasicProperty data=data property='total' localizeString='DS4.TalentRankTotal' disabled='disabled'}}
+            </div>
+        </div>
+    </header>
+    
+    {{!-- Common Item body --}}
+    {{> systems/ds4/templates/item/partials/body.hbs}}
+
+</form>
diff --git a/src/templates/item/weapon-sheet.hbs b/src/templates/item/weapon-sheet.hbs
index 7a7efcfd..24a5f2d7 100644
--- a/src/templates/item/weapon-sheet.hbs
+++ b/src/templates/item/weapon-sheet.hbs
@@ -6,8 +6,8 @@
             <h2 class="item-type">{{localize (lookup config.itemTypes item.type)}}</h2>
             <div class="grid grid-3col basic-properties">
                 <div class="basic-property">
-                    <label class="basic-property-label">{{localize "DS4.AttackType"}}</label>
-                    <select class="basic-property-select" name="data.attackType" data-type="String">
+                    <label>{{localize "DS4.AttackType"}}</label>
+                    <select name="data.attackType" data-type="String">
                         {{#select data.attackType}}
                         {{#each config.attackTypes as |value key|}}
                         <option value="{{key}}">{{value}}</option>
@@ -16,13 +16,13 @@
                     </select>
                 </div>
                 <div class="basic-property">
-                    <label class="basic-property-label">{{localize "DS4.WeaponBonus"}}</label>
-                    <input class="basic-property-input" type="number" name="data.weaponBonus" value="{{data.weaponBonus}}"
+                    <label>{{localize "DS4.WeaponBonus"}}</label>
+                    <input type="number" name="data.weaponBonus" value="{{data.weaponBonus}}"
                         placeholder="0" data-dtype="Number" />
                 </div>
                 <div class="basic-property">
-                    <label class="basic-property-label">{{localize "DS4.OpponentDefense"}}</label>
-                    <input class="basic-property-input" type="number" name="data.opponentDefense"
+                    <label>{{localize "DS4.OpponentDefense"}}</label>
+                    <input type="number" name="data.opponentDefense"
                         value="{{data.opponentDefense}}" placeholder="0" data-dtype="Number" />
                 </div>
             </div>