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>
577 lines
12 KiB
SCSS
577 lines
12 KiB
SCSS
// Vagabond RPG - Chat Card Styles
|
|
// ================================
|
|
// Uses CSS custom properties for theme support.
|
|
|
|
// Base chat card
|
|
.vagabond.chat-card {
|
|
@include panel;
|
|
overflow: hidden;
|
|
background-color: var(--color-bg-primary);
|
|
|
|
// Card header
|
|
.card-header {
|
|
@include flex-between;
|
|
padding: $spacing-2 $spacing-3;
|
|
background-color: var(--color-bg-secondary);
|
|
border-bottom: 1px solid var(--color-border);
|
|
|
|
.card-title,
|
|
h3 {
|
|
@include flex-center;
|
|
gap: $spacing-2;
|
|
font-family: $font-family-header;
|
|
font-size: $font-size-base;
|
|
font-weight: $font-weight-bold;
|
|
margin: 0;
|
|
color: var(--color-text-primary);
|
|
|
|
i {
|
|
color: var(--color-accent-primary);
|
|
}
|
|
}
|
|
|
|
.card-subtitle {
|
|
font-size: $font-size-sm;
|
|
color: var(--color-text-muted);
|
|
}
|
|
|
|
.trained-badge {
|
|
font-size: $font-size-xs;
|
|
padding: $spacing-1 $spacing-2;
|
|
background-color: rgba(74, 159, 66, 0.2);
|
|
color: var(--color-success);
|
|
border-radius: $radius-full;
|
|
font-weight: $font-weight-medium;
|
|
}
|
|
}
|
|
|
|
// Card content
|
|
.card-content {
|
|
padding: $spacing-3;
|
|
}
|
|
|
|
// Roll result (large total display)
|
|
.roll-result {
|
|
@include flex-column;
|
|
align-items: center;
|
|
gap: $spacing-2;
|
|
padding: $spacing-4;
|
|
margin: $spacing-3;
|
|
background-color: var(--color-bg-secondary);
|
|
border-radius: $radius-md;
|
|
border: 2px solid var(--color-border);
|
|
|
|
.roll-total {
|
|
font-family: $font-family-header;
|
|
font-size: $font-size-4xl;
|
|
font-weight: $font-weight-bold;
|
|
line-height: 1;
|
|
color: var(--color-text-primary);
|
|
}
|
|
|
|
.roll-status {
|
|
.status {
|
|
display: inline-block;
|
|
padding: $spacing-1 $spacing-3;
|
|
font-size: $font-size-sm;
|
|
font-weight: $font-weight-bold;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.1em;
|
|
border-radius: $radius-md;
|
|
}
|
|
|
|
.success {
|
|
background-color: rgba(74, 159, 66, 0.2);
|
|
color: var(--color-success);
|
|
}
|
|
|
|
.failure {
|
|
background-color: rgba(201, 68, 68, 0.2);
|
|
color: var(--color-danger);
|
|
}
|
|
|
|
.critical {
|
|
background-color: rgba(212, 163, 44, 0.3);
|
|
color: var(--color-warning);
|
|
animation: pulse 1s ease-in-out;
|
|
}
|
|
|
|
.fumble {
|
|
background-color: rgba(201, 68, 68, 0.3);
|
|
color: var(--color-danger);
|
|
animation: shake 0.5s ease-in-out;
|
|
}
|
|
}
|
|
|
|
// Conditional styling based on result
|
|
&.success {
|
|
border-color: var(--color-success);
|
|
}
|
|
|
|
&.failure {
|
|
border-color: var(--color-danger);
|
|
}
|
|
|
|
&.critical {
|
|
border-color: var(--color-warning);
|
|
background-color: rgba(212, 163, 44, 0.1);
|
|
}
|
|
|
|
&.fumble {
|
|
border-color: var(--color-danger);
|
|
background-color: rgba(201, 68, 68, 0.1);
|
|
}
|
|
}
|
|
|
|
// Roll details
|
|
.roll-details {
|
|
@include flex-column;
|
|
gap: $spacing-2;
|
|
padding: $spacing-3;
|
|
margin: 0 $spacing-3 $spacing-3;
|
|
background-color: var(--color-bg-secondary);
|
|
border-radius: $radius-md;
|
|
font-size: $font-size-sm;
|
|
|
|
.roll-formula {
|
|
@include flex-between;
|
|
|
|
.label {
|
|
color: var(--color-text-muted);
|
|
}
|
|
|
|
.value {
|
|
font-family: $font-family-mono;
|
|
color: var(--color-text-primary);
|
|
}
|
|
}
|
|
|
|
.roll-breakdown {
|
|
@include flex-center;
|
|
gap: $spacing-3;
|
|
padding-top: $spacing-2;
|
|
border-top: 1px solid var(--color-border);
|
|
|
|
span {
|
|
@include flex-center;
|
|
gap: $spacing-1;
|
|
}
|
|
|
|
.d20-result {
|
|
font-family: $font-family-mono;
|
|
font-weight: $font-weight-bold;
|
|
color: var(--color-text-primary);
|
|
}
|
|
|
|
.favor-die {
|
|
font-family: $font-family-mono;
|
|
|
|
&.favor {
|
|
color: var(--color-success);
|
|
}
|
|
|
|
&.hinder {
|
|
color: var(--color-danger);
|
|
}
|
|
}
|
|
|
|
.modifier {
|
|
font-family: $font-family-mono;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Info sections (save-info, skill-info, target-info)
|
|
.save-info,
|
|
.skill-info,
|
|
.target-info {
|
|
@include flex-column;
|
|
gap: $spacing-1;
|
|
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;
|
|
|
|
> div {
|
|
@include flex-between;
|
|
}
|
|
|
|
.label {
|
|
color: var(--color-text-muted);
|
|
}
|
|
|
|
.value {
|
|
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);
|
|
}
|
|
}
|
|
|
|
// Favor/Hinder sources
|
|
.favor-sources,
|
|
.hinder-sources {
|
|
@include flex-center;
|
|
gap: $spacing-2;
|
|
margin: 0 $spacing-3 $spacing-3;
|
|
padding: $spacing-2;
|
|
font-size: $font-size-sm;
|
|
border-radius: $radius-md;
|
|
}
|
|
|
|
.favor-sources {
|
|
background-color: rgba(74, 159, 66, 0.1);
|
|
color: var(--color-success);
|
|
}
|
|
|
|
.hinder-sources {
|
|
background-color: rgba(201, 68, 68, 0.1);
|
|
color: var(--color-danger);
|
|
}
|
|
|
|
// Result status (legacy)
|
|
.result-status {
|
|
@include flex-center;
|
|
padding: $spacing-2;
|
|
font-weight: $font-weight-bold;
|
|
text-transform: uppercase;
|
|
letter-spacing: 0.1em;
|
|
border-radius: $radius-md;
|
|
|
|
&.success {
|
|
background-color: rgba(74, 159, 66, 0.2);
|
|
color: var(--color-success);
|
|
}
|
|
|
|
&.failure {
|
|
background-color: rgba(201, 68, 68, 0.2);
|
|
color: var(--color-danger);
|
|
}
|
|
|
|
&.critical {
|
|
background-color: rgba(212, 163, 44, 0.2);
|
|
color: var(--color-warning);
|
|
animation: pulse 1s ease-in-out;
|
|
}
|
|
}
|
|
|
|
// Damage display
|
|
.damage-display {
|
|
@include flex-center;
|
|
gap: $spacing-2;
|
|
margin: $spacing-3;
|
|
padding: $spacing-2;
|
|
background-color: rgba(201, 68, 68, 0.1);
|
|
border: 1px solid var(--color-danger);
|
|
border-radius: $radius-md;
|
|
|
|
.damage-label {
|
|
font-size: $font-size-sm;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
.damage-value {
|
|
font-family: $font-family-header;
|
|
font-size: $font-size-xl;
|
|
font-weight: $font-weight-bold;
|
|
color: var(--color-danger);
|
|
}
|
|
|
|
.damage-type {
|
|
font-size: $font-size-sm;
|
|
color: var(--color-text-muted);
|
|
}
|
|
}
|
|
|
|
// Card buttons (for interactive cards)
|
|
.card-buttons {
|
|
display: flex;
|
|
gap: $spacing-2;
|
|
padding: $spacing-3;
|
|
border-top: 1px solid var(--color-border);
|
|
|
|
button {
|
|
flex: 1;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Skill roll card specific
|
|
.vagabond.chat-card.skill-roll {
|
|
.skill-name {
|
|
margin: 0;
|
|
}
|
|
}
|
|
|
|
// Save roll card specific
|
|
.vagabond.chat-card.save-roll {
|
|
.save-name {
|
|
margin: 0;
|
|
}
|
|
}
|
|
|
|
// Attack roll card specific
|
|
.vagabond.chat-card.attack-roll {
|
|
.card-header {
|
|
display: flex;
|
|
align-items: center;
|
|
gap: $spacing-3;
|
|
|
|
.weapon-icon {
|
|
width: 32px;
|
|
height: 32px;
|
|
border-radius: $radius-sm;
|
|
border: 1px solid var(--color-border);
|
|
}
|
|
|
|
.header-text {
|
|
flex: 1;
|
|
|
|
.weapon-name {
|
|
margin: 0;
|
|
font-size: $font-size-base;
|
|
color: var(--color-text-primary);
|
|
}
|
|
|
|
.attack-type-badge {
|
|
font-size: $font-size-xs;
|
|
padding: $spacing-1 $spacing-2;
|
|
background-color: rgba(139, 69, 19, 0.2);
|
|
color: var(--color-accent-primary);
|
|
border-radius: $radius-full;
|
|
font-weight: $font-weight-medium;
|
|
}
|
|
}
|
|
}
|
|
|
|
.damage-section {
|
|
margin: $spacing-3;
|
|
padding: $spacing-3;
|
|
background-color: rgba(201, 68, 68, 0.1);
|
|
border: 1px solid rgba(201, 68, 68, 0.3);
|
|
border-radius: $radius-md;
|
|
|
|
&.critical {
|
|
background-color: rgba(212, 163, 44, 0.15);
|
|
border-color: var(--color-warning);
|
|
|
|
.damage-total {
|
|
color: var(--color-warning);
|
|
}
|
|
}
|
|
|
|
.damage-header {
|
|
@include flex-center;
|
|
gap: $spacing-2;
|
|
font-weight: $font-weight-semibold;
|
|
margin-bottom: $spacing-2;
|
|
color: var(--color-text-primary);
|
|
|
|
i {
|
|
color: var(--color-danger);
|
|
}
|
|
|
|
.crit-label {
|
|
color: var(--color-warning);
|
|
font-size: $font-size-sm;
|
|
}
|
|
}
|
|
|
|
.damage-result {
|
|
@include flex-center;
|
|
gap: $spacing-2;
|
|
|
|
.damage-total {
|
|
font-family: $font-family-header;
|
|
font-size: $font-size-3xl;
|
|
font-weight: $font-weight-bold;
|
|
color: var(--color-danger);
|
|
line-height: 1;
|
|
}
|
|
|
|
.damage-type {
|
|
font-size: $font-size-sm;
|
|
color: var(--color-text-secondary);
|
|
text-transform: capitalize;
|
|
}
|
|
}
|
|
|
|
.damage-formula {
|
|
@include flex-center;
|
|
gap: $spacing-2;
|
|
margin-top: $spacing-2;
|
|
font-family: $font-family-mono;
|
|
font-size: $font-size-sm;
|
|
color: var(--color-text-muted);
|
|
|
|
.grip-indicator {
|
|
color: var(--color-text-secondary);
|
|
}
|
|
}
|
|
}
|
|
|
|
.weapon-properties {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: $spacing-1;
|
|
margin: $spacing-2 $spacing-3;
|
|
padding: $spacing-2;
|
|
|
|
.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: capitalize;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Spell card specific
|
|
.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 {
|
|
padding: $spacing-3;
|
|
font-style: italic;
|
|
border-left: 3px solid var(--color-accent-primary);
|
|
background-color: var(--color-bg-secondary);
|
|
margin: $spacing-3;
|
|
color: var(--color-text-secondary);
|
|
}
|
|
|
|
.spell-meta {
|
|
@include grid(2, $spacing-2);
|
|
margin: 0 $spacing-3 $spacing-3;
|
|
font-size: $font-size-sm;
|
|
|
|
.meta-item {
|
|
@include flex-between;
|
|
padding: $spacing-1;
|
|
|
|
.meta-label {
|
|
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
|
|
@keyframes pulse {
|
|
0%,
|
|
100% {
|
|
transform: scale(1);
|
|
}
|
|
50% {
|
|
transform: scale(1.05);
|
|
}
|
|
}
|
|
|
|
@keyframes shake {
|
|
0%,
|
|
100% {
|
|
transform: translateX(0);
|
|
}
|
|
25% {
|
|
transform: translateX(-5px);
|
|
}
|
|
75% {
|
|
transform: translateX(5px);
|
|
}
|
|
}
|