import { NavLink, Outlet, useNavigate, useLocation } from 'react-router-dom' import MoonDot from '../../components/MoonDot.jsx' import { useAuth } from '../../contexts/AuthContext.jsx' import { useSite } from '../../contexts/SiteContext.jsx' // Shared shell for the logged-in player portal. Uses the same sidebar shell as // Admin (icon nav, sticky content header, footer sign-out) so the two logged-in // experiences read as one app — the portal just carries fewer nav rows. // Small inline stroke icons (16px, currentColor) — same frame as AdminLayout. function Icon({ children, size = 16 }) { return ( ) } const IconUser = () => const IconGear = () => const IconShield = () => const NAV = [ { to: '/player', label: 'Characters', end: true, icon: IconUser }, { to: '/account/appeals', label: 'Appeals', icon: IconShield }, { to: '/account', label: 'Account', end: true, icon: IconGear }, ] // The sticky content header mirrors the active page. Character sheets live under // /player/char/:serial and keep their own in-page back link. const TITLES = { '/player': 'Characters', '/account': 'Account', '/account/appeals': 'Appeals', } const navBtnBase = { textAlign: 'left', borderRadius: 8, padding: '10px 14px', fontFamily: 'var(--sans)', fontSize: '0.92rem', textDecoration: 'none', display: 'flex', alignItems: 'center', gap: 10, transition: 'background .15s,color .15s', } export default function PlayerPortalLayout() { const { user, logout } = useAuth() const { siteTitle } = useSite() const navigate = useNavigate() const location = useLocation() const title = TITLES[location.pathname] || (location.pathname.startsWith('/player/char/') ? 'Character' : 'Player Portal') async function signOut() { await logout() navigate('/account/login', { replace: true }) } return (
{/* Sidebar */} {/* Main */}

{title}

← Site
) }