Style Magic and Biography tabs, update senses system
Magic tab: - Mana display matching inventory header format - Focus status panel with active spell tracking - Spell list with damage/effect badges and cast buttons - Spellcasting reference guide with delivery/duration costs Biography tab: - Character details section with Size and Being Type dropdowns - Senses as 3-column grid of boolean checkboxes - Biography and Notes textareas with proper styling - Languages section hidden (not yet implemented) Senses system overhaul: - Changed from mixed boolean/number to all boolean toggles - Renamed darksight to darkvision - Added: allsight, echolocation, seismicsense, telepathy - Removed: tremorsense (not in system) - Updated both character and NPC data models - Updated NPC sheet template and hasSenses logic Also updated PROJECT_ROADMAP.json with styling progress notes. 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
10963403e9
commit
15fd9f684f
@ -382,7 +382,7 @@
|
|||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "critical",
|
"priority": "critical",
|
||||||
"dependencies": ["2.2"],
|
"dependencies": ["2.2"],
|
||||||
"notes": "Uses Foundry v13 ApplicationV2 with HandlebarsApplicationMixin. Includes action handlers, drag-drop, item management."
|
"notes": "Uses Foundry v13 ApplicationV2 with HandlebarsApplicationMixin. Includes action handlers, drag-drop, item management. Added _cleanupInactiveTabs() to fix ApplicationV2 part stacking issue with tabs."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "3.2",
|
"id": "3.2",
|
||||||
@ -472,7 +472,7 @@
|
|||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
"dependencies": ["3.2"],
|
"dependencies": ["3.2"],
|
||||||
"notes": "Abilities tab with ancestry, features, perks, and active effects display."
|
"notes": "Abilities tab with ancestry, features, perks, and active effects display. Perk prerequisites use getPrerequisiteString() from data model for proper formatting."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "3.11",
|
"id": "3.11",
|
||||||
@ -663,7 +663,8 @@
|
|||||||
"completed": false,
|
"completed": false,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
"dependencies": ["5.1", "5.2", "5.3", "3.2"]
|
"dependencies": ["5.1", "5.2", "5.3", "3.2"],
|
||||||
|
"notes": "In progress. Completed: Header, Main tab (stats, combat, saves, skills, attacks), Inventory tab (inline header with item slots/currencies, item lists), Abilities tab (ancestry, features, perks with prerequisite display, active effects). Remaining: Magic tab, Biography tab."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "5.5",
|
"id": "5.5",
|
||||||
|
|||||||
@ -331,9 +331,12 @@
|
|||||||
"VAGABOND.Languages": "Languages",
|
"VAGABOND.Languages": "Languages",
|
||||||
"VAGABOND.NoLanguages": "No languages",
|
"VAGABOND.NoLanguages": "No languages",
|
||||||
"VAGABOND.Senses": "Senses",
|
"VAGABOND.Senses": "Senses",
|
||||||
"VAGABOND.Darksight": "Darksight",
|
"VAGABOND.Allsight": "Allsight",
|
||||||
"VAGABOND.Blindsight": "Blindsight",
|
"VAGABOND.Blindsight": "Blindsight",
|
||||||
"VAGABOND.Tremorsense": "Tremorsense",
|
"VAGABOND.Darkvision": "Darkvision",
|
||||||
|
"VAGABOND.Echolocation": "Echolocation",
|
||||||
|
"VAGABOND.Seismicsense": "Seismicsense",
|
||||||
|
"VAGABOND.Telepathy": "Telepathy",
|
||||||
"VAGABOND.BiographyPlaceholder": "Enter character background...",
|
"VAGABOND.BiographyPlaceholder": "Enter character background...",
|
||||||
"VAGABOND.Notes": "Notes",
|
"VAGABOND.Notes": "Notes",
|
||||||
"VAGABOND.NotesPlaceholder": "Enter notes...",
|
"VAGABOND.NotesPlaceholder": "Enter notes...",
|
||||||
|
|||||||
@ -419,17 +419,14 @@ export default class CharacterData extends VagabondActorBase {
|
|||||||
statIncreasesByLevel: new fields.ObjectField({ initial: {} }), // { "2": "might", "4": "dexterity" }
|
statIncreasesByLevel: new fields.ObjectField({ initial: {} }), // { "2": "might", "4": "dexterity" }
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Senses and vision types
|
// Senses - binary toggles, may be granted by perks/traits
|
||||||
senses: new fields.SchemaField({
|
senses: new fields.SchemaField({
|
||||||
darksight: new fields.BooleanField({ initial: false }), // Dwarf, Goblin, Orc, Infravision perk
|
allsight: new fields.BooleanField({ initial: false }),
|
||||||
blindsight: new fields.NumberField({ integer: true, initial: 0, min: 0 }), // Range in feet
|
blindsight: new fields.BooleanField({ initial: false }),
|
||||||
tremorsense: new fields.NumberField({ integer: true, initial: 0, min: 0 }), // Range in feet
|
darkvision: new fields.BooleanField({ initial: false }), // Dwarf, Goblin, Orc, Infravision perk
|
||||||
// Special vision abilities from perks/ancestry
|
echolocation: new fields.BooleanField({ initial: false }),
|
||||||
specialVision: new fields.SchemaField({
|
seismicsense: new fields.BooleanField({ initial: false }),
|
||||||
elvenEyes: new fields.BooleanField({ initial: false }), // Favor on sight Detect
|
telepathy: new fields.BooleanField({ initial: false }),
|
||||||
witchsight: new fields.BooleanField({ initial: false }), // See Invisible, Favor vs illusions
|
|
||||||
sixthSense: new fields.BooleanField({ initial: false }), // Ignore Blinded for sight-based checks
|
|
||||||
}),
|
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Known languages
|
// Known languages
|
||||||
|
|||||||
@ -113,11 +113,14 @@ export default class NPCData extends VagabondActorBase {
|
|||||||
// Being type (for targeting by certain effects)
|
// Being type (for targeting by certain effects)
|
||||||
beingType: new fields.StringField({ initial: "beast" }),
|
beingType: new fields.StringField({ initial: "beast" }),
|
||||||
|
|
||||||
// Senses (vision types)
|
// Senses - binary toggles, may be granted by abilities/traits
|
||||||
senses: new fields.SchemaField({
|
senses: new fields.SchemaField({
|
||||||
darksight: new fields.BooleanField({ initial: false }),
|
allsight: new fields.BooleanField({ initial: false }),
|
||||||
blindsight: new fields.NumberField({ integer: true, initial: 0, min: 0 }), // Range in feet
|
blindsight: new fields.BooleanField({ initial: false }),
|
||||||
tremorsense: new fields.NumberField({ integer: true, initial: 0, min: 0 }), // Range in feet
|
darkvision: new fields.BooleanField({ initial: false }),
|
||||||
|
echolocation: new fields.BooleanField({ initial: false }),
|
||||||
|
seismicsense: new fields.BooleanField({ initial: false }),
|
||||||
|
telepathy: new fields.BooleanField({ initial: false }),
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// Movement speed
|
// Movement speed
|
||||||
|
|||||||
@ -119,7 +119,12 @@ export default class VagabondNPCSheet extends VagabondActorSheet {
|
|||||||
// Senses
|
// Senses
|
||||||
context.senses = system.senses;
|
context.senses = system.senses;
|
||||||
context.hasSenses =
|
context.hasSenses =
|
||||||
system.senses.darksight || system.senses.blindsight > 0 || system.senses.tremorsense > 0;
|
system.senses.allsight ||
|
||||||
|
system.senses.blindsight ||
|
||||||
|
system.senses.darkvision ||
|
||||||
|
system.senses.echolocation ||
|
||||||
|
system.senses.seismicsense ||
|
||||||
|
system.senses.telepathy;
|
||||||
|
|
||||||
// Damage modifiers
|
// Damage modifiers
|
||||||
context.immunities = system.immunities || [];
|
context.immunities = system.immunities || [];
|
||||||
|
|||||||
@ -664,19 +664,19 @@ export function registerActorTests(quenchRunner) {
|
|||||||
describe("NPC Senses", () => {
|
describe("NPC Senses", () => {
|
||||||
it("tracks vision types for NPCs", async () => {
|
it("tracks vision types for NPCs", async () => {
|
||||||
/**
|
/**
|
||||||
* Senses determine what an NPC can perceive:
|
* Senses are binary toggles that determine what an NPC can perceive:
|
||||||
* darksight = see in darkness, blindsight/tremorsense = range in feet
|
* allsight, blindsight, darkvision, echolocation, seismicsense, telepathy
|
||||||
*/
|
*/
|
||||||
expect(testNPC.system.senses.darksight).to.equal(false);
|
expect(testNPC.system.senses.darkvision).to.equal(false);
|
||||||
expect(testNPC.system.senses.blindsight).to.equal(0);
|
expect(testNPC.system.senses.blindsight).to.equal(false);
|
||||||
|
|
||||||
await testNPC.update({
|
await testNPC.update({
|
||||||
"system.senses.darksight": true,
|
"system.senses.darkvision": true,
|
||||||
"system.senses.blindsight": 30,
|
"system.senses.blindsight": true,
|
||||||
});
|
});
|
||||||
|
|
||||||
expect(testNPC.system.senses.darksight).to.equal(true);
|
expect(testNPC.system.senses.darkvision).to.equal(true);
|
||||||
expect(testNPC.system.senses.blindsight).to.equal(30);
|
expect(testNPC.system.senses.blindsight).to.equal(true);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@ -1379,6 +1379,581 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// Magic Tab Layout
|
||||||
|
// ----------------------------------------
|
||||||
|
.magic-tab {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Magic Header (Mana & Focus)
|
||||||
|
.magic-header {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: flex-start;
|
||||||
|
gap: $spacing-4;
|
||||||
|
padding-bottom: $spacing-3;
|
||||||
|
margin-bottom: $spacing-2;
|
||||||
|
border-bottom: 2px solid $color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Mana Display - matches inventory item-slots format
|
||||||
|
.mana-display {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
margin-right: auto;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mana-values {
|
||||||
|
display: flex;
|
||||||
|
align-items: baseline;
|
||||||
|
gap: 2px;
|
||||||
|
font-family: $font-family-header;
|
||||||
|
font-size: $font-size-lg;
|
||||||
|
|
||||||
|
input {
|
||||||
|
width: 40px;
|
||||||
|
padding: 2px 4px;
|
||||||
|
font-family: $font-family-header;
|
||||||
|
font-size: $font-size-lg;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
text-align: center;
|
||||||
|
color: $color-text-primary;
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: $color-accent-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.separator {
|
||||||
|
color: $color-text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.max {
|
||||||
|
color: $color-text-secondary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.casting-max {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
margin-left: $spacing-3;
|
||||||
|
padding-left: $spacing-3;
|
||||||
|
border-left: 1px solid $color-border-light;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
color: $color-text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
color: $color-info;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus Display
|
||||||
|
.focus-display {
|
||||||
|
flex: 1;
|
||||||
|
min-width: 200px;
|
||||||
|
padding: $spacing-3;
|
||||||
|
background-color: rgba($color-warning, 0.1);
|
||||||
|
border: 1px solid rgba($color-warning, 0.3);
|
||||||
|
border-radius: $radius-md;
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 0 0 $spacing-2 0;
|
||||||
|
font-family: $font-family-header;
|
||||||
|
font-size: $font-size-base;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
color: $color-warning;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus-list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus-item {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
padding: $spacing-2;
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
|
||||||
|
.focus-spell {
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
color: $color-text-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus-target {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus-cost {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
padding: $spacing-1 $spacing-2;
|
||||||
|
background-color: rgba($color-info, 0.1);
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
color: $color-info;
|
||||||
|
margin-left: auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spells Section
|
||||||
|
.spells-section {
|
||||||
|
.section-header-row {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
margin-bottom: $spacing-2;
|
||||||
|
|
||||||
|
.section-header {
|
||||||
|
margin: 0;
|
||||||
|
padding-bottom: 0;
|
||||||
|
border-bottom: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-create {
|
||||||
|
@include flex-center;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
padding: 0;
|
||||||
|
background-color: $color-parchment;
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $radius-md;
|
||||||
|
color: $color-text-primary;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all $transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $color-success;
|
||||||
|
border-color: $color-success;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Spell List
|
||||||
|
.spell-list {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-item {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: auto 1fr auto auto;
|
||||||
|
gap: $spacing-3;
|
||||||
|
align-items: center;
|
||||||
|
padding: $spacing-3;
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
border: 1px solid $color-border-light;
|
||||||
|
border-radius: $radius-md;
|
||||||
|
transition: all $transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $color-parchment;
|
||||||
|
border-color: $color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.empty {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
padding: $spacing-4;
|
||||||
|
font-style: italic;
|
||||||
|
color: $color-text-muted;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-img {
|
||||||
|
width: 40px;
|
||||||
|
height: 40px;
|
||||||
|
object-fit: cover;
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $radius-md;
|
||||||
|
background-color: $color-parchment;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-info {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 2px;
|
||||||
|
|
||||||
|
.spell-name {
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
color: $color-text-primary;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
color: $color-accent-primary;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-type {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
text-transform: capitalize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-details {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
.spell-damage {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-1;
|
||||||
|
padding: $spacing-1 $spacing-2;
|
||||||
|
background-color: rgba($color-danger, 0.1);
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
font-family: $font-family-mono;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
color: $color-danger;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-effect {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-1;
|
||||||
|
padding: $spacing-1 $spacing-2;
|
||||||
|
background-color: rgba($color-info, 0.1);
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: $color-info;
|
||||||
|
cursor: help;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-actions {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
.spell-cast {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-1;
|
||||||
|
padding: $spacing-2 $spacing-3;
|
||||||
|
background-color: $color-info;
|
||||||
|
border: none;
|
||||||
|
border-radius: $radius-md;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
color: white;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all $transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: darken($color-info, 10%);
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.item-delete {
|
||||||
|
@include flex-center;
|
||||||
|
width: 28px;
|
||||||
|
height: 28px;
|
||||||
|
padding: 0;
|
||||||
|
background-color: transparent;
|
||||||
|
border: 1px solid $color-border-light;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
color: $color-text-muted;
|
||||||
|
cursor: pointer;
|
||||||
|
transition: all $transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: rgba($color-danger, 0.1);
|
||||||
|
border-color: $color-danger;
|
||||||
|
color: $color-danger;
|
||||||
|
}
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Casting Reference
|
||||||
|
.casting-reference {
|
||||||
|
padding: $spacing-3;
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
border: 1px solid $color-border-light;
|
||||||
|
border-radius: $radius-md;
|
||||||
|
|
||||||
|
> h3 {
|
||||||
|
margin: 0 0 $spacing-3 0;
|
||||||
|
font-family: $font-family-header;
|
||||||
|
font-size: $font-size-base;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
padding-bottom: $spacing-2;
|
||||||
|
border-bottom: 1px solid $color-border-light;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reference-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: $spacing-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.reference-section {
|
||||||
|
h4 {
|
||||||
|
margin: 0 0 $spacing-2 0;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
color: $color-text-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
ul {
|
||||||
|
list-style: none;
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-1;
|
||||||
|
|
||||||
|
li {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
line-height: $line-height-normal;
|
||||||
|
|
||||||
|
strong {
|
||||||
|
color: $color-text-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Responsive magic layout
|
||||||
|
@container sheet-content (max-width: 500px) {
|
||||||
|
.magic-header {
|
||||||
|
flex-direction: column;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-item {
|
||||||
|
grid-template-columns: auto 1fr;
|
||||||
|
grid-template-rows: auto auto;
|
||||||
|
|
||||||
|
.spell-img {
|
||||||
|
grid-row: span 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-details {
|
||||||
|
grid-column: 2;
|
||||||
|
justify-content: flex-start;
|
||||||
|
}
|
||||||
|
|
||||||
|
.spell-actions {
|
||||||
|
grid-column: 1 / -1;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.casting-reference .reference-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------
|
||||||
|
// Biography Tab Layout
|
||||||
|
// ----------------------------------------
|
||||||
|
.biography-tab {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-4;
|
||||||
|
}
|
||||||
|
|
||||||
|
.biography-section {
|
||||||
|
// Hide languages section - not yet implemented
|
||||||
|
&.languages {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Character Details (Size, Being Type)
|
||||||
|
.details-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
gap: $spacing-3;
|
||||||
|
|
||||||
|
.detail-field {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-1;
|
||||||
|
|
||||||
|
label {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.05em;
|
||||||
|
color: $color-text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
@include input-base;
|
||||||
|
padding: $spacing-2;
|
||||||
|
font-size: $font-size-base;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
border-color: $color-accent-primary;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Senses Section
|
||||||
|
.senses-grid {
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: $spacing-3;
|
||||||
|
|
||||||
|
.sense-field {
|
||||||
|
label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
font-weight: $font-weight-medium;
|
||||||
|
color: $color-text-primary;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: $spacing-2;
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
border: 1px solid $color-border-light;
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
transition: all $transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: $color-parchment;
|
||||||
|
border-color: $color-border;
|
||||||
|
}
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: 16px;
|
||||||
|
height: 16px;
|
||||||
|
cursor: pointer;
|
||||||
|
accent-color: $color-accent-primary;
|
||||||
|
|
||||||
|
&:checked + span,
|
||||||
|
&:checked ~ span {
|
||||||
|
color: $color-accent-primary;
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Style when checkbox is checked
|
||||||
|
&:has(input:checked) label {
|
||||||
|
background-color: rgba($color-success, 0.1);
|
||||||
|
border-color: rgba($color-success, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Biography & Notes Text Areas
|
||||||
|
.biography-text,
|
||||||
|
.notes {
|
||||||
|
.editor-container {
|
||||||
|
background-color: $color-parchment-light;
|
||||||
|
border: 1px solid $color-border;
|
||||||
|
border-radius: $radius-md;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
width: 100%;
|
||||||
|
min-height: 150px;
|
||||||
|
padding: $spacing-3;
|
||||||
|
font-family: $font-family-body;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
line-height: $line-height-relaxed;
|
||||||
|
color: $color-text-primary;
|
||||||
|
background-color: transparent;
|
||||||
|
border: none;
|
||||||
|
resize: vertical;
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&::placeholder {
|
||||||
|
color: $color-text-muted;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Biography gets more height
|
||||||
|
.biography-text textarea {
|
||||||
|
min-height: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Responsive biography layout
|
||||||
|
@container sheet-content (max-width: 500px) {
|
||||||
|
.details-grid {
|
||||||
|
grid-template-columns: 1fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
.senses-grid {
|
||||||
|
grid-template-columns: repeat(2, 1fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==========================================
|
// ==========================================
|
||||||
|
|||||||
@ -46,22 +46,45 @@
|
|||||||
<div class="senses-grid">
|
<div class="senses-grid">
|
||||||
<div class="sense-field">
|
<div class="sense-field">
|
||||||
<label>
|
<label>
|
||||||
<input type="checkbox" name="system.senses.darksight"
|
<input type="checkbox" name="system.senses.allsight"
|
||||||
{{#if system.senses.darksight}}checked{{/if}} />
|
{{#if system.senses.allsight}}checked{{/if}} />
|
||||||
{{localize "VAGABOND.Darksight"}}
|
{{localize "VAGABOND.Allsight"}}
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="sense-field">
|
<div class="sense-field">
|
||||||
<label>{{localize "VAGABOND.Blindsight"}}</label>
|
<label>
|
||||||
<input type="number" name="system.senses.blindsight"
|
<input type="checkbox" name="system.senses.blindsight"
|
||||||
value="{{system.senses.blindsight}}" min="0" />
|
{{#if system.senses.blindsight}}checked{{/if}} />
|
||||||
<span class="unit">ft</span>
|
{{localize "VAGABOND.Blindsight"}}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<div class="sense-field">
|
<div class="sense-field">
|
||||||
<label>{{localize "VAGABOND.Tremorsense"}}</label>
|
<label>
|
||||||
<input type="number" name="system.senses.tremorsense"
|
<input type="checkbox" name="system.senses.darkvision"
|
||||||
value="{{system.senses.tremorsense}}" min="0" />
|
{{#if system.senses.darkvision}}checked{{/if}} />
|
||||||
<span class="unit">ft</span>
|
{{localize "VAGABOND.Darkvision"}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="sense-field">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="system.senses.echolocation"
|
||||||
|
{{#if system.senses.echolocation}}checked{{/if}} />
|
||||||
|
{{localize "VAGABOND.Echolocation"}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="sense-field">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="system.senses.seismicsense"
|
||||||
|
{{#if system.senses.seismicsense}}checked{{/if}} />
|
||||||
|
{{localize "VAGABOND.Seismicsense"}}
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="sense-field">
|
||||||
|
<label>
|
||||||
|
<input type="checkbox" name="system.senses.telepathy"
|
||||||
|
{{#if system.senses.telepathy}}checked{{/if}} />
|
||||||
|
{{localize "VAGABOND.Telepathy"}}
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -84,14 +84,23 @@
|
|||||||
{{#if hasSenses}}
|
{{#if hasSenses}}
|
||||||
<div class="senses-row">
|
<div class="senses-row">
|
||||||
<label>{{localize "VAGABOND.Senses"}}:</label>
|
<label>{{localize "VAGABOND.Senses"}}:</label>
|
||||||
{{#if senses.darksight}}
|
{{#if senses.allsight}}
|
||||||
<span class="sense-tag">{{localize "VAGABOND.Darksight"}}</span>
|
<span class="sense-tag">{{localize "VAGABOND.Allsight"}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if senses.blindsight}}
|
{{#if senses.blindsight}}
|
||||||
<span class="sense-tag">{{localize "VAGABOND.Blindsight"}} {{senses.blindsight}} ft</span>
|
<span class="sense-tag">{{localize "VAGABOND.Blindsight"}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
{{#if senses.tremorsense}}
|
{{#if senses.darkvision}}
|
||||||
<span class="sense-tag">{{localize "VAGABOND.Tremorsense"}} {{senses.tremorsense}} ft</span>
|
<span class="sense-tag">{{localize "VAGABOND.Darkvision"}}</span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if senses.echolocation}}
|
||||||
|
<span class="sense-tag">{{localize "VAGABOND.Echolocation"}}</span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if senses.seismicsense}}
|
||||||
|
<span class="sense-tag">{{localize "VAGABOND.Seismicsense"}}</span>
|
||||||
|
{{/if}}
|
||||||
|
{{#if senses.telepathy}}
|
||||||
|
<span class="sense-tag">{{localize "VAGABOND.Telepathy"}}</span>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
{{/if}}
|
{{/if}}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user