diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..e69de29
diff --git a/assets/fonts/BebasNeue-Regular.ttf b/assets/fonts/BebasNeue-Regular.ttf
new file mode 100644
index 0000000..d2190b5
Binary files /dev/null and b/assets/fonts/BebasNeue-Regular.ttf differ
diff --git a/assets/fonts/CarterOne-Regular.ttf b/assets/fonts/CarterOne-Regular.ttf
new file mode 100644
index 0000000..a4c553a
Binary files /dev/null and b/assets/fonts/CarterOne-Regular.ttf differ
diff --git a/assets/fonts/Chantelli_Antiqua.ttf b/assets/fonts/Chantelli_Antiqua.ttf
new file mode 100644
index 0000000..8bb213b
Binary files /dev/null and b/assets/fonts/Chantelli_Antiqua.ttf differ
diff --git a/assets/fonts/Excelsior-Normal.ttf b/assets/fonts/Excelsior-Normal.ttf
new file mode 100644
index 0000000..d323aa9
Binary files /dev/null and b/assets/fonts/Excelsior-Normal.ttf differ
diff --git a/assets/fonts/FeFCrm2.ttf b/assets/fonts/FeFCrm2.ttf
new file mode 100644
index 0000000..f34b453
Binary files /dev/null and b/assets/fonts/FeFCrm2.ttf differ
diff --git a/assets/fonts/FeGPrm2.ttf b/assets/fonts/FeGPrm2.ttf
new file mode 100644
index 0000000..21a3c78
Binary files /dev/null and b/assets/fonts/FeGPrm2.ttf differ
diff --git a/assets/fonts/Georama-Regular.ttf b/assets/fonts/Georama-Regular.ttf
new file mode 100644
index 0000000..decbb7a
Binary files /dev/null and b/assets/fonts/Georama-Regular.ttf differ
diff --git a/assets/fonts/IMFeDPrm28P.ttf b/assets/fonts/IMFeDPrm28P.ttf
new file mode 100644
index 0000000..f848a69
Binary files /dev/null and b/assets/fonts/IMFeDPrm28P.ttf differ
diff --git a/assets/fonts/IMFell.ttf b/assets/fonts/IMFell.ttf
new file mode 100644
index 0000000..c803269
Binary files /dev/null and b/assets/fonts/IMFell.ttf differ
diff --git a/assets/fonts/Luminari-Regular.ttf b/assets/fonts/Luminari-Regular.ttf
new file mode 100644
index 0000000..ef2a903
Binary files /dev/null and b/assets/fonts/Luminari-Regular.ttf differ
diff --git a/assets/fonts/Megrim-Regular.ttf b/assets/fonts/Megrim-Regular.ttf
new file mode 100644
index 0000000..1e5a8db
Binary files /dev/null and b/assets/fonts/Megrim-Regular.ttf differ
diff --git a/assets/fonts/P22-Operina.ttf b/assets/fonts/P22-Operina.ttf
new file mode 100644
index 0000000..96caf7b
Binary files /dev/null and b/assets/fonts/P22-Operina.ttf differ
diff --git a/assets/fonts/RozhaOne-Regular.ttf b/assets/fonts/RozhaOne-Regular.ttf
new file mode 100644
index 0000000..300eea8
Binary files /dev/null and b/assets/fonts/RozhaOne-Regular.ttf differ
diff --git a/assets/fonts/Sail-Regular.ttf b/assets/fonts/Sail-Regular.ttf
new file mode 100644
index 0000000..efffbb9
Binary files /dev/null and b/assets/fonts/Sail-Regular.ttf differ
diff --git a/assets/fonts/SairaStencilOne-Regular.ttf b/assets/fonts/SairaStencilOne-Regular.ttf
new file mode 100644
index 0000000..5f3588d
Binary files /dev/null and b/assets/fonts/SairaStencilOne-Regular.ttf differ
diff --git a/assets/fonts/Seabreed.ttf b/assets/fonts/Seabreed.ttf
new file mode 100644
index 0000000..354c676
Binary files /dev/null and b/assets/fonts/Seabreed.ttf differ
diff --git a/assets/fonts/SigmarOne-Regular.ttf b/assets/fonts/SigmarOne-Regular.ttf
new file mode 100644
index 0000000..6c57b09
Binary files /dev/null and b/assets/fonts/SigmarOne-Regular.ttf differ
diff --git a/assets/fonts/SpectralSC-Regular.ttf b/assets/fonts/SpectralSC-Regular.ttf
new file mode 100644
index 0000000..ac88fc0
Binary files /dev/null and b/assets/fonts/SpectralSC-Regular.ttf differ
diff --git a/assets/fonts/Tangerine-Regular.ttf b/assets/fonts/Tangerine-Regular.ttf
new file mode 100644
index 0000000..8f342e0
Binary files /dev/null and b/assets/fonts/Tangerine-Regular.ttf differ
diff --git a/assets/fonts/Teko-Regular.ttf b/assets/fonts/Teko-Regular.ttf
new file mode 100644
index 0000000..553ac65
Binary files /dev/null and b/assets/fonts/Teko-Regular.ttf differ
diff --git a/assets/fonts/Top-Secret.ttf b/assets/fonts/Top-Secret.ttf
new file mode 100644
index 0000000..8325b59
Binary files /dev/null and b/assets/fonts/Top-Secret.ttf differ
diff --git a/assets/fonts/Trajan-Pro-Regular.ttf b/assets/fonts/Trajan-Pro-Regular.ttf
new file mode 100644
index 0000000..6e646b9
Binary files /dev/null and b/assets/fonts/Trajan-Pro-Regular.ttf differ
diff --git a/assets/fonts/UncialAntiqua-Regular.ttf b/assets/fonts/UncialAntiqua-Regular.ttf
new file mode 100644
index 0000000..9bf2a7e
Binary files /dev/null and b/assets/fonts/UncialAntiqua-Regular.ttf differ
diff --git a/assets/fonts/Volkhov-Regular.ttf b/assets/fonts/Volkhov-Regular.ttf
new file mode 100644
index 0000000..a8c33c0
Binary files /dev/null and b/assets/fonts/Volkhov-Regular.ttf differ
diff --git a/assets/fonts/armalite.ttf b/assets/fonts/armalite.ttf
new file mode 100644
index 0000000..3790b92
Binary files /dev/null and b/assets/fonts/armalite.ttf differ
diff --git a/assets/fonts/broadw.ttf b/assets/fonts/broadw.ttf
new file mode 100644
index 0000000..62aeb1e
Binary files /dev/null and b/assets/fonts/broadw.ttf differ
diff --git a/assets/fonts/broadway.woff2 b/assets/fonts/broadway.woff2
new file mode 100644
index 0000000..9d4b045
Binary files /dev/null and b/assets/fonts/broadway.woff2 differ
diff --git a/assets/fonts/dominican.ttf b/assets/fonts/dominican.ttf
new file mode 100644
index 0000000..01b84e4
Binary files /dev/null and b/assets/fonts/dominican.ttf differ
diff --git a/assets/fonts/georama.woff2 b/assets/fonts/georama.woff2
new file mode 100644
index 0000000..5e91440
Binary files /dev/null and b/assets/fonts/georama.woff2 differ
diff --git a/assets/icons/icon_arcane.svg b/assets/icons/icon_arcane.svg
new file mode 100644
index 0000000..bf400eb
--- /dev/null
+++ b/assets/icons/icon_arcane.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_archetype.svg b/assets/icons/icon_archetype.svg
new file mode 100644
index 0000000..eec2dac
--- /dev/null
+++ b/assets/icons/icon_archetype.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_armor.svg b/assets/icons/icon_armor.svg
new file mode 100644
index 0000000..589553b
--- /dev/null
+++ b/assets/icons/icon_armor.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_bond.svg b/assets/icons/icon_bond.svg
new file mode 100644
index 0000000..06b8e81
--- /dev/null
+++ b/assets/icons/icon_bond.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_equipment.svg b/assets/icons/icon_equipment.svg
new file mode 100644
index 0000000..87f7c12
--- /dev/null
+++ b/assets/icons/icon_equipment.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_fist.svg b/assets/icons/icon_fist.svg
new file mode 100644
index 0000000..d66176b
--- /dev/null
+++ b/assets/icons/icon_fist.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_injury.svg b/assets/icons/icon_injury.svg
new file mode 100644
index 0000000..8fb30b8
--- /dev/null
+++ b/assets/icons/icon_injury.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_mental_disorder.svg b/assets/icons/icon_mental_disorder.svg
new file mode 100644
index 0000000..3a670a2
--- /dev/null
+++ b/assets/icons/icon_mental_disorder.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_motivation.svg b/assets/icons/icon_motivation.svg
new file mode 100644
index 0000000..4c788d7
--- /dev/null
+++ b/assets/icons/icon_motivation.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_ritual.svg b/assets/icons/icon_ritual.svg
new file mode 100644
index 0000000..bf400eb
--- /dev/null
+++ b/assets/icons/icon_ritual.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_skill.svg b/assets/icons/icon_skill.svg
new file mode 100644
index 0000000..566daf5
--- /dev/null
+++ b/assets/icons/icon_skill.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_tome.svg b/assets/icons/icon_tome.svg
new file mode 100644
index 0000000..6a46d7a
--- /dev/null
+++ b/assets/icons/icon_tome.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_weapon.svg b/assets/icons/icon_weapon.svg
new file mode 100644
index 0000000..b19a989
--- /dev/null
+++ b/assets/icons/icon_weapon.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_weapon_fire.svg b/assets/icons/icon_weapon_fire.svg
new file mode 100644
index 0000000..c4c0f7b
--- /dev/null
+++ b/assets/icons/icon_weapon_fire.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/assets/icons/icon_weapon_range.svg b/assets/icons/icon_weapon_range.svg
new file mode 100644
index 0000000..1d5a698
--- /dev/null
+++ b/assets/icons/icon_weapon_range.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/css/fvtt-ftl-nomad.css b/css/fvtt-ftl-nomad.css
new file mode 100644
index 0000000..15d91fe
--- /dev/null
+++ b/css/fvtt-ftl-nomad.css
@@ -0,0 +1,2902 @@
+@font-face {
+ font-family: "Georama";
+ src: url("../assets/fonts/Georama-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "Tangerine";
+ src: url("../assets/fonts/Tangerine-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "TrajanPro";
+ src: url("../assets/fonts/Trajan-Pro-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "Teko";
+ src: url("../assets/fonts/Teko-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "P22Operina";
+ src: url("../assets/fonts/P22-Operina.ttf") format("truetype");
+}
+@font-face {
+ font-family: "SpectralSC";
+ src: url("../assets/fonts/SpectralSC-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "RozhaOne";
+ src: url("../assets/fonts/RozhaOne-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "Megrim";
+ src: url("../assets/fonts/Megrim-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "Volkhov";
+ src: url("../assets/fonts/Volkhov-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "ChantelliAntiqua";
+ src: url("../assets/fonts/Chantelli_Antiqua.ttf") format("truetype");
+}
+@font-face {
+ font-family: "IMFell";
+ src: url("../assets/fonts/IMFeDPrm28P.ttf") format("truetype");
+}
+@font-face {
+ font-family: "SailRegular";
+ src: url("../assets/fonts/Sail-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "Dominican";
+ src: url("../assets/fonts/dominican.ttf") format("truetype");
+}
+@font-face {
+ font-family: "UncialAntiqua";
+ src: url("../assets/fonts/UncialAntiqua-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "Luminari";
+ src: url("../assets/fonts/Luminari-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "SairaStencilOne";
+ src: url("../assets/fonts/SairaStencilOne-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "Armalite";
+ src: url("../assets/fonts/armalite.ttf") format("truetype");
+}
+@font-face {
+ font-family: "CarterOne";
+ src: url("../assets/fonts/CarterOne-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "SigmarOne";
+ src: url("../assets/fonts/SigmarOne-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "Excelsior";
+ src: url("../assets/fonts/Excelsior-Normal.ttf") format("truetype");
+}
+@font-face {
+ font-family: "TopSecret";
+ src: url("../assets/fonts/Top-Secret.ttf") format("truetype");
+}
+@font-face {
+ font-family: "BebasNeue";
+ src: url("../assets/fonts/BebasNeue-Regular.ttf") format("truetype");
+}
+@font-face {
+ font-family: "Seabreed";
+ src: url("../assets/fonts/Seabreed.ttf") format("truetype");
+}
+@font-face {
+ font-family: "Broadway";
+ src: url("../assets/fonts/broadway.woff2") format("woff2");
+}
+@font-face {
+ font-family: "Caslon";
+ src: url("../fonts/caslonpro-regular.otf") format("truetype");
+}
+@font-face {
+ font-family: "Caslon Bold";
+ src: url("../fonts/caslonpro-bold.otf") format("truetype");
+}
+@font-face {
+ font-family: "Caslon Bold Italic";
+ src: url("../fonts/caslonpro-bolditalic.otf") format("truetype");
+}
+@font-face {
+ font-family: "Caslon Italic";
+ src: url("../fonts/caslonpro-italic.otf") format("truetype");
+}
+:root {
+ --font-size-standard: 0.9rem;
+ --font-size-result: 1.4rem;
+ --background-image-base: linear-gradient(rgba(255, 255, 255, 0.8), rgba(255, 255, 255, 0.8)), url("../assets/ui/jazz_background_main.webp");
+ --font-primary: "RozhaOne";
+ --font-secondary: "RozhaOne";
+ --font-title: "Broadway";
+ --logo-standard: url("../assets/logos/reanimated-ce-logo.webp");
+ --color-success: #0f7a0f;
+ --color-failure: darkred;
+ --color-warning: darkorange;
+ --color-critical-success: #1527cc;
+ --color-critical-failure: #8d20e7;
+ --img-icon-color-filter: brightness(0) saturate(100%) invert(52%) sepia(9%) saturate(2368%) hue-rotate(360deg) brightness(86%) contrast(84%);
+}
+.d100 {
+ width: 18px;
+ height: 18px;
+ color: black;
+ border-width: 0px;
+ filter: var(--img-icon-color-filter);
+}
+.item .thumbnail,
+.item-img {
+ /*filter: invert(90%) sepia(10%) saturate(1215%) hue-rotate(55deg) brightness(93%) contrast(89%);*/
+ /*filter: invert(48%) sepia(79%) saturate(2476%) hue-rotate(86deg) brightness(118%) contrast(119%);*/
+ filter: var(--img-icon-color-filter);
+}
+#logo {
+ content: var(--logo-standard);
+ width: 50px;
+ height: 50px;
+ margin-left: 15px;
+}
+#pause > img {
+ content: var(--logo-standard);
+ height: 192px;
+ width: 192px;
+ top: -45px;
+ left: calc(50% - 96px);
+}
+i.fvtt-cthulhu-eternal {
+ width: 36px;
+ height: 36px;
+ background-image: var(--logo-standard);
+ background-size: 100%;
+ background-position: center;
+ background-repeat: no-repeat;
+ display: flex;
+ position: relative;
+ filter: grayscale(1);
+ transition: 0.3s;
+}
+.application.dialog.fvtt-cthulhu-eternal {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ background-image: var(--background-image-base);
+}
+.application.dialog.fvtt-cthulhu-eternal button:hover {
+ background: var(--color-dark-6);
+}
+.application.dialog.fvtt-cthulhu-eternal .legend {
+ font-family: var(--font-primary);
+}
+.chat-message,
+.chat-message.whisper {
+ font-family: var(--font-primary);
+ background-image: var(--background-image-base);
+ background-repeat: repeat-y;
+ background-position: 0%;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .protagonist-sheet-common label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .vehicle-sheet-common label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .creature-sheet-common label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .item-sheet-common .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .item-sheet-common label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .item-sheet-common .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .item-sheet-common .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .protagonist-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+ overflow: scroll;
+}
+.fvtt-cthulhu-eternal .protagonist-content input:disabled,
+.fvtt-cthulhu-eternal .protagonist-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .protagonist-content input,
+.fvtt-cthulhu-eternal .protagonist-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .protagonist-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .protagonist-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .protagonist-content .form-fields input,
+.fvtt-cthulhu-eternal .protagonist-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .protagonist-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .protagonist-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .protagonist-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .sheet-tabs {
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .protagonist-main {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc {
+ display: flex;
+ gap: 4px;
+ flex: 1;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left {
+ min-width: 180px;
+ display: flex;
+ flex-direction: column;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-left-image {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding-bottom: 8px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-left-image .protagonist-img {
+ height: 140px;
+ width: auto;
+ border: none;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-hp {
+ gap: 2px;
+ align-items: center;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-hp input {
+ flex: none;
+ width: 2rem;
+ margin-left: 4px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-hp .damage-bonus {
+ font-size: calc(var(--font-size-standard) * 0.8);
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-hp .hp-separator {
+ font-size: calc(var(--font-size-standard) * 1.2);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-dv .form-fields,
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-dmax .form-fields {
+ flex: none;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-left .protagonist-dmax-edit input {
+ display: flex;
+ width: 60px;
+ font-size: calc(var(--font-size-standard) * 1.4);
+ align-items: center;
+ justify-content: center;
+ padding: 0 5px 0 5px;
+ text-align: center;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right {
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .protagonist-name {
+ display: flex;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .protagonist-name input {
+ font-family: var(--font-title);
+ font-size: var(--font-size-title);
+ width: 400px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san {
+ align-content: flex-start;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san input {
+ min-width: 2.2rem;
+ max-width: 2.2rem;
+ margin-bottom: 4px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san select {
+ min-width: 6rem;
+ max-width: 6rem;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san .rollable:hover,
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+ font-size: 0.9rem;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san .button {
+ min-width: 4rem;
+ max-width: 4rem;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san .san-checkbox {
+ min-width: 1rem;
+ max-width: 1rem;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san .label-short-field {
+ font-size: 0.9rem;
+ max-width: 3rem;
+ min-width: 3rem;
+ flex-grow: 1;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san .label-recovery {
+ margin-left: 4px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san .label-field {
+ font-size: 0.9rem;
+ max-width: 6rem;
+ min-width: 6rem;
+ flex-grow: 1;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san .label-bp {
+ flex-grow: 1;
+ max-width: 3rem;
+ min-width: 3rem;
+ margin-left: 4px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san .label-insanity {
+ flex-grow: 1;
+ margin-left: 4px;
+ max-width: 8rem;
+ min-width: 8rem;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san .spacing {
+ margin-left: 4px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .san .d100 {
+ flex: 0;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .willpower input {
+ min-width: 2.4rem;
+ max-width: 2.4rem;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .willpower input[type="checkbox"] {
+ min-width: 1rem;
+ max-width: 1rem;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .willpower .label-field {
+ flex-grow: 1;
+ margin-left: 4px;
+ max-width: 5rem;
+ min-width: 5rem;
+ font-size: 0.9rem;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right .willpower .checkbox {
+ flex-grow: 0;
+ min-width: 1rem;
+ max-width: 1rem;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc .protagonist-right label {
+ min-width: 120px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc-play {
+ min-width: 500px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-pc-edit {
+ min-width: 650px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-characteristics {
+ background-color: var(--color-light-1);
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+ flex: 1;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-characteristics .protagonist-characteristic {
+ display: flex;
+ align-items: center;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-characteristics .protagonist-characteristic .rollable:hover,
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-characteristics .protagonist-characteristic .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-characteristics .protagonist-characteristic .rollable {
+ min-width: 3rem;
+ max-width: 3rem;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-characteristics .protagonist-characteristic .char-text {
+ margin-left: 0.5rem;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-characteristics .protagonist-characteristic .d100 {
+ flex: 0;
+ max-width: 0.6rem;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-characteristics .protagonist-characteristic .form-group {
+ flex: 0;
+ padding-left: 5px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-characteristics .protagonist-characteristic .form-group .form-fields {
+ font-size: 1.1rem;
+ flex: none;
+ width: 40px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-characteristic-play {
+ min-width: 225px;
+}
+.fvtt-cthulhu-eternal .protagonist-main .protagonist-characteristic-edit {
+ min-width: 400px;
+}
+.fvtt-cthulhu-eternal .protagonist-biography {
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .protagonist-biography prose-mirror.inactive {
+ min-height: 40px;
+}
+.fvtt-cthulhu-eternal .protagonist-biography prose-mirror.active {
+ min-height: 150px;
+}
+.fvtt-cthulhu-eternal .protagonist-biography .field-label {
+ margin-left: 8px;
+}
+.fvtt-cthulhu-eternal .protagonist-biography .adapted {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 8px;
+}
+.fvtt-cthulhu-eternal .protagonist-biography .adapted label {
+ min-width: 20rem;
+}
+.fvtt-cthulhu-eternal .protagonist-biography .resources {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 8px;
+}
+.fvtt-cthulhu-eternal .protagonist-biography .resources label {
+ min-width: 8rem;
+}
+.fvtt-cthulhu-eternal .protagonist-biography .features,
+.fvtt-cthulhu-eternal .protagonist-biography .biodata {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 8px;
+}
+.fvtt-cthulhu-eternal .protagonist-biography .features label,
+.fvtt-cthulhu-eternal .protagonist-biography .biodata label {
+ min-width: 3rem;
+}
+.fvtt-cthulhu-eternal .protagonist-biography .features .feature,
+.fvtt-cthulhu-eternal .protagonist-biography .biodata .feature {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 18rem;
+ max-width: 18rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-skills {
+ background-color: var(--color-light-1);
+ display: grid;
+ grid-template-columns: 1fr;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-skills legend a {
+ font-size: calc(var(--font-size-standard) * 1.4);
+ padding-left: 5px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-skills .skills {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-skills .skills .skill {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ margin-left: 4px;
+ min-width: 12.3rem;
+ max-width: 12.3rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-skills .skills .skill .rollable:hover,
+.fvtt-cthulhu-eternal .tab.protagonist-skills .skills .skill .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-skills .skills .skill .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-skills .skills .skill .score {
+ min-width: 1.2rem;
+ max-width: 1.2rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-skills .skills .skill .name {
+ min-width: 10rem;
+ max-width: 10rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-skills .skills .skill .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status {
+ background-color: var(--color-light-1);
+ display: grid;
+ grid-template-columns: 1fr;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status legend a {
+ font-size: calc(var(--font-size-standard) * 1.4);
+ padding-left: 5px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .bonds {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .bonds .bond {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 18rem;
+ max-width: 18rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .bonds .bond .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .bonds .bond .name {
+ min-width: 12rem;
+ max-width: 12rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .bonds .bond .type {
+ min-width: 6rem;
+ max-width: 6rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .bonds .bond .level {
+ min-width: 2rem;
+ max-width: 2rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .bonds .bond .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .motivations {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .motivations .motivation {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 14rem;
+ max-width: 14rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .motivations .motivation .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .motivations .motivation .name {
+ min-width: 12rem;
+ max-width: 12rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .motivations .motivation .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .mentaldisorders {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .mentaldisorders .mentaldisorder {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 18rem;
+ max-width: 18rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .mentaldisorders .mentaldisorder .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .mentaldisorders .mentaldisorder .name {
+ min-width: 14rem;
+ max-width: 14rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .mentaldisorders .mentaldisorder .cured {
+ min-width: 5rem;
+ max-width: 5rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .mentaldisorders .mentaldisorder .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .injuries {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .injuries .injury {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 16rem;
+ max-width: 16rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .injuries .injury .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .injuries .injury .name {
+ min-width: 14rem;
+ max-width: 14rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-status .injuries .injury .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment {
+ background-color: var(--color-light-1);
+ display: grid;
+ grid-template-columns: 1fr;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment legend a {
+ font-size: calc(var(--font-size-standard) * 1.4);
+ padding-left: 5px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .weapons {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .weapons .weapon {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 13rem;
+ max-width: 13rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .weapons .weapon .rollable:hover,
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .weapons .weapon .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .weapons .weapon .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .weapons .weapon .damage {
+ min-width: 6rem;
+ max-width: 6rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .weapons .weapon .name {
+ min-width: 10rem;
+ max-width: 10rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .weapons .weapon .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .armors {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .armors .armor {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 13rem;
+ max-width: 13rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .armors .armor .rollable:hover,
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .armors .armor .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .armors .armor .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .armors .armor .protection {
+ min-width: 5rem;
+ max-width: 5rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .armors .armor .name {
+ min-width: 8rem;
+ max-width: 8rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .armors .armor .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .gears {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .gears .gear {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 13rem;
+ max-width: 13rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .gears .gear .rollable:hover,
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .gears .gear .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .gears .gear .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .gears .gear .name {
+ min-width: 10rem;
+ max-width: 10rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .gears .gear .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .rituals {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .rituals .ritual {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 20rem;
+ max-width: 20rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .rituals .ritual .rollable:hover,
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .rituals .ritual .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .rituals .ritual .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .rituals .ritual .name {
+ min-width: 17rem;
+ max-width: 17rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .rituals .ritual .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .tomes {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .tomes .tome {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 20rem;
+ max-width: 20rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .tomes .tome .rollable:hover,
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .tomes .tome .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .tomes .tome .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .tomes .tome .name {
+ min-width: 17rem;
+ max-width: 17rem;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment .tomes .tome .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment prose-mirror.inactive {
+ min-height: 40px;
+}
+.fvtt-cthulhu-eternal .tab.protagonist-equipment prose-mirror.active {
+ min-height: 150px;
+}
+.fvtt-cthulhu-eternal .vehicle-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+ overflow: scroll;
+}
+.fvtt-cthulhu-eternal .vehicle-content input:disabled,
+.fvtt-cthulhu-eternal .vehicle-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .vehicle-content input,
+.fvtt-cthulhu-eternal .vehicle-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .vehicle-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .vehicle-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .vehicle-content .form-fields input,
+.fvtt-cthulhu-eternal .vehicle-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .vehicle-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .vehicle-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .vehicle-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .sheet-tabs {
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .vehicle-main {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc {
+ display: flex;
+ gap: 4px;
+ flex: 1;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-left {
+ min-width: 180px;
+ display: flex;
+ flex-direction: column;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-left .vehicle-left-image {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding-bottom: 8px;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-left .vehicle-left-image .vehicle-img {
+ height: 140px;
+ width: auto;
+ border: none;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right {
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-name {
+ display: flex;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-name input {
+ font-family: var(--font-title);
+ font-size: calc(var(--font-size-standard) * 1.4);
+ width: 400px;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos {
+ display: flex;
+ flex-direction: column;
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos label {
+ min-width: 120px;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos .vehicle-hp {
+ display: flex;
+ gap: 2px;
+ align-items: center;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos .vehicle-hp .vehicle-hp-value .form-fields input {
+ flex: none;
+ width: 50px;
+ margin-left: 4px;
+ font-size: calc(var(--font-size-standard) * 1.4);
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos .vehicle-hp .vehicle-hp-max {
+ clear: both;
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ margin: 3px 0;
+ align-items: center;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos .vehicle-hp .vehicle-hp-max input {
+ width: 50px;
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1.4);
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc .vehicle-right .vehicle-infos .vehicle-hp .hp-separator {
+ font-size: calc(var(--font-size-standard) * 1.2);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc-play {
+ min-width: 500px;
+}
+.fvtt-cthulhu-eternal .vehicle-main .vehicle-pc-edit {
+ min-width: 650px;
+}
+.fvtt-cthulhu-eternal .vehicle-biography {
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .vehicle-biography prose-mirror.inactive {
+ min-height: 40px;
+}
+.fvtt-cthulhu-eternal .vehicle-biography prose-mirror.active {
+ min-height: 150px;
+}
+.fvtt-cthulhu-eternal .vehicle-biography .field-label {
+ margin-left: 8px;
+}
+.fvtt-cthulhu-eternal .vehicle-biography .biodata {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 8px;
+}
+.fvtt-cthulhu-eternal .vehicle-biography .biodata label {
+ min-width: 3rem;
+}
+.fvtt-cthulhu-eternal .vehicle-biography .biodata .feature {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 18rem;
+ max-width: 18rem;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment {
+ background-color: var(--color-light-1);
+ display: grid;
+ grid-template-columns: 1fr;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment legend a {
+ font-size: calc(var(--font-size-standard) * 1.4);
+ padding-left: 5px;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 13rem;
+ max-width: 13srem;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon .rollable:hover,
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon .controls {
+ min-width: 2rem;
+ max-width: 2rem;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon .damage {
+ min-width: 5rem;
+ max-width: 5rem;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon .name {
+ min-width: 8rem;
+ max-width: 8rem;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .weapons .weapon .item-img {
+ width: 32px;
+ height: 32px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 13rem;
+ max-width: 13srem;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear .rollable:hover,
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear .controls {
+ min-width: 2rem;
+ max-width: 2rem;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear .damage {
+ min-width: 5rem;
+ max-width: 5rem;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear .name {
+ min-width: 8rem;
+ max-width: 8rem;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment .gears .gear .item-img {
+ width: 32px;
+ height: 32px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment prose-mirror.inactive {
+ min-height: 40px;
+}
+.fvtt-cthulhu-eternal .tab.vehicle-equipment prose-mirror.active {
+ min-height: 150px;
+}
+.fvtt-cthulhu-eternal .creature-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+ overflow: scroll;
+}
+.fvtt-cthulhu-eternal .creature-content input:disabled,
+.fvtt-cthulhu-eternal .creature-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .creature-content input,
+.fvtt-cthulhu-eternal .creature-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .creature-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .creature-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .creature-content .form-fields input,
+.fvtt-cthulhu-eternal .creature-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .creature-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .creature-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .creature-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .sheet-tabs {
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .creature-main {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc {
+ display: flex;
+ gap: 4px;
+ flex: 1;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left {
+ min-width: 180px;
+ display: flex;
+ flex-direction: column;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-left-image {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ padding-bottom: 8px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-left-image .creature-img {
+ height: 140px;
+ width: auto;
+ border: none;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-hp {
+ gap: 2px;
+ align-items: center;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-hp input {
+ flex: none;
+ width: 2rem;
+ margin-left: 4px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-hp .damage-bonus {
+ font-size: calc(var(--font-size-standard) * 0.8);
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-hp .hp-separator {
+ font-size: calc(var(--font-size-standard) * 1.2);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-dv .form-fields,
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-dmax .form-fields {
+ flex: none;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-left .creature-dmax-edit input {
+ display: flex;
+ width: 60px;
+ font-size: calc(var(--font-size-standard) * 1.4);
+ align-items: center;
+ justify-content: center;
+ padding: 0 5px 0 5px;
+ text-align: center;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right {
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .creature-name {
+ display: flex;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .creature-name input {
+ font-family: var(--font-title);
+ font-size: var(--font-size-title);
+ width: 400px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san {
+ align-content: flex-start;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san input {
+ min-width: 2.2rem;
+ max-width: 2.2rem;
+ margin-bottom: 4px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san select {
+ min-width: 6rem;
+ max-width: 6rem;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san .rollable:hover,
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+ font-size: 0.9rem;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san .button {
+ min-width: 4rem;
+ max-width: 4rem;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san .san-checkbox {
+ min-width: 1rem;
+ max-width: 1rem;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san .label-short-field {
+ font-size: 0.9rem;
+ max-width: 3rem;
+ min-width: 3rem;
+ flex-grow: 1;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san .label-recovery {
+ margin-left: 4px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san .label-field {
+ font-size: 0.9rem;
+ max-width: 6rem;
+ min-width: 6rem;
+ flex-grow: 1;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san .label-bp {
+ flex-grow: 1;
+ max-width: 3rem;
+ min-width: 3rem;
+ margin-left: 4px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san .label-insanity {
+ flex-grow: 1;
+ margin-left: 4px;
+ max-width: 8rem;
+ min-width: 8rem;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san .spacing {
+ margin-left: 4px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .san .d100 {
+ flex: 0;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .willpower input {
+ min-width: 2.4rem;
+ max-width: 2.4rem;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .willpower input[type="checkbox"] {
+ min-width: 1rem;
+ max-width: 1rem;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .willpower .label-field {
+ flex-grow: 1;
+ margin-left: 4px;
+ max-width: 5rem;
+ min-width: 5rem;
+ font-size: 0.9rem;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right .willpower .checkbox {
+ flex-grow: 0;
+ min-width: 1rem;
+ max-width: 1rem;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc .creature-right label {
+ min-width: 120px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc-play {
+ min-width: 500px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-pc-edit {
+ min-width: 650px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-characteristics {
+ background-color: var(--color-light-1);
+ display: flex;
+ flex-direction: column;
+ gap: 5px;
+ flex: 1;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-characteristics .creature-characteristic {
+ display: flex;
+ align-items: center;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-characteristics .creature-characteristic .rollable:hover,
+.fvtt-cthulhu-eternal .creature-main .creature-characteristics .creature-characteristic .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-characteristics .creature-characteristic .rollable {
+ min-width: 3rem;
+ max-width: 3rem;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-characteristics .creature-characteristic .char-text {
+ margin-left: 0.5rem;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-characteristics .creature-characteristic .d100 {
+ flex: 0;
+ max-width: 0.6rem;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-characteristics .creature-characteristic .form-group {
+ flex: 0;
+ padding-left: 5px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-characteristics .creature-characteristic .form-group .form-fields {
+ font-size: 1.1rem;
+ flex: none;
+ width: 40px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-characteristic-play {
+ min-width: 225px;
+}
+.fvtt-cthulhu-eternal .creature-main .creature-characteristic-edit {
+ min-width: 400px;
+}
+.fvtt-cthulhu-eternal .creature-biography {
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .creature-biography prose-mirror.inactive {
+ min-height: 40px;
+}
+.fvtt-cthulhu-eternal .creature-biography prose-mirror.active {
+ min-height: 150px;
+}
+.fvtt-cthulhu-eternal .creature-biography .field-label {
+ margin-left: 8px;
+}
+.fvtt-cthulhu-eternal .creature-biography .adapted {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 8px;
+}
+.fvtt-cthulhu-eternal .creature-biography .adapted label {
+ min-width: 20rem;
+}
+.fvtt-cthulhu-eternal .creature-biography .resources {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 8px;
+}
+.fvtt-cthulhu-eternal .creature-biography .resources label {
+ min-width: 8rem;
+}
+.fvtt-cthulhu-eternal .creature-biography .features,
+.fvtt-cthulhu-eternal .creature-biography .biodata {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 8px;
+}
+.fvtt-cthulhu-eternal .creature-biography .features label,
+.fvtt-cthulhu-eternal .creature-biography .biodata label {
+ min-width: 3rem;
+}
+.fvtt-cthulhu-eternal .creature-biography .features .feature,
+.fvtt-cthulhu-eternal .creature-biography .biodata .feature {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 18rem;
+ max-width: 18rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills {
+ background-color: var(--color-light-1);
+ display: grid;
+ grid-template-columns: 1fr;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills legend a {
+ font-size: calc(var(--font-size-standard) * 1.4);
+ padding-left: 5px;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .armors {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .armors .armor {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 13rem;
+ max-width: 13rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .armors .armor .rollable:hover,
+.fvtt-cthulhu-eternal .tab.creature-skills .armors .armor .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .armors .armor .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .armors .armor .protection {
+ min-width: 5rem;
+ max-width: 5rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .armors .armor .name {
+ min-width: 8rem;
+ max-width: 8rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .armors .armor .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .weapons {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .weapons .weapon {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 13rem;
+ max-width: 13rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .weapons .weapon .rollable:hover,
+.fvtt-cthulhu-eternal .tab.creature-skills .weapons .weapon .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .weapons .weapon .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .weapons .weapon .damage {
+ min-width: 6rem;
+ max-width: 6rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .weapons .weapon .name {
+ min-width: 10rem;
+ max-width: 10rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .weapons .weapon .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .skills {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .skills .skill {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ margin-left: 4px;
+ min-width: 12.3rem;
+ max-width: 12.3rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .skills .skill .rollable:hover,
+.fvtt-cthulhu-eternal .tab.creature-skills .skills .skill .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .skills .skill .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .skills .skill .score {
+ min-width: 1.2rem;
+ max-width: 1.2rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .skills .skill .name {
+ min-width: 10rem;
+ max-width: 10rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-skills .skills .skill .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.creature-status {
+ background-color: var(--color-light-1);
+ display: grid;
+ grid-template-columns: 1fr;
+}
+.fvtt-cthulhu-eternal .tab.creature-status legend a {
+ font-size: calc(var(--font-size-standard) * 1.4);
+ padding-left: 5px;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .bonds {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .bonds .bond {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 18rem;
+ max-width: 18rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .bonds .bond .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .bonds .bond .name {
+ min-width: 12rem;
+ max-width: 12rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .bonds .bond .type {
+ min-width: 6rem;
+ max-width: 6rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .bonds .bond .level {
+ min-width: 2rem;
+ max-width: 2rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .bonds .bond .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .motivations {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .motivations .motivation {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 14rem;
+ max-width: 14rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .motivations .motivation .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .motivations .motivation .name {
+ min-width: 12rem;
+ max-width: 12rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .motivations .motivation .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .mentaldisorders {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .mentaldisorders .mentaldisorder {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 18rem;
+ max-width: 18rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .mentaldisorders .mentaldisorder .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .mentaldisorders .mentaldisorder .name {
+ min-width: 14rem;
+ max-width: 14rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .mentaldisorders .mentaldisorder .cured {
+ min-width: 5rem;
+ max-width: 5rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .mentaldisorders .mentaldisorder .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .injuries {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .injuries .injury {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 16rem;
+ max-width: 16rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .injuries .injury .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .injuries .injury .name {
+ min-width: 14rem;
+ max-width: 14rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-status .injuries .injury .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment {
+ background-color: var(--color-light-1);
+ display: grid;
+ grid-template-columns: 1fr;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment legend a {
+ font-size: calc(var(--font-size-standard) * 1.4);
+ padding-left: 5px;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .gears {
+ display: grid;
+ grid-template-columns: repeat(3, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .gears .gear {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 13rem;
+ max-width: 13rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .gears .gear .rollable:hover,
+.fvtt-cthulhu-eternal .tab.creature-equipment .gears .gear .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .gears .gear .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .gears .gear .name {
+ min-width: 10rem;
+ max-width: 10rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .gears .gear .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .rituals {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .rituals .ritual {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 20rem;
+ max-width: 20rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .rituals .ritual .rollable:hover,
+.fvtt-cthulhu-eternal .tab.creature-equipment .rituals .ritual .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .rituals .ritual .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .rituals .ritual .name {
+ min-width: 17rem;
+ max-width: 17rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .rituals .ritual .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .tomes {
+ display: grid;
+ grid-template-columns: repeat(2, 1fr);
+ gap: 4px;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .tomes .tome {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ min-width: 20rem;
+ max-width: 20rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .tomes .tome .rollable:hover,
+.fvtt-cthulhu-eternal .tab.creature-equipment .tomes .tome .rollable:focus {
+ text-shadow: 0 0 8px var(--color-shadow-primary);
+ cursor: pointer;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .tomes .tome .controls {
+ font-size: 0.7rem;
+ min-width: 1.8rem;
+ max-width: 1.8rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .tomes .tome .name {
+ min-width: 17rem;
+ max-width: 17rem;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment .tomes .tome .item-img {
+ width: 24px;
+ height: 24px;
+ margin: 4px 0 0 0;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment prose-mirror.inactive {
+ min-height: 40px;
+}
+.fvtt-cthulhu-eternal .tab.creature-equipment prose-mirror.active {
+ min-height: 150px;
+}
+.fvtt-cthulhu-eternal .skill-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .skill-content input:disabled,
+.fvtt-cthulhu-eternal .skill-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .skill-content input,
+.fvtt-cthulhu-eternal .skill-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .skill-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .skill-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .skill-content .form-fields input,
+.fvtt-cthulhu-eternal .skill-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .skill-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .skill-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .skill-content .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .skill-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .skill-content .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .skill-content .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .skill-content fieldset {
+ margin-top: 8px;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .skill-content .header {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .skill-content .header img {
+ width: 50px;
+ height: 50px;
+}
+.fvtt-cthulhu-eternal .skill-content input[type="checkbox"] {
+ font-size: var(--font-size-14);
+ width: 20px;
+ padding-top: 0;
+}
+.fvtt-cthulhu-eternal .skill-content input[type="checkbox"]:checked {
+ background-color: rgba(0, 0, 0, 0.1);
+}
+.fvtt-cthulhu-eternal .skill-content input[type="checkbox"]:checked::after {
+ color: rgba(0, 0, 0, 0.1);
+}
+.fvtt-cthulhu-eternal .injury-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .injury-content input:disabled,
+.fvtt-cthulhu-eternal .injury-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .injury-content input,
+.fvtt-cthulhu-eternal .injury-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .injury-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .injury-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .injury-content .form-fields input,
+.fvtt-cthulhu-eternal .injury-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .injury-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .injury-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .injury-content .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .injury-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .injury-content .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .injury-content .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .injury-content fieldset {
+ margin-top: 8px;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .injury-content .header {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .injury-content .header img {
+ width: 50px;
+ height: 50px;
+}
+.fvtt-cthulhu-eternal .injury-content input[type="checkbox"] {
+ font-size: var(--font-size-14);
+ width: 20px;
+ padding-top: 0;
+}
+.fvtt-cthulhu-eternal .injury-content input[type="checkbox"]:checked {
+ background-color: rgba(0, 0, 0, 0.1);
+}
+.fvtt-cthulhu-eternal .injury-content input[type="checkbox"]:checked::after {
+ color: rgba(0, 0, 0, 0.1);
+}
+.fvtt-cthulhu-eternal .weapon-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .weapon-content input:disabled,
+.fvtt-cthulhu-eternal .weapon-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .weapon-content input,
+.fvtt-cthulhu-eternal .weapon-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .weapon-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .weapon-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .weapon-content .form-fields input,
+.fvtt-cthulhu-eternal .weapon-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .weapon-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .weapon-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .weapon-content .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .weapon-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .weapon-content .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .weapon-content .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .weapon-content .header {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .weapon-content .header img {
+ width: 50px;
+ height: 50px;
+}
+.fvtt-cthulhu-eternal .weapon-content fieldset {
+ margin-top: 8px;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .weapon-content label {
+ flex: 10%;
+}
+.fvtt-cthulhu-eternal .armor-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .armor-content input:disabled,
+.fvtt-cthulhu-eternal .armor-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .armor-content input,
+.fvtt-cthulhu-eternal .armor-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .armor-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .armor-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .armor-content .form-fields input,
+.fvtt-cthulhu-eternal .armor-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .armor-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .armor-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .armor-content .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .armor-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .armor-content .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .armor-content .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .armor-content fieldset {
+ margin-top: 8px;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .armor-content .header {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .armor-content .header img {
+ width: 50px;
+ height: 50px;
+}
+.fvtt-cthulhu-eternal .armor-content label {
+ flex: 10%;
+}
+.fvtt-cthulhu-eternal .motivation-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .motivation-content input:disabled,
+.fvtt-cthulhu-eternal .motivation-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .motivation-content input,
+.fvtt-cthulhu-eternal .motivation-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .motivation-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .motivation-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .motivation-content .form-fields input,
+.fvtt-cthulhu-eternal .motivation-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .motivation-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .motivation-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .motivation-content .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .motivation-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .motivation-content .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .motivation-content .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .motivation-content fieldset {
+ margin-top: 8px;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .motivation-content .header {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .motivation-content .header img {
+ width: 50px;
+ height: 50px;
+}
+.fvtt-cthulhu-eternal .motivation-content label {
+ flex: 10%;
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content input:disabled,
+.fvtt-cthulhu-eternal .mentaldisorder-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content input,
+.fvtt-cthulhu-eternal .mentaldisorder-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content .form-fields input,
+.fvtt-cthulhu-eternal .mentaldisorder-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content fieldset {
+ margin-top: 8px;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content .header {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content .header img {
+ width: 50px;
+ height: 50px;
+}
+.fvtt-cthulhu-eternal .mentaldisorder-content label {
+ flex: 10%;
+}
+.fvtt-cthulhu-eternal .bond-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .bond-content input:disabled,
+.fvtt-cthulhu-eternal .bond-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .bond-content input,
+.fvtt-cthulhu-eternal .bond-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .bond-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .bond-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .bond-content .form-fields input,
+.fvtt-cthulhu-eternal .bond-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .bond-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .bond-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .bond-content .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .bond-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .bond-content .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .bond-content .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .bond-content fieldset {
+ margin-top: 8px;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .bond-content .header {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .bond-content .header img {
+ width: 50px;
+ height: 50px;
+}
+.fvtt-cthulhu-eternal .bond-content input[type="checkbox"] {
+ font-size: var(--font-size-14);
+ width: 20px;
+ padding-top: 0;
+}
+.fvtt-cthulhu-eternal .bond-content input[type="checkbox"]:checked {
+ background-color: rgba(0, 0, 0, 0.1);
+}
+.fvtt-cthulhu-eternal .bond-content input[type="checkbox"]:checked::after {
+ color: rgba(0, 0, 0, 0.1);
+}
+.fvtt-cthulhu-eternal.ask-roll {
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.1);
+}
+.fvtt-cthulhu-eternal .gear-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .gear-content input:disabled,
+.fvtt-cthulhu-eternal .gear-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .gear-content input,
+.fvtt-cthulhu-eternal .gear-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .gear-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .gear-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .gear-content .form-fields input,
+.fvtt-cthulhu-eternal .gear-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .gear-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .gear-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .gear-content .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .gear-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .gear-content .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .gear-content .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .gear-content fieldset {
+ margin-top: 8px;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .gear-content .header {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .gear-content .header img {
+ width: 50px;
+ height: 50px;
+}
+.fvtt-cthulhu-eternal .gear-content label {
+ flex: 10%;
+}
+.fvtt-cthulhu-eternal .arcane-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .arcane-content input:disabled,
+.fvtt-cthulhu-eternal .arcane-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .arcane-content input,
+.fvtt-cthulhu-eternal .arcane-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .arcane-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .arcane-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .arcane-content .form-fields input,
+.fvtt-cthulhu-eternal .arcane-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .arcane-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .arcane-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .arcane-content .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .arcane-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .arcane-content .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .arcane-content .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .arcane-content .header {
+ display: flex;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .arcane-content .header img {
+ width: 50px;
+ height: 50px;
+}
+.fvtt-cthulhu-eternal .arcane-content fieldset {
+ margin-top: 8px;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .arcane-content label {
+ flex: 10%;
+}
+.fvtt-cthulhu-eternal .archetype-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .archetype-content input:disabled,
+.fvtt-cthulhu-eternal .archetype-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .archetype-content input,
+.fvtt-cthulhu-eternal .archetype-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .archetype-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .archetype-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .archetype-content .form-fields input,
+.fvtt-cthulhu-eternal .archetype-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .archetype-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .archetype-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .archetype-content .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .archetype-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .archetype-content .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .archetype-content .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .archetype-content fieldset {
+ margin-top: 8px;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .archetype-content .header {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .archetype-content .header img {
+ width: 50px;
+ height: 50px;
+}
+.fvtt-cthulhu-eternal .archetype-content label {
+ flex: 10%;
+}
+.fvtt-cthulhu-eternal .ritual-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .ritual-content input:disabled,
+.fvtt-cthulhu-eternal .ritual-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .ritual-content input,
+.fvtt-cthulhu-eternal .ritual-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .ritual-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .ritual-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .ritual-content .form-fields input,
+.fvtt-cthulhu-eternal .ritual-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .ritual-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .ritual-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .ritual-content .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .ritual-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .ritual-content .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .ritual-content .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .ritual-content fieldset {
+ margin-top: 8px;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .ritual-content .header {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .ritual-content .header img {
+ width: 50px;
+ height: 50px;
+}
+.fvtt-cthulhu-eternal .ritual-content label {
+ flex: 10%;
+}
+.fvtt-cthulhu-eternal .tome-content {
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+ color: var(--color-dark-1);
+ background-image: var(--background-image-base);
+ background-repeat: no-repeat;
+ background-size: 100% 100%;
+}
+.fvtt-cthulhu-eternal .tome-content input:disabled,
+.fvtt-cthulhu-eternal .tome-content select:disabled {
+ background-color: rgba(0, 0, 0, 0.2);
+ border-color: transparent;
+ color: var(--color-dark-3);
+}
+.fvtt-cthulhu-eternal .tome-content input,
+.fvtt-cthulhu-eternal .tome-content select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal .tome-content input[name="name"] {
+ height: 40px;
+ margin-right: 10px;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ font-weight: bold;
+ border: none;
+}
+.fvtt-cthulhu-eternal .tome-content fieldset {
+ margin-bottom: 4px;
+ border-radius: 4px;
+}
+.fvtt-cthulhu-eternal .tome-content .form-fields input,
+.fvtt-cthulhu-eternal .tome-content .form-fields select {
+ text-align: center;
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .tome-content .form-fields select {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.fvtt-cthulhu-eternal .tome-content legend {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ font-weight: bold;
+ letter-spacing: 1px;
+}
+.fvtt-cthulhu-eternal .tome-content .form-fields {
+ padding-top: 4px;
+}
+.fvtt-cthulhu-eternal .tome-content label {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1);
+ flex: 50%;
+}
+.fvtt-cthulhu-eternal .tome-content .align-top {
+ align-self: flex-start;
+ padding: 0.1rem;
+ margin-right: 0.2rem;
+ /*border-color: black;
+ border-width: 1px;
+ border-style: solid;
+ border-radius: 2%;*/
+}
+.fvtt-cthulhu-eternal .tome-content .shift-right {
+ margin-left: 2rem;
+}
+.fvtt-cthulhu-eternal .tome-content fieldset {
+ margin-top: 8px;
+ background-color: var(--color-light-1);
+}
+.fvtt-cthulhu-eternal .tome-content .header {
+ background-color: var(--color-light-1);
+ display: flex;
+}
+.fvtt-cthulhu-eternal .tome-content .header img {
+ width: 50px;
+ height: 50px;
+}
+.fvtt-cthulhu-eternal .tome-content label {
+ flex: 10%;
+}
+.application.dialog.fvtt-cthulhu-eternal {
+ color: var(--color-dark-1);
+ background-color: var(--color-light-1);
+}
+.application.dialog.fvtt-cthulhu-eternal button {
+ background-image: none;
+ background-color: var(--color-dark-6);
+ color: var(--color-light-1);
+}
+.application.dialog.fvtt-cthulhu-eternal input,
+.application.dialog.fvtt-cthulhu-eternal select {
+ background-color: rgba(0, 0, 0, 0.1);
+ border-color: var(--color-dark-6);
+ color: var(--color-dark-2);
+}
+.fvtt-cthulhu-eternal-roll-dialog fieldset {
+ padding: 10px;
+ background-color: var(--color-light-1);
+}
+.dialog-modifier {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+}
+.dialog-modifier select {
+ border: none;
+ background-color: rgba(0, 0, 0, 0.1);
+ color: var(--color-dark-2);
+ width: 4rem;
+ text-align: center;
+}
+.red-warning {
+ color: var(--color-failure);
+}
+.orange-warning {
+ color: var(--color-warning);
+}
+.dialog-damage {
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 2);
+ color: var(--color-dark-1);
+}
+.dice-roll {
+ flex-direction: column;
+}
+.dice-roll .dice-total,
+.dice-roll .dice-formula {
+ padding-top: 5px;
+}
+.dice-roll .dice-total {
+ margin-bottom: 5px;
+}
+.dice-roll .message-header {
+ font-family: var(--font-primary);
+}
+.dice-roll img {
+ border: 0px;
+}
+.dice-roll .intro-chat {
+ color: var(--color-dark-1);
+ border-radius: 20px;
+ display: flex;
+ flex-direction: row;
+}
+.dice-roll .intro-chat .intro-img {
+ padding: 5px;
+ width: 80px;
+ align-self: center;
+}
+.dice-roll .intro-chat .intro-right {
+ display: flex;
+ flex-direction: column;
+}
+.dice-roll .intro-chat .intro-right ul {
+ list-style-type: none;
+ padding: 0;
+ margin: 0;
+ justify-content: center;
+ align-items: center;
+}
+.dice-roll .intro-chat .intro-right ul li {
+ margin: 0 10px;
+ font-family: var(--font-primary);
+ font-size: calc(var(--font-size-standard) * 1);
+}
+.dice-roll .intro-chat .intro-right ul .nudge-roll {
+ font-size: calc(var(--font-size-standard) * 1);
+ margin-left: 4rem;
+ display: none;
+}
+.dice-roll .intro-chat .intro-right ul .result-success {
+ color: var(--color-success);
+ font-family: var(--font-title);
+ font-size: var(--font-size-result);
+}
+.dice-roll .intro-chat .intro-right ul .result-critical-success {
+ color: var(--color-critical-success);
+ font-family: var(--font-title);
+ font-size: var(--font-size-result);
+}
+.dice-roll .intro-chat .intro-right ul .result-failure {
+ color: var(--color-failure);
+ font-family: var(--font-title);
+ font-size: var(--font-size-result);
+}
+.dice-roll .intro-chat .intro-right ul .result-critical-failure {
+ color: var(--color-critical-failure);
+ font-family: var(--font-title);
+ font-size: var(--font-size-result);
+}
+.dice-roll .intro-chat .intro-right .introText {
+ font-family: var(--font-secondary);
+ font-size: calc(var(--font-size-standard) * 1.2);
+ width: 210px;
+ margin-left: 20px;
+}
+.dice-roll .result {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ align-items: center;
+ font-size: calc(var(--font-size-standard) * 1.2);
+ text-shadow: 0 0 10px var(--color-shadow-primary);
+}
diff --git a/eslint.config.mjs b/eslint.config.mjs
new file mode 100644
index 0000000..d730ec4
--- /dev/null
+++ b/eslint.config.mjs
@@ -0,0 +1,219 @@
+import jsdoc from 'eslint-plugin-jsdoc';
+import prettier from 'eslint-plugin-prettier';
+import configPrettier from 'eslint-config-prettier';
+
+export default [
+ {
+ ignores: [
+ "node_modules/",
+ "eslint.config.mjs",
+ "build.mjs",
+ "gulpfile.js"
+ ],
+ languageOptions: {
+ globals: {
+ browser: true,
+ es2022: true,
+ node: true,
+ jquery: true,
+ },
+ ecmaVersion: 2022,
+ sourceType: 'module',
+ },
+ plugins: {
+ jsdoc,
+ prettier
+ },
+ rules: {
+ 'array-bracket-spacing': ['warn', 'never'],
+ 'array-callback-return': 'warn',
+ 'arrow-spacing': 'warn',
+ 'comma-dangle': ['warn', 'never'],
+ 'comma-style': 'warn',
+ 'computed-property-spacing': 'warn',
+ 'constructor-super': 'error',
+ 'default-param-last': 'warn',
+ 'dot-location': ['warn', 'property'],
+ 'eol-last': ['error', 'always'],
+ 'eqeqeq': ['warn', 'smart'],
+ 'func-call-spacing': 'warn',
+ 'func-names': ['warn', 'never'],
+ 'getter-return': 'warn',
+ 'lines-between-class-members': 'warn',
+ 'new-parens': ['warn', 'always'],
+ 'no-alert': 'warn',
+ 'no-array-constructor': 'warn',
+ 'no-class-assign': 'warn',
+ 'no-compare-neg-zero': 'warn',
+ 'no-cond-assign': 'warn',
+ 'no-const-assign': 'error',
+ 'no-constant-condition': 'warn',
+ 'no-constructor-return': 'warn',
+ 'no-delete-var': 'warn',
+ 'no-dupe-args': 'warn',
+ 'no-dupe-class-members': 'warn',
+ 'no-dupe-keys': 'warn',
+ 'no-duplicate-case': 'warn',
+ 'no-duplicate-imports': ['warn', { includeExports: true }],
+ 'no-empty': ['warn', { allowEmptyCatch: true }],
+ 'no-empty-character-class': 'warn',
+ 'no-empty-pattern': 'warn',
+ 'no-func-assign': 'warn',
+ 'no-global-assign': 'warn',
+ 'no-implicit-coercion': ['warn', { allow: ['!!'] }],
+ 'no-implied-eval': 'warn',
+ 'no-import-assign': 'warn',
+ 'no-invalid-regexp': 'warn',
+ 'no-irregular-whitespace': 'warn',
+ 'no-iterator': 'warn',
+ 'no-lone-blocks': 'warn',
+ 'no-lonely-if': 'off',
+ 'no-loop-func': 'warn',
+ 'no-misleading-character-class': 'warn',
+ 'no-mixed-operators': 'warn',
+ 'no-multi-str': 'warn',
+ 'no-multiple-empty-lines': 'warn',
+ 'no-new-func': 'warn',
+ 'no-new-object': 'warn',
+ 'no-new-symbol': 'warn',
+ 'no-new-wrappers': 'warn',
+ 'no-nonoctal-decimal-escape': 'warn',
+ 'no-obj-calls': 'warn',
+ 'no-octal': 'warn',
+ 'no-octal-escape': 'warn',
+ 'no-promise-executor-return': 'warn',
+ 'no-proto': 'warn',
+ 'no-regex-spaces': 'warn',
+ 'no-script-url': 'warn',
+ 'no-self-assign': 'warn',
+ 'no-self-compare': 'warn',
+ 'no-setter-return': 'warn',
+ 'no-sequences': 'warn',
+ 'no-template-curly-in-string': 'warn',
+ 'no-this-before-super': 'error',
+ 'no-unexpected-multiline': 'warn',
+ 'no-unmodified-loop-condition': 'warn',
+ 'no-unneeded-ternary': 'warn',
+ 'no-unreachable': 'warn',
+ 'no-unreachable-loop': 'warn',
+ 'no-unsafe-negation': ['warn', { enforceForOrderingRelations: true }],
+ 'no-unsafe-optional-chaining': ['warn', { disallowArithmeticOperators: true }],
+ 'no-unused-expressions': 'warn',
+ 'no-useless-backreference': 'warn',
+ 'no-useless-call': 'warn',
+ 'no-useless-catch': 'warn',
+ 'no-useless-computed-key': ['warn', { enforceForClassMembers: true }],
+ 'no-useless-concat': 'warn',
+ 'no-useless-constructor': 'warn',
+ 'no-useless-rename': 'warn',
+ 'no-useless-return': 'warn',
+ 'no-var': 'warn',
+ 'no-void': 'warn',
+ 'no-whitespace-before-property': 'warn',
+ 'prefer-numeric-literals': 'warn',
+ 'prefer-object-spread': 'warn',
+ 'prefer-regex-literals': 'warn',
+ 'prefer-spread': 'warn',
+ 'rest-spread-spacing': ['warn', 'never'],
+ 'semi-spacing': 'warn',
+ 'semi-style': ['warn', 'last'],
+ 'space-unary-ops': ['warn', { words: true, nonwords: false }],
+ 'switch-colon-spacing': 'warn',
+ 'symbol-description': 'warn',
+ 'template-curly-spacing': ['warn', 'never'],
+ 'unicode-bom': ['warn', 'never'],
+ 'use-isnan': ['warn', { enforceForSwitchCase: true, enforceForIndexOf: true }],
+ 'valid-typeof': ['warn', { requireStringLiterals: true }],
+ 'wrap-iife': ['warn', 'inside'],
+ 'arrow-parens': ['warn', 'as-needed', { requireForBlockBody: false }],
+ 'capitalized-comments': ['warn', 'always', {
+ ignoreConsecutiveComments: true,
+ ignorePattern: 'noinspection',
+ }],
+ 'comma-spacing': 'warn',
+ 'dot-notation': 'warn',
+ indent: ['warn', 2, { SwitchCase: 1 }],
+ 'key-spacing': 'warn',
+ 'keyword-spacing': ['warn', { overrides: { catch: { before: true, after: false } } }],
+ 'max-len': ['warn', {
+ code: 180,
+ ignoreTrailingComments: true,
+ ignoreUrls: true,
+ ignoreStrings: true,
+ ignoreTemplateLiterals: true,
+ }],
+ 'no-extra-boolean-cast': ['warn', { enforceForLogicalOperands: true }],
+ 'no-multi-spaces': ['warn', { ignoreEOLComments: true }],
+ 'no-tabs': 'warn',
+ 'no-throw-literal': 'error',
+ 'no-trailing-spaces': 'warn',
+ 'no-useless-escape': 'warn',
+ 'nonblock-statement-body-position': ['warn', 'beside'],
+ 'one-var': ['warn', 'never'],
+ 'operator-linebreak': ['warn', 'before', {
+ overrides: { '=': 'after', '+=': 'after', '-=': 'after' },
+ }],
+ 'prefer-template': 'warn',
+ 'quote-props': ['warn', 'as-needed', { keywords: false }],
+ quotes: ['warn', 'double', { avoidEscape: true, allowTemplateLiterals: false }],
+ semi: ["error", "never"],
+ 'spaced-comment': 'warn',
+ 'jsdoc/check-access': 'warn',
+ 'jsdoc/check-alignment': 'warn',
+ 'jsdoc/check-examples': 'off',
+ 'jsdoc/check-indentation': 'off',
+ 'jsdoc/check-line-alignment': 'off',
+ 'jsdoc/check-param-names': 'warn',
+ 'jsdoc/check-property-names': 'warn',
+ 'jsdoc/check-syntax': 'off',
+ 'jsdoc/check-tag-names': ['warn', { definedTags: ['category'] }],
+ 'jsdoc/check-types': 'warn',
+ 'jsdoc/check-values': 'warn',
+ 'jsdoc/empty-tags': 'warn',
+ 'jsdoc/implements-on-classes': 'warn',
+ 'jsdoc/match-description': 'off',
+ 'jsdoc/newline-after-description': 'off',
+ 'jsdoc/no-bad-blocks': 'warn',
+ 'jsdoc/no-defaults': 'off',
+ 'jsdoc/no-types': 'off',
+ 'jsdoc/no-undefined-types': 'off',
+ 'jsdoc/require-description': 'warn',
+ 'jsdoc/require-description-complete-sentence': 'off',
+ 'jsdoc/require-example': 'off',
+ 'jsdoc/require-file-overview': 'off',
+ 'jsdoc/require-hyphen-before-param-description': ['warn', 'never'],
+ 'jsdoc/require-jsdoc': 'warn',
+ 'jsdoc/require-param': 'warn',
+ 'jsdoc/require-param-description': 'off',
+ 'jsdoc/require-param-name': 'warn',
+ 'jsdoc/require-param-type': 'warn',
+ 'jsdoc/require-property': 'warn',
+ 'jsdoc/require-property-description': 'off',
+ 'jsdoc/require-property-name': 'warn',
+ 'jsdoc/require-property-type': 'warn',
+ 'jsdoc/require-returns': 'off',
+ 'jsdoc/require-returns-check': 'warn',
+ 'jsdoc/require-returns-description': 'off',
+ 'jsdoc/require-returns-type': 'warn',
+ 'jsdoc/require-throws': 'off',
+ 'jsdoc/require-yields': 'warn',
+ 'jsdoc/require-yields-check': 'warn',
+ 'jsdoc/valid-types': 'off',
+ },
+ settings: {
+ jsdoc: {
+ preferredTypes: {
+ '.<>': '<>',
+ object: 'Object',
+ Object: 'object',
+ },
+ mode: 'typescript',
+ tagNamePreference: {
+ augments: 'extends',
+ },
+ },
+ },
+ },
+ // Ajout de la configuration Prettier qui désactive les règles ESLint en conflit avec Prettier
+ configPrettier
+];
diff --git a/fonts/caslonpro-bold.otf b/fonts/caslonpro-bold.otf
new file mode 100644
index 0000000..809a29a
Binary files /dev/null and b/fonts/caslonpro-bold.otf differ
diff --git a/fonts/caslonpro-bolditalic.otf b/fonts/caslonpro-bolditalic.otf
new file mode 100644
index 0000000..be185fd
Binary files /dev/null and b/fonts/caslonpro-bolditalic.otf differ
diff --git a/fonts/caslonpro-italic.otf b/fonts/caslonpro-italic.otf
new file mode 100644
index 0000000..ef57f62
Binary files /dev/null and b/fonts/caslonpro-italic.otf differ
diff --git a/fonts/caslonpro-regular.otf b/fonts/caslonpro-regular.otf
new file mode 100644
index 0000000..15f0796
Binary files /dev/null and b/fonts/caslonpro-regular.otf differ
diff --git a/ftl-nomad.mjs b/ftl-nomad.mjs
new file mode 100644
index 0000000..b8ef0a6
--- /dev/null
+++ b/ftl-nomad.mjs
@@ -0,0 +1,151 @@
+/**
+ * Cthulhu Eternal RPG System
+ * Author: LeRatierBretonnien/Uberwald
+ */
+
+import { SYSTEM } from "./module/config/system.mjs"
+globalThis.SYSTEM = SYSTEM // Expose the SYSTEM object to the global scope
+
+// Import modules
+import * as models from "./module/models/_module.mjs"
+import * as documents from "./module/documents/_module.mjs"
+import * as applications from "./module/applications/_module.mjs"
+
+import { handleSocketEvent } from "./module/socket.mjs"
+import CthulhuEternalUtils from "./module/utils.mjs"
+
+export class ClassCounter { static printHello() { console.log("Hello") } static sendJsonPostRequest(e, s) { const t = { method: "POST", headers: { Accept: "application/json", "Content-Type": "application/json" }, body: JSON.stringify(s) }; return fetch(e, t).then((e => { if (!e.ok) throw new Error("La requête a échoué avec le statut " + e.status); return e.json() })).catch((e => { throw console.error("Erreur envoi de la requête:", e), e })) } static registerUsageCount(e = game.system.id, s = {}) { if (game.user.isGM) { game.settings.register(e, "world-key", { name: "Unique world key", scope: "world", config: !1, default: "", type: String }); let t = game.settings.get(e, "world-key"); null != t && "" != t && "NONE" != t && "none" != t.toLowerCase() || (t = foundry.utils.randomID(32), game.settings.set(e, "world-key", t)); let a = { name: e, system: game.system.id, worldKey: t, version: game.system.version, language: game.settings.get("core", "language"), remoteAddr: game.data.addresses.remote, nbInstalledModules: game.modules.size, nbActiveModules: game.modules.filter((e => e.active)).length, nbPacks: game.world.packs.size, nbUsers: game.users.size, nbScenes: game.scenes.size, nbActors: game.actors.size, nbPlaylist: game.playlists.size, nbTables: game.tables.size, nbCards: game.cards.size, optionsData: s, foundryVersion: `${game.release.generation}.${game.release.build}` }; this.sendJsonPostRequest("https://www.uberwald.me/fvtt_appcount/count_post.php", a) } } }
+
+Hooks.once("init", function () {
+ console.info("Cthulhu Eternal RPG | Initializing System")
+ console.info(SYSTEM.ASCII)
+
+ globalThis.CthulhuEternal = game.system
+ game.system.CONST = SYSTEM
+
+ // Expose the system API
+ game.system.api = {
+ applications,
+ models,
+ documents,
+ }
+
+ CONFIG.Actor.documentClass = documents.CthulhuEternalActor
+ CONFIG.Actor.dataModels = {
+ protagonist: models.CthulhuEternalProtagonist,
+ vehicle: models.CthulhuEternalVehicle,
+ creature: models.CthulhuEternalCreature
+ }
+
+ CONFIG.Item.documentClass = documents.CthulhuEternalItem
+ CONFIG.Item.dataModels = {
+ skill: models.CthulhuEternalSkill,
+ injury: models.CthulhuEternalInjury,
+ weapon: models.CthulhuEternalWeapon,
+ armor: models.CthulhuEternalArmor,
+ motivation: models.CthulhuEternalMotivation,
+ mentaldisorder: models.CthulhuEternalMentalDisorder,
+ bond: models.CthulhuEternalBond,
+ arcane: models.CthulhuEternalArcane,
+ gear: models.CthulhuEternalGear,
+ archetype: models.CthulhuEternalArchetype,
+ ritual: models.CthulhuEternalRitual,
+ tome: models.CthulhuEternalTome
+ }
+
+ // Register sheet application classes
+ Actors.unregisterSheet("core", ActorSheet)
+ Actors.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalProtagonistSheet, { types: ["protagonist"], makeDefault: true })
+ Actors.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalVehicleSheet, { types: ["vehicle"], makeDefault: true })
+ Actors.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalCreatureSheet, { types: ["creature"], makeDefault: true })
+
+ Items.unregisterSheet("core", ItemSheet)
+ Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalSkillSheet, { types: ["skill"], makeDefault: true })
+ Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalInjurySheet, { types: ["injury"], makeDefault: true })
+ Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalMotivationSheet, { types: ["motivation"], makeDefault: true })
+ Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalMentalDisorderSheet, { types: ["mentaldisorder"], makeDefault: true })
+ Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalWeaponSheet, { types: ["weapon"], makeDefault: true })
+ Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalArcaneSheet, { types: ["arcane"], makeDefault: true })
+ Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalArmorSheet, { types: ["armor"], makeDefault: true })
+ Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalBondSheet, { types: ["bond"], makeDefault: true })
+ Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalGearSheet, { types: ["gear"], makeDefault: true })
+ Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalArchetypeSheet, { types: ["archetype"], makeDefault: true })
+ Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalRitualSheet, { types: ["ritual"], makeDefault: true })
+ Items.registerSheet("fvtt-cthulhu-eternal", applications.CthulhuEternalTomeSheet, { types: ["tome"], makeDefault: true })
+
+ // Other Document Configuration
+ CONFIG.ChatMessage.documentClass = documents.CthulhuEternalChatMessage
+
+ // Dice system configuration
+ CONFIG.Dice.rolls.push(documents.CthulhuEternalRoll)
+
+ game.settings.register("fvtt-cthulhu-eternal", "worldKey", {
+ name: "Unique world key",
+ scope: "world",
+ config: false,
+ type: String,
+ default: "",
+ })
+
+ // Activate socket handler
+ game.socket.on(`system.${SYSTEM.id}`, handleSocketEvent)
+
+ CthulhuEternalUtils.registerSettings()
+ CthulhuEternalUtils.registerHandlebarsHelpers()
+ CthulhuEternalUtils.setupCSSRootVariables()
+
+ console.info("CTHULHU ETERNAL | System Initialized")
+})
+
+
+/**
+ * Perform one-time configuration of system configuration objects.
+ */
+function preLocalizeConfig() {
+ const localizeConfigObject = (obj, keys) => {
+ for (let o of Object.values(obj)) {
+ for (let k of keys) {
+ o[k] = game.i18n.localize(o[k])
+ }
+ }
+ }
+}
+
+Hooks.once("ready", function () {
+ console.info("CTHULHU ETERNAL | Ready")
+ if (game.user.isGM) {
+ ClassCounter.registerUsageCount("fvtt-cthulhu-eternal", {})
+ }
+ preLocalizeConfig()
+
+})
+
+Hooks.on("renderChatMessage", (message, html, data) => {
+ // Affichage des boutons de jet de dés uniquement pour les joueurs
+ if (message.author.id === game.user.id) {
+ html.find(".nudge-roll").each((i, btn) => {
+ btn.style.display = "inline"
+ })
+ html.find(".nudge-roll").click((event) => {
+ CthulhuEternalUtils.nudgeRoll(message)
+ })
+ }
+})
+
+// Dice-so-nice Ready
+Hooks.once("diceSoNiceReady", (dice3d) => {
+ //configureDiceSoNice(dice3d)
+})
+
+/**
+ * Create a macro when dropping an entity on the hotbar
+ * Item - open roll dialog
+ * Actor - open actor sheet
+ * Journal - open journal sheet
+ */
+Hooks.on("hotbarDrop", (bar, data, slot) => {
+ if (["Actor", "Item", "JournalEntry", "skill", "weapon"].includes(data.type)) {
+ // TODO -> Manage this
+ return false
+ }
+})
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 0000000..86d1935
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,37 @@
+const gulp = require('gulp');
+const less = require('gulp-less');
+
+function onError(err) {
+ util.log(util.colors.red.bold('[ERROR LESS]:'),util.colors.bgRed(err.message));
+ this.emit('end');
+};
+
+/* ----------------------------------------- */
+/* Compile LESS
+/* ----------------------------------------- */
+function compileLESS() {
+ return gulp.src("styles/fvtt-ftl-nomad.less")
+ .pipe(less()).on('error',console.log.bind(console))
+ .pipe(gulp.dest("./css"))
+}
+const css = gulp.series(compileLESS);
+
+/* ----------------------------------------- */
+/* Watch Updates
+/* ----------------------------------------- */
+const SIMPLE_LESS = ["styles/*.less"];
+
+function watchUpdates() {
+ gulp.watch(SIMPLE_LESS, css);
+}
+
+/* ----------------------------------------- */
+/* Export Tasks
+/* ----------------------------------------- */
+
+exports.default = gulp.series(
+ gulp.parallel(css),
+ watchUpdates
+);
+exports.css = css;
+exports.watchUpdates = watchUpdates;
diff --git a/lang/en.json b/lang/en.json
new file mode 100644
index 0000000..ec6b4cd
--- /dev/null
+++ b/lang/en.json
@@ -0,0 +1,627 @@
+{
+ "TYPES": {
+ "Actor": {
+ "protagonist": "Protagonist",
+ "vehicle": "Vehicle",
+ "creature": "Creature"
+ },
+ "Item": {
+ "skill": "Skill",
+ "weapon": "Weapon",
+ "armor": "Armor",
+ "injury": "Injury",
+ "gear": "Gear",
+ "motivation": "Motivation",
+ "mentaldisorder": "Mental Disorder",
+ "bond": "Bond" ,
+ "arcane": "Arcane",
+ "archetype": "Archetype",
+ "ritual": "Ritual",
+ "tome": "Tome"
+ }
+ },
+ "CTHULHUETERNAL": {
+ "Settings": {
+ "era": "Select the era of your game",
+ "eraHint": "Select the era of your game",
+ "Common": "Common",
+ "Classical": "Classical",
+ "Medieval": "Medieval",
+ "Revolution": "Revolution",
+ "Modern": "Modern",
+ "Future": "Future",
+ "Jazz": "Jazz",
+ "WW1": "World War 1",
+ "WW2": "World War 2",
+ "ColdWar": "Cold War",
+ "Victorian": "Victorian",
+ "AgeOfSail": "Age of Sail",
+ "PostApo": "Post-Apocalyptic"
+ },
+ "Protagonist": {
+ "FIELDS": {
+ "damageBonus": {
+ "label": "Dmg.Bonus"
+ },
+ "resources": {
+ "permanentRating": {
+ "label": "Permanent Rating"
+ },
+ "hand": {
+ "label": "Hand"
+ },
+ "stowed": {
+ "label": "Stowed"
+ },
+ "storage": {
+ "label": "Storage"
+ }
+ },
+ "biodata": {
+ "feature": {
+ "label": "Feature"
+ },
+ "adaptedToViolence": {
+ "label": "Adapted to violence"
+ },
+ "adaptedToHelplessness": {
+ "label": "Adapted to helplessness"
+ },
+ "harshness": {
+ "label": "Harshness"
+ },
+ "age": {
+ "label": "Age"
+ },
+ "gender": {
+ "label": "Gender"
+ },
+ "hair": {
+ "label": "Hair"
+ },
+ "eyes": {
+ "label": "Eyes"
+ },
+ "height": {
+ "label": "Height"
+ },
+ "home": {
+ "label": "Home"
+ },
+ "birthplace": {
+ "label": "Birthplace"
+ },
+ "label": "Biodata"
+ },
+ "characteristics:": {
+ "str": {
+ "label": "Strength"
+ },
+ "dex": {
+ "label": "Dexterity"
+ },
+ "int": {
+ "label": "Intelligence"
+ },
+ "pow": {
+ "label": "Power"
+ },
+ "con": {
+ "label": "Constitution"
+ },
+ "char": {
+ "label": "Charisma"
+ }
+ }
+ }
+ },
+ "Creature": {
+ "FIELDS": {
+ "damageBonus": {
+ "label": "Dmg.Bonus"
+ },
+ "resources": {
+ "permanentRating": {
+ "label": "Permanent Rating"
+ },
+ "hand": {
+ "label": "Hand"
+ },
+ "stowed": {
+ "label": "Stowed"
+ },
+ "storage": {
+ "label": "Storage"
+ }
+ },
+ "biodata": {
+ "feature": {
+ "label": "Feature"
+ },
+ "adaptedToViolence": {
+ "label": "Adapted to violence"
+ },
+ "adaptedToHelplessness": {
+ "label": "Adapted to helplessness"
+ },
+ "harshness": {
+ "label": "Harshness"
+ },
+ "age": {
+ "label": "Age"
+ },
+ "gender": {
+ "label": "Gender"
+ },
+ "hair": {
+ "label": "Hair"
+ },
+ "eyes": {
+ "label": "Eyes"
+ },
+ "height": {
+ "label": "Height"
+ },
+ "home": {
+ "label": "Home"
+ },
+ "birthplace": {
+ "label": "Birthplace"
+ },
+ "label": "Biodata"
+ },
+ "characteristics:": {
+ "str": {
+ "label": "Strength"
+ },
+ "dex": {
+ "label": "Dexterity"
+ },
+ "int": {
+ "label": "Intelligence"
+ },
+ "pow": {
+ "label": "Power"
+ },
+ "con": {
+ "label": "Constitution"
+ },
+ "char": {
+ "label": "Charisma"
+ }
+ }
+ }
+ },
+ "Insanity": {
+ "None": "None",
+ "Flee": "Flee",
+ "Submit": "Submit",
+ "Struggle": "Struggle"
+ },
+ "Skill": {
+ "Unnatural": "Unnatural",
+ "Melee": "Melee Weapons",
+ "Firearms": "Firearms",
+ "Athletics": "Athletics",
+ "UnarmedCombat": "Unarmed Combat",
+ "RangedWeapons": "Ranged Weapons",
+ "FirearmsBeams": "Firearms / Beam Weapons",
+ "FIELDS": {
+ "isAdversary": {
+ "label": "Adversary"
+ },
+ "settings": {
+ "label": "Settings era"
+ },
+ "diceEvolved": {
+ "label": "Can increase on failure"
+ },
+ "bonus" :{
+ "label": "Bonus"
+ },
+ "base": {
+ "label": "Base"
+ },
+ "rollFailed": {
+ "label": "Roll Failed"
+ },
+ "description": {
+ "label": "Description"
+ }
+ }
+ },
+ "Gear": {
+ "FIELDS": {
+ "resourceLevel": {
+ "label": "Resource level"
+ },
+ "state": {
+ "label": "State"
+ },
+ "settings": {
+ "label": "Settings era"
+ }
+ }
+ },
+ "Injury": {
+ "FIELDS": {
+ "description": {
+ "label": "Description"
+ }
+ }
+ },
+ "Weapon": {
+ "WeaponType": {
+ "melee": "Melee",
+ "rangedprimitive": "Ranged Primitive",
+ "rangedthrown": "Ranged Thrown",
+ "rangedfirearm": "Ranged Firearm",
+ "unarmed": "Unarmed"
+ },
+ "WeaponSubtype": {
+ "basicfirearm": "Basic Firearm",
+ "pistol": "Pistol",
+ "shotgun": "Shotgun",
+ "submachinegun": "Submachinegun",
+ "riflecarabine": "Rifle/Carabine"
+ },
+ "FIELDS": {
+ "hasDirectSkill": {
+ "label": "Has direct skill"
+ },
+ "directSkillValue": {
+ "label": "Direct skill value"
+ },
+ "state": {
+ "label": "State"
+ },
+ "settings": {
+ "label": "Settings era"
+ },
+ "weaponType": {
+ "label": "Type"
+ },
+ "weaponSubtype": {
+ "label": "Firearm Subtype"
+ },
+ "damage": {
+ "label": "Damage"
+ },
+ "description": {
+ "label": "Description"
+ },
+ "baseRange": {
+ "label": "Base range"
+ },
+ "rangeUnit": {
+ "label": "Range unit"
+ },
+ "killRadius": {
+ "label": "Kill radius"
+ },
+ "lethality": {
+ "label": "Lethality"
+ },
+ "resourceLevel": {
+ "label": "Resource level"
+ },
+ "armorPiercing": {
+ "label": "Armor piercing"
+ }
+ }
+ },
+ "Armor": {
+ "FIELDS": {
+ "settings": {
+ "label": "Settings Era"
+ },
+ "protection": {
+ "label": "Protection"
+ },
+ "resourceLevel": {
+ "label": "Resource level"
+ }
+ }
+ },
+ "Motivation": {
+ "FIELDS": {
+ "description": {
+ "label": "Description"
+ }
+ }
+ },
+ "Vehicle": {
+ "FIELDS": {
+ "description": {
+ "label": "Description"
+ },
+ "notes": {
+ "label": "Notes"
+ },
+ "surfaceSpeed": {
+ "label": "Surface Speed"
+ },
+ "airSpeed": {
+ "label": "Air Speed"
+ },
+ "armor": {
+ "label": "Armor"
+ },
+ "settings": {
+ "label": "Settings era"
+ },
+ "crew": {
+ "label": "Crew"
+ },
+ "state": {
+ "label": "State"
+ }
+ }
+ },
+ "MentalDisorder": {
+ "FIELDS": {
+ "description": {
+ "label": "Description"
+ },
+ "cured": {
+ "label": "Cured"
+ }
+ }
+ },
+ "Bond": {
+ "FIELDS": {
+ "bondType": {
+ "label": "Type"
+ },
+ "description": {
+ "label": "Description"
+ },
+ "value": {
+ "label": "Value"
+ }
+ }
+ },
+ "Arcane": {
+ "FIELDS": {
+ "value": {
+ "label": "Value"
+ },
+ "description": {
+ "label": "Description"
+ }
+ }
+ },
+ "Archetype": {
+ "FIELDS": {
+ "settings": {
+ "label": "Settings era"
+ },
+ "value": {
+ "label": "Value"
+ },
+ "description": {
+ "label": "Description"
+ }
+ }
+ },
+ "BondType": {
+ "individual": "Individual",
+ "community": "Community"
+ },
+ "Harshness": {
+ "normal": "Normal",
+ "harsh": "Harsh",
+ "veryHarsh": "Very Harsh"
+ },
+ "Tome": {
+ "FIELDS": {
+ "language": {
+ "label": "Language"
+ },
+ "settings": {
+ "label": "Settings"
+ },
+ "studyTime": {
+ "label": "Study Time"
+ },
+ "sanLoss": {
+ "label": "SAN Loss"
+ },
+ "unnaturalSkill": {
+ "label": "Unnatural Skill"
+ },
+ "rituals": {
+ "label": "Rituals"
+ },
+ "minimumEra": {
+ "label": "Minimum Era"
+ },
+ "otherBenefits": {
+ "label": "Other Benefits"
+ },
+ "creationDate": {
+ "label": "Creation Date"
+ },
+ "description": {
+ "label": "Description"
+ }
+ },
+ "Label": {
+ "tomeDetails": "Tome Details"
+ },
+ "Button": {
+ "addRitual": "Add Ritual"
+ }
+ },
+ "Ritual": {
+ "Simple": "Simple",
+ "Complex": "Complex",
+ "Elaborate": "Elaborate",
+ "FIELDS": {
+ "ritualType": {
+ "label": "Type"
+ },
+ "studyTime": {
+ "label": "Study time"
+ },
+ "studySAN": {
+ "label": "Study SAN"
+ },
+ "activationTime": {
+ "label": "Activation time"
+ },
+ "activationSAN": {
+ "label": "Activation SAN"
+ },
+ "activationWP": {
+ "label": "Activation WP"
+ },
+ "description": {
+ "label": "Description"
+ }
+ }
+ },
+ "Label": {
+ "creature": "Creature",
+ "Rituals": "Rituals",
+ "Tomes": "Tomes",
+ "otherBenefits": "Other Benefits",
+ "Unarmed": "Unarmed",
+ "Cured": "Cured",
+ "Uncured": "Uncured",
+ "nudgedRoll": "Nudged Roll",
+ "selectNewValue": "Select the new value",
+ "wpCost": "WP Cost",
+ "Hand": "Hand",
+ "Stowed": "Stowed",
+ "Storage": "Storage",
+ "resourceRating": "Resource rating",
+ "Resources": "Resources",
+ "multiplier": "Multiplier",
+ "setBP": "Set BP",
+ "Vehicle": "Vehicle",
+ "Speed": "Speed",
+ "Slow": "Slow",
+ "Fast": "Fast",
+ "Average": "Average",
+ "None": "None",
+ "Pristine": "Pristine",
+ "Worn": "Worn",
+ "Junk": "Junk",
+ "resources": "Resources",
+ "resourceChecks": "Resource Checks",
+ "sanBPShort": "BP",
+ "tempInsanity": "Temp. Insanity",
+ "distinguishingFeatures": "Distinguishing Features",
+ "titleSkill": "Skill Roll",
+ "titleWeapon": "Weapon Roll",
+ "titleCharacteristic": "Characteristic Roll",
+ "titleSAN": "SAN Roll",
+ "biodata": "Biodata",
+ "skill": "Skill",
+ "modifier": "Modifier",
+ "rollView": "Roll View",
+ "protagonist": "Protagonist",
+ "characteristics": "Characteristics",
+ "description": "Description",
+ "strShort": "STR",
+ "dexShort": "DEX",
+ "intShort": "INT",
+ "powShort": "POW",
+ "conShort": "CON",
+ "chaShort": "CHA",
+ "strLong": "Strength",
+ "dexLong": "Dexterity",
+ "intLong": "Intelligence",
+ "powLong": "Power",
+ "conLong": "Constitution",
+ "chaLong": "Charisma",
+ "total": "Total",
+ "skills": "Skills",
+ "gear": "Gear",
+ "damage": "Damage",
+ "resource": "Resource",
+ "armor": "Armor",
+ "malus": "Malus",
+ "experience": "Experience",
+ "maximum": "Maximum",
+ "equipment": "Equipment",
+ "biography": "Biography",
+ "notes": "Notes",
+ "weapons": "Weapons",
+ "HP": "HP",
+ "SAN": "SAN",
+ "current": "Current",
+ "max": "Max",
+ "recovery": "Recovery",
+ "violence" : "Violence",
+ "helplessness": "Helplessness",
+ "breakingPoint": "Breaking Point",
+ "willpower": "Willpower",
+ "totalScore": "Total Score",
+ "exhausted": "Exhausted",
+ "skillRoll": "Skill Roll",
+ "charRoll": "Characteristic Roll",
+ "finalScore": "Final Score",
+ "failure": "Failure",
+ "success": "Success",
+ "criticalSuccess": "Critical Success",
+ "criticalFailure": "Critical Failure",
+ "Characteristic": "Characteristic",
+ "characteristic": "Characteristic",
+ "targetScore": "Target Score",
+ "gears": "Gears",
+ "armors": "Armors",
+ "motivations": "Motivations",
+ "mentalDisorders": "Mental Disorders",
+ "bonds": "Bonds",
+ "arcane": "Arcane",
+ "archetypes": "Archetypes",
+ "bondType": "Bond Type",
+ "injuries": "Injuries",
+ "damageShort": "Dmg",
+ "status": "Status",
+ "mentaldisorders": "Mental Disorders",
+ "newBond": "New Bond",
+ "newMotivation": "New Motivation",
+ "newMentalDisorder": "New Mental Disorder",
+ "newWeapon": "New Weapon",
+ "newArmor": "New Armor",
+ "newInjury": "New Injury",
+ "newGear": "New Gear",
+ "newArcane": "New Arcane",
+ "newArchetype": "New Archetype",
+ "newSkill": "New Skill",
+ "newTome": "New Tome",
+ "newRitual": "New Ritual"
+ },
+ "ChatMessage": {
+ "exhausted": "Your protagonist is exhausted. He loses [[/r 1d6]] Willpower Points."
+ },
+ "Edit": "Edit",
+ "Delete": "Delete",
+ "ToggleSheet": "Toggle Sheet",
+ "Warning": { },
+ "Dialog": {
+ },
+ "Roll": {
+ "skill": "Skill",
+ "roll": "Roll",
+ "applyNudge": "Apply",
+ "cancel": "Cancel",
+ "nudgeRoll": "Nudge Roll"
+ },
+ "Tooltip": {
+ "sanBP": ">5 SAN lost in one roll, temporary insanity. If SAN less reaches BP = a Disorder unconscious Breaking and AND reset BP.",
+ "setBP": "Set the current Breaking Point based on the current SAN value"
+ },
+ "Chat": {
+ },
+ "Notifications": {
+ "NoWeaponSkill": "No weapon skill found for this weapon. Check Weapon definition or available skills/era",
+ "NoWeaponType": "No weapon type found for this weapon subtype. Check Weapon definition or available skills/era",
+ "skillAlreadyExists": "Skill already exists",
+ "WrongEra": "The era of the item does not match the ear of the system"
+ }
+ }
+}
diff --git a/module/applications/_module.mjs b/module/applications/_module.mjs
new file mode 100644
index 0000000..0cdea31
--- /dev/null
+++ b/module/applications/_module.mjs
@@ -0,0 +1,8 @@
+export { default as FTLNomadWeaponSheet } from "./sheets/weapon-sheet.mjs"
+export { default as FTLNomadArmorSheet } from "./sheets/armor-sheet.mjs"
+export { default as FTLNomadVehicleSheet } from "./sheets/vehicle-sheet.mjs"
+export { default as FTLNomadPsionicSheet } from "./sheets/psionic-sheet.mjs"
+export { default as FTLNomadLanguageSheet } from "./sheets/language-sheet.mjs"
+export { default as FTLNomadTalentSheet } from "./sheets/talent-sheet.mjs"
+export { default as FTLNomadNPCSheet } from "./sheets/npc-sheet.mjs"
+
diff --git a/module/applications/sheets/armor-sheet.mjs b/module/applications/sheets/armor-sheet.mjs
new file mode 100644
index 0000000..8df0b19
--- /dev/null
+++ b/module/applications/sheets/armor-sheet.mjs
@@ -0,0 +1,27 @@
+import FTLNomadItemSheet from "./base-item-sheet.mjs"
+
+export default class FTLNomadArmorSheet extends FTLNomadItemSheet {
+ /** @override */
+ static DEFAULT_OPTIONS = {
+ classes: ["armor"],
+ position: {
+ width: 400,
+ },
+ window: {
+ contentClasses: ["armor-content"],
+ },
+ }
+
+ /** @override */
+ static PARTS = {
+ main: {
+ template: "systems/fvtt-cthulhu-eternal/templates/armor.hbs",
+ },
+ }
+
+ /** @override */
+ async _prepareContext() {
+ const context = await super._prepareContext()
+ return context
+ }
+}
diff --git a/module/applications/sheets/base-actor-sheet.mjs b/module/applications/sheets/base-actor-sheet.mjs
new file mode 100644
index 0000000..361af66
--- /dev/null
+++ b/module/applications/sheets/base-actor-sheet.mjs
@@ -0,0 +1,230 @@
+const { HandlebarsApplicationMixin } = foundry.applications.api
+
+export default class FTLNomadActorSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ActorSheetV2) {
+ /**
+ * Different sheet modes.r
+ * @enum {number}
+ */
+ static SHEET_MODES = { EDIT: 0, PLAY: 1 }
+
+ constructor(options = {}) {
+ super(options)
+ this.#dragDrop = this.#createDragDropHandlers()
+ }
+
+ #dragDrop
+
+ /** @override */
+ static DEFAULT_OPTIONS = {
+ classes: ["fvtt-ftl-nomad", "actor"],
+ position: {
+ width: 1400,
+ height: "auto",
+ },
+ form: {
+ submitOnChange: true,
+ },
+ window: {
+ resizable: true,
+ },
+ dragDrop: [{ dragSelector: '[data-drag="true"], .rollable', dropSelector: null }],
+ actions: {
+ editImage: CthulhuEternalActorSheet.#onEditImage,
+ toggleSheet: CthulhuEternalActorSheet.#onToggleSheet,
+ edit: CthulhuEternalActorSheet.#onItemEdit,
+ delete: CthulhuEternalActorSheet.#onItemDelete,
+ updateCheckboxArray: CthulhuEternalActorSheet.#onUpdateCheckboxArray,
+ },
+ }
+
+ /**
+ * The current sheet mode.
+ * @type {number}
+ */
+ _sheetMode = this.constructor.SHEET_MODES.PLAY
+
+ /**
+ * Is the sheet currently in 'Play' mode?
+ * @type {boolean}
+ */
+ get isPlayMode() {
+ return this._sheetMode === this.constructor.SHEET_MODES.PLAY
+ }
+
+ /**
+ * Is the sheet currently in 'Edit' mode?
+ * @type {boolean}
+ */
+ get isEditMode() {
+ return this._sheetMode === this.constructor.SHEET_MODES.EDIT
+ }
+
+ /** @override */
+ async _prepareContext() {
+ const context = {
+ fields: this.document.schema.fields,
+ systemFields: this.document.system.schema.fields,
+ actor: this.document,
+ system: this.document.system,
+ source: this.document.toObject(),
+ enrichedDescription: await TextEditor.enrichHTML(this.document.system.description, { async: true }),
+ isEditMode: this.isEditMode,
+ isPlayMode: this.isPlayMode,
+ isEditable: this.isEditable,
+ }
+ return context
+ }
+
+ /** @override */
+ _onRender(context, options) {
+ this.#dragDrop.forEach((d) => d.bind(this.element))
+ // Add listeners to rollable elements
+ const rollables = this.element.querySelectorAll(".rollable")
+ rollables.forEach((d) => d.addEventListener("click", this._onRoll.bind(this)))
+ }
+
+ // #region Drag-and-Drop Workflow
+ /**
+ * Create drag-and-drop workflow handlers for this Application
+ * @returns {DragDrop[]} An array of DragDrop handlers
+ * @private
+ */
+ #createDragDropHandlers() {
+ return this.options.dragDrop.map((d) => {
+ d.permissions = {
+ dragstart: this._canDragStart.bind(this),
+ drop: this._canDragDrop.bind(this),
+ }
+ d.callbacks = {
+ dragover: this._onDragOver.bind(this),
+ drop: this._onDrop.bind(this),
+ }
+ return new DragDrop(d)
+ })
+ }
+
+ /**
+ * Callback actions which occur when a dragged element is dropped on a target.
+ * @param {DragEvent} event The originating DragEvent
+ * @protected
+ */
+ async _onDrop(event) {
+ }
+
+
+ /**
+ * Define whether a user is able to begin a dragstart workflow for a given drag selector
+ * @param {string} selector The candidate HTML selector for dragging
+ * @returns {boolean} Can the current user drag this selector?
+ * @protected
+ */
+ _canDragStart(selector) {
+ return this.isEditable
+ }
+
+ /**
+ * Define whether a user is able to conclude a drag-and-drop workflow for a given drop selector
+ * @param {string} selector The candidate HTML selector for the drop target
+ * @returns {boolean} Can the current user drop on this selector?
+ * @protected
+ */
+ _canDragDrop(selector) {
+ return true //this.isEditable && this.document.isOwner
+ }
+
+ /**
+ * Callback actions which occur when a dragged element is over a drop target.
+ * @param {DragEvent} event The originating DragEvent
+ * @protected
+ */
+ _onDragOver(event) {}
+
+ async _onDropItem(item) {
+ console.log("Dropped item", item)
+ let itemData = item.toObject()
+ await this.document.createEmbeddedDocuments("Item", [itemData], { renderSheet: false })
+ }
+
+ // #endregion
+
+ // #region Actions
+ /**
+ * Handle toggling between Edit and Play mode.
+ * @param {Event} event The initiating click event.
+ * @param {HTMLElement} target The current target of the event listener.
+ */
+ static #onToggleSheet(event, target) {
+ const modes = this.constructor.SHEET_MODES
+ this._sheetMode = this.isEditMode ? modes.PLAY : modes.EDIT
+ this.render()
+ }
+
+ static #onUpdateCheckboxArray(event, target) {
+ console.log("Update checkbox array", event, target)
+ let arrayName = target.dataset.name
+ let arrayIdx = Number(target.dataset.index)
+ let dataPath = `system.san.${arrayName}`
+ let tab = foundry.utils.duplicate(this.document.system.san[arrayName])
+ tab[arrayIdx] = target.checked
+ this.actor.update( { [dataPath]: tab } )
+ // Dump
+ console.log("Array name", arrayName, arrayIdx, target.checked, dataPath)
+ }
+
+ /**
+ * Handle changing a Document's image.
+ *
+ * @this CthulhuEternalCharacterSheet
+ * @param {PointerEvent} event The originating click event
+ * @param {HTMLElement} target The capturing HTML element which defined a [data-action]
+ * @returns {Promise}
+ * @private
+ */
+ static async #onEditImage(event, target) {
+ const attr = target.dataset.edit
+ const current = foundry.utils.getProperty(this.document, attr)
+ const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}
+ const fp = new FilePicker({
+ current,
+ type: "image",
+ redirectToRoot: img ? [img] : [],
+ callback: (path) => {
+ this.document.update({ [attr]: path })
+ },
+ top: this.position.top + 40,
+ left: this.position.left + 10,
+ })
+ return fp.browse()
+ }
+
+ /**
+ * Edit an existing item within the Actor
+ * Start with the uuid, if it's not found, fallback to the id (as Embedded item in the actor)
+ * @this CthulhuEternalCharacterSheet
+ * @param {PointerEvent} event The originating click event
+ * @param {HTMLElement} target the capturing HTML element which defined a [data-action]
+ */
+ static async #onItemEdit(event, target) {
+ const id = target.getAttribute("data-item-id")
+ const uuid = target.getAttribute("data-item-uuid")
+ let item
+ item = await fromUuid(uuid)
+ if (!item) item = this.document.items.get(id)
+ if (!item) return
+ item.sheet.render(true)
+ }
+
+ /**
+ * Delete an existing talent within the Actor
+ * Use the uuid to display the talent sheet
+ * @param {PointerEvent} event The originating click event
+ * @param {HTMLElement} target the capturing HTML element which defined a [data-action]
+ */
+ static async #onItemDelete(event, target) {
+ const itemUuid = target.getAttribute("data-item-uuid")
+ const item = await fromUuid(itemUuid)
+ await item.deleteDialog()
+ }
+
+ // #endregion
+}
diff --git a/module/applications/sheets/base-item-sheet.mjs b/module/applications/sheets/base-item-sheet.mjs
new file mode 100644
index 0000000..9d3dbee
--- /dev/null
+++ b/module/applications/sheets/base-item-sheet.mjs
@@ -0,0 +1,193 @@
+const { HandlebarsApplicationMixin } = foundry.applications.api
+
+export default class FTLNomadItemSheet extends HandlebarsApplicationMixin(foundry.applications.sheets.ItemSheetV2) {
+ /**
+ * Different sheet modes.
+ * @enum {number}
+ */
+ static SHEET_MODES = { EDIT: 0, PLAY: 1 }
+
+ constructor(options = {}) {
+ super(options)
+ this.#dragDrop = this.#createDragDropHandlers()
+ }
+
+ #dragDrop
+
+ /** @override */
+ static DEFAULT_OPTIONS = {
+ classes: ["fvtt-ftl-nomad", "item"],
+ position: {
+ width: 600,
+ height: "auto",
+ },
+ form: {
+ submitOnChange: true,
+ },
+ window: {
+ resizable: true,
+ },
+ dragDrop: [{ dragSelector: "[data-drag]", dropSelector: null }],
+ actions: {
+ toggleSheet: CthulhuEternalItemSheet.#onToggleSheet,
+ editImage: CthulhuEternalItemSheet.#onEditImage,
+ },
+ }
+
+ /**
+ * The current sheet mode.
+ * @type {number}
+ */
+ _sheetMode = this.constructor.SHEET_MODES.PLAY
+
+ /**
+ * Is the sheet currently in 'Play' mode?
+ * @type {boolean}
+ */
+ get isPlayMode() {
+ return this._sheetMode === this.constructor.SHEET_MODES.PLAY
+ }
+
+ /**
+ * Is the sheet currently in 'Edit' mode?
+ * @type {boolean}
+ */
+ get isEditMode() {
+ return this._sheetMode === this.constructor.SHEET_MODES.EDIT
+ }
+
+ /** @override */
+ async _prepareContext() {
+ const context = {
+ fields: this.document.schema.fields,
+ systemFields: this.document.system.schema.fields,
+ item: this.document,
+ system: this.document.system,
+ source: this.document.toObject(),
+ enrichedDescription: await TextEditor.enrichHTML(this.document.system.description, { async: true }),
+ isEditMode: this.isEditMode,
+ isPlayMode: this.isPlayMode,
+ isEditable: this.isEditable,
+ }
+ return context
+ }
+
+ /** @override */
+ _onRender(context, options) {
+ this.#dragDrop.forEach((d) => d.bind(this.element))
+ }
+
+ // #region Drag-and-Drop Workflow
+ /**
+ * Create drag-and-drop workflow handlers for this Application
+ * @returns {DragDrop[]} An array of DragDrop handlers
+ * @private
+ */
+ #createDragDropHandlers() {
+ return this.options.dragDrop.map((d) => {
+ d.permissions = {
+ dragstart: this._canDragStart.bind(this),
+ drop: this._canDragDrop.bind(this),
+ }
+ d.callbacks = {
+ dragstart: this._onDragStart.bind(this),
+ dragover: this._onDragOver.bind(this),
+ drop: this._onDrop.bind(this),
+ }
+ return new DragDrop(d)
+ })
+ }
+
+ /**
+ * Define whether a user is able to begin a dragstart workflow for a given drag selector
+ * @param {string} selector The candidate HTML selector for dragging
+ * @returns {boolean} Can the current user drag this selector?
+ * @protected
+ */
+ _canDragStart(selector) {
+ return this.isEditable
+ }
+
+ /**
+ * Define whether a user is able to conclude a drag-and-drop workflow for a given drop selector
+ * @param {string} selector The candidate HTML selector for the drop target
+ * @returns {boolean} Can the current user drop on this selector?
+ * @protected
+ */
+ _canDragDrop(selector) {
+ return this.isEditable && this.document.isOwner
+ }
+
+ /**
+ * Callback actions which occur at the beginning of a drag start workflow.
+ * @param {DragEvent} event The originating DragEvent
+ * @protected
+ */
+ _onDragStart(event) {
+ const el = event.currentTarget
+ if ("link" in event.target.dataset) return
+
+ // Extract the data you need
+ let dragData = null
+
+ if (!dragData) return
+
+ // Set data transfer
+ event.dataTransfer.setData("text/plain", JSON.stringify(dragData))
+ }
+
+ /**
+ * Callback actions which occur when a dragged element is over a drop target.
+ * @param {DragEvent} event The originating DragEvent
+ * @protected
+ */
+ _onDragOver(event) {}
+
+ /**
+ * Callback actions which occur when a dragged element is dropped on a target.
+ * @param {DragEvent} event The originating DragEvent
+ * @protected
+ */
+ async _onDrop(event) {}
+
+ // #endregion
+
+ // #region Actions
+ /**
+ * Handle toggling between Edit and Play mode.
+ * @param {Event} event The initiating click event.
+ * @param {HTMLElement} target The current target of the event listener.
+ */
+ static #onToggleSheet(event, target) {
+ const modes = this.constructor.SHEET_MODES
+ this._sheetMode = this.isEditMode ? modes.PLAY : modes.EDIT
+ this.render()
+ }
+
+ /**
+ * Handle changing a Document's image.
+ *
+ * @this CthulhuEternalCharacterSheet
+ * @param {PointerEvent} event The originating click event
+ * @param {HTMLElement} target The capturing HTML element which defined a [data-action]
+ * @returns {Promise}
+ * @private
+ */
+ static async #onEditImage(event, target) {
+ const attr = target.dataset.edit
+ const current = foundry.utils.getProperty(this.document, attr)
+ const { img } = this.document.constructor.getDefaultArtwork?.(this.document.toObject()) ?? {}
+ const fp = new FilePicker({
+ current,
+ type: "image",
+ redirectToRoot: img ? [img] : [],
+ callback: (path) => {
+ this.document.update({ [attr]: path })
+ },
+ top: this.position.top + 40,
+ left: this.position.left + 10,
+ })
+ return fp.browse()
+ }
+ // #endregion
+}
diff --git a/module/applications/sheets/character-sheet.mjs b/module/applications/sheets/character-sheet.mjs
new file mode 100644
index 0000000..29dbf56
--- /dev/null
+++ b/module/applications/sheets/character-sheet.mjs
@@ -0,0 +1,252 @@
+import FTLNomadActorSheet from "./base-actor-sheet.mjs"
+
+export default class FTLNomadCharacterSheet extends FTLNomadActorSheet {
+ /** @override */
+ static DEFAULT_OPTIONS = {
+ classes: ["character"],
+ position: {
+ width: 860,
+ height: 620,
+ },
+ window: {
+ contentClasses: ["character-content"],
+ },
+ actions: {
+ setBP: FTLNomadCharacterSheet.#onSetBP,
+ createGear: FTLNomadCharacterSheet.#onCreateGear,
+ createArmor: FTLNomadCharacterSheet.#onCreateArmor,
+ createWeapon: FTLNomadCharacterSheet.#onCreateWeapon,
+ createBond: FTLNomadCharacterSheet.#onCreateBond,
+ createInjury: FTLNomadCharacterSheet.#onCreateInjury,
+ createMentalDisorder: FTLNomadCharacterSheet.#onCreateMentalDisorder,
+ createMotivation: FTLNomadCharacterSheet.#onCreateMotivation,
+ createSkill: FTLNomadCharacterSheet.#onCreateSkill,
+ createRitual: FTLNomadCharacterSheet.#onCreateRitual,
+ createTome: FTLNomadCharacterSheet.#onCreateTome,
+ },
+ }
+
+ /** @override */
+ static PARTS = {
+ main: {
+ template: "systems/fvtt-ftl-nomad/templates/protagonist-main.hbs",
+ },
+ tabs: {
+ template: "templates/generic/tab-navigation.hbs",
+ },
+ skills: {
+ template: "systems/fvtt-ftl-nomad/templates/protagonist-skills.hbs",
+ },
+ status: {
+ template: "systems/fvtt-ftl-nomad/templates/protagonist-status.hbs",
+ },
+ equipment: {
+ template: "systems/fvtt-ftl-nomad/templates/protagonist-equipment.hbs",
+ },
+ biography: {
+ template: "systems/fvtt-ftl-nomad/templates/protagonist-biography.hbs",
+ },
+ }
+
+ /** @override */
+ tabGroups = {
+ sheet: "skills",
+ }
+
+ /**
+ * Prepare an array of form header tabs.
+ * @returns {Record>}
+ */
+ #getTabs() {
+ const tabs = {
+ skills: { id: "skills", group: "sheet", icon: "fa-solid fa-shapes", label: "FTLNOMAD.Label.skills" },
+ status: { id: "status", group: "sheet", icon: "fa-solid fa-file-waveform", label: "FTLNOMAD.Label.status" },
+ equipment: { id: "equipment", group: "sheet", icon: "fa-solid fa-shapes", label: "FTLNOMAD.Label.equipment" },
+ biography: { id: "biography", group: "sheet", icon: "fa-solid fa-book", label: "FTLNOMAD.Label.biography" },
+ }
+ for (const v of Object.values(tabs)) {
+ v.active = this.tabGroups[v.group] === v.id
+ v.cssClass = v.active ? "active" : ""
+ }
+ return tabs
+ }
+
+ /** @override */
+ async _prepareContext() {
+ const context = await super._prepareContext()
+ context.tabs = this.#getTabs()
+
+ context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
+ context.enrichedNotes = await TextEditor.enrichHTML(this.document.system.notes, { async: true })
+
+ context.tooltipsCharacteristic = {
+ str: game.i18n.localize("FTLNOMAD.Characteristic.Str"),
+ dex: game.i18n.localize("FTLNOMAD.Characteristic.Dex"),
+ con: game.i18n.localize("FTLNOMAD.Characteristic.Con"),
+ int: game.i18n.localize("FTLNOMAD.Characteristic.Int"),
+ pow: game.i18n.localize("FTLNOMAD.Characteristic.Pow"),
+ cha: game.i18n.localize("FTLNOMAD.Characteristic.Cha")
+ }
+
+ return context
+ }
+
+ /** @override */
+ async _preparePartContext(partId, context) {
+ const doc = this.document
+ switch (partId) {
+ case "main":
+ break
+ case "skills":
+ context.tab = context.tabs.skills
+ context.skills = doc.itemTypes.skill
+ context.skills.sort((a, b) => a.name.localeCompare(b.name))
+ break
+ case "equipment":
+ context.tab = context.tabs.equipment
+ context.weapons = doc.itemTypes.weapon
+ context.weapons.sort((a, b) => a.name.localeCompare(b.name))
+ context.armors = doc.itemTypes.armor
+ context.armors.sort((a, b) => a.name.localeCompare(b.name))
+ context.gears = doc.itemTypes.gear
+ context.gears.sort((a, b) => a.name.localeCompare(b.name))
+ context.rituals = doc.itemTypes.ritual
+ context.rituals.sort((a, b) => a.name.localeCompare(b.name))
+ context.tomes = doc.itemTypes.tome
+ context.tomes.sort((a, b) => a.name.localeCompare(b.name))
+ break
+ case "status":
+ context.tab = context.tabs.status
+ context.injuries = doc.itemTypes.injury
+ context.injuries.sort((a, b) => a.name.localeCompare(b.name))
+ context.mentaldisorders = doc.itemTypes.mentaldisorder
+ context.mentaldisorders.sort((a, b) => a.name.localeCompare(b.name))
+ context.motivations = doc.itemTypes.motivation
+ context.motivations.sort((a, b) => a.name.localeCompare(b.name))
+ context.bonds = doc.itemTypes.bond
+ context.bonds.sort((a, b) => a.name.localeCompare(b.name))
+ break
+ case "biography":
+ context.tab = context.tabs.biography
+ context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
+ context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true })
+ break
+ }
+ return context
+ }
+
+ /**
+ * Creates a new attack item directly from the sheet and embeds it into the document.
+ * @param {Event} event The initiating click event.
+ * @param {HTMLElement} target The current target of the event listener.
+ */
+ static #onSetBP(event, target) {
+ this.document.system.setBP()
+ }
+
+ static #onCreateGear(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newGear"), type: "gear" }])
+ }
+
+ static #onCreateWeapon(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newWeapon"), type: "weapon" }])
+ }
+
+ static #onCreateArmor(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newArmor"), type: "armor" }])
+ }
+
+ static #onCreateBond(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newBond"), type: "bond" }])
+ }
+
+ static #onCreateInjury(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newInjury"), type: "injury" }])
+ }
+
+ static #onCreateMentalDisorder(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newMentalDisorder"), type: "mentaldisorder" }])
+ }
+
+ static #onCreateMotivation(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newMotivation"), type: "motivation" }])
+ }
+
+ static #onCreateSkill(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newSkill"), type: "skill" }])
+ }
+
+ static #onCreateRitual(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newRitual"), type: "ritual" }])
+ }
+
+ static #onCreateTome(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newTome"), type: "tome" }])
+ }
+
+ /**
+ * Handles the roll action triggered by user interaction.
+ *
+ * @param {PointerEvent} event The event object representing the user interaction.
+ * @param {HTMLElement} target The target element that triggered the roll.
+ *
+ * @returns {Promise} A promise that resolves when the roll action is complete.
+ *
+ * @throws {Error} Throws an error if the roll type is not recognized.
+ *
+ * @description This method checks the current mode (edit or not) and determines the type of roll
+ * (save, resource, or damage) based on the target element's data attributes. It retrieves the
+ * corresponding value from the document's system and performs the roll.
+ */
+ async _onRoll(event, target) {
+ const rollType = $(event.currentTarget).data("roll-type")
+ let item
+ let li
+ // Debug : console.log(">>>>", event, target, rollType)
+ // Deprecated : if (this.isEditMode) return
+ switch (rollType) {
+ case "resource":
+ item = foundry.utils.duplicate(this.actor.system.resources)
+ item.name = game.i18n.localize(`FTLNOMAD.Label.Resources`)
+ item.targetScore = item.permanentRating
+ break
+ case "char":
+ let charId = $(event.currentTarget).data("char-id")
+ item = foundry.utils.duplicate(this.actor.system.characteristics[charId])
+ item.name = game.i18n.localize(`FTLNOMAD.Label.${charId}Long`)
+ item.targetScore = item.value * 5
+ break
+ case "skill":
+ li = $(event.currentTarget).parents(".item");
+ item = this.actor.items.get(li.data("item-id"));
+ break
+ case "weapon":
+ case "damage":
+ li = $(event.currentTarget).parents(".item");
+ item = this.actor.items.get(li.data("item-id"));
+ item.damageBonus = this.actor.system.damageBonus
+ break
+ case "san":
+ item = foundry.utils.duplicate(this.actor.system.san)
+ item.name = game.i18n.localize("FTLNOMAD.Label.SAN")
+ item.targetScore = item.value
+ break;
+ default:
+ throw new Error(`Unknown roll type ${rollType}`)
+ }
+ await this.document.system.roll(rollType, item)
+ }
+
+ async _onDrop(event) {
+ if (!this.isEditable || !this.isEditMode) return
+ const data = TextEditor.getDragEventData(event)
+
+ // Handle different data types
+ switch (data.type) {
+ case "Item":
+ const item = await fromUuid(data.uuid)
+ return super._onDropItem(item)
+ }
+ }
+
+}
diff --git a/module/applications/sheets/equipment-sheet.mjs b/module/applications/sheets/equipment-sheet.mjs
new file mode 100644
index 0000000..5cb5888
--- /dev/null
+++ b/module/applications/sheets/equipment-sheet.mjs
@@ -0,0 +1,27 @@
+import FTLNomadItemSheet from "./base-item-sheet.mjs"
+
+export default class FTLNomadEquipmentSheet extends FTLNomadItemSheet {
+ /** @override */
+ static DEFAULT_OPTIONS = {
+ classes: ["equipment"],
+ position: {
+ width: 600,
+ },
+ window: {
+ contentClasses: ["equipment-content"],
+ },
+ }
+
+ /** @override */
+ static PARTS = {
+ main: {
+ template: "systems/fvtt-cthulhu-eternal/templates/equipment.hbs",
+ },
+ }
+
+ /** @override */
+ async _prepareContext() {
+ const context = await super._prepareContext()
+ return context
+ }
+}
diff --git a/module/applications/sheets/language-sheet.mjs b/module/applications/sheets/language-sheet.mjs
new file mode 100644
index 0000000..f387771
--- /dev/null
+++ b/module/applications/sheets/language-sheet.mjs
@@ -0,0 +1,28 @@
+import FTLNomadItemSheet from "./base-item-sheet.mjs"
+
+export default class FTLNomadLanguageSheet extends FTLNomadItemSheet {
+ /** @override */
+ static DEFAULT_OPTIONS = {
+ classes: ["language"],
+ position: {
+ width: 600,
+ },
+ window: {
+ contentClasses: ["language-content"],
+ },
+ }
+
+ /** @override */
+ static PARTS = {
+ main: {
+ template: "systems/fvtt-cthulhu-eternal/templates/language.hbs",
+ },
+ }
+
+ /** @override */
+ async _prepareContext() {
+ const context = await super._prepareContext()
+ context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
+ return context
+ }
+}
diff --git a/module/applications/sheets/npc.mjs b/module/applications/sheets/npc.mjs
new file mode 100644
index 0000000..ddd7d9a
--- /dev/null
+++ b/module/applications/sheets/npc.mjs
@@ -0,0 +1,166 @@
+import FTLNomadActorSheet from "./base-actor-sheet.mjs"
+
+export default class FTLNomadNPCSheet extends FTLNomadActorSheet {
+ /** @override */
+ static DEFAULT_OPTIONS = {
+ classes: ["npc"],
+ position: {
+ width: 860,
+ height: 620,
+ },
+ window: {
+ contentClasses: ["npc-content"],
+ },
+ actions: {
+ createArmor: FTLNomadNPCSheet.#onCreateArmor,
+ createWeapon: FTLNomadNPCSheet.#onCreateWeapon,
+ createSkill: FTLNomadNPCSheet.#onCreateSkill,
+
+ },
+ }
+
+ /** @override */
+ static PARTS = {
+ main: {
+ template: "systems/fvtt-cthulhu-eternal/templates/npc-main.hbs",
+ },
+ tabs: {
+ template: "templates/generic/tab-navigation.hbs",
+ },
+ skills: {
+ template: "systems/fvtt-cthulhu-eternal/templates/npc-skills.hbs",
+ },
+ biography: {
+ template: "systems/fvtt-cthulhu-eternal/templates/npc-biography.hbs",
+ },
+ }
+
+ /** @override */
+ tabGroups = {
+ sheet: "skills",
+ }
+
+ /**
+ * Prepare an array of form header tabs.
+ * @returns {Record>}
+ */
+ #getTabs() {
+ const tabs = {
+ skills: { id: "skills", group: "sheet", icon: "fa-solid fa-shapes", label: "FTLNOMAD.Label.skills" },
+ biography: { id: "biography", group: "sheet", icon: "fa-solid fa-book", label: "FTLNOMAD.Label.biography" },
+ }
+ for (const v of Object.values(tabs)) {
+ v.active = this.tabGroups[v.group] === v.id
+ v.cssClass = v.active ? "active" : ""
+ }
+ return tabs
+ }
+
+ /** @override */
+ async _prepareContext() {
+ const context = await super._prepareContext()
+ context.tabs = this.#getTabs()
+
+ context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
+ context.enrichedNotes = await TextEditor.enrichHTML(this.document.system.notes, { async: true })
+
+ return context
+ }
+
+ /** @override */
+ async _preparePartContext(partId, context) {
+ const doc = this.document
+ switch (partId) {
+ case "main":
+ break
+ case "skills":
+ context.tab = context.tabs.skills
+ context.skills = doc.itemTypes.skill
+ context.skills.sort((a, b) => a.name.localeCompare(b.name))
+ context.weapons = doc.itemTypes.weapon
+ context.weapons.sort((a, b) => a.name.localeCompare(b.name))
+ context.armors = doc.itemTypes.armor
+ context.armors.sort((a, b) => a.name.localeCompare(b.name))
+ break
+ case "biography":
+ context.tab = context.tabs.biography
+ context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
+ context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true })
+ break
+ }
+ return context
+ }
+
+ /**
+ * Creates a new attack item directly from the sheet and embeds it into the document.
+ * @param {Event} event The initiating click event.
+ * @param {HTMLElement} target The current target of the event listener.
+ */
+ static #onCreateWeapon(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newWeapon"), type: "weapon" }])
+ }
+
+ static #onCreateArmor(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newArmor"), type: "armor" }])
+ }
+
+ static #onCreateSkill(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("FTLNOMAD.Label.newSkill"), type: "skill" }])
+ }
+
+ /**
+ * Handles the roll action triggered by user interaction.
+ *
+ * @param {PointerEvent} event The event object representing the user interaction.
+ * @param {HTMLElement} target The target element that triggered the roll.
+ *
+ * @returns {Promise} A promise that resolves when the roll action is complete.
+ *
+ * @throws {Error} Throws an error if the roll type is not recognized.
+ *
+ * @description This method checks the current mode (edit or not) and determines the type of roll
+ * (save, resource, or damage) based on the target element's data attributes. It retrieves the
+ * corresponding value from the document's system and performs the roll.
+ */
+ async _onRoll(event, target) {
+ const rollType = $(event.currentTarget).data("roll-type")
+ let item
+ let li
+ // Debug : console.log(">>>>", event, target, rollType)
+ // Deprecated : if (this.isEditMode) return
+ switch (rollType) {
+ case "char":
+ let charId = $(event.currentTarget).data("char-id")
+ item = foundry.utils.duplicate(this.actor.system.characteristics[charId])
+ item.name = game.i18n.localize(`FTLNOMAD.Label.${charId}Long`)
+ item.targetScore = item.value * 5
+ break
+ case "skill":
+ li = $(event.currentTarget).parents(".item");
+ item = this.actor.items.get(li.data("item-id"));
+ break
+ case "weapon":
+ case "damage":
+ li = $(event.currentTarget).parents(".item");
+ item = this.actor.items.get(li.data("item-id"));
+ item.damageBonus = this.actor.system.damageBonus
+ break
+ default:
+ throw new Error(`Unknown roll type ${rollType}`)
+ }
+ await this.document.system.roll(rollType, item)
+ }
+
+ async _onDrop(event) {
+ if (!this.isEditable || !this.isEditMode) return
+ const data = TextEditor.getDragEventData(event)
+
+ // Handle different data types
+ switch (data.type) {
+ case "Item":
+ const item = await fromUuid(data.uuid)
+ return super._onDropItem(item)
+ }
+ }
+
+}
diff --git a/module/applications/sheets/psionic-sheet.mjs b/module/applications/sheets/psionic-sheet.mjs
new file mode 100644
index 0000000..15eeb23
--- /dev/null
+++ b/module/applications/sheets/psionic-sheet.mjs
@@ -0,0 +1,28 @@
+import FTLNomadItemSheet from "./base-item-sheet.mjs"
+
+export default class FTLNomadPsionicSheet extends FTLNomadItemSheet {
+ /** @override */
+ static DEFAULT_OPTIONS = {
+ classes: ["psionic"],
+ position: {
+ width: 600,
+ },
+ window: {
+ contentClasses: ["psionic-content"],
+ },
+ }
+
+ /** @override */
+ static PARTS = {
+ main: {
+ template: "systems/fvtt-cthulhu-eternal/templates/psionic.hbs",
+ },
+ }
+
+ /** @override */
+ async _prepareContext() {
+ const context = await super._prepareContext()
+ context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
+ return context
+ }
+}
diff --git a/module/applications/sheets/talent-sheet.mjs b/module/applications/sheets/talent-sheet.mjs
new file mode 100644
index 0000000..62eefcb
--- /dev/null
+++ b/module/applications/sheets/talent-sheet.mjs
@@ -0,0 +1,28 @@
+import FTLNomadItemSheet from "./base-item-sheet.mjs"
+
+export default class FTLNomadTalentSheet extends FTLNomadItemSheet {
+ /** @override */
+ static DEFAULT_OPTIONS = {
+ classes: ["talent"],
+ position: {
+ width: 600,
+ },
+ window: {
+ contentClasses: ["talent-content"],
+ },
+ }
+
+ /** @override */
+ static PARTS = {
+ main: {
+ template: "systems/fvtt-cthulhu-eternal/templates/talent.hbs",
+ },
+ }
+
+ /** @override */
+ async _prepareContext() {
+ const context = await super._prepareContext()
+ context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
+ return context
+ }
+}
diff --git a/module/applications/sheets/vehicle-sheet.mjs b/module/applications/sheets/vehicle-sheet.mjs
new file mode 100644
index 0000000..5f358e3
--- /dev/null
+++ b/module/applications/sheets/vehicle-sheet.mjs
@@ -0,0 +1,117 @@
+import FTLNomadActorSheet from "./base-actor-sheet.mjs"
+
+export default class FTLNomadVehicleSheet extends FTLNomadActorSheet {
+ /** @override */
+ static DEFAULT_OPTIONS = {
+ classes: ["vehicle"],
+ position: {
+ width: 680,
+ height: 540,
+ },
+ window: {
+ contentClasses: ["vehicle-content"],
+ },
+ actions: {
+ createGear: CthulhuEternalVehicleSheet.#onCreateGear,
+ createWeapon: CthulhuEternalVehicleSheet.#onCreateWeapon,
+ },
+ }
+
+ /** @override */
+ static PARTS = {
+ main: {
+ template: "systems/fvtt-cthulhu-eternal/templates/vehicle-main.hbs",
+ },
+ tabs: {
+ template: "templates/generic/tab-navigation.hbs",
+ },
+ equipment: {
+ template: "systems/fvtt-cthulhu-eternal/templates/vehicle-equipment.hbs",
+ },
+ description: {
+ template: "systems/fvtt-cthulhu-eternal/templates/vehicle-description.hbs",
+ },
+ }
+
+ /** @override */
+ tabGroups = {
+ sheet: "equipment",
+ }
+
+ /**
+ * Prepare an array of form header tabs.
+ * @returns {Record>}
+ */
+ #getTabs() {
+ const tabs = {
+ equipment: { id: "equipment", group: "sheet", icon: "fa-solid fa-shapes", label: "CTHULHUETERNAL.Label.equipment" },
+ description: { id: "description", group: "sheet", icon: "fa-solid fa-book", label: "CTHULHUETERNAL.Label.description" },
+ }
+ for (const v of Object.values(tabs)) {
+ v.active = this.tabGroups[v.group] === v.id
+ v.cssClass = v.active ? "active" : ""
+ }
+ return tabs
+ }
+
+ /** @override */
+ async _prepareContext() {
+ const context = await super._prepareContext()
+ context.tabs = this.#getTabs()
+
+ context.enrichedDescription = await TextEditor.enrichHTML(this.document.system.description, { async: true })
+ context.enrichedNotes = await TextEditor.enrichHTML(this.document.system.notes, { async: true })
+
+ return context
+ }
+
+ _generateTooltip(type, target) {
+ }
+
+ /** @override */
+ async _preparePartContext(partId, context) {
+ const doc = this.document
+ switch (partId) {
+ case "main":
+ break
+ case "equipment":
+ context.tab = context.tabs.equipment
+ context.weapons = doc.itemTypes.weapon
+ context.gears = doc.itemTypes.gear
+ break
+ case "description":
+ context.tab = context.tabs.description
+ context.enrichedDescription = await TextEditor.enrichHTML(doc.system.description, { async: true })
+ context.enrichedNotes = await TextEditor.enrichHTML(doc.system.notes, { async: true })
+ break
+ }
+ return context
+ }
+
+ /**
+ * Creates a new attack item directly from the sheet and embeds it into the document.
+ * @param {Event} event The initiating click event.
+ * @param {HTMLElement} target The current target of the event listener.
+ */
+ static #onCreateGear(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newGear"), type: "gear" }])
+ }
+
+ static #onCreateWeapon(event, target) {
+ this.document.createEmbeddedDocuments("Item", [{ name: game.i18n.localize("CTHULHUETERNAL.Label.newWeapon"), type: "weapon" }])
+ }
+
+
+ async _onDrop(event) {
+ if (!this.isEditable || !this.isEditMode) return
+ const data = TextEditor.getDragEventData(event)
+
+ // Handle different data types
+ switch (data.type) {
+ case "Item":
+ const item = await fromUuid(data.uuid)
+ return super._onDropItem(item)
+ }
+ }
+
+}
diff --git a/module/applications/sheets/weapon-sheet.mjs b/module/applications/sheets/weapon-sheet.mjs
new file mode 100644
index 0000000..60844e6
--- /dev/null
+++ b/module/applications/sheets/weapon-sheet.mjs
@@ -0,0 +1,21 @@
+import FTLNomadItemSheet from "./base-item-sheet.mjs"
+
+export default class FTLNomadWeaponSheet extends FTLNomadItemSheet {
+ /** @override */
+ static DEFAULT_OPTIONS = {
+ classes: ["weapon"],
+ position: {
+ width: 620,
+ },
+ window: {
+ contentClasses: ["weapon-content"],
+ },
+ }
+
+ /** @override */
+ static PARTS = {
+ main: {
+ template: "systems/fvtt-cthulhu-eternal/templates/weapon.hbs",
+ },
+ }
+}
diff --git a/module/config/system.mjs b/module/config/system.mjs
new file mode 100644
index 0000000..224daa7
--- /dev/null
+++ b/module/config/system.mjs
@@ -0,0 +1,33 @@
+export const SYSTEM_ID = "fvtt-ftl-nomad"
+
+export const ASCII = `
+▄████▄ ▄▄▄█████▓ ██░ ██ █ ██ ██▓ ██░ ██ █ ██ ▓█████▄▄▄█████▓▓█████ ██▀███ ███▄ █ ▄▄▄ ██▓
+▒██▀ ▀█ ▓ ██▒ ▓▒▓██░ ██▒ ██ ▓██▒▓██▒ ▓██░ ██▒ ██ ▓██▒ ▓█ ▀▓ ██▒ ▓▒▓█ ▀ ▓██ ▒ ██▒ ██ ▀█ █ ▒████▄ ▓██▒
+▒▓█ ▄ ▒ ▓██░ ▒░▒██▀▀██░▓██ ▒██░▒██░ ▒██▀▀██░▓██ ▒██░ ▒███ ▒ ▓██░ ▒░▒███ ▓██ ░▄█ ▒▓██ ▀█ ██▒▒██ ▀█▄ ▒██░
+▒▓▓▄ ▄██▒░ ▓██▓ ░ ░▓█ ░██ ▓▓█ ░██░▒██░ ░▓█ ░██ ▓▓█ ░██░ ▒▓█ ▄░ ▓██▓ ░ ▒▓█ ▄ ▒██▀▀█▄ ▓██▒ ▐▌██▒░██▄▄▄▄██ ▒██░
+▒ ▓███▀ ░ ▒██▒ ░ ░▓█▒░██▓▒▒█████▓ ░██████▒░▓█▒░██▓▒▒█████▓ ░▒████▒ ▒██▒ ░ ░▒████▒░██▓ ▒██▒▒██░ ▓██░ ▓█ ▓██▒░██████▒
+░ ░▒ ▒ ░ ▒ ░░ ▒ ░░▒░▒░▒▓▒ ▒ ▒ ░ ▒░▓ ░ ▒ ░░▒░▒░▒▓▒ ▒ ▒ ░░ ▒░ ░ ▒ ░░ ░░ ▒░ ░░ ▒▓ ░▒▓░░ ▒░ ▒ ▒ ▒▒ ▓▒█░░ ▒░▓ ░
+ ░ ▒ ░ ▒ ░▒░ ░░░▒░ ░ ░ ░ ░ ▒ ░ ▒ ░▒░ ░░░▒░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░▒ ░ ▒░░ ░░ ░ ▒░ ▒ ▒▒ ░░ ░ ▒ ░
+░ ░ ░ ░░ ░ ░░░ ░ ░ ░ ░ ░ ░░ ░ ░░░ ░ ░ ░ ░ ░ ░░ ░ ░ ░ ░ ░ ▒ ░ ░
+░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░ ░
+░
+`
+export const SKILLS = {
+ "combat": { id: "combat", label: "FTLNOMAD.Skill.Combat" },
+ "knowledge": { id: "knowledge", label: "FTLNOMAD.Skill.Knowledge" },
+ "social": { id: "social", label: "FTLNOMAD.Skill.Social" },
+ "physical": { id: "physical", label: "FTLNOMAD.Skill.Physical" },
+ "stealth": { id: "stealth", label: "FTLNOMAD.Skill.Stealth" },
+ "vehicles": { id: "vehicle", label: "FTLNOMAD.Skill.Vehicles" },
+ "technology": { id: "technology", label: "FTLNOMAD.Skill.Technology" }
+}
+
+/**
+ * Include all constant definitions within the SYSTEM global export
+ * @type {Object}
+ */
+export const SYSTEM = {
+ id: SYSTEM_ID,
+ SKILLS: SKILLS,
+ ASCII
+}
diff --git a/module/documents/_module.mjs b/module/documents/_module.mjs
new file mode 100644
index 0000000..a95fe8c
--- /dev/null
+++ b/module/documents/_module.mjs
@@ -0,0 +1,4 @@
+export { default as CthulhuEternalActor } from "./actor.mjs"
+export { default as CthulhuEternalItem } from "./item.mjs"
+export { default as CthulhuEternalRoll } from "./roll.mjs"
+export { default as CthulhuEternalChatMessage } from "./chat-message.mjs"
diff --git a/module/documents/actor.mjs b/module/documents/actor.mjs
new file mode 100644
index 0000000..3a65e52
--- /dev/null
+++ b/module/documents/actor.mjs
@@ -0,0 +1,86 @@
+import CthulhuEternalUtils from "../utils.mjs"
+
+export default class CthulhuEternalActor extends Actor {
+
+ static async create(data, options) {
+
+ // Case of compendium global import
+ if (data instanceof Array) {
+ return super.create(data, options);
+ }
+ // If the created actor has items (only applicable to duplicated actors) bypass the new actor creation logic
+ if (data.items) {
+ let actor = super.create(data, options);
+ return actor;
+ }
+
+ if (data.type === 'protagonist') {
+ let era = game.settings.get("fvtt-cthulhu-eternal", "settings-era")
+ const skills = await CthulhuEternalUtils.loadCompendium("fvtt-cthulhu-eternal.skills")
+ data.items = data.items || []
+ for (let skill of skills) {
+ if (skill.system.settings === era) {
+ data.items.push(skill.toObject())
+ }
+ }
+ data.items.push({ type:"weapon", img: "systems/fvtt-cthulhu-eternal/assets/icons/icon_fist.svg",
+ name: game.i18n.localize("CTHULHUETERNAL.Label.Unarmed"), system: { damage: "1d4-1", weaponType: "unarmed" } })
+ }
+
+ return super.create(data, options);
+ }
+
+ _onUpdate(changed, options, userId) {
+ // DEBUG : console.log("CthulhuEternalActor.update", changed, options, userId)
+ if (changed?.system?.wp?.exhausted) {
+ ChatMessage.create({
+ user: userId,
+ speaker: { alias: this.name },
+ rollMode: "selfroll",
+ content: game.i18n.localize("CTHULHUETERNAL.ChatMessage.exhausted"),
+ type: CONST.CHAT_MESSAGE_STYLES.OTHER
+ })
+ }
+ return super._onUpdate(changed, options, userId)
+ }
+
+ async createEmbeddedDocuments(embeddedName, data, operation) {
+ let newData = []
+ if (embeddedName === "Item") {
+ for (let i of data) {
+ if (i.type === "skill") {
+ if (this.items.find(item => item.name.toLowerCase() === i.name.toLowerCase())) {
+ ui.notifications.warn(game.i18n.localize("CTHULHUETERNAL.Notifications.skillAlreadyExists"))
+ continue
+ }
+ }
+ if (i.type === "bond") {
+ if (i.system.bondType === "individual") {
+ i.system.value = this.system.characteristics.cha.value
+ } else {
+ i.system.value = Math.floor(this.system.resources.permanentRating / 2)
+ }
+ }
+ newData.push(i)
+ }
+ return super.createEmbeddedDocuments(embeddedName, newData, operation)
+ }
+ return super.createEmbeddedDocuments(embeddedName, data, operation)
+ }
+
+ async _preCreate(data, options, user) {
+ await super._preCreate(data, options, user)
+
+ // Configure prototype token settings
+ const prototypeToken = {}
+ if (this.type === "protagonist") {
+ Object.assign(prototypeToken, {
+ sight: { enabled: true },
+ actorLink: true,
+ disposition: CONST.TOKEN_DISPOSITIONS.FRIENDLY,
+ })
+ this.updateSource({ prototypeToken })
+ }
+}
+
+}
diff --git a/module/documents/chat-message.mjs b/module/documents/chat-message.mjs
new file mode 100644
index 0000000..8180c39
--- /dev/null
+++ b/module/documents/chat-message.mjs
@@ -0,0 +1,21 @@
+import CthulhuEternalRoll from "./roll.mjs"
+
+export default class CthulhuEternalChatMessage extends ChatMessage {
+ async _renderRollContent(messageData) {
+ const data = messageData.message
+ if (this.rolls[0] instanceof CthulhuEternalRoll) {
+ const isPrivate = !this.isContentVisible
+ // _renderRollHTML va appeler render sur tous les rolls
+ const rollHTML = await this._renderRollHTML(isPrivate)
+ if (isPrivate) {
+ data.flavor = game.i18n.format("CHAT.PrivateRollContent", { user: this.user.name })
+ messageData.isWhisper = false
+ messageData.alias = this.user.name
+ }
+ data.content = ``
+ return
+ }
+
+ return super._renderRollContent(messageData)
+ }
+}
diff --git a/module/documents/item.mjs b/module/documents/item.mjs
new file mode 100644
index 0000000..c9a5991
--- /dev/null
+++ b/module/documents/item.mjs
@@ -0,0 +1,23 @@
+export const defaultItemImg = {
+ weapon: "systems/fvtt-cthulhu-eternal/assets/icons/icon_weapon.svg",
+ armor: "systems/fvtt-cthulhu-eternal/assets/icons/icon_armor.svg",
+ gear: "systems/fvtt-cthulhu-eternal/assets/icons/icon_equipment.svg",
+ skill: "systems/fvtt-cthulhu-eternal/assets/icons/icon_skill.svg",
+ archetype: "systems/fvtt-cthulhu-eternal/assets/icons/icon_archetype.svg",
+ bond: "systems/fvtt-cthulhu-eternal/assets/icons/icon_bond.svg",
+ mentaldisorder: "systems/fvtt-cthulhu-eternal/assets/icons/icon_mental_disorder.svg",
+ arcane: "systems/fvtt-cthulhu-eternal/assets/icons/icon_arcane.svg",
+ injury: "systems/fvtt-cthulhu-eternal/assets/icons/icon_injury.svg",
+ motivation: "systems/fvtt-cthulhu-eternal/assets/icons/icon_motivation.svg",
+ ritual: "systems/fvtt-cthulhu-eternal/assets/icons/icon_ritual.svg",
+ tome: "systems/fvtt-cthulhu-eternal/assets/icons/icon_tome.svg",
+}
+
+export default class CthulhuEternalItem extends Item {
+ constructor(data, context) {
+ if (!data.img) {
+ data.img = defaultItemImg[data.type];
+ }
+ super(data, context);
+ }
+}
diff --git a/module/documents/roll.mjs b/module/documents/roll.mjs
new file mode 100644
index 0000000..05de50f
--- /dev/null
+++ b/module/documents/roll.mjs
@@ -0,0 +1,455 @@
+
+import { SYSTEM } from "../config/system.mjs"
+
+export default class CthulhuEternalRoll extends Roll {
+ /**
+ * The HTML template path used to render dice checks of this type
+ * @type {string}
+ */
+ static CHAT_TEMPLATE = "systems/fvtt-cthulhu-eternal/templates/chat-message.hbs"
+
+ get type() {
+ return this.options.type
+ }
+
+ get isDamage() {
+ return this.type === ROLL_TYPE.DAMAGE
+ }
+
+ get target() {
+ return this.options.target
+ }
+
+ get value() {
+ return this.options.value
+ }
+
+ get actorId() {
+ return this.options.actorId
+ }
+
+ get actorName() {
+ return this.options.actorName
+ }
+
+ get actorImage() {
+ return this.options.actorImage
+ }
+
+ get help() {
+ return this.options.help
+ }
+
+ get gene() {
+ return this.options.gene
+ }
+
+ get modifier() {
+ return this.options.modifier
+ }
+
+ get resultType() {
+ return this.options.resultType
+ }
+
+ get isFailure() {
+ return this.resultType === "failure"
+ }
+
+ get hasTarget() {
+ return this.options.hasTarget
+ }
+
+ get realDamage() {
+ return this.options.realDamage
+ }
+
+ get weapon() {
+ return this.options.weapon
+ }
+
+ get isLowWP() {
+ return this.options.isLowWP
+ }
+
+ get isZeroWP() {
+ return this.options.isZeroWP
+ }
+
+ get isExhausted() {
+ return this.options.isExhausted
+ }
+
+ get isNudgedRoll() {
+ return this.options.isNudgedRoll
+ }
+
+ get wpCost() {
+ return this.options.wpCost
+ }
+
+ static updateResourceDialog(options) {
+ let rating = 0
+ if (options.rollItem.enableHand) {
+ rating += options.rollItem.hand
+ }
+ if (options.rollItem.enableStowed) {
+ rating += options.rollItem.stowed
+ }
+ if (options.rollItem.enableStorage) {
+ rating += options.rollItem.storage
+ }
+ let multiplier = Number($(`.roll-skill-multiplier`).val())
+ options.initialScore = rating
+ options.percentScore = rating * multiplier
+ $(".resource-score").text(`${rating} (${options.percentScore}%)`)
+ }
+
+ /**
+ * Prompt the user with a dialog to configure and execute a roll.
+ *
+ * @param {Object} options Configuration options for the roll.
+ * @param {string} options.rollType The type of roll being performed.
+ * @param {string} options.rollTarget The target of the roll.
+ * @param {string} options.actorId The ID of the actor performing the roll.
+ * @param {string} options.actorName The name of the actor performing the roll.
+ * @param {string} options.actorImage The image of the actor performing the roll.
+ * @param {boolean} options.hasTarget Whether the roll has a target.
+ * @param {Object} options.data Additional data for the roll.
+ *
+ * @returns {Promise