diff --git a/src/lib/components/collection/BulkDeleteConfirmModal.svelte b/src/lib/components/collection/BulkDeleteConfirmModal.svelte
new file mode 100644
index 00000000..2d8913ce
--- /dev/null
+++ b/src/lib/components/collection/BulkDeleteConfirmModal.svelte
@@ -0,0 +1,60 @@
+
+
+
+
+
diff --git a/src/lib/components/collection/SelectableCollectionCard.svelte b/src/lib/components/collection/SelectableCollectionCard.svelte
new file mode 100644
index 00000000..d2ce6fb0
--- /dev/null
+++ b/src/lib/components/collection/SelectableCollectionCard.svelte
@@ -0,0 +1,82 @@
+
+
+
+ {#if selectionMode?.isActive}
+
+
+
+
+
+ {/if}
+
+
+
+ {@render children()}
+
+
+
+
diff --git a/src/lib/components/collection/SelectableCollectionRow.svelte b/src/lib/components/collection/SelectableCollectionRow.svelte
new file mode 100644
index 00000000..2667c59c
--- /dev/null
+++ b/src/lib/components/collection/SelectableCollectionRow.svelte
@@ -0,0 +1,80 @@
+
+
+
+ {#if selectionMode?.isActive}
+
+
+
+
+
+ {/if}
+
+
+
+ {@render children()}
+
+
+
+
diff --git a/src/lib/stores/selectionMode.svelte.ts b/src/lib/stores/selectionMode.svelte.ts
new file mode 100644
index 00000000..8c2d36fa
--- /dev/null
+++ b/src/lib/stores/selectionMode.svelte.ts
@@ -0,0 +1,87 @@
+/**
+ * Selection mode store for collection bulk operations.
+ * Used to manage multi-select state across collection pages.
+ */
+
+export type EntityType = 'characters' | 'weapons' | 'summons' | 'artifacts'
+
+export interface SelectionModeContext {
+ readonly isActive: boolean
+ readonly entityType: EntityType | null
+ readonly selectedIds: Set
+ readonly selectedCount: number
+ enter: (type: EntityType) => void
+ exit: () => void
+ toggle: (id: string) => void
+ selectAll: (ids: string[]) => void
+ clearSelection: () => void
+ isSelected: (id: string) => boolean
+}
+
+/**
+ * Creates a selection mode context for managing bulk selection state.
+ * Should be created in the collection layout and provided via Svelte context.
+ */
+export function createSelectionModeContext(): SelectionModeContext {
+ let isActive = $state(false)
+ let entityType = $state(null)
+ let selectedIds = $state>(new Set())
+
+ return {
+ get isActive() {
+ return isActive
+ },
+ get entityType() {
+ return entityType
+ },
+ get selectedIds() {
+ return selectedIds
+ },
+ get selectedCount() {
+ return selectedIds.size
+ },
+
+ enter(type: EntityType) {
+ isActive = true
+ entityType = type
+ selectedIds = new Set()
+ },
+
+ exit() {
+ isActive = false
+ entityType = null
+ selectedIds = new Set()
+ },
+
+ toggle(id: string) {
+ const newSet = new Set(selectedIds)
+ if (newSet.has(id)) {
+ newSet.delete(id)
+ } else {
+ newSet.add(id)
+ }
+ selectedIds = newSet
+ },
+
+ selectAll(ids: string[]) {
+ selectedIds = new Set(ids)
+ },
+
+ clearSelection() {
+ selectedIds = new Set()
+ },
+
+ isSelected(id: string) {
+ return selectedIds.has(id)
+ }
+ }
+}
+
+export const SELECTION_MODE_KEY = Symbol('selection-mode')
+
+/** Context key for child pages to provide their loaded item IDs to the layout */
+export const LOADED_IDS_KEY = Symbol('loaded-ids')
+
+export interface LoadedIdsContext {
+ setIds: (ids: string[]) => void
+}