diff --git a/docs/circular-deps.txt b/docs/circular-deps.txt
index e9106fa..bb6360c 100644
--- a/docs/circular-deps.txt
+++ b/docs/circular-deps.txt
@@ -1,5 +1,5 @@
# Circular Dependencies
-Generated: 2026-06-08T11:14:13.243Z
+Generated: 2026-06-08T11:29:45.994Z
Found: 1 circular chain(s) — these MUST be fixed before modifying involved files.
1. 1) stores/golem-combat-actions.ts > stores/golem-combat-helpers.ts
diff --git a/docs/dependency-graph.json b/docs/dependency-graph.json
index 25b3a71..a400ef7 100644
--- a/docs/dependency-graph.json
+++ b/docs/dependency-graph.json
@@ -1,6 +1,6 @@
{
"_meta": {
- "generated": "2026-06-08T11:14:11.296Z",
+ "generated": "2026-06-08T11:29:44.022Z",
"description": "Import dependency graph for src/lib/game. Keys are files, values are arrays of files they import.",
"usage": "To find what a file affects, search for its path in the VALUES. To find what a file depends on, look at its KEY entry."
},
diff --git a/src/components/game/tabs/StatsTab.tsx b/src/components/game/tabs/StatsTab.tsx
index ba800a3..5186527 100644
--- a/src/components/game/tabs/StatsTab.tsx
+++ b/src/components/game/tabs/StatsTab.tsx
@@ -51,6 +51,8 @@ export function StatsTab() {
/>
diff --git a/src/components/game/tabs/StatsTab/ElementStatsSection.tsx b/src/components/game/tabs/StatsTab/ElementStatsSection.tsx
index e715b52..e92e47c 100644
--- a/src/components/game/tabs/StatsTab/ElementStatsSection.tsx
+++ b/src/components/game/tabs/StatsTab/ElementStatsSection.tsx
@@ -15,9 +15,11 @@ import type { ElementState } from '@/lib/game/types';
interface ElementStatsSectionProps {
elemMax: number;
+ meditationMultiplier: number;
+ baseRegen: number;
}
-export function ElementStatsSection({ elemMax }: ElementStatsSectionProps) {
+export function ElementStatsSection({ elemMax, meditationMultiplier, baseRegen }: ElementStatsSectionProps) {
const prestigeUpgrades = usePrestigeStore((s) => s.prestigeUpgrades);
const signedPacts = usePrestigeStore((s) => s.signedPacts);
const elements = useManaStore((s) => s.elements);
@@ -48,9 +50,9 @@ export function ElementStatsSection({ elemMax }: ElementStatsSectionProps) {
signedPacts,
pactElementMap,
invokerLevel,
- meditationMultiplier: 1,
+ meditationMultiplier,
grossRegen,
- rawGrossRegen: 2,
+ rawGrossRegen: baseRegen,
});
}, [disciplines, attunements, signedPacts]);
@@ -123,7 +125,7 @@ export function ElementStatsSection({ elemMax }: ElementStatsSectionProps) {
Conversion Breakdown:
{activeConversions.map((entry) => (
-
+
))}
>
@@ -134,8 +136,31 @@ export function ElementStatsSection({ elemMax }: ElementStatsSectionProps) {
);
}
-function ConversionRow({ entry }: { entry: { element: string; distance: number; disciplineRate: number; attunementBase: number; pactBase: number; baseRate: number; attunementMult: number; pactMult: number; meditationMult: number; finalRate: number; paused: boolean; pauseReason: string | null } }) {
+function ConversionRow({ entry, elementDrain }: {
+ entry: {
+ element: string;
+ distance: number;
+ disciplineRate: number;
+ attunementBase: number;
+ pactBase: number;
+ baseRate: number;
+ attunementMult: number;
+ pactMult: number;
+ meditationMult: number;
+ finalRate: number;
+ paused: boolean;
+ pauseReason: string | null;
+ rawCost: number;
+ componentCosts: Record;
+ };
+ elementDrain: Record;
+}) {
const def = ELEMENTS[entry.element];
+ const effectiveRate = entry.paused ? 0 : entry.finalRate;
+ const rawDrain = effectiveRate * entry.rawCost;
+ const isComponentDrained = Object.keys(entry.componentCosts).length > 0 &&
+ Object.keys(elementDrain).length > 0;
+
return (
@@ -144,6 +169,7 @@ function ConversionRow({ entry }: { entry: { element: string; distance: number;
(d={entry.distance})
{entry.paused && ⏸️ PAUSED}
+ {/* Rate breakdown */}
Discipline: +{fmtDec(entry.disciplineRate, 2)}/hr
Attunement: +{fmtDec(entry.attunementBase, 2)}/hr
@@ -154,6 +180,32 @@ function ConversionRow({ entry }: { entry: { element: string; distance: number;
Med mult: ×{fmtDec(entry.meditationMult, 2)}
Final: {entry.paused ? '0.00' : fmtDec(entry.finalRate, 2)}/hr
+ {/* Cost breakdown (per spec §11) */}
+ {!entry.paused && effectiveRate > 0 && (
+
+
Costs (deducted from regen):
+
+
Raw: -{fmtDec(rawDrain, 2)} raw/hr ({entry.rawCost} × {fmtDec(effectiveRate, 2)})
+ {Object.entries(entry.componentCosts).map(([comp, cost]) => {
+ const compDrain = effectiveRate * cost;
+ const compDef = ELEMENTS[comp];
+ return (
+
+ {compDef?.sym} {comp}:{' '}
+ -{fmtDec(compDrain, 2)}/hr{' '}
+ ({cost} × {fmtDec(effectiveRate, 2)})
+
+ );
+ })}
+
+ {/* Downstream drain (this element consumed by higher conversions) */}
+ {isComponentDrained && elementDrain[entry.element] > 0 && (
+
+ ↓ Drained by downstream: -{fmtDec(elementDrain[entry.element], 2)} {def?.name}/hr
+
+ )}
+
+ )}
{entry.paused && entry.pauseReason && (
⚠️ {entry.pauseReason}
)}