diff --git a/src/assets/styles/app-shell.css b/src/assets/styles/app-shell.css index b9a235a..ca2ddcf 100644 --- a/src/assets/styles/app-shell.css +++ b/src/assets/styles/app-shell.css @@ -104,36 +104,60 @@ } } -/* ── Guest pages (login, checkout) ── */ +/* ── Guest pages (login, register, checkout) — all breakpoints ── */ +.app-shell--no-nav { + align-items: center; + justify-content: center; + padding: 16px; + background: var(--color-page-background); +} + +.app-shell--no-nav .app-layout { + max-width: var(--form-max-width); + width: 100%; + height: auto; + max-height: calc(100dvh - 32px); +} + +.app-shell--no-nav .app-frame { + max-width: var(--form-max-width); + width: 100%; + height: auto; + max-height: calc(100dvh - 32px); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-frame); + background: var(--color-surface); +} + +.app-shell--no-nav .app-content { + padding-inline: var(--page-padding); +} + +.app-shell--no-nav .page { + background: transparent; +} + +.app-shell--no-nav.app-shell--wide .app-layout, +.app-shell--no-nav.app-shell--wide .app-frame { + max-width: min(var(--content-max-width), calc(100vw - 32px)); +} + +.app-shell--no-nav.app-shell--wide .app-frame { + background: var(--color-bg); +} + @media (min-width: 768px) { .app-shell--no-nav { - align-items: center; - justify-content: center; padding: 24px; - background: var(--color-page-background); - } - - .app-shell--no-nav .app-layout { - max-width: var(--form-max-width); - width: 100%; - height: auto; - max-height: calc(100dvh - 48px); } + .app-shell--no-nav .app-layout, .app-shell--no-nav .app-frame { - max-width: var(--form-max-width); - border-radius: var(--radius-lg); - box-shadow: var(--shadow-frame); max-height: calc(100dvh - 48px); - background: var(--color-surface); } .app-shell--no-nav.app-shell--wide .app-layout, .app-shell--no-nav.app-shell--wide .app-frame { max-width: min(var(--content-max-width), calc(100vw - 48px)); } - - .app-shell--no-nav.app-shell--wide .app-frame { - background: var(--color-bg); - } } diff --git a/src/assets/styles/main.css b/src/assets/styles/main.css index 1caef9b..a0ca911 100644 --- a/src/assets/styles/main.css +++ b/src/assets/styles/main.css @@ -204,6 +204,13 @@ input[type='number'] { color: var(--color-text); } +.auth-page .card { + background: transparent; + border: none; + box-shadow: none; + padding-inline: 0; +} + .card + .card { margin-top: var(--page-gap); } diff --git a/src/components/ui/AuthThemeToggle.vue b/src/components/ui/AuthThemeToggle.vue new file mode 100644 index 0000000..5478ed9 --- /dev/null +++ b/src/components/ui/AuthThemeToggle.vue @@ -0,0 +1,59 @@ + + + + + diff --git a/src/stores/theme.ts b/src/stores/theme.ts index 4702205..d4adbc9 100644 --- a/src/stores/theme.ts +++ b/src/stores/theme.ts @@ -25,10 +25,23 @@ export const useThemeStore = defineStore('theme', () => { preference.value = value } + function cyclePreference() { + const order: ThemePreference[] = ['light', 'dark', 'system'] + const index = order.indexOf(preference.value) + preference.value = order[(index + 1) % order.length]! + } + + /** Explicit light ↔ dark toggle (skips system). */ + function toggleLightDark() { + preference.value = isDark.value ? 'light' : 'dark' + } + return { preference, resolved, isDark, setPreference, + cyclePreference, + toggleLightDark, } }) diff --git a/src/views/auth/LoginView.vue b/src/views/auth/LoginView.vue index 88e6633..5bd20b8 100644 --- a/src/views/auth/LoginView.vue +++ b/src/views/auth/LoginView.vue @@ -5,6 +5,7 @@ import { useAuthStore } from '@/stores/auth' import BaseInput from '@/components/ui/BaseInput.vue' import FormErrorBanner from '@/components/ui/FormErrorBanner.vue' import BaseButton from '@/components/ui/BaseButton.vue' +import AuthThemeToggle from '@/components/ui/AuthThemeToggle.vue' import { normalizePhone, toPersianDigits } from '@/utils/format' import { validatePhone } from '@/utils/validation' import { @@ -72,6 +73,8 @@ async function submit() {