<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { storeToRefs } from 'pinia'
import { useDisplay, useTheme } from 'vuetify'
import { useRoute, useRouter } from 'vue-router'

import iconImage from '@/assets/images/icon.svg'
import { useSidebarRoutes } from '@/composables/useSidebarRoutes'
import { routes } from '@/plugins/routesLayout'
import {
  AuthRequestError,
  fetchCurrentUser,
  logout,
  type CurrentUser,
} from '@/services/authSession'
import { useAppBannersStore } from '@/stores/appBanners'

const display = useDisplay()
const theme = useTheme()
const route = useRoute()
const router = useRouter()
const showDrawer = ref(true)
const currentYear = new Date().getFullYear()
const themeStorageKey = 'theme'
const currentUser = ref<CurrentUser | null>(null)
const isLoggingOut = ref(false)
const appBannersStore = useAppBannersStore()
const { banners } = storeToRefs(appBannersStore)

const { adminSidebarRoutes, primarySidebarRoutes, footerRoutes } = useSidebarRoutes(currentUser)

const activeRoute = computed(() => {
  const byName = routes.find((x) => x.meta?.name === route.name)
  if (byName) {
    return byName
  }

  return routes.find((x) => x.path === route.path)
})

const pageName = computed(() => activeRoute.value?.name ?? 'Hoard')
const pageDescription = computed(
  () => activeRoute.value?.description ?? 'Self-hosted Datei-Workspace im Browser',
)
const shouldShowFooter = computed(() => activeRoute.value?.disableFooter !== true)
const isDarkTheme = computed(() => theme.global.name.value === 'dark')
const themeIcon = computed(() => (isDarkTheme.value ? 'mdi-white-balance-sunny' : 'mdi-weather-night'))
const themeLabel = computed(() =>
  isDarkTheme.value ? 'Hellen Modus aktivieren' : 'Dunklen Modus aktivieren',
)
const isAuthenticated = computed(() => currentUser.value !== null)
const userLabel = computed(() => currentUser.value?.userName ?? 'Konto')
const userInitials = computed(() => {
  const name = currentUser.value?.userName?.trim() ?? ''
  if (name.length === 0) {
    return 'H'
  }

  const parts = name.split(/[\s._-]+/).filter((part) => part.length > 0)
  if (parts.length === 0) {
    return name.slice(0, 2).toUpperCase()
  }

  if (parts.length === 1) {
    const first = parts[0] as string
    return first.slice(0, 2).toUpperCase()
  }

  const first = parts[0] as string
  const second = parts[1] as string
  return `${first.charAt(0)}${second.charAt(0)}`.toUpperCase()
})

function applyTheme(nextTheme: 'light' | 'dark', persist = true) {
  theme.global.name.value = nextTheme
  document.documentElement.setAttribute('data-theme', nextTheme)
  if (persist) {
    localStorage.setItem(themeStorageKey, nextTheme)
  }
}

function toggleDrawer() {
  showDrawer.value = !showDrawer.value
  localStorage.setItem('drawer', showDrawer.value ? 'Y' : 'N')
}

function toggleTheme() {
  applyTheme(isDarkTheme.value ? 'light' : 'dark')
}

async function navigateToBrandTarget() {
  let resolvedUser = currentUser.value

  if (!resolvedUser) {
    try {
      resolvedUser = await fetchCurrentUser()
      currentUser.value = resolvedUser
    } catch {
      resolvedUser = null
      currentUser.value = null
    }
  }

  const targetRouteName = resolvedUser ? 'Dashboard' : 'Home'
  await router.push({ name: targetRouteName })
}

async function refreshAuthState(options: { force?: boolean } = {}) {
  try {
    currentUser.value = await fetchCurrentUser({ force: options.force === true })
  } catch {
    currentUser.value = null
  }
}

