diff --git a/configurator/src/components/inputs/ValueField.svelte b/configurator/src/components/inputs/ValueField.svelte
index 7e3d81bc..d94c8267 100644
--- a/configurator/src/components/inputs/ValueField.svelte
+++ b/configurator/src/components/inputs/ValueField.svelte
@@ -22,10 +22,17 @@
let draft = $state("");
let editing = $state(false);
let cancelling = $state(false);
- // Reset a user-selected tab when another surface changes this token.
+ // Switching back to Inherit throws away the override. The tab sits right next
+ // to Value/Expression and reads like a harmless view switch, so a stray click
+ // used to silently wipe an edit. When there's an actual override to lose we
+ // arm this confirm step instead of resetting immediately.
+ let confirmingInherit = $state(false);
+ // Reset a user-selected tab (and any pending confirm) when another surface
+ // changes this token.
$effect(() => {
overrideValue;
manualMode = null;
+ confirmingInherit = false;
});
// Seed the text field from the live value whenever we're not mid-edit.
$effect(() => {
@@ -41,8 +48,22 @@
}
function setMode(m: ValueMode) {
+ if (m === "inherit") {
+ // Nothing overridden → already inheriting, so this is a no-op, not a
+ // destructive reset; just settle on auto-detect.
+ if (overrideValue === undefined) { manualMode = null; confirmingInherit = false; return; }
+ // Otherwise require an explicit confirmation before discarding the value.
+ confirmingInherit = true;
+ return;
+ }
+ confirmingInherit = false;
manualMode = m;
- if (m === "inherit") { onReset(); manualMode = null; }
+ }
+
+ function confirmInherit() {
+ confirmingInherit = false;
+ manualMode = null;
+ onReset();
}
const TABS: { id: ValueMode; label: string }[] = [
@@ -56,11 +77,12 @@
{#each TABS as t (t.id)}
+ {@const active = confirmingInherit ? t.id === "inherit" : mode === t.id}
+
+ {#if confirmingInherit}
+
+
+ Discard this override and inherit {token.value}?
+
+
+
+
SLASHED flows this text across as many equal columns as fit the box, divided by the column rule. Lower the min column width to pack in more, narrower columns; raise it for fewer, roomier ones. The rule width, style and colour draw the divider.
+
+
@@ -549,6 +568,18 @@
{/if}
+
+
+
+ {#each [1, 2, 3, 4, 5, 6] as n (n)}
+
{n}
+ {/each}
+
+
diff --git a/configurator/src/components/panels/MiscPanel.svelte b/configurator/src/components/panels/MiscPanel.svelte
index f03008a2..af9e48e8 100644
--- a/configurator/src/components/panels/MiscPanel.svelte
+++ b/configurator/src/components/panels/MiscPanel.svelte
@@ -53,6 +53,24 @@
function getSizeValue(t: typeof SIZE_TOKENS[0]): number {
return parseNum(overrides[t.token]?.replace("rem",""), t.default);
}
+
+ const ICON_STEPS = ["xs", "s", "m", "l", "xl", "2xl"];
+
+ // A deliberately landscape (2:1) sample with a centered ring and a full-bleed
+ // border, so object-fit differences are unmistakable: cover crops the sides,
+ // contain letterboxes, fill distorts the circle, none overflows at native px.
+ const OBJECT_FIT_IMG = `data:image/svg+xml,${encodeURIComponent(
+ ``,
+ )}`;
+
+ // Layering ladder for the preview: ordered by each rung's *current* value
+ // (override or default), highest first, so reordering the numbers reorders
+ // the visual stack instead of showing a fixed hierarchy.
+ let zLadder = $derived(
+ Z_INDEX_STEPS
+ .map((z) => ({ ...z, val: parseNum(overrides[z.token], z.def) }))
+ .sort((a, b) => b.val - a.val),
+ );