diff --git a/css/fvtt-lethal-fantasy.css b/css/fvtt-lethal-fantasy.css
index 0333b60..5b21d5b 100644
--- a/css/fvtt-lethal-fantasy.css
+++ b/css/fvtt-lethal-fantasy.css
@@ -2974,7 +2974,7 @@ i.lethalfantasy {
.message.fvtt-lethal-fantasy.dice-roll .result-section .d30-result .d30-header .d30-label {
flex-grow: 1;
font-weight: bold;
- color: #e0d5f0;
+ color: #2a1a3a;
text-transform: uppercase;
letter-spacing: 0.5px;
font-size: calc(var(--font-size-standard) * 0.9);
@@ -2986,11 +2986,11 @@ i.lethalfantasy {
font-family: var(--font-primary);
font-size: calc(var(--font-size-standard) * 1.5);
font-weight: bold;
- color: #ff69b4;
- background: rgba(255, 105, 180, 0.1);
+ color: #3d006e;
+ background: rgba(255, 255, 255, 0.35);
padding: 4px 12px;
border-radius: 12px;
- border: 1px solid rgba(255, 105, 180, 0.3);
+ border: 1px solid rgba(138, 43, 226, 0.4);
}
.lethalfantasy.dice-roll .result-section .d30-result .d30-message,
.fvtt-lethal-fantasy.dice-roll .result-section .d30-result .d30-message,
@@ -3994,3 +3994,226 @@ i.lethalfantasy {
padding-left: 8px;
font-size: 0.9rem;
}
+/* -------------------------------------------------- */
+/* Dice Tray — injected into the Foundry chat sidebar */
+/* -------------------------------------------------- */
+.lf-dice-tray {
+ padding: 6px 8px;
+ background: linear-gradient(135deg, rgba(245, 232, 200, 0.97) 0%, rgba(238, 222, 185, 0.97) 100%), url("/systems/fvtt-lethal-fantasy/assets/ui/lethal_fantasy_background.webp") center / cover;
+ border-top: 2px solid rgba(139, 69, 19, 0.5);
+ border-bottom: 1px solid rgba(139, 69, 19, 0.25);
+ width: 100%;
+ box-sizing: border-box;
+ pointer-events: all;
+}
+.lf-dice-tray .lf-dt-row {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ flex-wrap: wrap;
+}
+.lf-dice-tray .lf-dt-label {
+ color: #3a2a10;
+ font-size: 15px;
+ flex-shrink: 0;
+ opacity: 0.7;
+}
+.lf-dice-tray .lf-dt-count {
+ width: 44px;
+ flex-shrink: 0;
+ padding: 3px 4px;
+ background: rgba(139, 69, 19, 0.15);
+ border: 1px solid rgba(139, 69, 19, 0.45);
+ border-radius: 4px;
+ color: #2a1a08;
+ font-size: 11px;
+ font-weight: 700;
+ cursor: pointer;
+ text-align: center;
+}
+.lf-dice-tray .lf-dt-count option {
+ background: #f5ead0;
+ color: #2a1a08;
+}
+.lf-dice-tray .lf-dt-count:focus {
+ outline: none;
+ border-color: rgba(139, 69, 19, 0.7);
+ box-shadow: 0 0 4px rgba(139, 69, 19, 0.25);
+}
+.lf-dice-tray .lf-dt-dice {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 3px;
+ flex: 1;
+}
+.lf-dice-tray .lf-dt-die-btn {
+ padding: 3px 7px;
+ background: rgba(139, 69, 19, 0.15);
+ border: 1px solid rgba(139, 69, 19, 0.4);
+ border-radius: 4px;
+ color: #2a1a08;
+ font-size: 10px;
+ font-weight: 700;
+ cursor: pointer;
+ transition: background 0.15s, border-color 0.15s, box-shadow 0.15s, transform 0.1s;
+ line-height: 1.5;
+ letter-spacing: 0.3px;
+}
+.lf-dice-tray .lf-dt-die-btn:hover {
+ background: rgba(139, 69, 19, 0.35);
+ border-color: rgba(139, 69, 19, 0.7);
+ color: #5a2a00;
+ box-shadow: 0 0 5px rgba(139, 69, 19, 0.3);
+ transform: translateY(-1px);
+}
+.lf-dice-tray .lf-dt-die-btn:active {
+ transform: translateY(0);
+ box-shadow: none;
+ background: rgba(139, 69, 19, 0.5);
+}
+.lf-dice-tray .lf-dt-explode-label {
+ display: flex;
+ align-items: center;
+ gap: 3px;
+ cursor: pointer;
+ color: rgba(160, 80, 20, 0.7);
+ font-size: 14px;
+ flex-shrink: 0;
+ padding: 3px 6px;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ transition: color 0.15s, border-color 0.15s, background 0.15s;
+}
+.lf-dice-tray .lf-dt-explode-label:hover {
+ color: rgba(200, 100, 30, 0.9);
+ border-color: rgba(139, 69, 19, 0.45);
+ background: rgba(139, 69, 19, 0.12);
+}
+.lf-dice-tray .lf-dt-explode-label input[type="checkbox"] {
+ appearance: none;
+ width: 0;
+ height: 0;
+ position: absolute;
+ opacity: 0;
+}
+.lf-dice-tray .lf-dt-explode-label input[type="checkbox"]:checked ~ i {
+ color: #cc4400;
+ filter: drop-shadow(0 0 4px rgba(200, 80, 0, 0.6));
+}
+.lf-dice-tray .lf-dt-explode-label:has(input:checked) {
+ color: #cc4400;
+ border-color: rgba(139, 69, 19, 0.55);
+ background: rgba(139, 60, 10, 0.2);
+}
+/* Free roll chat card — styled to match regular system roll cards */
+.lf-free-roll-card {
+ border-radius: 6px;
+ overflow: hidden;
+}
+.lf-free-roll-card .lf-frc-header {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ padding: 6px 8px;
+ background: linear-gradient(135deg, rgba(40, 30, 20, 0.7) 0%, rgba(30, 22, 15, 0.9) 100%);
+ border-bottom: 2px solid rgba(139, 69, 19, 0.4);
+}
+.lf-free-roll-card .lf-frc-header i {
+ color: #c9b896;
+ font-size: calc(var(--font-size-standard, 14px) * 1.1);
+}
+.lf-free-roll-card .lf-frc-header .lf-frc-title-text {
+ font-size: calc(var(--font-size-standard, 14px) * 0.85);
+ color: #c9b896;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+}
+.lf-free-roll-card .lf-frc-header .lf-frc-badge {
+ display: inline-flex;
+ align-items: center;
+ padding: 2px 8px;
+ background: rgba(139, 69, 19, 0.3);
+ border: 1px solid rgba(139, 69, 19, 0.5);
+ border-radius: 10px;
+ font-size: calc(var(--font-size-standard, 14px) * 0.85);
+ font-weight: 600;
+ color: #d4c5a9;
+}
+.lf-free-roll-card .lf-frc-dice {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 4px;
+ padding: 6px 8px;
+ background: rgba(0, 0, 0, 0.15);
+ border: 1px solid rgba(139, 69, 19, 0.3);
+ border-top: none;
+}
+.lf-free-roll-card .lf-frc-dice .lf-frc-die-chip {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ padding: 3px 8px;
+ background: rgba(139, 69, 19, 0.2);
+ border: 1px solid rgba(139, 69, 19, 0.3);
+ border-radius: 4px;
+}
+.lf-free-roll-card .lf-frc-dice .lf-frc-die-chip .lf-frc-die-type {
+ font-size: calc(var(--font-size-standard, 14px) * 0.85);
+ font-weight: 600;
+ color: #2a2a1a;
+ text-transform: uppercase;
+}
+.lf-free-roll-card .lf-frc-dice .lf-frc-die-chip .lf-frc-die-sep {
+ color: rgba(0, 0, 0, 0.35);
+ font-weight: 300;
+ font-size: calc(var(--font-size-standard, 14px) * 0.8);
+}
+.lf-free-roll-card .lf-frc-dice .lf-frc-die-chip .lf-frc-die-val {
+ font-weight: bold;
+ color: #ffd700;
+ font-size: calc(var(--font-size-standard, 14px) * 0.95);
+}
+.lf-free-roll-card .lf-frc-dice .lf-frc-die-chip .lf-frc-die-val .lf-dt-explode-icon {
+ font-size: 8px;
+ color: #ffcc00;
+ margin-left: 2px;
+ vertical-align: super;
+ text-shadow: 0 0 4px rgba(255, 200, 0, 0.8);
+}
+.lf-free-roll-card .lf-frc-dice .lf-frc-die-chip.lf-frc-max {
+ background: rgba(139, 90, 19, 0.35);
+ border-color: rgba(200, 116, 42, 0.6);
+}
+.lf-free-roll-card .lf-frc-dice .lf-frc-die-chip.lf-frc-max .lf-frc-die-val {
+ color: #ff9a40;
+ text-shadow: 0 0 6px rgba(200, 116, 42, 0.6);
+}
+.lf-free-roll-card .lf-frc-dice .lf-frc-die-chip.lf-frc-min {
+ background: rgba(139, 20, 20, 0.25);
+ border-color: rgba(139, 34, 34, 0.5);
+}
+.lf-free-roll-card .lf-frc-dice .lf-frc-die-chip.lf-frc-min .lf-frc-die-val {
+ color: #ff6b6b;
+}
+.lf-free-roll-card .lf-frc-total-bar {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ padding: 6px 10px;
+ background: linear-gradient(135deg, rgba(40, 30, 20, 0.6) 0%, rgba(20, 15, 10, 0.8) 100%);
+ border: 2px solid rgba(139, 69, 19, 0.5);
+}
+.lf-free-roll-card .lf-frc-total-bar .lf-frc-total-label {
+ font-size: calc(var(--font-size-standard, 14px) * 0.85);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ color: #c9b896;
+}
+.lf-free-roll-card .lf-frc-total-bar .lf-frc-total-value {
+ font-family: var(--font-primary, serif);
+ font-size: calc(var(--font-size-standard, 14px) * 1.6);
+ font-weight: bold;
+ color: #e8d5a0;
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
+}
diff --git a/lang/en.json b/lang/en.json
index 1f00952..8f968ed 100644
--- a/lang/en.json
+++ b/lang/en.json
@@ -152,6 +152,57 @@
"wis": {
"label": "Wisdom"
}
+ },
+ "agility": {
+ "label": "Agility"
+ },
+ "app": {
+ "label": "Appearance"
+ },
+ "cha": {
+ "label": "Charisma"
+ },
+ "con": {
+ "label": "Constitution"
+ },
+ "contagion": {
+ "label": "Contagion Save"
+ },
+ "dex": {
+ "label": "Dexterity"
+ },
+ "dodge": {
+ "label": "Dodge Save"
+ },
+ "dying": {
+ "label": "Dying Challenge"
+ },
+ "int": {
+ "label": "Intelligence"
+ },
+ "luc": {
+ "label": "Luck"
+ },
+ "pain": {
+ "label": "Pain Save"
+ },
+ "painCourage": {
+ "label": "Pain/Courage Save"
+ },
+ "poison": {
+ "label": "Poison Save"
+ },
+ "str": {
+ "label": "Strength"
+ },
+ "toughness": {
+ "label": "Toughness Save"
+ },
+ "will": {
+ "label": "Willpower Save"
+ },
+ "wis": {
+ "label": "Wisdom"
}
},
"Monster": {
@@ -250,6 +301,21 @@
"wis": {
"label": "Wisdom"
}
+ },
+ "perception": {
+ "label": "Perception"
+ },
+ "resistIntimidation": {
+ "label": "Resist Intimidation"
+ },
+ "resistPerformance": {
+ "label": "Resist Performance"
+ },
+ "resistTorture": {
+ "label": "Resist Torture"
+ },
+ "stealth": {
+ "label": "Stealth"
}
},
"Delete": "Delete",
@@ -429,7 +495,9 @@
"wis": "WIS",
"weapon-damage-medium": "Weapon damage medium",
"weapon-damage-small": "Weapon damage small",
- "combatProgressionStart": "Combat start threshold"
+ "combatProgressionStart": "Combat start threshold",
+ "miracle": "Miracle",
+ "titleStandard": "Standard Roll"
},
"Miracle": {
"FIELDS": {
@@ -519,7 +587,9 @@
"save": "Save roll {save}",
"success": "Success",
"visibility": "Visibility",
- "favorDisfavor": "Favor/Disfavor"
+ "favorDisfavor": "Favor/Disfavor",
+ "displayArmor": "Target: {targetName} — Armor DR: {targetArmor} — Damage: {realDamage}",
+ "resourceLost": "Resource spent"
},
"Save": {
"FIELDS": {
@@ -661,6 +731,9 @@
"weaponClass": {
"label": "Class"
}
+ },
+ "error": {
+ "weaponBonus": "Weapon bonus exceeds the allowed maximum (skill total / 10)"
}
},
"Spell": {
@@ -727,6 +800,13 @@
"damageDice": {
"label": "Damage dice"
}
+ },
+ "Range": {
+ "contact": "Contact",
+ "distant": "Distant",
+ "loin": "Far",
+ "na": "N/A",
+ "proche": "Close"
}
},
"ToggleSheet": "Toggle mode",
@@ -734,7 +814,11 @@
"addEquipment": "New equipment",
"addSpell": "New spells",
"skill": "Skills list",
- "combatProgressionStart": "First attack of combat can succeed on a roll of 1 through this value. Resets to 1 for subsequent attacks."
+ "combatProgressionStart": "First attack of combat can succeed on a roll of 1 through this value. Resets to 1 for subsequent attacks.",
+ "addMiracle": "Add Miracle",
+ "gifts": "Gifts list",
+ "skills": "Skills list",
+ "vulnerabilities": "Vulnerabilities list"
},
"Vulnerability": {
"FIELDS": {
@@ -893,6 +977,25 @@
"cannotAct": "cannot act this second",
"diceResult": "Dice result",
"progressionCount": "Progression count:"
+ },
+ "EquipmentCategories": {
+ "ClassKit": "Class Kit",
+ "Clothing": "Clothing",
+ "EssentialKit": "Essential Kit",
+ "FoodDrink": "Food & Drink",
+ "LandTransport": "Land Transport",
+ "Light": "Light",
+ "LoadBearing": "Load Bearing",
+ "Misc": "Miscellaneous",
+ "Mount": "Mount",
+ "Music": "Music",
+ "Sleeping": "Sleeping",
+ "WaterTransport": "Water Transport"
+ },
+ "DiceTray": {
+ "CountTitle": "Number of dice",
+ "ExplodeTitle": "Exploding dice — re-roll on maximum value",
+ "ChatTitle": "Free Roll"
}
},
"TYPES": {
@@ -913,4 +1016,4 @@
"weapon": "Weapon"
}
}
-}
\ No newline at end of file
+}
diff --git a/lethal-fantasy.mjs b/lethal-fantasy.mjs
index f284eb2..643a85a 100644
--- a/lethal-fantasy.mjs
+++ b/lethal-fantasy.mjs
@@ -938,6 +938,12 @@ Hooks.on("hotbarDrop", (bar, data, slot) => {
}
})
+/* -------------------------------------------- */
+/**
+ * Inject the Lethal Fantasy dice tray into the chat sidebar.
+ */
+Hooks.on("renderChatLog", (_chatLog, html) => applications.injectDiceTray(_chatLog, html))
+
/**
* Register world usage statistics
* @param {string} registerKey
diff --git a/module/applications/_module.mjs b/module/applications/_module.mjs
index a96939e..ad8f52c 100644
--- a/module/applications/_module.mjs
+++ b/module/applications/_module.mjs
@@ -9,4 +9,5 @@ export { default as LethalFantasySpellSheet } from "./sheets/spell-sheet.mjs"
export { default as LethalFantasyEquipmentSheet } from "./sheets/equipment-sheet.mjs"
export { default as LethalFantasyShieldSheet } from "./sheets/shield-sheet.mjs"
export { default as LethalFantasyMiracleSheet } from "./sheets/miracle-sheet.mjs"
+export { injectDiceTray } from "./free-roll.mjs"
diff --git a/module/applications/free-roll.mjs b/module/applications/free-roll.mjs
new file mode 100644
index 0000000..29adaba
--- /dev/null
+++ b/module/applications/free-roll.mjs
@@ -0,0 +1,139 @@
+/**
+ * Free Dice Tray — injected into the Foundry chat sidebar.
+ *
+ * Provides a compact bar for GM and players to roll any standard die (d4–d30)
+ * or its exploding variant (dXx) without needing an actor sheet.
+ * Supports selecting how many dice to roll (1–9).
+ */
+
+/** Standard dice available in Lethal Fantasy */
+const DICE_TYPES = ["d4", "d6", "d8", "d10", "d12", "d20", "d30"]
+
+/**
+ * Inject the dice tray bar into the ChatLog HTML.
+ * Called from `Hooks.on("renderChatLog", ...)`.
+ *
+ * @param {Application} _chatLog
+ * @param {HTMLElement|jQuery} html
+ */
+export function injectDiceTray(_chatLog, html) {
+ const el = (html instanceof HTMLElement) ? html : (html[0] ?? html)
+ if (!el?.querySelector) return
+ if (el.querySelector(".lf-dice-tray")) return
+
+ const bar = document.createElement("div")
+ bar.className = "lf-dice-tray"
+
+ const diceButtons = DICE_TYPES.map(d =>
+ ``
+ ).join("")
+
+ const countOptions = Array.from({ length: 9 }, (_, i) =>
+ ``
+ ).join("")
+
+ bar.innerHTML = `
+
+
+
+
${diceButtons}
+
+
+ `
+
+ bar.addEventListener("click", async ev => {
+ const btn = ev.target.closest(".lf-dt-die-btn")
+ if (!btn) return
+ ev.stopPropagation()
+
+ const dieType = btn.dataset.die
+ const count = parseInt(bar.querySelector(".lf-dt-count").value) || 1
+ const explode = bar.querySelector(".lf-dt-explode").checked
+
+ try {
+ await rollFreeDie(dieType, count, explode)
+ } catch (err) {
+ console.error("Lethal Fantasy | Dice Tray error:", err)
+ ui.notifications?.error("Dice Tray roll failed — see console")
+ }
+ })
+
+ const anchor = el.querySelector(".chat-form")
+ ?? el.querySelector(".chat-message-form")
+ ?? el.querySelector("form")
+ if (anchor) {
+ anchor.parentElement.insertBefore(bar, anchor)
+ } else {
+ el.appendChild(bar)
+ }
+}
+
+/**
+ * Roll one or more dice of the given type and post the result to chat.
+ *
+ * @param {string} dieType Die face, e.g. "d20"
+ * @param {number} count Number of dice to roll (1–9)
+ * @param {boolean} explode Whether to use the exploding modifier (x = max-value explode)
+ * @returns {Promise}
+ */
+export async function rollFreeDie(dieType, count = 1, explode = false) {
+ const sides = parseInt(dieType.replace("d", "")) || 20
+ const formula = explode ? `${count}d${sides}x` : `${count}d${sides}`
+ const label = explode
+ ? `${count}${dieType.toUpperCase()}E`
+ : `${count}${dieType.toUpperCase()}`
+
+ const roll = new Roll(formula)
+ await roll.evaluate()
+
+ const results = roll.terms
+ .filter(t => t.results)
+ .flatMap(t => t.results)
+
+ const total = roll.total
+
+ const dieLabel = dieType.toUpperCase()
+ const resultHtml = results.map(r => {
+ const val = r.result
+ const isMax = val === sides
+ const isMin = val === 1
+ const explodeIcon = r.exploded ? `` : ""
+ const classes = ["lf-frc-die-chip", isMax ? "lf-frc-max" : "", isMin ? "lf-frc-min" : ""].filter(Boolean).join(" ")
+ return `
+ ${dieLabel}
+ →
+ ${val}${explodeIcon}
+
`
+ }).join("")
+
+ const totalLabel = game.i18n.localize("LETHALFANTASY.Label.total").toUpperCase()
+ const content = `
+
+
+
${resultHtml}
+
+ ${totalLabel}
+ ${total}
+
+
+ `
+
+ const rollMode = game.settings.get("core", "rollMode")
+ const msgData = {
+ speaker: ChatMessage.getSpeaker(),
+ content,
+ rolls: [roll],
+ sound: CONFIG.sounds.dice,
+ }
+ ChatMessage.applyRollMode(msgData, rollMode)
+ await ChatMessage.create(msgData)
+}
diff --git a/packs-system/lf-equipment/000565.log b/packs-system/lf-equipment/000568.log
similarity index 100%
rename from packs-system/lf-equipment/000565.log
rename to packs-system/lf-equipment/000568.log
diff --git a/packs-system/lf-equipment/CURRENT b/packs-system/lf-equipment/CURRENT
index 38571d7..b06900d 100644
--- a/packs-system/lf-equipment/CURRENT
+++ b/packs-system/lf-equipment/CURRENT
@@ -1 +1 @@
-MANIFEST-000563
+MANIFEST-000567
diff --git a/packs-system/lf-equipment/LOG b/packs-system/lf-equipment/LOG
index 84a85ee..15be7ca 100644
--- a/packs-system/lf-equipment/LOG
+++ b/packs-system/lf-equipment/LOG
@@ -1,8 +1,3 @@
-2026/04/16-08:58:49.556234 7fc1d97bc6c0 Recovering log #561
-2026/04/16-08:58:49.566786 7fc1d97bc6c0 Delete type=3 #559
-2026/04/16-08:58:49.566849 7fc1d97bc6c0 Delete type=0 #561
-2026/04/16-10:53:23.903167 7fc1d8fbb6c0 Level-0 table #566: started
-2026/04/16-10:53:23.903203 7fc1d8fbb6c0 Level-0 table #566: 0 bytes OK
-2026/04/16-10:53:23.909050 7fc1d8fbb6c0 Delete type=0 #564
-2026/04/16-10:53:23.921766 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
-2026/04/16-10:53:23.921790 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
+2026/04/17-15:59:28.854423 7fc1d9fbd6c0 Recovering log #565
+2026/04/17-15:59:28.865018 7fc1d9fbd6c0 Delete type=3 #563
+2026/04/17-15:59:28.865088 7fc1d9fbd6c0 Delete type=0 #565
diff --git a/packs-system/lf-equipment/LOG.old b/packs-system/lf-equipment/LOG.old
index 82912fd..84a85ee 100644
--- a/packs-system/lf-equipment/LOG.old
+++ b/packs-system/lf-equipment/LOG.old
@@ -1,8 +1,8 @@
-2026/04/14-20:54:14.172569 7fc1dafbf6c0 Recovering log #557
-2026/04/14-20:54:14.184089 7fc1dafbf6c0 Delete type=3 #555
-2026/04/14-20:54:14.184186 7fc1dafbf6c0 Delete type=0 #557
-2026/04/14-21:31:09.240081 7fc1d8fbb6c0 Level-0 table #562: started
-2026/04/14-21:31:09.240104 7fc1d8fbb6c0 Level-0 table #562: 0 bytes OK
-2026/04/14-21:31:09.273756 7fc1d8fbb6c0 Delete type=0 #560
-2026/04/14-21:31:09.274050 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
-2026/04/14-21:31:09.274107 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
+2026/04/16-08:58:49.556234 7fc1d97bc6c0 Recovering log #561
+2026/04/16-08:58:49.566786 7fc1d97bc6c0 Delete type=3 #559
+2026/04/16-08:58:49.566849 7fc1d97bc6c0 Delete type=0 #561
+2026/04/16-10:53:23.903167 7fc1d8fbb6c0 Level-0 table #566: started
+2026/04/16-10:53:23.903203 7fc1d8fbb6c0 Level-0 table #566: 0 bytes OK
+2026/04/16-10:53:23.909050 7fc1d8fbb6c0 Delete type=0 #564
+2026/04/16-10:53:23.921766 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
+2026/04/16-10:53:23.921790 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!ATr9wZhg5uTVTksM' @ 72057594037927935 : 1 .. '!items!zw9RQocTdz3HRjZK' @ 0 : 0; will stop at (end)
diff --git a/packs-system/lf-equipment/MANIFEST-000563 b/packs-system/lf-equipment/MANIFEST-000567
similarity index 71%
rename from packs-system/lf-equipment/MANIFEST-000563
rename to packs-system/lf-equipment/MANIFEST-000567
index 6e5bdd0..2ab2895 100644
Binary files a/packs-system/lf-equipment/MANIFEST-000563 and b/packs-system/lf-equipment/MANIFEST-000567 differ
diff --git a/packs-system/lf-gifts/000562.log b/packs-system/lf-gifts/000565.log
similarity index 100%
rename from packs-system/lf-gifts/000562.log
rename to packs-system/lf-gifts/000565.log
diff --git a/packs-system/lf-gifts/CURRENT b/packs-system/lf-gifts/CURRENT
index 63d81ff..9d27143 100644
--- a/packs-system/lf-gifts/CURRENT
+++ b/packs-system/lf-gifts/CURRENT
@@ -1 +1 @@
-MANIFEST-000560
+MANIFEST-000564
diff --git a/packs-system/lf-gifts/LOG b/packs-system/lf-gifts/LOG
index 89e0d5d..4658ba1 100644
--- a/packs-system/lf-gifts/LOG
+++ b/packs-system/lf-gifts/LOG
@@ -1,8 +1,3 @@
-2026/04/16-08:58:49.571861 7fc1da7be6c0 Recovering log #558
-2026/04/16-08:58:49.581625 7fc1da7be6c0 Delete type=3 #556
-2026/04/16-08:58:49.581687 7fc1da7be6c0 Delete type=0 #558
-2026/04/16-10:53:23.896992 7fc1d8fbb6c0 Level-0 table #563: started
-2026/04/16-10:53:23.897059 7fc1d8fbb6c0 Level-0 table #563: 0 bytes OK
-2026/04/16-10:53:23.903074 7fc1d8fbb6c0 Delete type=0 #561
-2026/04/16-10:53:23.921755 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)
-2026/04/16-10:53:23.921797 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)
+2026/04/17-15:59:28.871085 7fc1dafbf6c0 Recovering log #562
+2026/04/17-15:59:28.880683 7fc1dafbf6c0 Delete type=3 #560
+2026/04/17-15:59:28.880729 7fc1dafbf6c0 Delete type=0 #562
diff --git a/packs-system/lf-gifts/LOG.old b/packs-system/lf-gifts/LOG.old
index 4ab55af..89e0d5d 100644
--- a/packs-system/lf-gifts/LOG.old
+++ b/packs-system/lf-gifts/LOG.old
@@ -1,8 +1,8 @@
-2026/04/14-20:54:14.189613 7fc1d9fbd6c0 Recovering log #554
-2026/04/14-20:54:14.199454 7fc1d9fbd6c0 Delete type=3 #552
-2026/04/14-20:54:14.199515 7fc1d9fbd6c0 Delete type=0 #554
-2026/04/14-21:31:09.274309 7fc1d8fbb6c0 Level-0 table #559: started
-2026/04/14-21:31:09.274344 7fc1d8fbb6c0 Level-0 table #559: 0 bytes OK
-2026/04/14-21:31:09.316123 7fc1d8fbb6c0 Delete type=0 #557
-2026/04/14-21:31:09.426109 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)
-2026/04/14-21:31:09.426138 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)
+2026/04/16-08:58:49.571861 7fc1da7be6c0 Recovering log #558
+2026/04/16-08:58:49.581625 7fc1da7be6c0 Delete type=3 #556
+2026/04/16-08:58:49.581687 7fc1da7be6c0 Delete type=0 #558
+2026/04/16-10:53:23.896992 7fc1d8fbb6c0 Level-0 table #563: started
+2026/04/16-10:53:23.897059 7fc1d8fbb6c0 Level-0 table #563: 0 bytes OK
+2026/04/16-10:53:23.903074 7fc1d8fbb6c0 Delete type=0 #561
+2026/04/16-10:53:23.921755 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)
+2026/04/16-10:53:23.921797 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!yPWGvxHJbDNHVSnY' @ 72057594037927935 : 1 .. '!items!x5gLtqlW4sdDmHTd' @ 0 : 0; will stop at (end)
diff --git a/packs-system/lf-gifts/MANIFEST-000560 b/packs-system/lf-gifts/MANIFEST-000564
similarity index 77%
rename from packs-system/lf-gifts/MANIFEST-000560
rename to packs-system/lf-gifts/MANIFEST-000564
index e081d59..45cf728 100644
Binary files a/packs-system/lf-gifts/MANIFEST-000560 and b/packs-system/lf-gifts/MANIFEST-000564 differ
diff --git a/packs-system/lf-skills/000567.log b/packs-system/lf-skills/000570.log
similarity index 100%
rename from packs-system/lf-skills/000567.log
rename to packs-system/lf-skills/000570.log
diff --git a/packs-system/lf-skills/CURRENT b/packs-system/lf-skills/CURRENT
index 6971e86..ea062f1 100644
--- a/packs-system/lf-skills/CURRENT
+++ b/packs-system/lf-skills/CURRENT
@@ -1 +1 @@
-MANIFEST-000565
+MANIFEST-000569
diff --git a/packs-system/lf-skills/LOG b/packs-system/lf-skills/LOG
index 4399ab4..3c00901 100644
--- a/packs-system/lf-skills/LOG
+++ b/packs-system/lf-skills/LOG
@@ -1,8 +1,3 @@
-2026/04/16-08:58:49.542216 7fc1dafbf6c0 Recovering log #563
-2026/04/16-08:58:49.551998 7fc1dafbf6c0 Delete type=3 #561
-2026/04/16-08:58:49.552067 7fc1dafbf6c0 Delete type=0 #563
-2026/04/16-10:53:23.915570 7fc1d8fbb6c0 Level-0 table #568: started
-2026/04/16-10:53:23.915589 7fc1d8fbb6c0 Level-0 table #568: 0 bytes OK
-2026/04/16-10:53:23.921669 7fc1d8fbb6c0 Delete type=0 #566
-2026/04/16-10:53:23.921782 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
-2026/04/16-10:53:23.921813 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
+2026/04/17-15:59:28.839432 7fc1da7be6c0 Recovering log #567
+2026/04/17-15:59:28.849242 7fc1da7be6c0 Delete type=3 #565
+2026/04/17-15:59:28.849292 7fc1da7be6c0 Delete type=0 #567
diff --git a/packs-system/lf-skills/LOG.old b/packs-system/lf-skills/LOG.old
index d9db6bc..4399ab4 100644
--- a/packs-system/lf-skills/LOG.old
+++ b/packs-system/lf-skills/LOG.old
@@ -1,8 +1,8 @@
-2026/04/14-20:54:14.156150 7fc1d97bc6c0 Recovering log #559
-2026/04/14-20:54:14.166976 7fc1d97bc6c0 Delete type=3 #557
-2026/04/14-20:54:14.167099 7fc1d97bc6c0 Delete type=0 #559
-2026/04/14-21:31:09.203242 7fc1d8fbb6c0 Level-0 table #564: started
-2026/04/14-21:31:09.203283 7fc1d8fbb6c0 Level-0 table #564: 0 bytes OK
-2026/04/14-21:31:09.239957 7fc1d8fbb6c0 Delete type=0 #562
-2026/04/14-21:31:09.274032 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
-2026/04/14-21:31:09.274121 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
+2026/04/16-08:58:49.542216 7fc1dafbf6c0 Recovering log #563
+2026/04/16-08:58:49.551998 7fc1dafbf6c0 Delete type=3 #561
+2026/04/16-08:58:49.552067 7fc1dafbf6c0 Delete type=0 #563
+2026/04/16-10:53:23.915570 7fc1d8fbb6c0 Level-0 table #568: started
+2026/04/16-10:53:23.915589 7fc1d8fbb6c0 Level-0 table #568: 0 bytes OK
+2026/04/16-10:53:23.921669 7fc1d8fbb6c0 Delete type=0 #566
+2026/04/16-10:53:23.921782 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
+2026/04/16-10:53:23.921813 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!7j8H7DbmBb9Uza2X' @ 72057594037927935 : 1 .. '!items!zt8s7564ep1La4XQ' @ 0 : 0; will stop at (end)
diff --git a/packs-system/lf-skills/MANIFEST-000565 b/packs-system/lf-skills/MANIFEST-000569
similarity index 71%
rename from packs-system/lf-skills/MANIFEST-000565
rename to packs-system/lf-skills/MANIFEST-000569
index 87ceef3..34fda82 100644
Binary files a/packs-system/lf-skills/MANIFEST-000565 and b/packs-system/lf-skills/MANIFEST-000569 differ
diff --git a/packs-system/lf-spells-miracles/000262.log b/packs-system/lf-spells-miracles/000265.log
similarity index 100%
rename from packs-system/lf-spells-miracles/000262.log
rename to packs-system/lf-spells-miracles/000265.log
diff --git a/packs-system/lf-spells-miracles/CURRENT b/packs-system/lf-spells-miracles/CURRENT
index 8819f7c..a744b45 100644
--- a/packs-system/lf-spells-miracles/CURRENT
+++ b/packs-system/lf-spells-miracles/CURRENT
@@ -1 +1 @@
-MANIFEST-000260
+MANIFEST-000264
diff --git a/packs-system/lf-spells-miracles/LOG b/packs-system/lf-spells-miracles/LOG
index 31de34f..985aa4f 100644
--- a/packs-system/lf-spells-miracles/LOG
+++ b/packs-system/lf-spells-miracles/LOG
@@ -1,8 +1,3 @@
-2026/04/16-08:58:49.600337 7fc1dafbf6c0 Recovering log #258
-2026/04/16-08:58:49.610136 7fc1dafbf6c0 Delete type=3 #256
-2026/04/16-08:58:49.610209 7fc1dafbf6c0 Delete type=0 #258
-2026/04/16-10:53:23.940580 7fc1d8fbb6c0 Level-0 table #263: started
-2026/04/16-10:53:23.940611 7fc1d8fbb6c0 Level-0 table #263: 0 bytes OK
-2026/04/16-10:53:23.947242 7fc1d8fbb6c0 Delete type=0 #261
-2026/04/16-10:53:23.947402 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
-2026/04/16-10:53:23.947419 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
+2026/04/17-15:59:28.899464 7fc1d97bc6c0 Recovering log #262
+2026/04/17-15:59:28.910004 7fc1d97bc6c0 Delete type=3 #260
+2026/04/17-15:59:28.910074 7fc1d97bc6c0 Delete type=0 #262
diff --git a/packs-system/lf-spells-miracles/LOG.old b/packs-system/lf-spells-miracles/LOG.old
index 1c3f273..31de34f 100644
--- a/packs-system/lf-spells-miracles/LOG.old
+++ b/packs-system/lf-spells-miracles/LOG.old
@@ -1,8 +1,8 @@
-2026/04/14-20:54:14.216969 7fc1d97bc6c0 Recovering log #254
-2026/04/14-20:54:14.226830 7fc1d97bc6c0 Delete type=3 #252
-2026/04/14-20:54:14.226876 7fc1d97bc6c0 Delete type=0 #254
-2026/04/14-21:31:09.316377 7fc1d8fbb6c0 Level-0 table #259: started
-2026/04/14-21:31:09.316424 7fc1d8fbb6c0 Level-0 table #259: 0 bytes OK
-2026/04/14-21:31:09.353574 7fc1d8fbb6c0 Delete type=0 #257
-2026/04/14-21:31:09.426120 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
-2026/04/14-21:31:09.426154 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
+2026/04/16-08:58:49.600337 7fc1dafbf6c0 Recovering log #258
+2026/04/16-08:58:49.610136 7fc1dafbf6c0 Delete type=3 #256
+2026/04/16-08:58:49.610209 7fc1dafbf6c0 Delete type=0 #258
+2026/04/16-10:53:23.940580 7fc1d8fbb6c0 Level-0 table #263: started
+2026/04/16-10:53:23.940611 7fc1d8fbb6c0 Level-0 table #263: 0 bytes OK
+2026/04/16-10:53:23.947242 7fc1d8fbb6c0 Delete type=0 #261
+2026/04/16-10:53:23.947402 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
+2026/04/16-10:53:23.947419 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!37mu4dxsSuftlnmP' @ 72057594037927935 : 1 .. '!items!zKOpU34oLziGJW6y' @ 0 : 0; will stop at (end)
diff --git a/packs-system/lf-spells-miracles/MANIFEST-000260 b/packs-system/lf-spells-miracles/MANIFEST-000264
similarity index 72%
rename from packs-system/lf-spells-miracles/MANIFEST-000260
rename to packs-system/lf-spells-miracles/MANIFEST-000264
index 30eca59..7d09365 100644
Binary files a/packs-system/lf-spells-miracles/MANIFEST-000260 and b/packs-system/lf-spells-miracles/MANIFEST-000264 differ
diff --git a/packs-system/lf-vulnerabilities/000561.log b/packs-system/lf-vulnerabilities/000564.log
similarity index 100%
rename from packs-system/lf-vulnerabilities/000561.log
rename to packs-system/lf-vulnerabilities/000564.log
diff --git a/packs-system/lf-vulnerabilities/CURRENT b/packs-system/lf-vulnerabilities/CURRENT
index 2093527..38571d7 100644
--- a/packs-system/lf-vulnerabilities/CURRENT
+++ b/packs-system/lf-vulnerabilities/CURRENT
@@ -1 +1 @@
-MANIFEST-000559
+MANIFEST-000563
diff --git a/packs-system/lf-vulnerabilities/LOG b/packs-system/lf-vulnerabilities/LOG
index 0facdf8..223136e 100644
--- a/packs-system/lf-vulnerabilities/LOG
+++ b/packs-system/lf-vulnerabilities/LOG
@@ -1,8 +1,3 @@
-2026/04/16-08:58:49.586323 7fc1d9fbd6c0 Recovering log #557
-2026/04/16-08:58:49.596973 7fc1d9fbd6c0 Delete type=3 #555
-2026/04/16-08:58:49.597026 7fc1d9fbd6c0 Delete type=0 #557
-2026/04/16-10:53:23.909144 7fc1d8fbb6c0 Level-0 table #562: started
-2026/04/16-10:53:23.909174 7fc1d8fbb6c0 Level-0 table #562: 0 bytes OK
-2026/04/16-10:53:23.915478 7fc1d8fbb6c0 Delete type=0 #560
-2026/04/16-10:53:23.921775 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
-2026/04/16-10:53:23.921804 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
+2026/04/17-15:59:28.886104 7fc1da7be6c0 Recovering log #561
+2026/04/17-15:59:28.896104 7fc1da7be6c0 Delete type=3 #559
+2026/04/17-15:59:28.896157 7fc1da7be6c0 Delete type=0 #561
diff --git a/packs-system/lf-vulnerabilities/LOG.old b/packs-system/lf-vulnerabilities/LOG.old
index e72f629..0facdf8 100644
--- a/packs-system/lf-vulnerabilities/LOG.old
+++ b/packs-system/lf-vulnerabilities/LOG.old
@@ -1,8 +1,8 @@
-2026/04/14-20:54:14.202677 7fc1da7be6c0 Recovering log #553
-2026/04/14-20:54:14.213358 7fc1da7be6c0 Delete type=3 #551
-2026/04/14-20:54:14.213482 7fc1da7be6c0 Delete type=0 #553
-2026/04/14-21:31:09.160202 7fc1d8fbb6c0 Level-0 table #558: started
-2026/04/14-21:31:09.160283 7fc1d8fbb6c0 Level-0 table #558: 0 bytes OK
-2026/04/14-21:31:09.203034 7fc1d8fbb6c0 Delete type=0 #556
-2026/04/14-21:31:09.274014 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
-2026/04/14-21:31:09.274091 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
+2026/04/16-08:58:49.586323 7fc1d9fbd6c0 Recovering log #557
+2026/04/16-08:58:49.596973 7fc1d9fbd6c0 Delete type=3 #555
+2026/04/16-08:58:49.597026 7fc1d9fbd6c0 Delete type=0 #557
+2026/04/16-10:53:23.909144 7fc1d8fbb6c0 Level-0 table #562: started
+2026/04/16-10:53:23.909174 7fc1d8fbb6c0 Level-0 table #562: 0 bytes OK
+2026/04/16-10:53:23.915478 7fc1d8fbb6c0 Delete type=0 #560
+2026/04/16-10:53:23.921775 7fc1d8fbb6c0 Manual compaction at level-0 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
+2026/04/16-10:53:23.921804 7fc1d8fbb6c0 Manual compaction at level-1 from '!folders!mnO9OzE7BEE2KDfh' @ 72057594037927935 : 1 .. '!items!zkK6ixtCsCw3RH9X' @ 0 : 0; will stop at (end)
diff --git a/packs-system/lf-vulnerabilities/MANIFEST-000559 b/packs-system/lf-vulnerabilities/MANIFEST-000563
similarity index 72%
rename from packs-system/lf-vulnerabilities/MANIFEST-000559
rename to packs-system/lf-vulnerabilities/MANIFEST-000563
index d63d46a..3f09afd 100644
Binary files a/packs-system/lf-vulnerabilities/MANIFEST-000559 and b/packs-system/lf-vulnerabilities/MANIFEST-000563 differ
diff --git a/styles/hud.less b/styles/hud.less
index 3034c4b..68be8fd 100644
--- a/styles/hud.less
+++ b/styles/hud.less
@@ -88,3 +88,249 @@
padding-left: 8px;
font-size: 0.9rem;
}
+
+/* -------------------------------------------------- */
+/* Dice Tray — injected into the Foundry chat sidebar */
+/* -------------------------------------------------- */
+
+.lf-dice-tray {
+ padding: 6px 8px;
+ background:
+ linear-gradient(135deg, rgba(245, 232, 200, 0.97) 0%, rgba(238, 222, 185, 0.97) 100%),
+ url("/systems/fvtt-lethal-fantasy/assets/ui/lethal_fantasy_background.webp") center / cover;
+ border-top: 2px solid rgba(139, 69, 19, 0.5);
+ border-bottom: 1px solid rgba(139, 69, 19, 0.25);
+ width: 100%;
+ box-sizing: border-box;
+ pointer-events: all;
+
+ .lf-dt-row {
+ display: flex;
+ align-items: center;
+ gap: 5px;
+ flex-wrap: wrap;
+ }
+
+ .lf-dt-label {
+ color: #3a2a10;
+ font-size: 15px;
+ flex-shrink: 0;
+ opacity: 0.7;
+ }
+
+ .lf-dt-count {
+ width: 44px;
+ flex-shrink: 0;
+ padding: 3px 4px;
+ background: rgba(139, 69, 19, 0.15);
+ border: 1px solid rgba(139, 69, 19, 0.45);
+ border-radius: 4px;
+ color: #2a1a08;
+ font-size: 11px;
+ font-weight: 700;
+ cursor: pointer;
+ text-align: center;
+
+ option { background: #f5ead0; color: #2a1a08; }
+
+ &:focus {
+ outline: none;
+ border-color: rgba(139, 69, 19, 0.7);
+ box-shadow: 0 0 4px rgba(139, 69, 19, 0.25);
+ }
+ }
+
+ .lf-dt-dice {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 3px;
+ flex: 1;
+ }
+
+ .lf-dt-die-btn {
+ padding: 3px 7px;
+ background: rgba(139, 69, 19, 0.15);
+ border: 1px solid rgba(139, 69, 19, 0.4);
+ border-radius: 4px;
+ color: #2a1a08;
+ font-size: 10px;
+ font-weight: 700;
+ cursor: pointer;
+ transition: background 0.15s, border-color 0.15s, box-shadow 0.15s, transform 0.1s;
+ line-height: 1.5;
+ letter-spacing: 0.3px;
+
+ &:hover {
+ background: rgba(139, 69, 19, 0.35);
+ border-color: rgba(139, 69, 19, 0.7);
+ color: #5a2a00;
+ box-shadow: 0 0 5px rgba(139, 69, 19, 0.3);
+ transform: translateY(-1px);
+ }
+
+ &:active {
+ transform: translateY(0);
+ box-shadow: none;
+ background: rgba(139, 69, 19, 0.5);
+ }
+ }
+
+ .lf-dt-explode-label {
+ display: flex;
+ align-items: center;
+ gap: 3px;
+ cursor: pointer;
+ color: rgba(160, 80, 20, 0.7);
+ font-size: 14px;
+ flex-shrink: 0;
+ padding: 3px 6px;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ transition: color 0.15s, border-color 0.15s, background 0.15s;
+
+ &:hover {
+ color: rgba(200, 100, 30, 0.9);
+ border-color: rgba(139, 69, 19, 0.45);
+ background: rgba(139, 69, 19, 0.12);
+ }
+
+ input[type="checkbox"] {
+ appearance: none;
+ width: 0;
+ height: 0;
+ position: absolute;
+ opacity: 0;
+
+ &:checked ~ i {
+ color: #cc4400;
+ filter: drop-shadow(0 0 4px rgba(200, 80, 0, 0.6));
+ }
+ }
+
+ &:has(input:checked) {
+ color: #cc4400;
+ border-color: rgba(139, 69, 19, 0.55);
+ background: rgba(139, 60, 10, 0.2);
+ }
+ }
+}
+
+/* Free roll chat card — styled to match regular system roll cards */
+.lf-free-roll-card {
+ border-radius: 6px;
+ overflow: hidden;
+
+ .lf-frc-header {
+ display: flex;
+ align-items: center;
+ gap: 6px;
+ padding: 6px 8px;
+ background: linear-gradient(135deg, rgba(40, 30, 20, 0.7) 0%, rgba(30, 22, 15, 0.9) 100%);
+ border-bottom: 2px solid rgba(139, 69, 19, 0.4);
+
+ i { color: #c9b896; font-size: calc(var(--font-size-standard, 14px) * 1.1); }
+
+ .lf-frc-title-text {
+ font-size: calc(var(--font-size-standard, 14px) * 0.85);
+ color: #c9b896;
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ }
+
+ .lf-frc-badge {
+ display: inline-flex;
+ align-items: center;
+ padding: 2px 8px;
+ background: rgba(139, 69, 19, 0.3);
+ border: 1px solid rgba(139, 69, 19, 0.5);
+ border-radius: 10px;
+ font-size: calc(var(--font-size-standard, 14px) * 0.85);
+ font-weight: 600;
+ color: #d4c5a9;
+ }
+ }
+
+ .lf-frc-dice {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 4px;
+ padding: 6px 8px;
+ background: rgba(0, 0, 0, 0.15);
+ border: 1px solid rgba(139, 69, 19, 0.3);
+ border-top: none;
+
+ .lf-frc-die-chip {
+ display: flex;
+ align-items: center;
+ gap: 4px;
+ padding: 3px 8px;
+ background: rgba(139, 69, 19, 0.2);
+ border: 1px solid rgba(139, 69, 19, 0.3);
+ border-radius: 4px;
+
+ .lf-frc-die-type {
+ font-size: calc(var(--font-size-standard, 14px) * 0.85);
+ font-weight: 600;
+ color: #2a2a1a;
+ text-transform: uppercase;
+ }
+
+ .lf-frc-die-sep {
+ color: rgba(0, 0, 0, 0.35);
+ font-weight: 300;
+ font-size: calc(var(--font-size-standard, 14px) * 0.8);
+ }
+
+ .lf-frc-die-val {
+ font-weight: bold;
+ color: #ffd700;
+ font-size: calc(var(--font-size-standard, 14px) * 0.95);
+
+ .lf-dt-explode-icon {
+ font-size: 8px;
+ color: #ffcc00;
+ margin-left: 2px;
+ vertical-align: super;
+ text-shadow: 0 0 4px rgba(255, 200, 0, 0.8);
+ }
+ }
+
+ &.lf-frc-max {
+ background: rgba(139, 90, 19, 0.35);
+ border-color: rgba(200, 116, 42, 0.6);
+ .lf-frc-die-val { color: #ff9a40; text-shadow: 0 0 6px rgba(200, 116, 42, 0.6); }
+ }
+
+ &.lf-frc-min {
+ background: rgba(139, 20, 20, 0.25);
+ border-color: rgba(139, 34, 34, 0.5);
+ .lf-frc-die-val { color: #ff6b6b; }
+ }
+ }
+ }
+
+ .lf-frc-total-bar {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ padding: 6px 10px;
+ background: linear-gradient(135deg, rgba(40, 30, 20, 0.6) 0%, rgba(20, 15, 10, 0.8) 100%);
+ border: 2px solid rgba(139, 69, 19, 0.5);
+
+ .lf-frc-total-label {
+ font-size: calc(var(--font-size-standard, 14px) * 0.85);
+ text-transform: uppercase;
+ letter-spacing: 0.5px;
+ color: #c9b896;
+ }
+
+ .lf-frc-total-value {
+ font-family: var(--font-primary, serif);
+ font-size: calc(var(--font-size-standard, 14px) * 1.6);
+ font-weight: bold;
+ color: #e8d5a0;
+ text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.8);
+ }
+ }
+}
diff --git a/styles/roll.less b/styles/roll.less
index 1163e78..60d9a36 100644
--- a/styles/roll.less
+++ b/styles/roll.less
@@ -467,7 +467,7 @@
.d30-label {
flex-grow: 1;
font-weight: bold;
- color: #e0d5f0;
+ color: #2a1a3a;
text-transform: uppercase;
letter-spacing: 0.5px;
font-size: calc(var(--font-size-standard) * 0.9);
@@ -477,11 +477,11 @@
font-family: var(--font-primary);
font-size: calc(var(--font-size-standard) * 1.5);
font-weight: bold;
- color: #ff69b4;
- background: rgba(255, 105, 180, 0.1);
+ color: #3d006e;
+ background: rgba(255, 255, 255, 0.35);
padding: 4px 12px;
border-radius: 12px;
- border: 1px solid rgba(255, 105, 180, 0.3);
+ border: 1px solid rgba(138, 43, 226, 0.4);
}
}