async function handleLogout() {
  if (isLoggingOut.value) {
    return
  }

  isLoggingOut.value = true

  try {
    await logout()
    currentUser.value = null
    await router.replace({ name: 'Login' })
  } catch (error) {
    if (error instanceof AuthRequestError) {
      appBannersStore.pushError(error.message, 'Abmeldung fehlgeschlagen')
    } else {
      appBannersStore.pushError(
        'Abmeldung fehlgeschlagen. Bitte versuche es erneut.',
        'Abmeldung fehlgeschlagen',
      )
    }
  } finally {
    isLoggingOut.value = false
    void refreshAuthState()
  }
}

function dismissBanner(id: string) {
  appBannersStore.dismiss(id)
}

function changeWebsiteTitle() {
  if (activeRoute.value) {
    document.title = `Hoard · ${activeRoute.value.name}`
    return
  }

  document.title = 'Hoard · Self-hosted Workspace'
}

onMounted(() => {
  const storedTheme = localStorage.getItem(themeStorageKey)
  const validTheme = storedTheme === 'dark' || storedTheme === 'light' ? storedTheme : 'light'
  applyTheme(validTheme, false)

  const storedDrawer = localStorage.getItem('drawer')
  showDrawer.value = storedDrawer ? storedDrawer.startsWith('Y') : !display.mobile.value
  void refreshAuthState({ force: true })
})

watch(
  () => route.fullPath,
  () => {
    changeWebsiteTitle()
    void refreshAuthState()
    if (display.mobile.value) {
      showDrawer.value = false
    }
  },
  { immediate: true },
)
</script>

