diff --git a/frontend/src/routes/+page.svelte b/frontend/src/routes/+page.svelte
index b60a5e7..8382f49 100644
--- a/frontend/src/routes/+page.svelte
+++ b/frontend/src/routes/+page.svelte
@@ -136,16 +136,6 @@
scheduleRecompute();
}
- function onEdgeOffsetChange(val) {
- maskState = reduceMaskState(maskState, { type: 'set_edge_offset', value: Number(val) });
- scheduleRecompute();
- }
-
- function onFeatherChange(val) {
- maskState = reduceMaskState(maskState, { type: 'set_feather', value: Number(val) });
- scheduleRecompute();
- }
-
function approveMask() {
if (!maskState || maskState.stats.empty) return;
maskState = reduceMaskState(maskState, { type: 'approve' });
@@ -394,18 +384,6 @@
{maskState.sensitivity}
-
-
-
- {maskState.edgeOffset}px
-
-
-
-
-
- {maskState.feather}px
-
-
diff --git a/frontend/tests/e2e/mask.spec.js b/frontend/tests/e2e/mask.spec.js
index 56a67a0..98e4593 100644
--- a/frontend/tests/e2e/mask.spec.js
+++ b/frontend/tests/e2e/mask.spec.js
@@ -8,7 +8,8 @@ import { test, expect } from '@playwright/test';
// - "Approve is blocked when the mask has no slab pixels. User retakes."
// - "If the file is HEIC and the browser cannot decode it, show a one-tap
// notice to retake the photo as JPEG."
-// - 4 knobs: sheet Auto/Green/Black, sensitivity 0–100, edge offset, feather.
+// - 2 knobs: sheet Auto/Green/Black, sensitivity 0–100 (slider + minus/plus).
+// Edge offset and feather are NOT user-exposed in M1 (core params only).
// - Sensitivity slider updates immediately; overlay recomputes 2.0 s after
// the last change.
@@ -49,7 +50,7 @@ test.describe('Mask state (M1-5 live UI)', () => {
await expect(approve).toBeEnabled();
});
- test('keys the green sheet and shows the 4 knobs', async ({ page }) => {
+ test('keys the green sheet and shows the 2 spec knobs', async ({ page }) => {
await page.goto('/');
await page.locator('input[type="file"]').setInputFiles(SLAB_FIXTURE);
// Sheet control with Auto/Green/Black.
@@ -64,9 +65,10 @@ test.describe('Mask state (M1-5 live UI)', () => {
await expect(slider).toHaveAttribute('max', '100');
await expect(page.getByRole('button', { name: /decrease sensitivity/i })).toBeVisible();
await expect(page.getByRole('button', { name: /increase sensitivity/i })).toBeVisible();
- // Edge offset and feather knobs.
- await expect(page.getByRole('slider', { name: /edge offset/i })).toBeVisible();
- await expect(page.getByRole('slider', { name: /feather/i })).toBeVisible();
+ // Edge offset and feather are NOT in the spec — they must not be
+ // user-exposed in the Mask UI.
+ await expect(page.getByRole('slider', { name: /edge offset/i })).not.toBeVisible();
+ await expect(page.getByRole('slider', { name: /feather/i })).not.toBeVisible();
// Overlay visible (photo with checkerboard on removed px).
await expect(page.locator('[data-testid="mask-overlay"]')).toBeVisible();
});
@@ -80,17 +82,6 @@ test.describe('Mask state (M1-5 live UI)', () => {
await expect(slider).toHaveValue('80');
});
- test('edge offset and feather update immediately', async ({ page }) => {
- await page.goto('/');
- await page.locator('input[type="file"]').setInputFiles(SLAB_FIXTURE);
- const edge = page.getByRole('slider', { name: /edge offset/i });
- const feather = page.getByRole('slider', { name: /feather/i });
- await edge.fill('2');
- await expect(edge).toHaveValue('2');
- await feather.fill('3');
- await expect(feather).toHaveValue('3');
- });
-
test('approve advances to Length axis after a non-empty mask', async ({ page }) => {
await page.goto('/');
await page.locator('input[type="file"]').setInputFiles(SLAB_FIXTURE);