Repository Public
1'use client';2import { AnimatePresence, motion } from 'motion/react';3import { Logo } from '@/components/shell/logo';45/** Welcoming, centred card for sign-in and setup. `step` keys the slide transition between steps. */6export function AuthCard({ title, subtitle, step, children }: { title: string; subtitle?: React.ReactNode; step?: string; children: React.ReactNode }) {7 return (8 <main className="app-viewport relative flex flex-col items-center overflow-y-auto overflow-x-hidden px-5 py-[max(28px,env(safe-area-inset-top))]">9 {/* soft brand glow behind the mark only — not a page wallpaper */}10 <div aria-hidden className="bg-brand pointer-events-none absolute left-1/2 top-[-180px] size-[420px] -translate-x-1/2 rounded-full opacity-[.16] blur-3xl" />11 <div className="relative my-auto w-full max-w-[400px]">12 <div className="mb-7 flex flex-col items-center gap-4 text-center">13 <motion.div initial={{ scale: 0.8, opacity: 0 }} animate={{ scale: 1, opacity: 1 }} transition={{ type: 'spring', stiffness: 300, damping: 20 }}>14 <Logo className="size-16 rounded-[20px] shadow-float" />15 </motion.div>16 <div>17 <h1 data-brand-text className="text-[26px] font-bold leading-tight tracking-tight">{title}</h1>18 {subtitle && <p data-brand-text className="mx-auto mt-1.5 max-w-xs text-sm leading-relaxed text-text-2">{subtitle}</p>}19 </div>20 </div>21 <div className="overflow-hidden rounded-lg border border-card-line bg-surface p-6 shadow-float">22 <AnimatePresence mode="wait" initial={false}>23 <motion.div key={step ?? 'only'} initial={{ opacity: 0, x: 28 }} animate={{ opacity: 1, x: 0 }} exit={{ opacity: 0, x: -28 }} transition={{ type: 'spring', stiffness: 420, damping: 36 }}>24 {children}25 </motion.div>26 </AnimatePresence>27 </div>28 <p className="mt-5 text-center text-xs text-muted">Private instance · single administrator</p>29 </div>30 </main>31 );32}33