<template>
  <v-app class="hoard-shell">
    <v-app-bar class="hoard-app-bar" elevation="0" height="68">
      <template #prepend>
        <v-app-bar-nav-icon
          v-tooltip="!showDrawer ? 'Menü öffnen' : 'Menü schließen'"
          @click="toggleDrawer()"
        />
      </template>

      <button type="button" class="brand-button" @click="navigateToBrandTarget">
        <span class="brand-mark">
          <span class="brand-mark__halo" aria-hidden="true" />
          <img :src="iconImage" alt="Hoard Icon" class="brand-mark__logo" />
        </span>
        <span class="brand-text">
          <span class="brand-title">Hoard</span>
          <span class="brand-subtitle">Self-hosted Workspace</span>
        </span>
      </button>

      <span class="topbar-divider" aria-hidden="true" />

      <div class="page-context">
        <p class="page-name">{{ pageName }}</p>
        <p class="page-description">{{ pageDescription }}</p>
      </div>

      <v-spacer />

      <div class="topbar-actions">
        <v-tooltip location="bottom">
          <template #activator="{ props }">
            <v-btn
              icon
              variant="text"
              :aria-label="themeLabel"
              v-bind="props"
              @click="toggleTheme"
            >
              <v-icon>{{ themeIcon }}</v-icon>
            </v-btn>
          </template>
          {{ themeLabel }}
        </v-tooltip>

        <template v-if="isAuthenticated">
          <v-menu
            v-if="!display.smAndDown.value"
            open-on-hover
            :open-on-click="false"
            location="bottom end"
            offset="10"
          >
            <template #activator="{ props }">
              <button
                type="button"
                class="account-pill"
                v-bind="props"
                @click="router.push({ name: 'Dashboard' })"
              >
                <span class="account-pill__avatar">{{ userInitials }}</span>
                <span class="account-pill__label">
                  <span class="account-pill__hint">Angemeldet</span>
                  <span class="account-pill__name">{{ userLabel }}</span>
                </span>
                <v-icon class="account-pill__chev">mdi-chevron-down</v-icon>
              </button>
            </template>

            <v-list density="compact" class="account-menu-list">
              <v-list-item
                prepend-icon="mdi-view-dashboard-outline"
                title="Dashboard"
                :to="{ name: 'Dashboard' }"
              />
              <v-list-item
                prepend-icon="mdi-lock-reset"
                title="Passwort ändern"
                :to="{ name: 'ChangePassword' }"
              />
              <v-divider />
              <v-list-item
                prepend-icon="mdi-logout"
                :title="isLoggingOut ? 'Abmelden …' : 'Abmelden'"
                :disabled="isLoggingOut"
                @click="handleLogout"
              />
            </v-list>
          </v-menu>

          <v-menu v-else location="bottom end" offset="10">
            <template #activator="{ props }">
              <v-btn icon variant="text" v-bind="props" :aria-label="`Angemeldet als ${userLabel}`">
                <span class="account-pill__avatar account-pill__avatar--mobile">{{ userInitials }}</span>
              </v-btn>
            </template>

            <v-list density="compact" class="account-menu-list">
              <v-list-item
                prepend-icon="mdi-view-dashboard-outline"
                title="Zum Dashboard"
                :to="{ name: 'Dashboard' }"
              />
              <v-list-item
                prepend-icon="mdi-lock-reset"
                title="Passwort ändern"
                :to="{ name: 'ChangePassword' }"
              />
              <v-divider />
              <v-list-item
                prepend-icon="mdi-logout"
                :title="isLoggingOut ? 'Abmelden …' : 'Abmelden'"
                :disabled="isLoggingOut"
                @click="handleLogout"
              />
            </v-list>
          </v-menu>
        </template>

        <template v-else>
          <v-btn
            v-if="!display.smAndDown.value"
            variant="elevated"
            prepend-icon="mdi-login"
            to="/login"
          >
            Anmelden
          </v-btn>

          <v-btn v-else icon variant="text" to="/login" aria-label="Zum Login">
            <v-icon>mdi-login</v-icon>
          </v-btn>
        </template>
      </div>
    </v-app-bar>

    <v-navigation-drawer
      v-model="showDrawer"
      :class="['hoard-drawer', { 'hoard-drawer--mobile': display.mobile.value }]"
      :location="display.mobile.value ? 'bottom' : 'left'"
      :temporary="display.mobile.value"
      :permanent="!display.mobile.value"
      :width="276"
      :elevation="display.mobile.value ? 6 : 0"
    >
      <div class="drawer-top">
        <p class="drawer-kicker hoard-kicker hoard-kicker--xs">Navigation</p>
      </div>

      <v-list nav :density="display.mobile.value ? 'default' : 'comfortable'" class="px-1">
        <v-list-item
          v-for="item in primarySidebarRoutes"
          :key="item.path"
          :to="item.path"
          :active="route.path === item.path"
          :prepend-icon="item.icon"
          :title="item.name"
          class="hoard-nav-item"
          rounded="md"
          link
        />

        <template v-if="adminSidebarRoutes.length > 0">
          <hr class="hoard-divider-soft drawer-section-divider" />
          <div class="drawer-section-head">
            <p class="drawer-kicker hoard-kicker hoard-kicker--xs">Admin</p>
          </div>

          <v-list-item
            v-for="item in adminSidebarRoutes"
            :key="item.path"
            :to="item.path"
            :active="route.path === item.path"
            :prepend-icon="item.icon"
            :title="item.name"
            class="hoard-nav-item"
            rounded="md"
            link
          />
        </template>
      </v-list>

      <template #append>
        <div class="drawer-bottom">
          <div v-if="isAuthenticated" class="drawer-card">
            <span class="drawer-card__avatar">{{ userInitials }}</span>
            <div class="drawer-card__body">
              <p class="drawer-card__hint">Eingeloggt</p>
              <p class="drawer-card__name">{{ userLabel }}</p>
            </div>
            <v-btn
              v-tooltip="'Abmelden'"
              icon
              size="small"
              variant="text"
              :aria-label="isLoggingOut ? 'Abmelden …' : 'Abmelden'"
              :disabled="isLoggingOut"
              @click="handleLogout"
            >
              <v-icon>mdi-logout</v-icon>
            </v-btn>
          </div>

          <v-btn
            v-else
            variant="text"
            prepend-icon="mdi-home-outline"
            to="/welcome"
            :block="display.mobile.value"
          >
            Zur Startseite
          </v-btn>
        </div>
      </template>
    </v-navigation-drawer>

    <v-main class="hoard-main">
      <div class="main-shell">
        <router-view v-slot="{ Component }">
          <transition name="route-fade" mode="out-in">
            <component :is="Component" />
          </transition>
        </router-view>
      </div>

      <v-footer
        v-if="shouldShowFooter"
        class="hoard-footer"
      >
        <div class="footer-inner">
          <div class="footer-brand">
            <img :src="iconImage" alt="" class="footer-logo" />
            <span>
              <strong>Hoard</strong>
              <span class="footer-tag"> · {{ currentYear }}</span>
            </span>
          </div>

          <nav class="footer-links" aria-label="Footer-Navigation">
            <v-btn
              v-for="link in footerRoutes"
              :key="link.path"
              :to="link.path"
              variant="text"
              size="small"
            >
              {{ link.name }}
            </v-btn>
          </nav>
        </div>
      </v-footer>
    </v-main>

    <section
      v-if="banners.length > 0"
      class="app-banner-stack"
      aria-live="polite"
      aria-label="Systemmeldungen"
    >
      <transition-group name="app-banner-transition" tag="div" class="app-banner-list">
        <v-alert
          v-for="banner in banners"
          :key="banner.id"
          :class="['app-banner-item', `app-banner-item--${banner.type}`]"
          :type="banner.type"
          variant="tonal"
          border="start"
          closable
          @click:close="dismissBanner(banner.id)"
        >
          <p v-if="banner.title" class="app-banner-title">{{ banner.title }}</p>
          <p class="app-banner-text">{{ banner.message }}</p>
        </v-alert>
      </transition-group>
    </section>
  </v-app>
