diff --git a/ui/src/components/OperationPanel.jsx b/ui/src/components/OperationPanel.jsx
index bd09fff..45e770a 100644
--- a/ui/src/components/OperationPanel.jsx
+++ b/ui/src/components/OperationPanel.jsx
@@ -834,17 +834,17 @@ function ScaleLedger({ currentTotals, scaleInputs, setScaleInputs, scalePlug, se
const plugState = (() => {
if (!(valueCol && unitsCol)) return null
const u = filled('units'), p = filled('price'), v = filled('value')
- if (u && p) return { value: null, live: false, why: 'Both qty and price are named, so the dollars follow from them.' }
- if (u && v) return { value: null, live: false, why: `Both ${valueCol} and ${unitsCol} are named, so price falls out of the two — this is the deliberate price change.` }
- if (u) return { value: null, live: false, why: `Price holds; ${valueCol} follows ${unitsCol} in proportion. Name the dollars as well to move price instead.`, unpin: 'units' }
- if (p) return { value: 'volume', live: false, why: `Price is pinned, so ${unitsCol} absorbs the change.`, unpin: 'price' }
- if (!v) return { value: null, live: false, why: 'Applies to a dollar figure entered on its own — nothing else names price or qty.' }
+ if (u && p) return { value: null, live: false, why: `${unitsCol} and price named — ${valueCol} follows` }
+ if (u && v) return { value: null, live: false, why: `${valueCol} and ${unitsCol} named — price follows` }
+ if (u) return { value: null, live: false, why: `price holds — ${valueCol} follows ${unitsCol}`, unpin: 'units' }
+ if (p) return { value: 'volume', live: false, why: `price pinned — ${unitsCol} absorbs it`, unpin: 'price' }
+ if (!v) return { value: null, live: false, why: `for a ${valueCol} figure on its own` }
return {
value: scalePlug,
live: true,
why: scalePlug === 'price'
- ? `${unitsCol} holds; price moves to reach the number.`
- : `Price holds; ${unitsCol} scales with the dollars.`,
+ ? `${unitsCol} holds — price moves`
+ : `price holds — ${unitsCol} moves`,
}
})()
@@ -1046,7 +1046,7 @@ function ScaleLedger({ currentTotals, scaleInputs, setScaleInputs, scalePlug, se
{plugState && (
-
+
+ ? `${exclName} can't move — the forecast absorbs it`
+ : `${exclName} left out — the pivot will show your number plus ${fmtNum(excl.value)}`}>
{/* "Adjustable" and "Selected total" are the writer's words for
it -- which rows the SQL may touch. What a rep is choosing is
whether the number they type is the forecast alone or the
@@ -1087,9 +1087,8 @@ function ScaleLedger({ currentTotals, scaleInputs, setScaleInputs, scalePlug, se
)}
{perSlice && (
-
- Applied to each slice separately
+
+ figures above are combined totals
)}
@@ -1233,6 +1232,9 @@ function MovingTotal({ currentTotals, verb, factor, includeExcluded }) {
}
// ── Apply mode ──────────────────────────────────────────────────────────────
+// The detail lives on each option's tooltip. It used to be a sentence printed
+// under the control, and a sentence under a control is read once and skipped
+// forever after -- while costing the top strip its height on every render.
function ApplyModeChooser({ op, applyMode, setApplyMode, count }) {
const options = op === 'scale'
? [
@@ -1243,14 +1245,7 @@ function ApplyModeChooser({ op, applyMode, setApplyMode, count }) {
['prorate', 'Together', `One operation over all ${count} slices — a single log entry.`],
['each', 'Each', `One operation per slice — ${count} log entries, undoable separately.`],
]
- const active = options.find(([v]) => v === applyMode)
- return (
-
- [v, l, t])} />
- {active &&
{active[2]}
}
-
- )
+ return
}
function RequestPreview({ payload }) {
@@ -1351,9 +1346,7 @@ export default function OperationPanel({
which is the point: a period with no baseline borrows its
shape from prior year or plan. */}
+ hint={cloneFrom ? 'only that segment, out of the selection' : undefined}>