Add light/dark theme system with CSS variables, fix ProseMirror editors
Theme System:
- Add _theme-variables.scss with light (parchment) and dark color palettes
- Register theme options in system.json for Foundry v13 color scheme support
- Convert all SCSS color variables to CSS custom properties
- Update base, mixins, components, and sheet styles for theme support
- Add _applyThemeClass() to actor and item sheet classes
ProseMirror Editor Fix (v13 ApplicationV2):
- Replace {{editor}} helper with <prose-mirror> custom element
- Add TextEditor.enrichHTML() for rich text content preparation
- Update all 8 item templates (spell, weapon, armor, equipment, etc.)
- Fix toolbar hiding content by renaming wrapper to .editor-wrapper
- Style prose-mirror with sticky toolbar and proper flex layout
Roll Dialog & Chat Card Styling:
- Complete roll dialog styling with favor/hinder toggles, info panels
- Complete chat card styling with roll results, damage display, animations
- Mark tasks 5.7 and 5.8 complete in roadmap
- Add task 5.11 for deferred resizable editor feature
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
parent
5ddd33c41c
commit
8b9daa1f36
BIN
.claude/references/Vagabond_-_Hero_Record_Interactive_PDF.pdf
Executable file
BIN
.claude/references/Vagabond_-_Hero_Record_Interactive_PDF.pdf
Executable file
Binary file not shown.
BIN
.claude/references/Vagabond_-_Hero_Record_Print.pdf
Executable file
BIN
.claude/references/Vagabond_-_Hero_Record_Print.pdf
Executable file
Binary file not shown.
BIN
.claude/references/Vagabond_RPG_-_Pulp_Fantasy_Core_Rulebook_Interactive_PDF.pdf
Executable file
BIN
.claude/references/Vagabond_RPG_-_Pulp_Fantasy_Core_Rulebook_Interactive_PDF.pdf
Executable file
Binary file not shown.
@ -118,6 +118,10 @@ cd ~/.claude/skills/notediscovery && python client.py search "keyword"
|
|||||||
Original PDF at: `/mnt/NV2/Development/claude-home/gaming/Vagabond_RPG_-_Pulp_Fantasy_Core_Rulebook_Interactive_PDF.pdf`
|
Original PDF at: `/mnt/NV2/Development/claude-home/gaming/Vagabond_RPG_-_Pulp_Fantasy_Core_Rulebook_Interactive_PDF.pdf`
|
||||||
Character sheet reference: `/mnt/NV2/Development/claude-home/gaming/Vagabond_-_Hero_Record_Interactive_PDF.pdf`
|
Character sheet reference: `/mnt/NV2/Development/claude-home/gaming/Vagabond_-_Hero_Record_Interactive_PDF.pdf`
|
||||||
|
|
||||||
|
## Reference Project Documentation
|
||||||
|
|
||||||
|
The D&D 5e Foundry system is very well documented here: https://deepwiki.com/foundryvtt/dnd5e/1-dnd5e-system-overview
|
||||||
|
|
||||||
## Project Roadmap
|
## Project Roadmap
|
||||||
|
|
||||||
See `PROJECT_ROADMAP.json` for complete task breakdown with dependencies.
|
See `PROJECT_ROADMAP.json` for complete task breakdown with dependencies.
|
||||||
|
|||||||
@ -680,28 +680,31 @@
|
|||||||
"id": "5.6",
|
"id": "5.6",
|
||||||
"name": "Style Item sheets",
|
"name": "Style Item sheets",
|
||||||
"description": "Consistent look across all item types, clear form layouts",
|
"description": "Consistent look across all item types, clear form layouts",
|
||||||
"completed": false,
|
"completed": true,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "medium",
|
"priority": "medium",
|
||||||
"dependencies": ["5.1", "5.2", "5.3", "4.1"]
|
"dependencies": ["5.1", "5.2", "5.3", "4.1"],
|
||||||
|
"notes": "Styled all 8 item types with: header (image with hover effect, styled name input, color-coded type badges), tab navigation, form inputs (transitions, focus states, disabled states), fieldsets, properties grids, type-specific sections (traits, prerequisites, progression tables, features, relic sections, spell effects). Added .hidden utility for tab switching, custom scrollbar, flexbox layout for proper scrolling. ALSO IMPLEMENTED: Light/Dark theme system with CSS custom properties - registered themes in system.json, created _theme-variables.scss with light (parchment) and dark color palettes, converted all SCSS color variables to CSS custom properties across base, mixins, components, and sheet styles."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "5.7",
|
"id": "5.7",
|
||||||
"name": "Style roll dialogs",
|
"name": "Style roll dialogs",
|
||||||
"description": "Favor/Hinder toggles, modifier inputs, clear roll button",
|
"description": "Favor/Hinder toggles, modifier inputs, clear roll button",
|
||||||
"completed": false,
|
"completed": true,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "medium",
|
"priority": "medium",
|
||||||
"dependencies": ["5.1", "5.2"]
|
"dependencies": ["5.1", "5.2"],
|
||||||
|
"notes": "Comprehensive styling in _roll-dialog.scss (950 lines): ApplicationV2 dialogs with themed backgrounds, skill/weapon/save/spell selections, info panels with difficulty/crit display, favor/hinder toggles with active states, damage preview, mana display for spells, focus warnings, legacy dialog support, Favor/Hinder Debug Panel."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "5.8",
|
"id": "5.8",
|
||||||
"name": "Style chat cards",
|
"name": "Style chat cards",
|
||||||
"description": "Roll results, spell casts, attack outcomes in themed chat messages",
|
"description": "Roll results, spell casts, attack outcomes in themed chat messages",
|
||||||
"completed": false,
|
"completed": true,
|
||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "medium",
|
"priority": "medium",
|
||||||
"dependencies": ["5.1", "5.2"]
|
"dependencies": ["5.1", "5.2"],
|
||||||
|
"notes": "Comprehensive styling in _chat-cards.scss (577 lines): Card headers with icons and badges, roll results with success/failure/critical/fumble states, roll breakdown display, damage sections with critical highlighting, weapon properties, spell cards with mana cost and focus indicator, animations for crits and fumbles."
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "5.9",
|
"id": "5.9",
|
||||||
@ -711,6 +714,26 @@
|
|||||||
"tested": false,
|
"tested": false,
|
||||||
"priority": "high",
|
"priority": "high",
|
||||||
"dependencies": ["5.4", "5.5", "5.6"]
|
"dependencies": ["5.4", "5.5", "5.6"]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "5.10",
|
||||||
|
"name": "Investigate per-sheet theming in Foundry v13",
|
||||||
|
"description": "Per-sheet theme selection via Configure Sheet dialog doesn't work - Foundry v13 shows theme options but doesn't store selection in document flags or apply theme classes to ApplicationV2 sheets. Infrastructure exists (CSS variables, _applyThemeClass JS), need to find correct Foundry API for per-sheet theme storage. Global theme switching works via Settings > Color Scheme.",
|
||||||
|
"completed": false,
|
||||||
|
"tested": false,
|
||||||
|
"priority": "low",
|
||||||
|
"dependencies": ["5.6"],
|
||||||
|
"notes": "CSS infrastructure complete in _theme-variables.scss. JS _applyThemeClass() in base-actor-sheet.mjs and base-item-sheet.mjs applies theme class based on settings. Current workaround: use global Foundry color scheme (Settings > Configure Settings > Color Scheme > Applications). Per-sheet theme dropdown in Configure Sheet appears but selection not persisted to document.flags.core.sheetTheme."
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "5.11",
|
||||||
|
"name": "Add resizable editor containers",
|
||||||
|
"description": "Allow users to drag-resize ProseMirror editor text boxes on item sheets for viewing/editing longer content. CSS resize:vertical not working with Foundry's prose-mirror element structure.",
|
||||||
|
"completed": false,
|
||||||
|
"tested": false,
|
||||||
|
"priority": "low",
|
||||||
|
"dependencies": ["5.6"],
|
||||||
|
"notes": "Editors functional with prose-mirror element in v13 ApplicationV2. Resize handle not appearing despite CSS - may need JavaScript-based resize or different approach. Foundry's internal .editor-container conflicts with custom wrapper naming."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
|||||||
@ -2,6 +2,9 @@
|
|||||||
"VAGABOND.SystemName": "Vagabond RPG",
|
"VAGABOND.SystemName": "Vagabond RPG",
|
||||||
"VAGABOND.SystemDescription": "A Foundry VTT system for Vagabond RPG - Pulp Fantasy Roleplaying",
|
"VAGABOND.SystemDescription": "A Foundry VTT system for Vagabond RPG - Pulp Fantasy Roleplaying",
|
||||||
|
|
||||||
|
"VAGABOND.ThemeLight": "Light (Parchment)",
|
||||||
|
"VAGABOND.ThemeDark": "Dark",
|
||||||
|
|
||||||
"VAGABOND.SheetCharacter": "Character Sheet",
|
"VAGABOND.SheetCharacter": "Character Sheet",
|
||||||
"VAGABOND.SheetNPC": "NPC Sheet",
|
"VAGABOND.SheetNPC": "NPC Sheet",
|
||||||
"VAGABOND.SheetItem": "Item Sheet",
|
"VAGABOND.SheetItem": "Item Sheet",
|
||||||
|
|||||||
@ -44,7 +44,7 @@ export default class VagabondRollDialog extends HandlebarsApplicationMixin(Appli
|
|||||||
/** @override */
|
/** @override */
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
id: "vagabond-roll-dialog",
|
id: "vagabond-roll-dialog",
|
||||||
classes: ["vagabond", "roll-dialog"],
|
classes: ["vagabond", "roll-dialog", "themed"],
|
||||||
tag: "form",
|
tag: "form",
|
||||||
window: {
|
window: {
|
||||||
title: "VAGABOND.RollDialog",
|
title: "VAGABOND.RollDialog",
|
||||||
@ -143,6 +143,9 @@ export default class VagabondRollDialog extends HandlebarsApplicationMixin(Appli
|
|||||||
_onRender(context, options) {
|
_onRender(context, options) {
|
||||||
super._onRender(context, options);
|
super._onRender(context, options);
|
||||||
|
|
||||||
|
// Apply theme class based on configured theme
|
||||||
|
this._applyThemeClass();
|
||||||
|
|
||||||
// Favor/Hinder toggle buttons
|
// Favor/Hinder toggle buttons
|
||||||
const favorBtn = this.element.querySelector('[data-action="toggle-favor"]');
|
const favorBtn = this.element.querySelector('[data-action="toggle-favor"]');
|
||||||
const hinderBtn = this.element.querySelector('[data-action="toggle-hinder"]');
|
const hinderBtn = this.element.querySelector('[data-action="toggle-hinder"]');
|
||||||
@ -166,6 +169,40 @@ export default class VagabondRollDialog extends HandlebarsApplicationMixin(Appli
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the configured theme class to the dialog element.
|
||||||
|
* Foundry v13 doesn't automatically add theme classes to ApplicationV2,
|
||||||
|
* so we handle it manually.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_applyThemeClass() {
|
||||||
|
if (!this.element) return;
|
||||||
|
|
||||||
|
// Remove any existing theme classes
|
||||||
|
this.element.classList.remove("theme-light", "theme-dark");
|
||||||
|
|
||||||
|
// Check global preference
|
||||||
|
let theme = null;
|
||||||
|
try {
|
||||||
|
const uiConfig = game.settings.get("core", "uiConfig");
|
||||||
|
const colorScheme = uiConfig?.colorScheme?.applications;
|
||||||
|
if (colorScheme === "dark") {
|
||||||
|
theme = "dark";
|
||||||
|
} else if (colorScheme === "light") {
|
||||||
|
theme = "light";
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Settings not available, use default
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the theme class
|
||||||
|
if (theme === "dark") {
|
||||||
|
this.element.classList.add("theme-dark");
|
||||||
|
} else if (theme === "light") {
|
||||||
|
this.element.classList.add("theme-light");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Toggle favor on/off.
|
* Toggle favor on/off.
|
||||||
* @private
|
* @private
|
||||||
|
|||||||
@ -26,7 +26,7 @@ export default class FavorHinderDebug extends HandlebarsApplicationMixin(Applica
|
|||||||
/** @override */
|
/** @override */
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
id: "vagabond-favor-hinder-debug",
|
id: "vagabond-favor-hinder-debug",
|
||||||
classes: ["vagabond", "favor-hinder-debug"],
|
classes: ["vagabond", "favor-hinder-debug", "themed"],
|
||||||
tag: "div",
|
tag: "div",
|
||||||
window: {
|
window: {
|
||||||
title: "Favor/Hinder Debug",
|
title: "Favor/Hinder Debug",
|
||||||
@ -174,6 +174,9 @@ export default class FavorHinderDebug extends HandlebarsApplicationMixin(Applica
|
|||||||
_onRender(context, options) {
|
_onRender(context, options) {
|
||||||
super._onRender(context, options);
|
super._onRender(context, options);
|
||||||
|
|
||||||
|
// Apply theme class based on configured theme
|
||||||
|
this._applyThemeClass();
|
||||||
|
|
||||||
// Actor selection dropdown
|
// Actor selection dropdown
|
||||||
const actorSelect = this.element.querySelector('[name="actorId"]');
|
const actorSelect = this.element.querySelector('[name="actorId"]');
|
||||||
actorSelect?.addEventListener("change", (event) => {
|
actorSelect?.addEventListener("change", (event) => {
|
||||||
@ -319,6 +322,40 @@ export default class FavorHinderDebug extends HandlebarsApplicationMixin(Applica
|
|||||||
SkillCheckDialog.prompt(this.actor);
|
SkillCheckDialog.prompt(this.actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the configured theme class to the dialog element.
|
||||||
|
* Foundry v13 doesn't automatically add theme classes to ApplicationV2,
|
||||||
|
* so we handle it manually.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_applyThemeClass() {
|
||||||
|
if (!this.element) return;
|
||||||
|
|
||||||
|
// Remove any existing theme classes
|
||||||
|
this.element.classList.remove("theme-light", "theme-dark");
|
||||||
|
|
||||||
|
// Check global preference
|
||||||
|
let theme = null;
|
||||||
|
try {
|
||||||
|
const uiConfig = game.settings.get("core", "uiConfig");
|
||||||
|
const colorScheme = uiConfig?.colorScheme?.applications;
|
||||||
|
if (colorScheme === "dark") {
|
||||||
|
theme = "dark";
|
||||||
|
} else if (colorScheme === "light") {
|
||||||
|
theme = "light";
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Settings not available, use default
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the theme class
|
||||||
|
if (theme === "dark") {
|
||||||
|
this.element.classList.add("theme-dark");
|
||||||
|
} else if (theme === "light") {
|
||||||
|
this.element.classList.add("theme-light");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
/* Static Methods */
|
/* Static Methods */
|
||||||
/* -------------------------------------------- */
|
/* -------------------------------------------- */
|
||||||
|
|||||||
@ -38,7 +38,7 @@ export default class VagabondActorSheet extends HandlebarsApplicationMixin(Actor
|
|||||||
/** @override */
|
/** @override */
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
id: "vagabond-actor-sheet-{id}",
|
id: "vagabond-actor-sheet-{id}",
|
||||||
classes: ["vagabond", "sheet", "actor"],
|
classes: ["vagabond", "sheet", "actor", "themed"],
|
||||||
tag: "form",
|
tag: "form",
|
||||||
window: {
|
window: {
|
||||||
title: "VAGABOND.ActorSheet",
|
title: "VAGABOND.ActorSheet",
|
||||||
@ -271,6 +271,9 @@ export default class VagabondActorSheet extends HandlebarsApplicationMixin(Actor
|
|||||||
_onRender(context, options) {
|
_onRender(context, options) {
|
||||||
super._onRender(context, options);
|
super._onRender(context, options);
|
||||||
|
|
||||||
|
// Apply theme class based on configured theme
|
||||||
|
this._applyThemeClass();
|
||||||
|
|
||||||
// Remove stale tab content (ApplicationV2 appends parts without removing old ones)
|
// Remove stale tab content (ApplicationV2 appends parts without removing old ones)
|
||||||
this._cleanupInactiveTabs();
|
this._cleanupInactiveTabs();
|
||||||
|
|
||||||
@ -284,6 +287,49 @@ export default class VagabondActorSheet extends HandlebarsApplicationMixin(Actor
|
|||||||
this._initializeEditors();
|
this._initializeEditors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the configured theme class to the sheet element.
|
||||||
|
* Foundry v13 doesn't automatically add theme classes to ApplicationV2 sheets,
|
||||||
|
* so we handle it manually.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_applyThemeClass() {
|
||||||
|
if (!this.element) return;
|
||||||
|
|
||||||
|
// Remove any existing theme classes
|
||||||
|
this.element.classList.remove("theme-light", "theme-dark");
|
||||||
|
|
||||||
|
// Get the configured theme for this sheet
|
||||||
|
// DocumentSheetConfig stores per-document and per-type theme preferences
|
||||||
|
const sheetConfig = this.document.getFlag("core", "sheetTheme");
|
||||||
|
const typeConfig = game.settings.get("core", "sheetClasses")?.[this.document.documentName]?.[
|
||||||
|
this.document.type
|
||||||
|
];
|
||||||
|
const defaultTheme = typeConfig?.defaultTheme;
|
||||||
|
|
||||||
|
// Determine which theme to apply: document-specific > type default > global
|
||||||
|
let theme = sheetConfig || defaultTheme;
|
||||||
|
|
||||||
|
// If no specific theme, check global preference
|
||||||
|
if (!theme) {
|
||||||
|
const uiConfig = game.settings.get("core", "uiConfig");
|
||||||
|
const colorScheme = uiConfig?.colorScheme?.applications;
|
||||||
|
if (colorScheme === "dark") {
|
||||||
|
theme = "dark";
|
||||||
|
} else if (colorScheme === "light") {
|
||||||
|
theme = "light";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the theme class
|
||||||
|
if (theme === "dark") {
|
||||||
|
this.element.classList.add("theme-dark");
|
||||||
|
} else if (theme === "light") {
|
||||||
|
this.element.classList.add("theme-light");
|
||||||
|
}
|
||||||
|
// If still no theme, it will use body.theme-dark/light via CSS
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove tab content sections that don't match the active tab.
|
* Remove tab content sections that don't match the active tab.
|
||||||
* ApplicationV2's parts rendering appends new parts without removing old ones,
|
* ApplicationV2's parts rendering appends new parts without removing old ones,
|
||||||
@ -581,7 +627,7 @@ export default class VagabondActorSheet extends HandlebarsApplicationMixin(Actor
|
|||||||
const weaponId = target.dataset.weaponId;
|
const weaponId = target.dataset.weaponId;
|
||||||
|
|
||||||
const { AttackRollDialog } = game.vagabond.applications;
|
const { AttackRollDialog } = game.vagabond.applications;
|
||||||
await AttackRollDialog.prompt(this.actor, { weaponId });
|
await AttackRollDialog.prompt(this.actor, weaponId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -594,11 +640,8 @@ export default class VagabondActorSheet extends HandlebarsApplicationMixin(Actor
|
|||||||
const spellId = target.dataset.spellId;
|
const spellId = target.dataset.spellId;
|
||||||
if (!spellId) return;
|
if (!spellId) return;
|
||||||
|
|
||||||
const spell = this.actor.items.get(spellId);
|
|
||||||
if (!spell) return;
|
|
||||||
|
|
||||||
const { SpellCastDialog } = game.vagabond.applications;
|
const { SpellCastDialog } = game.vagabond.applications;
|
||||||
await SpellCastDialog.prompt(this.actor, { spell });
|
await SpellCastDialog.prompt(this.actor, spellId);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@ -34,7 +34,7 @@ export default class VagabondItemSheet extends HandlebarsApplicationMixin(ItemSh
|
|||||||
/** @override */
|
/** @override */
|
||||||
static DEFAULT_OPTIONS = {
|
static DEFAULT_OPTIONS = {
|
||||||
id: "vagabond-item-sheet-{id}",
|
id: "vagabond-item-sheet-{id}",
|
||||||
classes: ["vagabond", "sheet", "item"],
|
classes: ["vagabond", "sheet", "item", "themed"],
|
||||||
tag: "form",
|
tag: "form",
|
||||||
window: {
|
window: {
|
||||||
title: "VAGABOND.ItemSheet",
|
title: "VAGABOND.ItemSheet",
|
||||||
@ -163,6 +163,39 @@ export default class VagabondItemSheet extends HandlebarsApplicationMixin(ItemSh
|
|||||||
// Active Effects on this item
|
// Active Effects on this item
|
||||||
context.effects = this._prepareEffects();
|
context.effects = this._prepareEffects();
|
||||||
|
|
||||||
|
// Enrich HTML content for ProseMirror editors
|
||||||
|
// ApplicationV2 requires enriched HTML to be prepared in context
|
||||||
|
const enrichOptions = {
|
||||||
|
secrets: this.item.isOwner,
|
||||||
|
rollData: context.rollData,
|
||||||
|
relativeTo: this.item,
|
||||||
|
};
|
||||||
|
const TextEditorImpl = foundry.applications.ux.TextEditor.implementation;
|
||||||
|
context.enrichedDescription = await TextEditorImpl.enrichHTML(
|
||||||
|
this.item.system.description ?? "",
|
||||||
|
enrichOptions
|
||||||
|
);
|
||||||
|
|
||||||
|
// Enrich spell-specific fields
|
||||||
|
if (this.item.type === "spell") {
|
||||||
|
context.enrichedEffect = await TextEditorImpl.enrichHTML(
|
||||||
|
this.item.system.effect ?? "",
|
||||||
|
enrichOptions
|
||||||
|
);
|
||||||
|
context.enrichedCritEffect = await TextEditorImpl.enrichHTML(
|
||||||
|
this.item.system.critEffect ?? "",
|
||||||
|
enrichOptions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enrich class-specific fields
|
||||||
|
if (this.item.type === "class") {
|
||||||
|
context.enrichedStartingPack = await TextEditorImpl.enrichHTML(
|
||||||
|
this.item.system.startingPack ?? "",
|
||||||
|
enrichOptions
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Type-specific context
|
// Type-specific context
|
||||||
await this._prepareTypeContext(context, options);
|
await this._prepareTypeContext(context, options);
|
||||||
|
|
||||||
@ -205,6 +238,9 @@ export default class VagabondItemSheet extends HandlebarsApplicationMixin(ItemSh
|
|||||||
_onRender(context, options) {
|
_onRender(context, options) {
|
||||||
super._onRender(context, options);
|
super._onRender(context, options);
|
||||||
|
|
||||||
|
// Apply theme class based on configured theme
|
||||||
|
this._applyThemeClass();
|
||||||
|
|
||||||
// Clean up inactive tabs if using tabs
|
// Clean up inactive tabs if using tabs
|
||||||
if (this.hasTabs) {
|
if (this.hasTabs) {
|
||||||
this._cleanupInactiveTabs();
|
this._cleanupInactiveTabs();
|
||||||
@ -214,6 +250,46 @@ export default class VagabondItemSheet extends HandlebarsApplicationMixin(ItemSh
|
|||||||
this._initializeEditors();
|
this._initializeEditors();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Apply the configured theme class to the sheet element.
|
||||||
|
* Foundry v13 doesn't automatically add theme classes to ApplicationV2 sheets,
|
||||||
|
* so we handle it manually.
|
||||||
|
* @protected
|
||||||
|
*/
|
||||||
|
_applyThemeClass() {
|
||||||
|
if (!this.element) return;
|
||||||
|
|
||||||
|
// Remove any existing theme classes
|
||||||
|
this.element.classList.remove("theme-light", "theme-dark");
|
||||||
|
|
||||||
|
// Try to get per-sheet theme (location TBD - Foundry v13 storage unclear)
|
||||||
|
// TODO: Find correct API for per-sheet theme in Foundry v13
|
||||||
|
const sheetConfig = this.document.getFlag("core", "sheetTheme");
|
||||||
|
const sheetClasses = game.settings.get("core", "sheetClasses");
|
||||||
|
const typeConfig = sheetClasses?.[this.document.documentName]?.[this.document.type];
|
||||||
|
|
||||||
|
// Determine which theme to apply: document-specific > type default > global
|
||||||
|
let theme = sheetConfig || typeConfig?.defaultTheme;
|
||||||
|
|
||||||
|
// If no specific theme, check global preference
|
||||||
|
if (!theme) {
|
||||||
|
const uiConfig = game.settings.get("core", "uiConfig");
|
||||||
|
const colorScheme = uiConfig?.colorScheme?.applications;
|
||||||
|
if (colorScheme === "dark") {
|
||||||
|
theme = "dark";
|
||||||
|
} else if (colorScheme === "light") {
|
||||||
|
theme = "light";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the theme class
|
||||||
|
if (theme === "dark") {
|
||||||
|
this.element.classList.add("theme-dark");
|
||||||
|
} else if (theme === "light") {
|
||||||
|
this.element.classList.add("theme-light");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove tab content sections that don't match the active tab.
|
* Remove tab content sections that don't match the active tab.
|
||||||
* ApplicationV2's parts rendering appends new parts without removing old ones.
|
* ApplicationV2's parts rendering appends new parts without removing old ones.
|
||||||
|
|||||||
@ -7,7 +7,7 @@
|
|||||||
font-family: $font-family-body;
|
font-family: $font-family-body;
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
line-height: $line-height-normal;
|
line-height: $line-height-normal;
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
|
|
||||||
// Box sizing
|
// Box sizing
|
||||||
*,
|
*,
|
||||||
@ -18,12 +18,12 @@
|
|||||||
|
|
||||||
// Links
|
// Links
|
||||||
a {
|
a {
|
||||||
color: $color-accent-primary;
|
color: var(--color-accent-primary);
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
transition: color $transition-fast;
|
transition: color $transition-fast;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $color-accent-secondary;
|
color: var(--color-accent-secondary);
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -40,7 +40,7 @@
|
|||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
line-height: $line-height-tight;
|
line-height: $line-height-tight;
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
margin: 0 0 $spacing-2 0;
|
margin: 0 0 $spacing-2 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,18 +100,18 @@
|
|||||||
td {
|
td {
|
||||||
padding: $spacing-2 $spacing-3;
|
padding: $spacing-2 $spacing-3;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-bottom: 1px solid $color-border-light;
|
border-bottom: 1px solid var(--color-border-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
font-weight: $font-weight-semibold;
|
font-weight: $font-weight-semibold;
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Horizontal rule
|
// Horizontal rule
|
||||||
hr {
|
hr {
|
||||||
border: none;
|
border: none;
|
||||||
border-top: 1px solid $color-border;
|
border-top: 1px solid var(--color-border);
|
||||||
margin: $spacing-4 0;
|
margin: $spacing-4 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -120,7 +120,7 @@
|
|||||||
font-family: $font-family-mono;
|
font-family: $font-family-mono;
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
padding: $spacing-1 $spacing-2;
|
padding: $spacing-1 $spacing-2;
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
border-radius: $radius-sm;
|
border-radius: $radius-sm;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,48 +128,41 @@
|
|||||||
blockquote {
|
blockquote {
|
||||||
margin: 0 0 $spacing-4 0;
|
margin: 0 0 $spacing-4 0;
|
||||||
padding: $spacing-3 $spacing-4;
|
padding: $spacing-3 $spacing-4;
|
||||||
border-left: 3px solid $color-accent-primary;
|
border-left: 3px solid var(--color-accent-primary);
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Selection
|
// Selection
|
||||||
::selection {
|
::selection {
|
||||||
background-color: $color-accent-highlight;
|
background-color: var(--color-accent-highlight);
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Foundry sheet wrapper styles
|
// Foundry sheet wrapper styles
|
||||||
.sheet.vagabond {
|
.sheet.vagabond {
|
||||||
@include custom-scrollbar;
|
@include custom-scrollbar;
|
||||||
background: $color-parchment;
|
background: var(--color-bg-primary);
|
||||||
background-image: linear-gradient(
|
|
||||||
to bottom,
|
|
||||||
rgba($color-parchment-light, 0.3) 0%,
|
|
||||||
transparent 5%,
|
|
||||||
transparent 95%,
|
|
||||||
rgba($color-parchment-dark, 0.3) 100%
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Window header customization
|
// Window header customization
|
||||||
.window-app.vagabond {
|
.window-app.vagabond {
|
||||||
.window-header {
|
.window-header {
|
||||||
background: linear-gradient(to bottom, $color-parchment-dark, $color-parchment-darker);
|
background: linear-gradient(to bottom, var(--color-bg-secondary), var(--color-bg-tertiary));
|
||||||
border-bottom: 2px solid $color-border-dark;
|
border-bottom: 2px solid var(--color-border-dark);
|
||||||
|
|
||||||
.window-title {
|
.window-title {
|
||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-size: $font-size-lg;
|
font-size: $font-size-lg;
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-button {
|
.header-button {
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,7 +32,7 @@
|
|||||||
font-size: $size;
|
font-size: $size;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
line-height: $line-height-tight;
|
line-height: $line-height-tight;
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin body-text($size: $font-size-base) {
|
@mixin body-text($size: $font-size-base) {
|
||||||
@ -40,7 +40,7 @@
|
|||||||
font-size: $size;
|
font-size: $size;
|
||||||
font-weight: $font-weight-normal;
|
font-weight: $font-weight-normal;
|
||||||
line-height: $line-height-normal;
|
line-height: $line-height-normal;
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Buttons
|
// Buttons
|
||||||
@ -60,7 +60,7 @@
|
|||||||
transition: all $transition-fast;
|
transition: all $transition-fast;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: 2px solid $color-accent-primary;
|
outline: 2px solid var(--color-accent-primary);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,23 +72,23 @@
|
|||||||
|
|
||||||
@mixin button-primary {
|
@mixin button-primary {
|
||||||
@include button-base;
|
@include button-base;
|
||||||
background-color: $color-accent-primary;
|
background-color: var(--color-accent-primary);
|
||||||
color: $color-text-inverse;
|
color: var(--color-text-inverse);
|
||||||
border-color: $color-accent-secondary;
|
border-color: var(--color-accent-secondary);
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
background-color: $color-accent-secondary;
|
background-color: var(--color-accent-secondary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin button-secondary {
|
@mixin button-secondary {
|
||||||
@include button-base;
|
@include button-base;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
border-color: $color-border;
|
border-color: var(--color-border);
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +100,7 @@
|
|||||||
height: 28px;
|
height: 28px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: $radius-sm;
|
border-radius: $radius-sm;
|
||||||
@ -108,13 +108,13 @@
|
|||||||
transition: all $transition-fast;
|
transition: all $transition-fast;
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
border-color: $color-border;
|
border-color: var(--color-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: 2px solid $color-accent-primary;
|
outline: 2px solid var(--color-accent-primary);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,41 +129,41 @@
|
|||||||
padding: $spacing-2 $spacing-3;
|
padding: $spacing-2 $spacing-3;
|
||||||
font-family: $font-family-body;
|
font-family: $font-family-body;
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
background-color: $color-parchment-light;
|
background-color: var(--color-bg-input);
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
transition: border-color $transition-fast;
|
transition: border-color $transition-fast;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
border-color: $color-accent-primary;
|
border-color: var(--color-accent-primary);
|
||||||
box-shadow: 0 0 0 2px rgba($color-accent-primary, 0.2);
|
box-shadow: 0 0 0 2px rgba(139, 69, 19, 0.2); // Using fixed color for box-shadow
|
||||||
}
|
}
|
||||||
|
|
||||||
&::placeholder {
|
&::placeholder {
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
background-color: $color-parchment-darker;
|
background-color: var(--color-bg-tertiary);
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cards/Panels
|
// Cards/Panels
|
||||||
@mixin panel {
|
@mixin panel {
|
||||||
background-color: $color-parchment;
|
background-color: var(--color-bg-primary);
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
box-shadow: 0 1px 3px $shadow-light;
|
box-shadow: 0 1px 3px var(--shadow-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin panel-header {
|
@mixin panel-header {
|
||||||
@include flex-between;
|
@include flex-between;
|
||||||
padding: $spacing-3 $spacing-4;
|
padding: $spacing-3 $spacing-4;
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
border-bottom: 1px solid $color-border;
|
border-bottom: 1px solid var(--color-border);
|
||||||
border-radius: $radius-md $radius-md 0 0;
|
border-radius: $radius-md $radius-md 0 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,16 +175,16 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-track {
|
&::-webkit-scrollbar-track {
|
||||||
background: $color-parchment-dark;
|
background: var(--color-bg-secondary);
|
||||||
border-radius: $radius-full;
|
border-radius: $radius-full;
|
||||||
}
|
}
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
&::-webkit-scrollbar-thumb {
|
||||||
background: $color-border;
|
background: var(--color-border);
|
||||||
border-radius: $radius-full;
|
border-radius: $radius-full;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: $color-border-dark;
|
background: var(--color-border-dark);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -192,7 +192,7 @@
|
|||||||
// Accessibility - focus visible
|
// Accessibility - focus visible
|
||||||
@mixin focus-visible {
|
@mixin focus-visible {
|
||||||
&:focus-visible {
|
&:focus-visible {
|
||||||
outline: 2px solid $color-accent-primary;
|
outline: 2px solid var(--color-accent-primary);
|
||||||
outline-offset: 2px;
|
outline-offset: 2px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -218,7 +218,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Stat badge (for the large stat numbers)
|
// Stat badge (for the large stat numbers)
|
||||||
@mixin stat-badge($color: $color-text-primary) {
|
@mixin stat-badge($color: var(--color-text-primary)) {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
width: 3rem;
|
width: 3rem;
|
||||||
height: 3rem;
|
height: 3rem;
|
||||||
@ -226,7 +226,7 @@
|
|||||||
font-size: $font-size-3xl;
|
font-size: $font-size-3xl;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
color: $color;
|
color: $color;
|
||||||
background-color: $color-parchment-light;
|
background-color: var(--color-bg-input);
|
||||||
border: 2px solid $color-border;
|
border: 2px solid var(--color-border);
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
}
|
}
|
||||||
|
|||||||
146
styles/scss/_theme-variables.scss
Normal file
146
styles/scss/_theme-variables.scss
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
// Vagabond RPG - Theme Variables (CSS Custom Properties)
|
||||||
|
// ======================================================
|
||||||
|
// These CSS custom properties enable theme switching.
|
||||||
|
// The SCSS variables are kept for compile-time calculations (like mix()).
|
||||||
|
// Runtime theming uses the CSS custom properties.
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// LIGHT THEME (Default - Parchment)
|
||||||
|
// ==========================================
|
||||||
|
// This is the default theme, warm parchment colors
|
||||||
|
// WCAG AA compliant (4.5:1 contrast ratio minimum)
|
||||||
|
|
||||||
|
.vagabond {
|
||||||
|
// Background colors
|
||||||
|
--color-bg-primary: #{$color-parchment};
|
||||||
|
--color-bg-secondary: #{$color-parchment-dark};
|
||||||
|
--color-bg-tertiary: #{$color-parchment-darker};
|
||||||
|
--color-bg-input: #{$color-parchment-light};
|
||||||
|
--color-bg-highlight: #{$color-parchment-light};
|
||||||
|
|
||||||
|
// Text colors
|
||||||
|
--color-text-primary: #{$color-text-primary};
|
||||||
|
--color-text-secondary: #{$color-text-secondary};
|
||||||
|
--color-text-muted: #{$color-text-muted};
|
||||||
|
--color-text-inverse: #{$color-text-inverse};
|
||||||
|
|
||||||
|
// Accent colors
|
||||||
|
--color-accent-primary: #{$color-accent-primary};
|
||||||
|
--color-accent-secondary: #{$color-accent-secondary};
|
||||||
|
--color-accent-highlight: #{$color-accent-highlight};
|
||||||
|
|
||||||
|
// Semantic colors
|
||||||
|
--color-success: #{$color-success};
|
||||||
|
--color-danger: #{$color-danger};
|
||||||
|
--color-warning: #{$color-warning};
|
||||||
|
--color-info: #{$color-info};
|
||||||
|
|
||||||
|
// Stat colors (for visual distinction)
|
||||||
|
--color-might: #{$color-might};
|
||||||
|
--color-dexterity: #{$color-dexterity};
|
||||||
|
--color-awareness: #{$color-awareness};
|
||||||
|
--color-reason: #{$color-reason};
|
||||||
|
--color-presence: #{$color-presence};
|
||||||
|
--color-luck: #{$color-luck};
|
||||||
|
|
||||||
|
// Border colors
|
||||||
|
--color-border: #{$color-border};
|
||||||
|
--color-border-light: #{$color-border-light};
|
||||||
|
--color-border-dark: #{$color-border-dark};
|
||||||
|
|
||||||
|
// Shadows
|
||||||
|
--shadow-light: #{$shadow-light};
|
||||||
|
--shadow-medium: #{$shadow-medium};
|
||||||
|
--shadow-dark: #{$shadow-dark};
|
||||||
|
|
||||||
|
// Resource bar colors (HP, Mana)
|
||||||
|
--color-hp-fill: #{$color-danger};
|
||||||
|
--color-hp-bg: #{$color-parchment-darker};
|
||||||
|
--color-mana-fill: #{$color-reason};
|
||||||
|
--color-mana-bg: #{$color-parchment-darker};
|
||||||
|
--color-bar-values-bg: rgba(245, 240, 225, 0.85);
|
||||||
|
--color-bar-input-bg: rgba(255, 255, 255, 0.9);
|
||||||
|
|
||||||
|
// Type badge backgrounds (mixed with background)
|
||||||
|
--color-badge-weapon: #{mix($color-danger, $color-parchment, 15%)};
|
||||||
|
--color-badge-armor: #{mix($color-info, $color-parchment, 15%)};
|
||||||
|
--color-badge-spell: #{mix($color-reason, $color-parchment, 15%)};
|
||||||
|
--color-badge-perk: #{mix($color-success, $color-parchment, 15%)};
|
||||||
|
--color-badge-class: #{mix($color-warning, $color-parchment, 15%)};
|
||||||
|
--color-badge-feature: #{mix($color-presence, $color-parchment, 15%)};
|
||||||
|
--color-badge-ancestry: #{mix($color-luck, $color-parchment, 15%)};
|
||||||
|
--color-badge-equipment: #{mix($color-dexterity, $color-parchment, 15%)};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ==========================================
|
||||||
|
// DARK THEME
|
||||||
|
// ==========================================
|
||||||
|
// Dark backgrounds with warm parchment-tinted text
|
||||||
|
// Maintains the fantasy aesthetic while being easier on eyes
|
||||||
|
//
|
||||||
|
// Two application methods:
|
||||||
|
// 1. Global: body.theme-dark .vagabond - when Foundry's global theme is dark
|
||||||
|
// 2. Per-sheet: .vagabond.theme-dark - when sheet has theme-dark class (applied by _applyThemeClass)
|
||||||
|
|
||||||
|
body.theme-dark .vagabond:not(.theme-light),
|
||||||
|
.vagabond.theme-dark {
|
||||||
|
// Dark background colors (warm-tinted darks)
|
||||||
|
--color-bg-primary: #1e1a16;
|
||||||
|
--color-bg-secondary: #2a2520;
|
||||||
|
--color-bg-tertiary: #36302a;
|
||||||
|
--color-bg-input: #252119;
|
||||||
|
--color-bg-highlight: #3d362e;
|
||||||
|
|
||||||
|
// Light text colors (parchment-tinted)
|
||||||
|
--color-text-primary: #e8dcc8;
|
||||||
|
--color-text-secondary: #c4b8a4;
|
||||||
|
--color-text-muted: #8a7e6e;
|
||||||
|
--color-text-inverse: #1e1a16;
|
||||||
|
|
||||||
|
// Accent colors (slightly brighter for dark bg)
|
||||||
|
--color-accent-primary: #c9682a;
|
||||||
|
--color-accent-secondary: #a85a24;
|
||||||
|
--color-accent-highlight: #e8a060;
|
||||||
|
|
||||||
|
// Semantic colors (adjusted for dark backgrounds)
|
||||||
|
--color-success: #4a9f42;
|
||||||
|
--color-danger: #c94444;
|
||||||
|
--color-warning: #d4a32c;
|
||||||
|
--color-info: #4a8080;
|
||||||
|
|
||||||
|
// Stat colors (brighter for dark bg)
|
||||||
|
--color-might: #e05050;
|
||||||
|
--color-dexterity: #50c050;
|
||||||
|
--color-awareness: #6090e0;
|
||||||
|
--color-reason: #b060e0;
|
||||||
|
--color-presence: #e0b030;
|
||||||
|
--color-luck: #40d0d0;
|
||||||
|
|
||||||
|
// Border colors (warm grays)
|
||||||
|
--color-border: #5c4a3a;
|
||||||
|
--color-border-light: #6d5a4a;
|
||||||
|
--color-border-dark: #4a3a2a;
|
||||||
|
|
||||||
|
// Shadows (more pronounced on dark)
|
||||||
|
--shadow-light: rgba(0, 0, 0, 0.2);
|
||||||
|
--shadow-medium: rgba(0, 0, 0, 0.35);
|
||||||
|
--shadow-dark: rgba(0, 0, 0, 0.5);
|
||||||
|
|
||||||
|
// Resource bar colors
|
||||||
|
--color-hp-fill: #c94444;
|
||||||
|
--color-hp-bg: #2a2520;
|
||||||
|
--color-mana-fill: #7050b0;
|
||||||
|
--color-mana-bg: #2a2520;
|
||||||
|
--color-bar-values-bg: rgba(30, 26, 22, 0.9);
|
||||||
|
--color-bar-input-bg: rgba(42, 37, 32, 0.95);
|
||||||
|
|
||||||
|
// Type badge backgrounds (for dark theme)
|
||||||
|
--color-badge-weapon: #3d2828;
|
||||||
|
--color-badge-armor: #283838;
|
||||||
|
--color-badge-spell: #382840;
|
||||||
|
--color-badge-perk: #283828;
|
||||||
|
--color-badge-class: #383828;
|
||||||
|
--color-badge-feature: #383028;
|
||||||
|
--color-badge-ancestry: #283838;
|
||||||
|
--color-badge-equipment: #283828;
|
||||||
|
}
|
||||||
@ -1,36 +1,45 @@
|
|||||||
// Vagabond RPG - Chat Card Styles
|
// Vagabond RPG - Chat Card Styles
|
||||||
// ================================
|
// ================================
|
||||||
|
// Uses CSS custom properties for theme support.
|
||||||
|
|
||||||
// Base chat card
|
// Base chat card
|
||||||
.vagabond.chat-card {
|
.vagabond.chat-card {
|
||||||
@include panel;
|
@include panel;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
background-color: var(--color-bg-primary);
|
||||||
|
|
||||||
// Card header
|
// Card header
|
||||||
.card-header {
|
.card-header {
|
||||||
@include flex-between;
|
@include flex-between;
|
||||||
padding: $spacing-2 $spacing-3;
|
padding: $spacing-2 $spacing-3;
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
border-bottom: 1px solid $color-border;
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
|
||||||
.card-title,
|
.card-title,
|
||||||
h3 {
|
h3 {
|
||||||
|
@include flex-center;
|
||||||
|
gap: $spacing-2;
|
||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: var(--color-accent-primary);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-subtitle {
|
.card-subtitle {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.trained-badge {
|
.trained-badge {
|
||||||
font-size: $font-size-xs;
|
font-size: $font-size-xs;
|
||||||
padding: $spacing-1 $spacing-2;
|
padding: $spacing-1 $spacing-2;
|
||||||
background-color: rgba($color-success, 0.2);
|
background-color: rgba(74, 159, 66, 0.2);
|
||||||
color: $color-success;
|
color: var(--color-success);
|
||||||
border-radius: $radius-full;
|
border-radius: $radius-full;
|
||||||
font-weight: $font-weight-medium;
|
font-weight: $font-weight-medium;
|
||||||
}
|
}
|
||||||
@ -46,17 +55,18 @@
|
|||||||
@include flex-column;
|
@include flex-column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
padding: $spacing-3;
|
padding: $spacing-4;
|
||||||
margin: $spacing-2 0;
|
margin: $spacing-3;
|
||||||
background-color: $color-parchment-light;
|
background-color: var(--color-bg-secondary);
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
border: 2px solid $color-border;
|
border: 2px solid var(--color-border);
|
||||||
|
|
||||||
.roll-total {
|
.roll-total {
|
||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-size: $font-size-4xl;
|
font-size: $font-size-4xl;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.roll-status {
|
.roll-status {
|
||||||
@ -71,45 +81,45 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.success {
|
.success {
|
||||||
background-color: rgba($color-success, 0.2);
|
background-color: rgba(74, 159, 66, 0.2);
|
||||||
color: $color-success;
|
color: var(--color-success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.failure {
|
.failure {
|
||||||
background-color: rgba($color-danger, 0.2);
|
background-color: rgba(201, 68, 68, 0.2);
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.critical {
|
.critical {
|
||||||
background-color: rgba($color-warning, 0.3);
|
background-color: rgba(212, 163, 44, 0.3);
|
||||||
color: $color-warning;
|
color: var(--color-warning);
|
||||||
animation: pulse 1s ease-in-out;
|
animation: pulse 1s ease-in-out;
|
||||||
}
|
}
|
||||||
|
|
||||||
.fumble {
|
.fumble {
|
||||||
background-color: rgba($color-danger, 0.3);
|
background-color: rgba(201, 68, 68, 0.3);
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
animation: shake 0.5s ease-in-out;
|
animation: shake 0.5s ease-in-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Conditional styling based on result
|
// Conditional styling based on result
|
||||||
&.success {
|
&.success {
|
||||||
border-color: $color-success;
|
border-color: var(--color-success);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.failure {
|
&.failure {
|
||||||
border-color: $color-danger;
|
border-color: var(--color-danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.critical {
|
&.critical {
|
||||||
border-color: $color-warning;
|
border-color: var(--color-warning);
|
||||||
background-color: rgba($color-warning, 0.1);
|
background-color: rgba(212, 163, 44, 0.1);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.fumble {
|
&.fumble {
|
||||||
border-color: $color-danger;
|
border-color: var(--color-danger);
|
||||||
background-color: rgba($color-danger, 0.1);
|
background-color: rgba(201, 68, 68, 0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,8 +127,9 @@
|
|||||||
.roll-details {
|
.roll-details {
|
||||||
@include flex-column;
|
@include flex-column;
|
||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
padding: $spacing-2;
|
padding: $spacing-3;
|
||||||
background-color: $color-parchment-dark;
|
margin: 0 $spacing-3 $spacing-3;
|
||||||
|
background-color: var(--color-bg-secondary);
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
|
|
||||||
@ -126,11 +137,12 @@
|
|||||||
@include flex-between;
|
@include flex-between;
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
font-family: $font-family-mono;
|
font-family: $font-family-mono;
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -138,7 +150,7 @@
|
|||||||
@include flex-center;
|
@include flex-center;
|
||||||
gap: $spacing-3;
|
gap: $spacing-3;
|
||||||
padding-top: $spacing-2;
|
padding-top: $spacing-2;
|
||||||
border-top: 1px solid $color-border;
|
border-top: 1px solid var(--color-border);
|
||||||
|
|
||||||
span {
|
span {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
@ -148,32 +160,38 @@
|
|||||||
.d20-result {
|
.d20-result {
|
||||||
font-family: $font-family-mono;
|
font-family: $font-family-mono;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.favor-die {
|
.favor-die {
|
||||||
font-family: $font-family-mono;
|
font-family: $font-family-mono;
|
||||||
|
|
||||||
&.favor {
|
&.favor {
|
||||||
color: $color-success;
|
color: var(--color-success);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.hinder {
|
&.hinder {
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.modifier {
|
.modifier {
|
||||||
font-family: $font-family-mono;
|
font-family: $font-family-mono;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Target info (difficulty, crit threshold)
|
// Info sections (save-info, skill-info, target-info)
|
||||||
|
.save-info,
|
||||||
|
.skill-info,
|
||||||
.target-info {
|
.target-info {
|
||||||
@include grid(2, $spacing-2);
|
@include flex-column;
|
||||||
margin-top: $spacing-2;
|
gap: $spacing-1;
|
||||||
padding: $spacing-2;
|
margin: 0 $spacing-3 $spacing-3;
|
||||||
|
padding: $spacing-2 $spacing-3;
|
||||||
|
background-color: var(--color-bg-tertiary);
|
||||||
|
border-radius: $radius-md;
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
|
|
||||||
> div {
|
> div {
|
||||||
@ -181,11 +199,53 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
font-weight: $font-weight-medium;
|
font-weight: $font-weight-medium;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-abbr {
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
color: var(--color-accent-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defense info display
|
||||||
|
.defense-info-display {
|
||||||
|
@include flex-center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
margin: 0 $spacing-3 $spacing-3;
|
||||||
|
padding: $spacing-2 $spacing-3;
|
||||||
|
background-color: rgba(64, 144, 224, 0.1);
|
||||||
|
border: 1px solid var(--color-info);
|
||||||
|
border-radius: $radius-md;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-info);
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: $font-size-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Defense badge
|
||||||
|
.defense-badge {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
padding: $spacing-1 $spacing-2;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
font-weight: $font-weight-medium;
|
||||||
|
text-transform: uppercase;
|
||||||
|
|
||||||
|
&.block {
|
||||||
|
background-color: rgba(64, 144, 224, 0.2);
|
||||||
|
color: var(--color-info);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.dodge {
|
||||||
|
background-color: rgba(74, 159, 66, 0.2);
|
||||||
|
color: var(--color-success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,20 +254,20 @@
|
|||||||
.hinder-sources {
|
.hinder-sources {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
margin-top: $spacing-2;
|
margin: 0 $spacing-3 $spacing-3;
|
||||||
padding: $spacing-2;
|
padding: $spacing-2;
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
}
|
}
|
||||||
|
|
||||||
.favor-sources {
|
.favor-sources {
|
||||||
background-color: rgba($color-success, 0.1);
|
background-color: rgba(74, 159, 66, 0.1);
|
||||||
color: $color-success;
|
color: var(--color-success);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hinder-sources {
|
.hinder-sources {
|
||||||
background-color: rgba($color-danger, 0.1);
|
background-color: rgba(201, 68, 68, 0.1);
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Result status (legacy)
|
// Result status (legacy)
|
||||||
@ -220,18 +280,18 @@
|
|||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
|
|
||||||
&.success {
|
&.success {
|
||||||
background-color: rgba($color-success, 0.2);
|
background-color: rgba(74, 159, 66, 0.2);
|
||||||
color: $color-success;
|
color: var(--color-success);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.failure {
|
&.failure {
|
||||||
background-color: rgba($color-danger, 0.2);
|
background-color: rgba(201, 68, 68, 0.2);
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.critical {
|
&.critical {
|
||||||
background-color: rgba($color-warning, 0.2);
|
background-color: rgba(212, 163, 44, 0.2);
|
||||||
color: $color-warning;
|
color: var(--color-warning);
|
||||||
animation: pulse 1s ease-in-out;
|
animation: pulse 1s ease-in-out;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -240,27 +300,27 @@
|
|||||||
.damage-display {
|
.damage-display {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
margin-top: $spacing-3;
|
margin: $spacing-3;
|
||||||
padding: $spacing-2;
|
padding: $spacing-2;
|
||||||
background-color: rgba($color-danger, 0.1);
|
background-color: rgba(201, 68, 68, 0.1);
|
||||||
border: 1px solid $color-danger;
|
border: 1px solid var(--color-danger);
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
|
|
||||||
.damage-label {
|
.damage-label {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.damage-value {
|
.damage-value {
|
||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-size: $font-size-xl;
|
font-size: $font-size-xl;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.damage-type {
|
.damage-type {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -269,7 +329,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
padding: $spacing-3;
|
padding: $spacing-3;
|
||||||
border-top: 1px solid $color-border;
|
border-top: 1px solid var(--color-border);
|
||||||
|
|
||||||
button {
|
button {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
@ -284,6 +344,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Save roll card specific
|
||||||
|
.vagabond.chat-card.save-roll {
|
||||||
|
.save-name {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Attack roll card specific
|
// Attack roll card specific
|
||||||
.vagabond.chat-card.attack-roll {
|
.vagabond.chat-card.attack-roll {
|
||||||
.card-header {
|
.card-header {
|
||||||
@ -295,7 +362,7 @@
|
|||||||
width: 32px;
|
width: 32px;
|
||||||
height: 32px;
|
height: 32px;
|
||||||
border-radius: $radius-sm;
|
border-radius: $radius-sm;
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-text {
|
.header-text {
|
||||||
@ -304,13 +371,14 @@
|
|||||||
.weapon-name {
|
.weapon-name {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.attack-type-badge {
|
.attack-type-badge {
|
||||||
font-size: $font-size-xs;
|
font-size: $font-size-xs;
|
||||||
padding: $spacing-1 $spacing-2;
|
padding: $spacing-1 $spacing-2;
|
||||||
background-color: rgba($color-accent-primary, 0.2);
|
background-color: rgba(139, 69, 19, 0.2);
|
||||||
color: $color-accent-primary;
|
color: var(--color-accent-primary);
|
||||||
border-radius: $radius-full;
|
border-radius: $radius-full;
|
||||||
font-weight: $font-weight-medium;
|
font-weight: $font-weight-medium;
|
||||||
}
|
}
|
||||||
@ -318,18 +386,18 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.damage-section {
|
.damage-section {
|
||||||
margin-top: $spacing-3;
|
margin: $spacing-3;
|
||||||
padding: $spacing-3;
|
padding: $spacing-3;
|
||||||
background-color: rgba($color-danger, 0.1);
|
background-color: rgba(201, 68, 68, 0.1);
|
||||||
border: 1px solid rgba($color-danger, 0.3);
|
border: 1px solid rgba(201, 68, 68, 0.3);
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
|
|
||||||
&.critical {
|
&.critical {
|
||||||
background-color: rgba($color-warning, 0.15);
|
background-color: rgba(212, 163, 44, 0.15);
|
||||||
border-color: $color-warning;
|
border-color: var(--color-warning);
|
||||||
|
|
||||||
.damage-total {
|
.damage-total {
|
||||||
color: $color-warning;
|
color: var(--color-warning);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -338,13 +406,14 @@
|
|||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
font-weight: $font-weight-semibold;
|
font-weight: $font-weight-semibold;
|
||||||
margin-bottom: $spacing-2;
|
margin-bottom: $spacing-2;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
|
||||||
i {
|
i {
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
|
|
||||||
.crit-label {
|
.crit-label {
|
||||||
color: $color-warning;
|
color: var(--color-warning);
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -357,13 +426,13 @@
|
|||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-size: $font-size-3xl;
|
font-size: $font-size-3xl;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
.damage-type {
|
.damage-type {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -374,10 +443,10 @@
|
|||||||
margin-top: $spacing-2;
|
margin-top: $spacing-2;
|
||||||
font-family: $font-family-mono;
|
font-family: $font-family-mono;
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
|
|
||||||
.grip-indicator {
|
.grip-indicator {
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -386,32 +455,54 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: $spacing-1;
|
gap: $spacing-1;
|
||||||
margin-top: $spacing-2;
|
margin: $spacing-2 $spacing-3;
|
||||||
padding: $spacing-2;
|
padding: $spacing-2;
|
||||||
|
|
||||||
.property-tag {
|
.property-tag {
|
||||||
font-size: $font-size-xs;
|
font-size: $font-size-xs;
|
||||||
padding: $spacing-1 $spacing-2;
|
padding: $spacing-1 $spacing-2;
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
border-radius: $radius-full;
|
border-radius: $radius-full;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spell card specific
|
// Spell card specific
|
||||||
.vagabond.chat-card.spell-card {
|
.vagabond.chat-card.spell-card,
|
||||||
|
.vagabond.chat-card.spell-cast {
|
||||||
|
.card-header {
|
||||||
|
.spell-name {
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mana-cost-badge {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
padding: $spacing-1 $spacing-2;
|
||||||
|
background-color: rgba(112, 80, 176, 0.2);
|
||||||
|
color: var(--color-reason);
|
||||||
|
border-radius: $radius-full;
|
||||||
|
font-weight: $font-weight-medium;
|
||||||
|
|
||||||
|
i {
|
||||||
|
margin-right: $spacing-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
.spell-effect {
|
.spell-effect {
|
||||||
padding: $spacing-3;
|
padding: $spacing-3;
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
border-left: 3px solid $color-accent-primary;
|
border-left: 3px solid var(--color-accent-primary);
|
||||||
background-color: $color-parchment-light;
|
background-color: var(--color-bg-secondary);
|
||||||
margin: $spacing-3 0;
|
margin: $spacing-3;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.spell-meta {
|
.spell-meta {
|
||||||
@include grid(2, $spacing-2);
|
@include grid(2, $spacing-2);
|
||||||
|
margin: 0 $spacing-3 $spacing-3;
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
|
|
||||||
.meta-item {
|
.meta-item {
|
||||||
@ -419,10 +510,45 @@
|
|||||||
padding: $spacing-1;
|
padding: $spacing-1;
|
||||||
|
|
||||||
.meta-label {
|
.meta-label {
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.meta-value {
|
||||||
|
font-weight: $font-weight-medium;
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Mana spent display
|
||||||
|
.mana-spent {
|
||||||
|
@include flex-center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
margin: 0 $spacing-3 $spacing-3;
|
||||||
|
padding: $spacing-2;
|
||||||
|
background-color: rgba(112, 80, 176, 0.1);
|
||||||
|
border: 1px solid rgba(112, 80, 176, 0.3);
|
||||||
|
border-radius: $radius-md;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-reason);
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: $font-size-base;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus indicator
|
||||||
|
.focus-indicator {
|
||||||
|
@include flex-center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
margin: 0 $spacing-3 $spacing-3;
|
||||||
|
padding: $spacing-2;
|
||||||
|
background-color: rgba(212, 163, 44, 0.1);
|
||||||
|
border: 1px solid var(--color-warning);
|
||||||
|
border-radius: $radius-md;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Animations
|
// Animations
|
||||||
|
|||||||
@ -33,11 +33,11 @@
|
|||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border-color: transparent;
|
border-color: transparent;
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
color: $color-accent-primary;
|
color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
@ -52,14 +52,14 @@
|
|||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
background-color: $color-parchment;
|
background-color: var(--color-bg-primary);
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
border-color: $color-accent-primary;
|
border-color: var(--color-accent-primary);
|
||||||
color: $color-accent-primary;
|
color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
@ -71,13 +71,13 @@
|
|||||||
// Rollable button (for dice rolls)
|
// Rollable button (for dice rolls)
|
||||||
.btn-roll {
|
.btn-roll {
|
||||||
@include button-base;
|
@include button-base;
|
||||||
background-color: $color-parchment-light;
|
background-color: var(--color-bg-input);
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
border-color: $color-border;
|
border-color: var(--color-border);
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
background-color: $color-accent-highlight;
|
background-color: var(--color-accent-highlight);
|
||||||
border-color: $color-accent-primary;
|
border-color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
@ -88,24 +88,24 @@
|
|||||||
// Danger button
|
// Danger button
|
||||||
.btn-danger {
|
.btn-danger {
|
||||||
@include button-base;
|
@include button-base;
|
||||||
background-color: $color-danger;
|
background-color: var(--color-danger);
|
||||||
color: $color-text-inverse;
|
color: var(--color-text-inverse);
|
||||||
border-color: darken($color-danger, 10%);
|
border-color: var(--color-danger);
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
background-color: darken($color-danger, 10%);
|
filter: brightness(0.85);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Success button
|
// Success button
|
||||||
.btn-success {
|
.btn-success {
|
||||||
@include button-base;
|
@include button-base;
|
||||||
background-color: $color-success;
|
background-color: var(--color-success);
|
||||||
color: $color-text-inverse;
|
color: var(--color-text-inverse);
|
||||||
border-color: darken($color-success, 10%);
|
border-color: var(--color-success);
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
background-color: darken($color-success, 10%);
|
filter: brightness(0.85);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -41,8 +41,8 @@
|
|||||||
padding: $spacing-2 $spacing-8 $spacing-2 $spacing-3;
|
padding: $spacing-2 $spacing-8 $spacing-2 $spacing-3;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
appearance: none;
|
appearance: none;
|
||||||
background-color: $color-parchment-light !important;
|
background-color: var(--color-bg-input) !important;
|
||||||
color: $color-text-primary !important;
|
color: var(--color-text-primary) !important;
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
line-height: 1.5;
|
line-height: 1.5;
|
||||||
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%232c2416' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%232c2416' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
|
||||||
@ -50,13 +50,18 @@
|
|||||||
background-position: right $spacing-3 center;
|
background-position: right $spacing-3 center;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Dark theme select arrow override (per-sheet, following D&D5e pattern)
|
||||||
|
&.themed.theme-dark select {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23e8dcc8' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|
||||||
// Checkbox
|
// Checkbox
|
||||||
input[type="checkbox"] {
|
input[type="checkbox"] {
|
||||||
width: 1rem;
|
width: 1rem;
|
||||||
height: 1rem;
|
height: 1rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
accent-color: $color-accent-primary;
|
accent-color: var(--color-accent-primary);
|
||||||
|
|
||||||
@include focus-visible;
|
@include focus-visible;
|
||||||
}
|
}
|
||||||
@ -78,7 +83,7 @@
|
|||||||
height: 1rem;
|
height: 1rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
accent-color: $color-accent-primary;
|
accent-color: var(--color-accent-primary);
|
||||||
|
|
||||||
@include focus-visible;
|
@include focus-visible;
|
||||||
}
|
}
|
||||||
@ -91,7 +96,7 @@
|
|||||||
display: block;
|
display: block;
|
||||||
margin-bottom: $spacing-1;
|
margin-bottom: $spacing-1;
|
||||||
font-weight: $font-weight-medium;
|
font-weight: $font-weight-medium;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.inline {
|
&.inline {
|
||||||
@ -134,6 +139,7 @@
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
|
color: inherit;
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
outline: none;
|
outline: none;
|
||||||
@ -153,7 +159,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.separator {
|
.separator {
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,12 +172,12 @@
|
|||||||
transition: all $transition-fast;
|
transition: all $transition-fast;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: $color-border-light;
|
border-color: var(--color-border-light);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
background: $color-parchment-light;
|
background: var(--color-bg-input);
|
||||||
border-color: $color-accent-primary;
|
border-color: var(--color-accent-primary);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -179,9 +185,14 @@
|
|||||||
// Readonly display (looks like text, not input)
|
// Readonly display (looks like text, not input)
|
||||||
.readonly-value {
|
.readonly-value {
|
||||||
padding: $spacing-2 $spacing-3;
|
padding: $spacing-2 $spacing-3;
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
border: 1px solid $color-border-light;
|
border: 1px solid var(--color-border-light);
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Global dark theme select arrow override (when body has theme-dark)
|
||||||
|
body.theme-dark .vagabond select {
|
||||||
|
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23e8dcc8' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
|
||||||
|
}
|
||||||
|
|||||||
@ -9,8 +9,8 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
border-bottom: 2px solid $color-border;
|
border-bottom: 2px solid var(--color-border);
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
@ -18,7 +18,7 @@
|
|||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
font-weight: $font-weight-medium;
|
font-weight: $font-weight-medium;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
border-bottom: 2px solid transparent;
|
border-bottom: 2px solid transparent;
|
||||||
@ -27,14 +27,14 @@
|
|||||||
transition: all $transition-fast;
|
transition: all $transition-fast;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
background-color: $color-parchment;
|
background-color: var(--color-bg-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
background-color: $color-parchment;
|
background-color: var(--color-bg-primary);
|
||||||
border-bottom-color: $color-accent-primary;
|
border-bottom-color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
@include focus-visible;
|
@include focus-visible;
|
||||||
@ -64,7 +64,7 @@
|
|||||||
.sheet-tabs.vertical {
|
.sheet-tabs.vertical {
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
border-right: 2px solid $color-border;
|
border-right: 2px solid var(--color-border);
|
||||||
|
|
||||||
.item {
|
.item {
|
||||||
border-bottom: none;
|
border-bottom: none;
|
||||||
@ -73,7 +73,7 @@
|
|||||||
margin-right: -2px;
|
margin-right: -2px;
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
border-right-color: $color-accent-primary;
|
border-right-color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -84,12 +84,12 @@
|
|||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
margin-bottom: $spacing-4;
|
margin-bottom: $spacing-4;
|
||||||
padding-bottom: $spacing-2;
|
padding-bottom: $spacing-2;
|
||||||
border-bottom: 1px solid $color-border-light;
|
border-bottom: 1px solid var(--color-border-light);
|
||||||
|
|
||||||
.sub-tab {
|
.sub-tab {
|
||||||
padding: $spacing-1 $spacing-3;
|
padding: $spacing-1 $spacing-3;
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
border: 1px solid transparent;
|
border: 1px solid transparent;
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
@ -97,14 +97,14 @@
|
|||||||
transition: all $transition-fast;
|
transition: all $transition-fast;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
border-color: $color-border;
|
border-color: var(--color-border);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,18 +1,21 @@
|
|||||||
// Vagabond RPG - Roll Dialog Styles
|
// Vagabond RPG - Roll Dialog Styles
|
||||||
// ==================================
|
// ==================================
|
||||||
|
// All roll dialogs use CSS custom properties for theme support.
|
||||||
|
|
||||||
// ApplicationV2 Roll Dialog Base
|
// ApplicationV2 Roll Dialog Base
|
||||||
.vagabond.roll-dialog {
|
.vagabond.roll-dialog {
|
||||||
// Force light background on the entire window
|
// Use themed class for proper theme support
|
||||||
background-color: $color-parchment;
|
&.themed {
|
||||||
color: $color-text-primary;
|
background-color: var(--color-bg-primary);
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
.roll-dialog-content {
|
.roll-dialog-content {
|
||||||
@include flex-column;
|
@include flex-column;
|
||||||
gap: $spacing-3;
|
gap: $spacing-3;
|
||||||
padding: $spacing-4;
|
padding: $spacing-4;
|
||||||
background-color: $color-parchment;
|
background-color: var(--color-bg-primary);
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Automatic favor/hinder from Active Effects
|
// Automatic favor/hinder from Active Effects
|
||||||
@ -28,30 +31,60 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
&.favor {
|
&.favor {
|
||||||
background-color: rgba($color-success, 0.15);
|
background-color: rgba(74, 159, 66, 0.15);
|
||||||
color: $color-success;
|
color: var(--color-success);
|
||||||
border: 1px solid $color-success;
|
border: 1px solid var(--color-success);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.hinder {
|
&.hinder {
|
||||||
background-color: rgba($color-danger, 0.15);
|
background-color: rgba(201, 68, 68, 0.15);
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
border: 1px solid $color-danger;
|
border: 1px solid var(--color-danger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skill selection
|
// Common selection dropdowns
|
||||||
.skill-selection {
|
.skill-selection,
|
||||||
|
.weapon-selection,
|
||||||
|
.save-selection,
|
||||||
|
.spell-selection {
|
||||||
@include flex-column;
|
@include flex-column;
|
||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
|
|
||||||
label {
|
label {
|
||||||
font-weight: $font-weight-semibold;
|
font-weight: $font-weight-semibold;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
@include input-base;
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.no-weapons-message,
|
||||||
|
.no-spells-warning {
|
||||||
|
@include flex-center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
padding: $spacing-3;
|
||||||
|
text-align: center;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-style: italic;
|
||||||
|
background-color: var(--color-bg-secondary);
|
||||||
|
border-radius: $radius-md;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: var(--color-warning);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skill info panel
|
// Info panels (skill-info, attack-info, save-info, spell-info)
|
||||||
.skill-info {
|
.skill-info,
|
||||||
|
.attack-info,
|
||||||
|
.save-info,
|
||||||
|
.spell-info,
|
||||||
|
.casting-skill {
|
||||||
@include panel;
|
@include panel;
|
||||||
@include grid(2, $spacing-2);
|
@include grid(2, $spacing-2);
|
||||||
padding: $spacing-3;
|
padding: $spacing-3;
|
||||||
@ -62,28 +95,113 @@
|
|||||||
|
|
||||||
.label {
|
.label {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
font-weight: $font-weight-medium;
|
font-weight: $font-weight-medium;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
|
||||||
&.trained {
|
&.trained {
|
||||||
color: $color-success;
|
color: var(--color-success);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.untrained {
|
&.untrained {
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.difficulty {
|
&.difficulty {
|
||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-size: $font-size-lg;
|
font-size: $font-size-lg;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
|
color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.crit {
|
&.crit {
|
||||||
color: $color-warning;
|
color: var(--color-warning);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.stat-name {
|
||||||
|
font-weight: $font-weight-medium;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Single-column info (for spell dialog)
|
||||||
|
.spell-info {
|
||||||
|
@include flex-column;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
> div {
|
||||||
|
@include flex-between;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Damage preview panel
|
||||||
|
.damage-preview {
|
||||||
|
@include panel;
|
||||||
|
padding: $spacing-3;
|
||||||
|
background-color: rgba(201, 68, 68, 0.08);
|
||||||
|
border-color: rgba(201, 68, 68, 0.3);
|
||||||
|
|
||||||
|
.damage-formula {
|
||||||
|
@include flex-center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-family: $font-family-mono;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
font-size: $font-size-lg;
|
||||||
|
color: var(--color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.damage-type {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.weapon-properties {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
gap: $spacing-1;
|
||||||
|
margin-top: $spacing-2;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
.property-tag {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
padding: $spacing-1 $spacing-2;
|
||||||
|
background-color: var(--color-bg-secondary);
|
||||||
|
border-radius: $radius-full;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
text-transform: uppercase;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Versatile weapon toggle
|
||||||
|
.versatile-toggle {
|
||||||
|
@include flex-center;
|
||||||
|
padding: $spacing-2;
|
||||||
|
|
||||||
|
.checkbox-label {
|
||||||
|
@include flex-center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
input[type="checkbox"] {
|
||||||
|
width: 1.25rem;
|
||||||
|
height: 1.25rem;
|
||||||
|
accent-color: var(--color-accent-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -95,6 +213,7 @@
|
|||||||
|
|
||||||
> label {
|
> label {
|
||||||
font-weight: $font-weight-semibold;
|
font-weight: $font-weight-semibold;
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.favor-hinder-toggles {
|
.favor-hinder-toggles {
|
||||||
@ -109,18 +228,18 @@
|
|||||||
&.favor-btn {
|
&.favor-btn {
|
||||||
&.active,
|
&.active,
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba($color-success, 0.15);
|
background-color: rgba(74, 159, 66, 0.15);
|
||||||
border-color: $color-success;
|
border-color: var(--color-success);
|
||||||
color: $color-success;
|
color: var(--color-success);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.hinder-btn {
|
&.hinder-btn {
|
||||||
&.active,
|
&.active,
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba($color-danger, 0.15);
|
background-color: rgba(201, 68, 68, 0.15);
|
||||||
border-color: $color-danger;
|
border-color: var(--color-danger);
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -128,19 +247,24 @@
|
|||||||
|
|
||||||
.net-favor-hinder {
|
.net-favor-hinder {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
padding: $spacing-1 $spacing-2;
|
gap: $spacing-2;
|
||||||
|
padding: $spacing-2 $spacing-3;
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
font-weight: $font-weight-medium;
|
font-weight: $font-weight-medium;
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
|
|
||||||
|
i {
|
||||||
|
font-size: $font-size-base;
|
||||||
|
}
|
||||||
|
|
||||||
&.favor {
|
&.favor {
|
||||||
background-color: rgba($color-success, 0.15);
|
background-color: rgba(74, 159, 66, 0.15);
|
||||||
color: $color-success;
|
color: var(--color-success);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.hinder {
|
&.hinder {
|
||||||
background-color: rgba($color-danger, 0.15);
|
background-color: rgba(201, 68, 68, 0.15);
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,6 +276,7 @@
|
|||||||
|
|
||||||
> label {
|
> label {
|
||||||
font-weight: $font-weight-semibold;
|
font-weight: $font-weight-semibold;
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.modifier-presets {
|
.modifier-presets {
|
||||||
@ -166,7 +291,7 @@
|
|||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -196,129 +321,310 @@
|
|||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.insufficient-mana-label {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
opacity: 0.8;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Skill check dialog specific
|
// ===========================================
|
||||||
.vagabond.skill-check-dialog {
|
// Save Roll Dialog Specific Styles
|
||||||
// Additional skill-specific styles if needed
|
// ===========================================
|
||||||
}
|
.vagabond.roll-dialog {
|
||||||
|
// Defense options (Block/Dodge for Reflex saves)
|
||||||
// Attack roll dialog specific
|
.defense-options {
|
||||||
.vagabond.attack-roll-dialog {
|
|
||||||
.weapon-selection {
|
|
||||||
@include flex-column;
|
@include flex-column;
|
||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
|
margin-top: $spacing-2;
|
||||||
|
|
||||||
label {
|
> label {
|
||||||
font-weight: $font-weight-semibold;
|
font-weight: $font-weight-semibold;
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-weapons-message {
|
.defense-buttons {
|
||||||
padding: $spacing-3;
|
display: flex;
|
||||||
text-align: center;
|
gap: $spacing-2;
|
||||||
color: $color-text-muted;
|
|
||||||
font-style: italic;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.attack-info {
|
.defense-btn {
|
||||||
@include panel;
|
@include button-secondary;
|
||||||
@include grid(2, $spacing-2);
|
flex: 1;
|
||||||
|
gap: $spacing-2;
|
||||||
padding: $spacing-3;
|
padding: $spacing-3;
|
||||||
|
|
||||||
> div {
|
i {
|
||||||
@include flex-between;
|
|
||||||
}
|
|
||||||
|
|
||||||
.label {
|
|
||||||
font-size: $font-size-sm;
|
|
||||||
color: $color-text-muted;
|
|
||||||
}
|
|
||||||
|
|
||||||
.value {
|
|
||||||
font-weight: $font-weight-medium;
|
|
||||||
|
|
||||||
&.difficulty {
|
|
||||||
font-family: $font-family-header;
|
|
||||||
font-size: $font-size-lg;
|
font-size: $font-size-lg;
|
||||||
font-weight: $font-weight-bold;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
&.crit {
|
&.dodge-btn {
|
||||||
color: $color-warning;
|
&.active,
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background-color: rgba(74, 159, 66, 0.15);
|
||||||
|
border-color: var(--color-success);
|
||||||
|
color: var(--color-success);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.block-btn {
|
||||||
|
&.active,
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
background-color: rgba(64, 144, 224, 0.15);
|
||||||
|
border-color: var(--color-info);
|
||||||
|
color: var(--color-info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
opacity: 0.5;
|
||||||
|
cursor: not-allowed;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
background-color: transparent;
|
||||||
|
border-color: var(--color-border);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.damage-preview {
|
.defense-info {
|
||||||
|
@include flex-center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
padding: $spacing-2 $spacing-3;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
background-color: var(--color-bg-secondary);
|
||||||
|
border-radius: $radius-md;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: var(--color-info);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===========================================
|
||||||
|
// Spell Cast Dialog Specific Styles
|
||||||
|
// ===========================================
|
||||||
|
.vagabond.roll-dialog {
|
||||||
|
// Mana display
|
||||||
|
.mana-display {
|
||||||
@include panel;
|
@include panel;
|
||||||
|
@include flex-between;
|
||||||
padding: $spacing-3;
|
padding: $spacing-3;
|
||||||
background-color: rgba($color-danger, 0.1);
|
background: linear-gradient(135deg, rgba(112, 80, 176, 0.1), rgba(112, 80, 176, 0.05));
|
||||||
border-color: rgba($color-danger, 0.3);
|
border-color: rgba(112, 80, 176, 0.3);
|
||||||
|
|
||||||
.damage-formula {
|
.mana-current,
|
||||||
|
.mana-cost {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
|
|
||||||
.label {
|
.label {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
|
|
||||||
.value {
|
.value {
|
||||||
font-family: $font-family-mono;
|
font-family: $font-family-header;
|
||||||
|
font-size: $font-size-xl;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
font-size: $font-size-lg;
|
color: var(--color-reason);
|
||||||
}
|
|
||||||
|
|
||||||
.damage-type {
|
&.insufficient {
|
||||||
font-size: $font-size-sm;
|
color: var(--color-danger);
|
||||||
color: $color-text-secondary;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.weapon-properties {
|
|
||||||
display: flex;
|
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: $spacing-1;
|
|
||||||
margin-top: $spacing-2;
|
|
||||||
justify-content: center;
|
|
||||||
|
|
||||||
.property-tag {
|
|
||||||
font-size: $font-size-xs;
|
|
||||||
padding: $spacing-1 $spacing-2;
|
|
||||||
background-color: $color-parchment-dark;
|
|
||||||
border-radius: $radius-full;
|
|
||||||
color: $color-text-secondary;
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.versatile-toggle {
|
// Spell effect section
|
||||||
@include flex-center;
|
.spell-effect {
|
||||||
padding: $spacing-2;
|
@include panel;
|
||||||
|
padding: $spacing-3;
|
||||||
.checkbox-label {
|
background-color: var(--color-bg-secondary);
|
||||||
|
|
||||||
|
.effect-header {
|
||||||
|
margin-bottom: $spacing-2;
|
||||||
|
|
||||||
|
.include-effect-toggle {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
|
justify-content: flex-start;
|
||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
input[type="checkbox"] {
|
input[type="checkbox"] {
|
||||||
width: 1.25rem;
|
width: 1.25rem;
|
||||||
height: 1.25rem;
|
height: 1.25rem;
|
||||||
accent-color: $color-accent-primary;
|
accent-color: var(--color-accent-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
span {
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.effect-text {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
padding: $spacing-2;
|
||||||
|
background-color: var(--color-bg-primary);
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
border-left: 3px solid var(--color-accent-primary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Damage configuration (dice slider)
|
||||||
|
.damage-config {
|
||||||
|
@include flex-column;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.damage-dice-input {
|
||||||
|
@include flex-center;
|
||||||
|
gap: $spacing-3;
|
||||||
|
|
||||||
|
input[type="range"] {
|
||||||
|
flex: 1;
|
||||||
|
height: 8px;
|
||||||
|
border-radius: $radius-full;
|
||||||
|
background: var(--color-bg-tertiary);
|
||||||
|
outline: none;
|
||||||
|
cursor: pointer;
|
||||||
|
|
||||||
|
&::-webkit-slider-thumb {
|
||||||
|
-webkit-appearance: none;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--color-danger);
|
||||||
|
cursor: pointer;
|
||||||
|
border: 2px solid var(--color-bg-primary);
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
|
||||||
|
&::-moz-range-thumb {
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
border-radius: 50%;
|
||||||
|
background: var(--color-danger);
|
||||||
|
cursor: pointer;
|
||||||
|
border: 2px solid var(--color-bg-primary);
|
||||||
|
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.dice-count {
|
||||||
|
font-family: $font-family-mono;
|
||||||
|
font-size: $font-size-lg;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
color: var(--color-danger);
|
||||||
|
min-width: 4rem;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.damage-preview {
|
||||||
|
@include flex-center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
padding: $spacing-2;
|
||||||
|
background-color: rgba(201, 68, 68, 0.08);
|
||||||
|
border-radius: $radius-md;
|
||||||
|
|
||||||
|
.label {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
}
|
||||||
|
|
||||||
|
.value {
|
||||||
|
font-family: $font-family-mono;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
color: var(--color-danger);
|
||||||
|
}
|
||||||
|
|
||||||
|
.damage-type {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Delivery and Duration selection
|
||||||
|
.delivery-selection,
|
||||||
|
.duration-selection {
|
||||||
|
@include flex-column;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
@include input-base;
|
||||||
|
width: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus warning
|
||||||
|
.focus-warning {
|
||||||
|
@include panel;
|
||||||
|
@include flex-column;
|
||||||
|
gap: $spacing-2;
|
||||||
|
padding: $spacing-3;
|
||||||
|
background-color: rgba(212, 163, 44, 0.1);
|
||||||
|
border-color: var(--color-warning);
|
||||||
|
|
||||||
|
> i {
|
||||||
|
color: var(--color-warning);
|
||||||
|
}
|
||||||
|
|
||||||
|
> span {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
}
|
||||||
|
|
||||||
|
.current-focus {
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.focus-limit-warning {
|
||||||
|
@include flex-center;
|
||||||
|
gap: $spacing-2;
|
||||||
|
padding: $spacing-2;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
font-weight: $font-weight-medium;
|
||||||
|
color: var(--color-danger);
|
||||||
|
background-color: rgba(201, 68, 68, 0.1);
|
||||||
|
border-radius: $radius-md;
|
||||||
|
|
||||||
|
i {
|
||||||
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===========================================
|
||||||
// Legacy dialog styles (for backward compatibility)
|
// Legacy dialog styles (for backward compatibility)
|
||||||
|
// ===========================================
|
||||||
.vagabond.dialog.roll-dialog {
|
.vagabond.dialog.roll-dialog {
|
||||||
.dialog-content {
|
.dialog-content {
|
||||||
padding: $spacing-4;
|
padding: $spacing-4;
|
||||||
|
background-color: var(--color-bg-primary);
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Roll info section
|
// Roll info section
|
||||||
@ -335,14 +641,15 @@
|
|||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-size: $font-size-3xl;
|
font-size: $font-size-3xl;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
|
color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.crit-threshold {
|
.crit-threshold {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
|
|
||||||
.crit-value {
|
.crit-value {
|
||||||
color: $color-accent-primary;
|
color: var(--color-warning);
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -361,14 +668,15 @@
|
|||||||
|
|
||||||
label {
|
label {
|
||||||
font-weight: $font-weight-medium;
|
font-weight: $font-weight-medium;
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.favor .toggle-active {
|
&.favor .toggle-active {
|
||||||
color: $color-success;
|
color: var(--color-success);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.hinder .toggle-active {
|
&.hinder .toggle-active {
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -398,7 +706,7 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Spell cast dialog specific
|
// Legacy spell cast dialog
|
||||||
.vagabond.dialog.spell-cast-dialog {
|
.vagabond.dialog.spell-cast-dialog {
|
||||||
.mana-cost {
|
.mana-cost {
|
||||||
@include panel;
|
@include panel;
|
||||||
@ -408,20 +716,21 @@
|
|||||||
|
|
||||||
.cost-label {
|
.cost-label {
|
||||||
font-weight: $font-weight-semibold;
|
font-weight: $font-weight-semibold;
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.cost-value {
|
.cost-value {
|
||||||
font-family: $font-family-header;
|
font-family: $font-family-header;
|
||||||
font-size: $font-size-xl;
|
font-size: $font-size-xl;
|
||||||
font-weight: $font-weight-bold;
|
font-weight: $font-weight-bold;
|
||||||
color: $color-accent-primary;
|
color: var(--color-reason);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.insufficient {
|
&.insufficient {
|
||||||
border-color: $color-danger;
|
border-color: var(--color-danger);
|
||||||
|
|
||||||
.cost-value {
|
.cost-value {
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -434,6 +743,7 @@
|
|||||||
.selection-label {
|
.selection-label {
|
||||||
font-weight: $font-weight-semibold;
|
font-weight: $font-weight-semibold;
|
||||||
margin-bottom: $spacing-2;
|
margin-bottom: $spacing-2;
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.selection-grid {
|
.selection-grid {
|
||||||
@ -447,35 +757,34 @@
|
|||||||
transition: all $transition-fast;
|
transition: all $transition-fast;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: $color-accent-primary;
|
border-color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
border-color: $color-accent-primary;
|
border-color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.option-name {
|
.option-name {
|
||||||
font-weight: $font-weight-medium;
|
font-weight: $font-weight-medium;
|
||||||
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.option-cost {
|
.option-cost {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ===========================================
|
||||||
// Favor/Hinder Debug Panel
|
// Favor/Hinder Debug Panel
|
||||||
|
// ===========================================
|
||||||
.vagabond.favor-hinder-debug {
|
.vagabond.favor-hinder-debug {
|
||||||
// Force light background on the entire window content
|
&.themed {
|
||||||
// Using !important to override Foundry's dark theme styles
|
background-color: var(--color-bg-primary);
|
||||||
background-color: $color-parchment !important;
|
color: var(--color-text-primary);
|
||||||
color: $color-text-primary !important;
|
|
||||||
|
|
||||||
* {
|
|
||||||
color: $color-text-primary;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Enable scrolling on the window content
|
// Enable scrolling on the window content
|
||||||
@ -489,7 +798,7 @@
|
|||||||
@include flex-column;
|
@include flex-column;
|
||||||
gap: $spacing-4;
|
gap: $spacing-4;
|
||||||
padding: $spacing-4;
|
padding: $spacing-4;
|
||||||
background-color: $color-parchment !important;
|
background-color: var(--color-bg-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.actor-selection {
|
.actor-selection {
|
||||||
@ -498,7 +807,7 @@
|
|||||||
|
|
||||||
label {
|
label {
|
||||||
font-weight: $font-weight-semibold;
|
font-weight: $font-weight-semibold;
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -510,7 +819,7 @@
|
|||||||
.debug-panel {
|
.debug-panel {
|
||||||
@include panel;
|
@include panel;
|
||||||
padding: $spacing-3;
|
padding: $spacing-3;
|
||||||
background-color: $color-parchment-light;
|
background-color: var(--color-bg-secondary);
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
@include flex-center;
|
@include flex-center;
|
||||||
@ -518,12 +827,12 @@
|
|||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
margin: 0 0 $spacing-3 0;
|
margin: 0 0 $spacing-3 0;
|
||||||
padding-bottom: $spacing-2;
|
padding-bottom: $spacing-2;
|
||||||
border-bottom: 1px solid $color-border;
|
border-bottom: 1px solid var(--color-border);
|
||||||
font-size: $font-size-base;
|
font-size: $font-size-base;
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
|
|
||||||
i {
|
i {
|
||||||
color: $color-accent-primary;
|
color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -531,21 +840,21 @@
|
|||||||
.flag-table {
|
.flag-table {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
background-color: $color-parchment-light;
|
background-color: var(--color-bg-secondary);
|
||||||
|
|
||||||
th,
|
th,
|
||||||
td {
|
td {
|
||||||
padding: $spacing-2;
|
padding: $spacing-2;
|
||||||
text-align: left;
|
text-align: left;
|
||||||
border-bottom: 1px solid $color-border-light;
|
border-bottom: 1px solid var(--color-border-light);
|
||||||
color: $color-text-primary;
|
color: var(--color-text-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
th {
|
th {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
font-weight: $font-weight-semibold;
|
font-weight: $font-weight-semibold;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-tertiary);
|
||||||
|
|
||||||
&.center {
|
&.center {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -553,7 +862,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
td {
|
td {
|
||||||
background-color: $color-parchment-light !important;
|
background-color: var(--color-bg-secondary);
|
||||||
|
|
||||||
&.center {
|
&.center {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
@ -564,17 +873,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Alternating row colors with good contrast
|
|
||||||
tbody tr:nth-child(even) td {
|
tbody tr:nth-child(even) td {
|
||||||
background-color: $color-parchment !important;
|
background-color: var(--color-bg-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
.stat-tag {
|
.stat-tag {
|
||||||
font-size: $font-size-xs;
|
font-size: $font-size-xs;
|
||||||
padding: $spacing-1 $spacing-2;
|
padding: $spacing-1 $spacing-2;
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-tertiary);
|
||||||
border-radius: $radius-full;
|
border-radius: $radius-full;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -582,11 +890,11 @@
|
|||||||
width: 1.25rem;
|
width: 1.25rem;
|
||||||
height: 1.25rem;
|
height: 1.25rem;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
accent-color: $color-accent-primary;
|
accent-color: var(--color-accent-primary);
|
||||||
}
|
}
|
||||||
|
|
||||||
tbody tr:hover td {
|
tbody tr:hover td {
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-tertiary);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -594,7 +902,7 @@
|
|||||||
display: flex;
|
display: flex;
|
||||||
gap: $spacing-3;
|
gap: $spacing-3;
|
||||||
padding-top: $spacing-3;
|
padding-top: $spacing-3;
|
||||||
border-top: 1px solid $color-border;
|
border-top: 1px solid var(--color-border);
|
||||||
|
|
||||||
button {
|
button {
|
||||||
@include button-base;
|
@include button-base;
|
||||||
@ -608,11 +916,11 @@
|
|||||||
|
|
||||||
.clear-btn {
|
.clear-btn {
|
||||||
@include button-secondary;
|
@include button-secondary;
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
border-color: $color-danger;
|
border-color: var(--color-danger);
|
||||||
|
|
||||||
&:hover:not(:disabled) {
|
&:hover:not(:disabled) {
|
||||||
background-color: rgba($color-danger, 0.1);
|
background-color: rgba(201, 68, 68, 0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -623,7 +931,7 @@
|
|||||||
gap: $spacing-3;
|
gap: $spacing-3;
|
||||||
padding: $spacing-6;
|
padding: $spacing-6;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: $color-text-muted;
|
color: var(--color-text-muted);
|
||||||
|
|
||||||
i {
|
i {
|
||||||
font-size: $font-size-4xl;
|
font-size: $font-size-4xl;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@ -4,25 +4,36 @@
|
|||||||
.vagabond.sheet.item {
|
.vagabond.sheet.item {
|
||||||
min-width: 500px;
|
min-width: 500px;
|
||||||
min-height: 400px;
|
min-height: 400px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
|
||||||
|
// Utility class for hiding inactive tabs
|
||||||
|
.hidden {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
// Header styling
|
// Header styling
|
||||||
.sheet-header.item-header {
|
.sheet-header.item-header {
|
||||||
@include flex-between;
|
@include flex-between;
|
||||||
padding: $spacing-4;
|
padding: $spacing-4;
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
border-bottom: 2px solid $color-border;
|
border-bottom: 2px solid var(--color-border);
|
||||||
gap: $spacing-4;
|
gap: $spacing-4;
|
||||||
|
|
||||||
.item-img {
|
.item-img {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
height: 64px;
|
height: 64px;
|
||||||
object-fit: cover;
|
object-fit: cover;
|
||||||
border: 2px solid $color-border;
|
border: 2px solid var(--color-border);
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
transition: all $transition-fast;
|
||||||
|
box-shadow: 0 1px 3px var(--shadow-light);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: $color-accent-primary;
|
border-color: var(--color-accent-primary);
|
||||||
|
box-shadow: 0 2px 6px var(--shadow-medium);
|
||||||
|
transform: scale(1.02);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,14 +48,23 @@
|
|||||||
|
|
||||||
input {
|
input {
|
||||||
width: 100%;
|
width: 100%;
|
||||||
font-size: $font-size-lg;
|
font-family: $font-family-header;
|
||||||
font-weight: bold;
|
font-size: $font-size-xl;
|
||||||
|
font-weight: $font-weight-bold;
|
||||||
|
color: var(--color-text-primary);
|
||||||
border: none;
|
border: none;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border-bottom: 1px solid transparent;
|
border-bottom: 1px solid transparent;
|
||||||
|
padding: $spacing-1 0;
|
||||||
|
transition: border-color $transition-fast;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-bottom-color: var(--color-border-light);
|
||||||
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border-bottom-color: $color-accent-primary;
|
border-bottom-color: var(--color-accent-primary);
|
||||||
|
outline: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -56,35 +76,64 @@
|
|||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
font-weight: 500;
|
font-weight: 500;
|
||||||
text-transform: capitalize;
|
text-transform: capitalize;
|
||||||
background-color: $color-parchment;
|
background-color: var(--color-bg-primary);
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
border-radius: $radius-full;
|
border-radius: $radius-full;
|
||||||
|
|
||||||
&.weapon {
|
&.weapon {
|
||||||
background-color: mix($color-danger, $color-parchment, 15%);
|
background-color: var(--color-badge-weapon);
|
||||||
}
|
}
|
||||||
&.armor {
|
&.armor {
|
||||||
background-color: mix($color-info, $color-parchment, 15%);
|
background-color: var(--color-badge-armor);
|
||||||
}
|
}
|
||||||
&.spell {
|
&.spell {
|
||||||
background-color: mix($color-reason, $color-parchment, 15%);
|
background-color: var(--color-badge-spell);
|
||||||
}
|
}
|
||||||
&.perk {
|
&.perk {
|
||||||
background-color: mix($color-success, $color-parchment, 15%);
|
background-color: var(--color-badge-perk);
|
||||||
}
|
}
|
||||||
&.class {
|
&.class {
|
||||||
background-color: mix($color-warning, $color-parchment, 15%);
|
background-color: var(--color-badge-class);
|
||||||
|
}
|
||||||
|
&.feature {
|
||||||
|
background-color: var(--color-badge-feature);
|
||||||
|
}
|
||||||
|
&.ancestry {
|
||||||
|
background-color: var(--color-badge-ancestry);
|
||||||
|
}
|
||||||
|
&.equipment {
|
||||||
|
background-color: var(--color-badge-equipment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Sheet body
|
// Tab content areas (both .sheet-body and .tab-content)
|
||||||
.sheet-body {
|
.sheet-body,
|
||||||
|
.tab-content {
|
||||||
padding: $spacing-4;
|
padding: $spacing-4;
|
||||||
overflow-y: auto;
|
overflow-y: auto;
|
||||||
max-height: calc(100% - 80px);
|
background-color: var(--color-bg-primary);
|
||||||
|
@include custom-scrollbar;
|
||||||
|
|
||||||
|
// When used as standalone body (no tabs)
|
||||||
|
&.sheet-body {
|
||||||
|
flex: 1;
|
||||||
|
min-height: 0; // Important for flexbox scrolling
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Details tab specific
|
||||||
|
.details-tab {
|
||||||
|
&.sheet-body {
|
||||||
|
// Combined class - body that's also the details tab
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Effects tab has its own padding defined in .effects-tab
|
||||||
|
.effects-tab.tab-content {
|
||||||
|
padding: 0; // Remove duplicate padding, .effects-tab handles it
|
||||||
}
|
}
|
||||||
|
|
||||||
// Item content container
|
// Item content container
|
||||||
@ -120,9 +169,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
label {
|
label {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-xs;
|
||||||
font-weight: 500;
|
font-weight: $font-weight-semibold;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="text"],
|
input[type="text"],
|
||||||
@ -130,17 +181,29 @@
|
|||||||
select,
|
select,
|
||||||
textarea {
|
textarea {
|
||||||
padding: $spacing-2;
|
padding: $spacing-2;
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
border-radius: $radius-sm;
|
border-radius: $radius-sm;
|
||||||
background-color: $color-parchment-light;
|
background-color: var(--color-bg-input);
|
||||||
|
font-family: $font-family-body;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
transition:
|
||||||
|
border-color $transition-fast,
|
||||||
|
box-shadow $transition-fast;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
border-color: var(--color-border-dark);
|
||||||
|
}
|
||||||
|
|
||||||
&:focus {
|
&:focus {
|
||||||
border-color: $color-accent-primary;
|
border-color: var(--color-accent-primary);
|
||||||
|
box-shadow: 0 0 0 2px rgba(139, 69, 19, 0.15);
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:disabled {
|
&:disabled {
|
||||||
background-color: $color-parchment;
|
background-color: var(--color-bg-primary);
|
||||||
|
color: var(--color-text-muted);
|
||||||
cursor: not-allowed;
|
cursor: not-allowed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,6 +213,12 @@
|
|||||||
height: 18px;
|
height: 18px;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
accent-color: var(--color-accent-primary);
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
input[type="number"] {
|
input[type="number"] {
|
||||||
@ -168,7 +237,7 @@
|
|||||||
|
|
||||||
.units {
|
.units {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
textarea {
|
textarea {
|
||||||
@ -180,11 +249,11 @@
|
|||||||
|
|
||||||
// Fieldset styling
|
// Fieldset styling
|
||||||
fieldset {
|
fieldset {
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
border-radius: $radius-md;
|
border-radius: $radius-md;
|
||||||
padding: $spacing-3;
|
padding: $spacing-3;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
background-color: rgba($color-parchment-dark, 0.3);
|
background-color: var(--color-bg-highlight);
|
||||||
|
|
||||||
legend {
|
legend {
|
||||||
padding: 0 $spacing-2;
|
padding: 0 $spacing-2;
|
||||||
@ -254,15 +323,55 @@
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-container {
|
.editor-wrapper {
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
border-radius: $radius-sm;
|
border-radius: $radius-sm;
|
||||||
overflow: hidden;
|
background-color: var(--color-bg-input);
|
||||||
|
|
||||||
.editor {
|
|
||||||
min-height: 120px;
|
min-height: 120px;
|
||||||
|
max-height: 400px;
|
||||||
|
overflow: auto;
|
||||||
|
resize: vertical;
|
||||||
|
|
||||||
|
// Static content display (non-editable)
|
||||||
|
> .editor-content {
|
||||||
|
min-height: 100px;
|
||||||
padding: $spacing-2;
|
padding: $spacing-2;
|
||||||
background-color: $color-parchment-light;
|
}
|
||||||
|
|
||||||
|
// ProseMirror custom element styling
|
||||||
|
prose-mirror {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 100px;
|
||||||
|
|
||||||
|
// The menu bar that appears when editing
|
||||||
|
> menu.editor-menu {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
background-color: var(--color-bg-secondary);
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Foundry's inner editor-container
|
||||||
|
> .editor-container {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 80px;
|
||||||
|
|
||||||
|
// The actual editable content area
|
||||||
|
> .editor-content {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
padding: $spacing-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle button
|
||||||
|
> button.toggle {
|
||||||
|
display: none; // Hide since we use toggled="false"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -275,9 +384,9 @@
|
|||||||
|
|
||||||
.trait-entry {
|
.trait-entry {
|
||||||
padding: $spacing-3;
|
padding: $spacing-3;
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
border-radius: $radius-sm;
|
border-radius: $radius-sm;
|
||||||
background-color: $color-parchment-light;
|
background-color: var(--color-bg-input);
|
||||||
|
|
||||||
.trait-header {
|
.trait-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -291,7 +400,7 @@
|
|||||||
|
|
||||||
button {
|
button {
|
||||||
@include button-icon;
|
@include button-icon;
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,7 +411,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.no-traits {
|
.no-traits {
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: $spacing-4;
|
padding: $spacing-4;
|
||||||
@ -330,7 +439,7 @@
|
|||||||
label {
|
label {
|
||||||
font-size: $font-size-xs;
|
font-size: $font-size-xs;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
}
|
}
|
||||||
|
|
||||||
input {
|
input {
|
||||||
@ -364,7 +473,7 @@
|
|||||||
|
|
||||||
.hint {
|
.hint {
|
||||||
font-size: $font-size-xs;
|
font-size: $font-size-xs;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -380,7 +489,7 @@
|
|||||||
grid-template-columns: 50px 60px 80px 80px 1fr 40px;
|
grid-template-columns: 50px 60px 80px 80px 1fr 40px;
|
||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
padding: $spacing-2;
|
padding: $spacing-2;
|
||||||
background-color: $color-parchment-dark;
|
background-color: var(--color-bg-secondary);
|
||||||
font-size: $font-size-xs;
|
font-size: $font-size-xs;
|
||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
border-radius: $radius-sm $radius-sm 0 0;
|
border-radius: $radius-sm $radius-sm 0 0;
|
||||||
@ -391,8 +500,8 @@
|
|||||||
grid-template-columns: 50px 60px 80px 80px 1fr 40px;
|
grid-template-columns: 50px 60px 80px 80px 1fr 40px;
|
||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
padding: $spacing-2;
|
padding: $spacing-2;
|
||||||
border-bottom: 1px solid $color-border;
|
border-bottom: 1px solid var(--color-border);
|
||||||
background-color: $color-parchment-light;
|
background-color: var(--color-bg-input);
|
||||||
|
|
||||||
&:last-child {
|
&:last-child {
|
||||||
border-radius: 0 0 $radius-sm $radius-sm;
|
border-radius: 0 0 $radius-sm $radius-sm;
|
||||||
@ -406,14 +515,14 @@
|
|||||||
|
|
||||||
button {
|
button {
|
||||||
@include button-icon;
|
@include button-icon;
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-progression {
|
.no-progression {
|
||||||
padding: $spacing-4;
|
padding: $spacing-4;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -429,9 +538,9 @@
|
|||||||
|
|
||||||
.feature-entry {
|
.feature-entry {
|
||||||
padding: $spacing-3;
|
padding: $spacing-3;
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
border-radius: $radius-sm;
|
border-radius: $radius-sm;
|
||||||
background-color: $color-parchment-light;
|
background-color: var(--color-bg-input);
|
||||||
|
|
||||||
.feature-header {
|
.feature-header {
|
||||||
display: flex;
|
display: flex;
|
||||||
@ -458,7 +567,7 @@
|
|||||||
|
|
||||||
button {
|
button {
|
||||||
@include button-icon;
|
@include button-icon;
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -471,7 +580,7 @@
|
|||||||
.no-features {
|
.no-features {
|
||||||
padding: $spacing-4;
|
padding: $spacing-4;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -488,14 +597,55 @@
|
|||||||
font-weight: 600;
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor-container {
|
.editor-wrapper {
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
border-radius: $radius-sm;
|
border-radius: $radius-sm;
|
||||||
|
background-color: var(--color-bg-input);
|
||||||
.editor {
|
|
||||||
min-height: 80px;
|
min-height: 80px;
|
||||||
|
max-height: 300px;
|
||||||
|
overflow: auto;
|
||||||
|
resize: vertical;
|
||||||
|
|
||||||
|
// Static content display (non-editable)
|
||||||
|
> .editor-content {
|
||||||
|
min-height: 60px;
|
||||||
padding: $spacing-2;
|
padding: $spacing-2;
|
||||||
background-color: $color-parchment-light;
|
}
|
||||||
|
|
||||||
|
// ProseMirror custom element styling
|
||||||
|
prose-mirror {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 60px;
|
||||||
|
|
||||||
|
// The menu bar that appears when editing
|
||||||
|
> menu.editor-menu {
|
||||||
|
flex: 0 0 auto;
|
||||||
|
position: sticky;
|
||||||
|
top: 0;
|
||||||
|
z-index: 1;
|
||||||
|
background-color: var(--color-bg-secondary);
|
||||||
|
border-bottom: 1px solid var(--color-border);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Foundry's inner editor-container
|
||||||
|
> .editor-container {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
min-height: 40px;
|
||||||
|
|
||||||
|
// The actual editable content area
|
||||||
|
> .editor-content {
|
||||||
|
flex: 1 1 auto;
|
||||||
|
padding: $spacing-2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Toggle button
|
||||||
|
> button.toggle {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -515,6 +665,94 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Requirements section (feature)
|
||||||
|
.requirements-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: $spacing-2;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
background-color: var(--color-bg-input);
|
||||||
|
font-family: $font-family-body;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
transition:
|
||||||
|
border-color $transition-fast,
|
||||||
|
box-shadow $transition-fast;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
border-color: var(--color-border-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: var(--color-accent-primary);
|
||||||
|
box-shadow: 0 0 0 2px rgba(139, 69, 19, 0.15);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background-color: var(--color-bg-primary);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ritual components (perk)
|
||||||
|
.ritual-components {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: $spacing-2;
|
||||||
|
|
||||||
|
> label {
|
||||||
|
font-size: $font-size-xs;
|
||||||
|
font-weight: $font-weight-semibold;
|
||||||
|
color: var(--color-text-secondary);
|
||||||
|
text-transform: uppercase;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
padding: $spacing-2;
|
||||||
|
border: 1px solid var(--color-border);
|
||||||
|
border-radius: $radius-sm;
|
||||||
|
background-color: var(--color-bg-input);
|
||||||
|
font-family: $font-family-body;
|
||||||
|
font-size: $font-size-sm;
|
||||||
|
color: var(--color-text-primary);
|
||||||
|
transition:
|
||||||
|
border-color $transition-fast,
|
||||||
|
box-shadow $transition-fast;
|
||||||
|
|
||||||
|
&:hover:not(:disabled) {
|
||||||
|
border-color: var(--color-border-dark);
|
||||||
|
}
|
||||||
|
|
||||||
|
&:focus {
|
||||||
|
border-color: var(--color-accent-primary);
|
||||||
|
box-shadow: 0 0 0 2px rgba(139, 69, 19, 0.15);
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:disabled {
|
||||||
|
background-color: var(--color-bg-primary);
|
||||||
|
color: var(--color-text-muted);
|
||||||
|
cursor: not-allowed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Effects tab
|
// Effects tab
|
||||||
.effects-tab {
|
.effects-tab {
|
||||||
padding: $spacing-4;
|
padding: $spacing-4;
|
||||||
@ -561,8 +799,8 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
gap: $spacing-2;
|
gap: $spacing-2;
|
||||||
padding: $spacing-2;
|
padding: $spacing-2;
|
||||||
background-color: $color-parchment-light;
|
background-color: var(--color-bg-input);
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
border-radius: $radius-sm;
|
border-radius: $radius-sm;
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
@ -587,7 +825,7 @@
|
|||||||
width: 24px;
|
width: 24px;
|
||||||
height: 24px;
|
height: 24px;
|
||||||
border-radius: $radius-sm;
|
border-radius: $radius-sm;
|
||||||
border: 1px solid $color-border;
|
border: 1px solid var(--color-border);
|
||||||
}
|
}
|
||||||
|
|
||||||
.effect-name {
|
.effect-name {
|
||||||
@ -603,10 +841,10 @@
|
|||||||
@include button-icon;
|
@include button-icon;
|
||||||
|
|
||||||
&.delete {
|
&.delete {
|
||||||
color: $color-danger;
|
color: var(--color-danger);
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background-color: rgba($color-danger, 0.1);
|
background-color: rgba(201, 68, 68, 0.1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -614,7 +852,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.no-effects {
|
.no-effects {
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
font-style: italic;
|
font-style: italic;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: $spacing-4;
|
padding: $spacing-4;
|
||||||
@ -622,7 +860,7 @@
|
|||||||
|
|
||||||
.effects-hint {
|
.effects-hint {
|
||||||
font-size: $font-size-sm;
|
font-size: $font-size-sm;
|
||||||
color: $color-text-secondary;
|
color: var(--color-text-secondary);
|
||||||
margin-top: $spacing-2;
|
margin-top: $spacing-2;
|
||||||
|
|
||||||
i {
|
i {
|
||||||
|
|||||||
@ -5,6 +5,9 @@
|
|||||||
@import "variables";
|
@import "variables";
|
||||||
@import "mixins";
|
@import "mixins";
|
||||||
|
|
||||||
|
// Theme system (CSS custom properties)
|
||||||
|
@import "theme-variables";
|
||||||
|
|
||||||
// Base styles
|
// Base styles
|
||||||
@import "base";
|
@import "base";
|
||||||
|
|
||||||
|
|||||||
11
system.json
11
system.json
@ -16,6 +16,17 @@
|
|||||||
],
|
],
|
||||||
"esmodules": ["module/vagabond.mjs"],
|
"esmodules": ["module/vagabond.mjs"],
|
||||||
"styles": ["styles/vagabond.css"],
|
"styles": ["styles/vagabond.css"],
|
||||||
|
"themes": [
|
||||||
|
{
|
||||||
|
"name": "light",
|
||||||
|
"label": "VAGABOND.ThemeLight",
|
||||||
|
"default": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dark",
|
||||||
|
"label": "VAGABOND.ThemeDark"
|
||||||
|
}
|
||||||
|
],
|
||||||
"languages": [
|
"languages": [
|
||||||
{
|
{
|
||||||
"lang": "en",
|
"lang": "en",
|
||||||
|
|||||||
@ -64,8 +64,12 @@
|
|||||||
{{!-- Description --}}
|
{{!-- Description --}}
|
||||||
<div class="item-description">
|
<div class="item-description">
|
||||||
<label>{{localize "VAGABOND.Description"}}</label>
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
<div class="editor-container">
|
<div class="editor-wrapper">
|
||||||
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
{{#if editable}}
|
||||||
|
<prose-mirror name="system.description" toggled="false">{{{enrichedDescription}}}</prose-mirror>
|
||||||
|
{{else}}
|
||||||
|
<div class="editor-content">{{{enrichedDescription}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -128,8 +128,12 @@
|
|||||||
{{!-- Description --}}
|
{{!-- Description --}}
|
||||||
<div class="item-description">
|
<div class="item-description">
|
||||||
<label>{{localize "VAGABOND.Description"}}</label>
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
<div class="editor-container">
|
<div class="editor-wrapper">
|
||||||
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
{{#if editable}}
|
||||||
|
<prose-mirror name="system.description" toggled="false">{{{enrichedDescription}}}</prose-mirror>
|
||||||
|
{{else}}
|
||||||
|
<div class="editor-content">{{{enrichedDescription}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -56,8 +56,12 @@
|
|||||||
{{!-- Starting Pack --}}
|
{{!-- Starting Pack --}}
|
||||||
<div class="starting-pack-section">
|
<div class="starting-pack-section">
|
||||||
<label>{{localize "VAGABOND.StartingPack"}}</label>
|
<label>{{localize "VAGABOND.StartingPack"}}</label>
|
||||||
<div class="editor-container">
|
<div class="editor-wrapper">
|
||||||
{{editor system.startingPack target="system.startingPack" button=true editable=editable engine="prosemirror"}}
|
{{#if editable}}
|
||||||
|
<prose-mirror name="system.startingPack" toggled="false">{{{enrichedStartingPack}}}</prose-mirror>
|
||||||
|
{{else}}
|
||||||
|
<div class="editor-content">{{{enrichedStartingPack}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -156,8 +160,12 @@
|
|||||||
{{!-- Description --}}
|
{{!-- Description --}}
|
||||||
<div class="item-description">
|
<div class="item-description">
|
||||||
<label>{{localize "VAGABOND.Description"}}</label>
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
<div class="editor-container">
|
<div class="editor-wrapper">
|
||||||
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
{{#if editable}}
|
||||||
|
<prose-mirror name="system.description" toggled="false">{{{enrichedDescription}}}</prose-mirror>
|
||||||
|
{{else}}
|
||||||
|
<div class="editor-content">{{{enrichedDescription}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -162,8 +162,12 @@
|
|||||||
{{!-- Description --}}
|
{{!-- Description --}}
|
||||||
<div class="item-description">
|
<div class="item-description">
|
||||||
<label>{{localize "VAGABOND.Description"}}</label>
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
<div class="editor-container">
|
<div class="editor-wrapper">
|
||||||
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
{{#if editable}}
|
||||||
|
<prose-mirror name="system.description" toggled="false">{{{enrichedDescription}}}</prose-mirror>
|
||||||
|
{{else}}
|
||||||
|
<div class="editor-content">{{{enrichedDescription}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -76,8 +76,12 @@
|
|||||||
{{!-- Description --}}
|
{{!-- Description --}}
|
||||||
<div class="item-description">
|
<div class="item-description">
|
||||||
<label>{{localize "VAGABOND.Description"}}</label>
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
<div class="editor-container">
|
<div class="editor-wrapper">
|
||||||
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
{{#if editable}}
|
||||||
|
<prose-mirror name="system.description" toggled="false">{{{enrichedDescription}}}</prose-mirror>
|
||||||
|
{{else}}
|
||||||
|
<div class="editor-content">{{{enrichedDescription}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -133,8 +133,12 @@
|
|||||||
{{!-- Description --}}
|
{{!-- Description --}}
|
||||||
<div class="item-description">
|
<div class="item-description">
|
||||||
<label>{{localize "VAGABOND.Description"}}</label>
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
<div class="editor-container">
|
<div class="editor-wrapper">
|
||||||
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
{{#if editable}}
|
||||||
|
<prose-mirror name="system.description" toggled="false">{{{enrichedDescription}}}</prose-mirror>
|
||||||
|
{{else}}
|
||||||
|
<div class="editor-content">{{{enrichedDescription}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -111,24 +111,36 @@
|
|||||||
{{!-- Effect --}}
|
{{!-- Effect --}}
|
||||||
<div class="spell-effect">
|
<div class="spell-effect">
|
||||||
<label>{{localize "VAGABOND.Effect"}}</label>
|
<label>{{localize "VAGABOND.Effect"}}</label>
|
||||||
<div class="editor-container">
|
<div class="editor-wrapper">
|
||||||
{{editor system.effect target="system.effect" button=true editable=editable engine="prosemirror"}}
|
{{#if editable}}
|
||||||
|
<prose-mirror name="system.effect" toggled="false">{{{enrichedEffect}}}</prose-mirror>
|
||||||
|
{{else}}
|
||||||
|
<div class="editor-content">{{{enrichedEffect}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{!-- Crit Effect --}}
|
{{!-- Crit Effect --}}
|
||||||
<div class="spell-crit-effect">
|
<div class="spell-crit-effect">
|
||||||
<label>{{localize "VAGABOND.CritEffect"}}</label>
|
<label>{{localize "VAGABOND.CritEffect"}}</label>
|
||||||
<div class="editor-container">
|
<div class="editor-wrapper">
|
||||||
{{editor system.critEffect target="system.critEffect" button=true editable=editable engine="prosemirror"}}
|
{{#if editable}}
|
||||||
|
<prose-mirror name="system.critEffect" toggled="false">{{{enrichedCritEffect}}}</prose-mirror>
|
||||||
|
{{else}}
|
||||||
|
<div class="editor-content">{{{enrichedCritEffect}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{!-- Description --}}
|
{{!-- Description --}}
|
||||||
<div class="item-description">
|
<div class="item-description">
|
||||||
<label>{{localize "VAGABOND.Description"}}</label>
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
<div class="editor-container">
|
<div class="editor-wrapper">
|
||||||
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
{{#if editable}}
|
||||||
|
<prose-mirror name="system.description" toggled="false">{{{enrichedDescription}}}</prose-mirror>
|
||||||
|
{{else}}
|
||||||
|
<div class="editor-content">{{{enrichedDescription}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@ -228,8 +228,12 @@
|
|||||||
{{!-- Description --}}
|
{{!-- Description --}}
|
||||||
<div class="item-description">
|
<div class="item-description">
|
||||||
<label>{{localize "VAGABOND.Description"}}</label>
|
<label>{{localize "VAGABOND.Description"}}</label>
|
||||||
<div class="editor-container">
|
<div class="editor-wrapper">
|
||||||
{{editor system.description target="system.description" button=true editable=editable engine="prosemirror"}}
|
{{#if editable}}
|
||||||
|
<prose-mirror name="system.description" toggled="false">{{{enrichedDescription}}}</prose-mirror>
|
||||||
|
{{else}}
|
||||||
|
<div class="editor-content">{{{enrichedDescription}}}</div>
|
||||||
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user