</template>

<style scoped>
.hoard-shell {
  min-height: 100vh;
}

.hoard-app-bar {
  padding-inline: var(--space-3);
}

/* ---------- Brand ---------- */
.brand-button {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: 4px 6px 4px 4px;
  border: none;
  border-radius: var(--radius-md);
  color: inherit;
  background: transparent;
  cursor: pointer;
  transition: background-color var(--transition-fast);
}

.brand-button:hover {
  background-color: color-mix(in srgb, var(--color-primary-100) 38%, transparent);
}

.brand-mark {
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
}

.brand-mark__halo {
  position: absolute;
  inset: -6px;
  border-radius: var(--radius-full);
  background:
    radial-gradient(
      closest-side,
      color-mix(in srgb, var(--color-accent-lime) 35%, transparent),
      transparent 70%
    );
  opacity: 0.7;
  filter: blur(6px);
  transition: opacity var(--transition-medium);
}

.brand-button:hover .brand-mark__halo {
  opacity: 1;
}

.brand-mark__logo {
  position: relative;
  width: 44px;
  height: 44px;
  object-fit: contain;
  filter: drop-shadow(0 4px 10px rgb(28 101 47 / 22%));
}

.brand-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.1;
}

.brand-title {
  color: var(--color-text);
  font-size: 17px;
  font-weight: 700;
  letter-spacing: -0.01em;
}

.brand-subtitle {
  color: var(--color-text-muted);
  font-size: var(--font-size-xs);
  font-weight: 500;
  letter-spacing: 0.04em;
}

/* ---------- Topbar ---------- */
.topbar-divider {
  display: inline-block;
  width: 1px;
  height: 28px;
  margin-inline: var(--space-4);
  background:
    linear-gradient(180deg, transparent, var(--color-border), transparent);
}

.page-context {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.page-name,
.page-description {
  margin: 0;
}

.page-name {
  color: var(--color-text);
  font-size: var(--font-size-md);
  font-weight: 600;
}

.page-description {
  max-width: min(380px, 32vw);
  color: var(--color-text-muted);
  font-size: var(--font-size-sm);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.topbar-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}

.account-pill {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  padding: 4px var(--space-3) 4px 4px;
  border: 1px solid var(--color-border);
  border-radius: var(--radius-full);
  background-color: color-mix(in srgb, var(--color-surface) 90%, var(--color-surface-alt) 10%);
  color: var(--color-text);
  font: inherit;
  cursor: pointer;
  transition:
    border-color var(--transition-fast),
    background-color var(--transition-fast),
    transform var(--transition-fast);
}

.account-pill:hover {
  border-color: color-mix(in srgb, var(--color-primary-300) 50%, var(--color-border) 50%);
  background-color: color-mix(in srgb, var(--color-primary-100) 32%, var(--color-surface) 68%);
  transform: translateY(-1px);
}

.account-pill__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  border-radius: var(--radius-full);
  background:
    linear-gradient(135deg, var(--color-primary-600), var(--color-primary-800));
  color: var(--color-text-on-primary);
  font-size: var(--font-size-sm);
  font-weight: 700;
  letter-spacing: 0.02em;
  box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--color-accent-lime) 20%, transparent);
}

