diff --git a/src/app/components/DatasetsModal.tsx b/src/app/components/DatasetsModal.tsx
index 0c85820..d1c1158 100644
--- a/src/app/components/DatasetsModal.tsx
+++ b/src/app/components/DatasetsModal.tsx
@@ -19,7 +19,12 @@ import { detectFormat, detectFormatFromUrl, type DataFormat } from '@core/format
import { closeModal, openModal, resnapshot } from '../modals/ModalCoordinator';
import { confirm } from '../stores/ConfirmStore';
import { notify } from '../stores/NotificationStore';
-import { selectSelectedDataset, useDatasetStore, byModifiedDesc } from '../stores/DatasetStore';
+import {
+ selectCanSave,
+ selectSelectedDataset,
+ useDatasetStore,
+ byModifiedDesc,
+} from '../stores/DatasetStore';
import { useSnippetStore } from '../stores/SnippetStore';
import { SegmentedControl, type SegmentedOption } from './SegmentedControl';
import { Icon } from './Icon';
@@ -338,6 +343,8 @@ function DatasetFormView({ editing }: { editing: boolean }) {
const updateForm = useDatasetStore((s) => s.updateForm);
const cancelForm = useDatasetStore((s) => s.cancelForm);
const save = useDatasetStore((s) => s.save);
+ // Save stays disabled until a name and valid data/URL are present (spec §05).
+ const canSave = useDatasetStore(selectCanSave);
// Live format/source hint from the current input (spec §05 → Auto-detection).
const detected =
@@ -433,7 +440,12 @@ function DatasetFormView({ editing }: { editing: boolean }) {
-