diff --git a/frontend/auth/App.vue b/frontend/auth/App.vue
index 96949f3..08dd74d 100644
--- a/frontend/auth/App.vue
+++ b/frontend/auth/App.vue
@@ -13,8 +13,10 @@
diff --git a/frontend/auth/admin/AdminApp.vue b/frontend/auth/admin/AdminApp.vue
index 81a029c..a35a30c 100644
--- a/frontend/auth/admin/AdminApp.vue
+++ b/frontend/auth/admin/AdminApp.vue
@@ -12,8 +12,8 @@ import AdminUserDetail from '@/admin/AdminUserDetail.vue'
import AdminDialogs from '@/admin/AdminDialogs.vue'
import { useAuthStore } from '@/stores/auth'
import { adminUiPath, makeUiHref } from '@/utils/settings'
-import { apiJson } from '@/utils/api'
-import { useSessionValidation } from '@/utils/session'
+import { apiJson } from '@/paskia/fetch'
+import { SessionValidator } from '@/paskia/validate'
import { getDirection } from '@/utils/keynav'
import { goBack } from '@/utils/helpers'
@@ -167,8 +167,11 @@ function onSessionLost(e) {
}
}
-const userUuid = computed(() => info.value?.ctx.user.uuid)
-useSessionValidation(userUuid, onSessionLost)
+const userUuidGetter = () => info.value?.ctx.user.uuid
+const sessionValidator = new SessionValidator(userUuidGetter, onSessionLost)
+
+onMounted(() => sessionValidator.start())
+onUnmounted(() => sessionValidator.stop())
async function load() {
loading.value = true
diff --git a/frontend/int/reset/ResetApp.vue b/frontend/int/reset/ResetApp.vue
index ff2048c..3548b86 100644
--- a/frontend/int/reset/ResetApp.vue
+++ b/frontend/int/reset/ResetApp.vue
@@ -59,7 +59,7 @@
import { computed, onMounted, reactive, ref } from 'vue'
import passkey from '@/utils/passkey'
import { getSettings, uiBasePath } from '@/utils/settings'
-import { apiJson, ApiError, getUserFriendlyErrorMessage } from '@/utils/api'
+import { apiJson, ApiError, getUserFriendlyErrorMessage } from '@/paskia/fetch'
const status = reactive({
show: false,
diff --git a/frontend/src/admin/AdminUserDetail.vue b/frontend/src/admin/AdminUserDetail.vue
index 6d277ae..3a8eacd 100644
--- a/frontend/src/admin/AdminUserDetail.vue
+++ b/frontend/src/admin/AdminUserDetail.vue
@@ -5,7 +5,7 @@ import CredentialList from '@/components/CredentialList.vue'
import RegistrationLinkModal from '@/components/RegistrationLinkModal.vue'
import SessionList from '@/components/SessionList.vue'
import { useAuthStore } from '@/stores/auth'
-import { apiJson } from '@/utils/api'
+import { apiJson } from '@/paskia/fetch'
import { getDirection, navigateButtonRow, focusPreferred, focusAtIndex } from '@/utils/keynav'
const props = defineProps({
diff --git a/frontend/src/assets/style.css b/frontend/src/assets/style.css
index 742f240..fc83fe5 100644
--- a/frontend/src/assets/style.css
+++ b/frontend/src/assets/style.css
@@ -731,42 +731,6 @@ th {
}
}
-/* Global backdrop controlled by api.js ref-counting */
-body::before {
- content: '';
- position: fixed;
- inset: 0;
- z-index: 1099;
- background: transparent;
- backdrop-filter: blur(0) brightness(1);
- -webkit-backdrop-filter: blur(0) brightness(1);
- pointer-events: none;
- visibility: hidden;
- transition: all 0.2s ease-out;
-}
-
-body.has-backdrop::before {
- -webkit-backdrop-filter: blur(.2rem) brightness(0.5);
- backdrop-filter: blur(.2rem) brightness(0.5);
- visibility: visible;
-}
-
-body.has-backdrop {
- overflow: auto;
-}
-
-#auth-iframe {
- border: none;
- position: fixed;
- top: 0;
- left: 0;
- width: 100%;
- height: 100%;
- z-index: 9999;
- color-scheme: auto;
- background: transparent;
-}
-
.slot-machine {
padding: 0.875rem 1rem;
background: var(--color-surface-hover, rgba(0, 0, 0, 0.03));
diff --git a/frontend/src/components/ProfileView.vue b/frontend/src/components/ProfileView.vue
index ccc52eb..96e7e88 100644
--- a/frontend/src/components/ProfileView.vue
+++ b/frontend/src/components/ProfileView.vue
@@ -127,7 +127,7 @@ import { useAuthStore } from '@/stores/auth'
import { adminUiPath, makeUiHref } from '@/utils/settings'
import passkey from '@/utils/passkey'
import { goBack } from '@/utils/helpers'
-import { apiJson } from '@/utils/api'
+import { apiJson } from '@/paskia/fetch'
import { navigateButtonRow, focusPreferred, focusAtIndex, getDirection } from '@/utils/keynav'
const authStore = useAuthStore()
diff --git a/frontend/src/components/RegistrationLinkModal.vue b/frontend/src/components/RegistrationLinkModal.vue
index e154f13..d5dd899 100644
--- a/frontend/src/components/RegistrationLinkModal.vue
+++ b/frontend/src/components/RegistrationLinkModal.vue
@@ -35,7 +35,7 @@