.account-pill__avatar--mobile {
  width: 28px;
  height: 28px;
  font-size: var(--font-size-xs);
}

.account-pill__label {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.1;
  max-width: 160px;
}

.account-pill__hint {
  color: var(--color-text-muted);
  font-size: var(--font-size-2xs);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.account-pill__name {
  color: var(--color-text);
  font-size: var(--font-size-sm);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  max-width: 160px;
}

.account-pill__chev {
  color: var(--color-text-muted);
  width: 18px;
  height: 18px;
}

@media (width <= 1280px) {
  .page-description {
    display: none;
  }

  .page-context {
    gap: 0;
  }
}

@media (width <= 1180px) {
  .topbar-divider,
  .page-context {
    display: none;
  }
}

/* ---------- Drawer ---------- */
.hoard-drawer {
  padding-top: var(--space-2);
}

.hoard-drawer--mobile {
  border-top-left-radius: var(--radius-xl);
  border-top-right-radius: var(--radius-xl);
  max-height: min(74vh, 580px);
}

.drawer-top {
  padding: var(--space-3) var(--space-5) var(--space-3);
}

.drawer-kicker {
  margin: 0;
}

.drawer-section-divider {
  margin: var(--space-3) var(--space-4);
}

.drawer-section-head {
  padding: 0 var(--space-5) var(--space-2);
}

:deep(.hoard-nav-item) {
  min-height: 44px;
}

:deep(.hoard-nav-item .v-list-item-title) {
  font-weight: 500;
}

.drawer-bottom {
  padding: var(--space-3) var(--space-3) var(--space-4);
  border-top: 1px solid var(--color-border-subtle);
}

.drawer-card {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  background-color: var(--color-surface);
  box-shadow: var(--shadow-xs);
}

.drawer-card__avatar {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: var(--radius-full);
  background: linear-gradient(135deg, var(--color-primary-600), var(--color-primary-800));
  color: var(--color-text-on-primary);
  font-size: var(--font-size-sm);
  font-weight: 700;
}

.drawer-card__body {
  min-width: 0;
}

.drawer-card__hint,
.drawer-card__name {
  margin: 0;
  line-height: 1.2;
}

.drawer-card__hint {
  color: var(--color-text-muted);
  font-size: var(--font-size-2xs);
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}

.drawer-card__name {
  color: var(--color-text);
  font-size: var(--font-size-sm);
  font-weight: 600;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ---------- Main ---------- */
.hoard-main {
  display: flex;
  flex-direction: column;
  min-height: calc(100vh - 68px);
}

.main-shell {
  flex: 1;
  padding: var(--space-6);
}

.route-fade-enter-active,
.route-fade-leave-active {
  transition:
    opacity var(--transition-medium),
    transform var(--transition-medium);
}

.route-fade-enter-from {
  opacity: 0;
  transform: translateY(8px);
}

.route-fade-leave-to {
  opacity: 0;
  transform: translateY(-4px);
}

/* ---------- Footer ---------- */
.hoard-footer {
  flex: 0 0 auto;
  height: auto !important;
  min-height: 0 !important;
  padding: 0 !important;
}

.footer-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  width: 100%;
  padding: var(--space-3) var(--space-6);
  flex-wrap: wrap;
}

.footer-brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  color: var(--color-text-secondary);
  font-size: var(--font-size-sm);
}

.footer-brand strong {
  color: var(--color-text);
  font-weight: 700;
  letter-spacing: -0.01em;
}

.footer-tag {
  color: var(--color-text-muted);
  font-weight: 500;
}

.footer-logo {
  width: 22px;
  height: 22px;
  object-fit: contain;
}

.footer-links {
  display: flex;
  flex-wrap: wrap;
  gap: 2px;
}

/* ---------- Banner stack ---------- */
.app-banner-stack {
  position: fixed;
  right: max(var(--space-5), env(safe-area-inset-right));
  bottom: max(var(--space-5), env(safe-area-inset-bottom));
  z-index: 2100;
  pointer-events: none;
}

.app-banner-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  width: min(420px, calc(100vw - (2 * var(--space-4))));
}

:deep(.app-banner-item) {
  pointer-events: auto;
  border: 1px solid var(--color-border) !important;
  box-shadow: var(--shadow-md);
  border-radius: var(--radius-md) !important;
}

:deep(.app-banner-item .v-alert__overlay),
:deep(.app-banner-item .v-alert__underlay) {
  opacity: 0 !important;
}

:deep(.app-banner-item .v-alert__content) {
  line-height: 1.45;
}

:deep(.app-banner-item--error) {
  background-color: color-mix(in srgb, var(--color-danger) 12%, var(--color-surface) 88%) !important;
}

:deep(.app-banner-item--warning) {
  background-color: color-mix(in srgb, var(--color-warning) 12%, var(--color-surface) 88%) !important;
}

:deep(.app-banner-item--info) {
  background-color: color-mix(in srgb, var(--color-info) 12%, var(--color-surface) 88%) !important;
}

:deep(.app-banner-item--success) {
  background-color: color-mix(in srgb, var(--color-success) 12%, var(--color-surface) 88%) !important;
}

.app-banner-title,
.app-banner-text {
  margin: 0;
}

.app-banner-title {
  margin-bottom: 2px;
  color: var(--color-text);
  font-size: var(--font-size-sm);
  font-weight: 700;
}

.app-banner-text {
  color: var(--color-text-secondary);
  line-height: 1.45;
}

.app-banner-transition-enter-active,
.app-banner-transition-leave-active {
  transition: opacity 180ms ease, transform 180ms ease;
}

.app-banner-transition-enter-from,
.app-banner-transition-leave-to {
  opacity: 0;
  transform: translateY(10px);
}

.app-banner-transition-move {
  transition: transform 180ms ease;
}

/* ---------- Responsive ---------- */
@media (width <= 960px) {
  .hoard-app-bar {
    padding-inline:
      max(var(--space-1), env(safe-area-inset-left))
      max(var(--space-1), env(safe-area-inset-right));
  }

  .brand-button {
    min-width: 0;
    gap: var(--space-2);
    padding: 2px;
  }

  .brand-mark,
  .brand-mark__logo {
    width: 38px;
    height: 38px;
  }

  .brand-title {
    font-size: 16px;
  }

  .brand-subtitle {
    display: none;
  }

  .topbar-actions {
    gap: 2px;
  }

  .topbar-divider,
  .page-context {
    display: none;
  }

  .hoard-drawer {
    padding-top: var(--space-1);
  }

  .drawer-top {
    padding: var(--space-3) var(--space-4);
  }

  .drawer-bottom {
    padding: var(--space-3) var(--space-3) calc(var(--space-3) + env(safe-area-inset-bottom));
  }

  :deep(.drawer-bottom .v-btn) {
    min-height: 44px;
  }

  .main-shell {
    padding: var(--space-4);
  }

  .footer-inner {
    justify-content: center;
    padding-inline:
      max(var(--space-3), env(safe-area-inset-left))
      max(var(--space-3), env(safe-area-inset-right));
  }

  .footer-links {
    width: 100%;
    justify-content: center;
  }

  .app-banner-stack {
    right: var(--hoard-mobile-safe-right);
    left: var(--hoard-mobile-safe-left);
    bottom: calc(var(--hoard-mobile-safe-bottom) + var(--space-1));
  }

  .app-banner-list {
    width: 100%;
  }
}

@media (width <= 600px) {
  .main-shell {
    padding: var(--space-3);
  }

  .brand-title {
    font-size: var(--font-size-md);
  }

  .footer-links {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
  }

  :deep(.footer-links .v-btn) {
    width: 100%;
    min-height: 44px;
  }
}
</style>
