feat: reskin member pages to zine direction
This commit is contained in:
parent
88caca94c7
commit
1ac21d6a98
4 changed files with 1972 additions and 1754 deletions
|
|
@ -1,347 +1,154 @@
|
|||
<template>
|
||||
<div>
|
||||
<!-- Page Header -->
|
||||
<PageHeader
|
||||
title="Member Dashboard"
|
||||
:subtitle="`Welcome back, ${memberData?.name || 'Member'}!`"
|
||||
size="medium"
|
||||
/>
|
||||
<div class="dashboard">
|
||||
<!-- Loading State -->
|
||||
<div v-if="authPending" class="loading-state">
|
||||
<div class="spinner" />
|
||||
<p>Loading your dashboard...</p>
|
||||
</div>
|
||||
|
||||
<UContainer class="">
|
||||
<!-- Loading State -->
|
||||
<div
|
||||
v-if="authPending"
|
||||
class="flex justify-center items-center py-20"
|
||||
<!-- Unauthenticated State -->
|
||||
<div v-else-if="!memberData" class="unauth-state">
|
||||
<h2>Sign in required</h2>
|
||||
<p>Please sign in to access your member dashboard.</p>
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
@click="openLoginModal({ title: 'Sign in to your dashboard', description: 'Enter your email to access your member dashboard' })"
|
||||
>
|
||||
<div class="text-center">
|
||||
<div
|
||||
class="w-8 h-8 border-4 border-candlelight-500 border-t-transparent rounded-full animate-spin mx-auto mb-4"
|
||||
/>
|
||||
<p class="text-guild-300">Loading your dashboard...</p>
|
||||
Sign In
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Dashboard Content -->
|
||||
<template v-else>
|
||||
<!-- Member Status Banner -->
|
||||
<MemberStatusBanner :dismissible="true" />
|
||||
|
||||
<!-- Welcome Header -->
|
||||
<div class="welcome">
|
||||
<h1>Welcome back, {{ memberData?.name }}</h1>
|
||||
<div class="meta">
|
||||
<CircleBadge :circle="memberData?.circle || 'community'" />
|
||||
<span>${{ memberData?.contributionTier }} CAD/mo</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Unauthenticated State -->
|
||||
<div
|
||||
v-else-if="!memberData"
|
||||
class="flex justify-center items-center py-20"
|
||||
>
|
||||
<div class="text-center max-w-md">
|
||||
<div class="w-16 h-16 bg-guild-800 border border-guild-600 rounded-full flex items-center justify-center mx-auto mb-4">
|
||||
<Icon name="heroicons:lock-closed" class="w-8 h-8 text-guild-400" />
|
||||
</div>
|
||||
<h2 class="text-xl font-semibold text-guild-100 mb-2">Sign in required</h2>
|
||||
<p class="text-guild-400 mb-6">Please sign in to access your member dashboard.</p>
|
||||
<UButton @click="openLoginModal({ title: 'Sign in to your dashboard', description: 'Enter your email to access your member dashboard' })">
|
||||
Sign In
|
||||
</UButton>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Upcoming Events + Quick Actions -->
|
||||
<div class="content-row">
|
||||
<div class="content-block">
|
||||
<div class="section-label">Your Upcoming Events</div>
|
||||
|
||||
<!-- Dashboard Content -->
|
||||
<div v-else class="space-y-8">
|
||||
<!-- Member Status Banner -->
|
||||
<MemberStatusBanner :dismissible="true" />
|
||||
<!-- Welcome Card -->
|
||||
<UCard
|
||||
|
||||
:ui="{
|
||||
root: 'bg-guild-900 border border-guild-700',
|
||||
header: 'border-b border-guild-700',
|
||||
body: 'bg-guild-900',
|
||||
}"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex items-start justify-between gap-4">
|
||||
<div class="flex-1">
|
||||
<h1 class="text-display-lg text-guild-100 warm-text">
|
||||
Welcome to Ghost Guild, {{ memberData?.name }}!
|
||||
</h1>
|
||||
<p
|
||||
:class="[
|
||||
'mt-2',
|
||||
isActive ? 'text-guild-300' : statusConfig.textColor,
|
||||
]"
|
||||
>
|
||||
{{
|
||||
isActive ? "Your membership is active!" : statusConfig.label
|
||||
}}
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex-shrink-0" v-if="memberData?.avatar">
|
||||
<img
|
||||
:src="`/ghosties/Ghost-${capitalize(memberData.avatar)}.png`"
|
||||
:alt="memberData.name"
|
||||
class="w-16 h-16"
|
||||
/>
|
||||
</div>
|
||||
<div v-else class="flex-shrink-0">
|
||||
<div
|
||||
class="w-16 h-16 bg-guild-700 border border-guild-600 flex items-center justify-center text-guild-200 font-bold text-xl"
|
||||
>
|
||||
{{ memberData?.name?.charAt(0)?.toUpperCase() }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div class="flex flex-wrap gap-4 text-sm">
|
||||
<div class="bg-guild-800 border border-guild-600 px-4 py-2">
|
||||
<span class="text-ui-label text-guild-200">Circle:</span>
|
||||
<span class="font-medium text-stone-50 ml-1 capitalize">{{
|
||||
memberData?.circle
|
||||
}}</span>
|
||||
</div>
|
||||
<div class="bg-guild-800 border border-guild-600 px-4 py-2">
|
||||
<span class="text-ui-label text-guild-200">Contribution:</span>
|
||||
<span class="font-medium text-stone-50 ml-1"
|
||||
>${{ memberData?.contributionTier }} CAD/month</span
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</UCard>
|
||||
|
||||
<!-- Quick Links -->
|
||||
<UCard
|
||||
:ui="{
|
||||
root: 'bg-guild-900 border border-guild-700',
|
||||
header: 'border-b border-guild-700 bg-guild-900',
|
||||
body: 'bg-guild-900',
|
||||
}"
|
||||
>
|
||||
<template #header>
|
||||
<h2 class="text-display-sm text-guild-100 warm-text">
|
||||
Quick Links
|
||||
</h2>
|
||||
</template>
|
||||
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 gap-3">
|
||||
<UButton
|
||||
to="/members?peerSupport=true"
|
||||
variant="outline"
|
||||
:disabled="!canPeerSupport"
|
||||
:class="[
|
||||
'border-guild-600 text-guild-200 justify-start',
|
||||
canPeerSupport
|
||||
? 'hover:bg-guild-800 hover:border-candlelight-500'
|
||||
: 'opacity-50 cursor-not-allowed',
|
||||
]"
|
||||
block
|
||||
:title="
|
||||
!canPeerSupport
|
||||
? 'Complete your membership to book peer sessions'
|
||||
: ''
|
||||
"
|
||||
>
|
||||
Book a Peer Session
|
||||
</UButton>
|
||||
|
||||
<UButton
|
||||
to="https://wiki.ghostguild.org"
|
||||
target="_blank"
|
||||
variant="outline"
|
||||
class="border-guild-600 text-guild-200 hover:bg-guild-800 hover:border-candlelight-500 justify-start"
|
||||
block
|
||||
>
|
||||
Browse Resources
|
||||
</UButton>
|
||||
|
||||
<UButton
|
||||
to="/member/profile"
|
||||
variant="outline"
|
||||
class="border-guild-600 text-guild-200 hover:bg-guild-800 hover:border-candlelight-500 justify-start"
|
||||
block
|
||||
>
|
||||
Update Profile
|
||||
</UButton>
|
||||
|
||||
<UButton
|
||||
to="/events"
|
||||
variant="outline"
|
||||
class="border-guild-600 text-guild-200 hover:bg-guild-800 hover:border-candlelight-500 justify-start"
|
||||
block
|
||||
>
|
||||
View Events
|
||||
</UButton>
|
||||
|
||||
<UButton
|
||||
to="/members"
|
||||
variant="outline"
|
||||
class="border-guild-600 text-guild-200 hover:bg-guild-800 hover:border-candlelight-500 justify-start"
|
||||
block
|
||||
>
|
||||
Browse Members
|
||||
</UButton>
|
||||
|
||||
<UButton
|
||||
to="/member/profile#account"
|
||||
variant="outline"
|
||||
class="border-guild-600 text-guild-200 hover:bg-guild-800 hover:border-candlelight-500 justify-start"
|
||||
block
|
||||
>
|
||||
Manage Account
|
||||
</UButton>
|
||||
</div>
|
||||
</UCard>
|
||||
|
||||
<!-- Your Registered Events -->
|
||||
<UCard
|
||||
:ui="{
|
||||
root: 'bg-guild-900 border border-guild-700',
|
||||
header: 'border-b border-guild-700 bg-guild-900',
|
||||
body: 'bg-guild-900',
|
||||
}"
|
||||
>
|
||||
<template #header>
|
||||
<div class="flex items-center justify-between">
|
||||
<h2 class="text-display-sm text-guild-100 warm-text">
|
||||
Your Upcoming Events
|
||||
</h2>
|
||||
<div class="flex items-center gap-2">
|
||||
<UButton
|
||||
v-if="registeredEvents.length > 0"
|
||||
@click="copyCalendarLink"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
class="text-guild-300 hover:text-guild-100"
|
||||
icon="heroicons:calendar"
|
||||
>
|
||||
{{
|
||||
calendarLinkCopied ? "Link Copied!" : "Get Calendar Link"
|
||||
}}
|
||||
</UButton>
|
||||
<UButton
|
||||
to="/events"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
class="text-guild-300 hover:text-guild-100"
|
||||
>
|
||||
Browse All Events
|
||||
</UButton>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<div v-if="loadingEvents" class="text-center py-8">
|
||||
<div
|
||||
class="w-6 h-6 border-2 border-candlelight-500 border-t-transparent rounded-full animate-spin mx-auto"
|
||||
></div>
|
||||
<div v-if="loadingEvents" class="loading-inline">
|
||||
<div class="spinner spinner-sm" />
|
||||
</div>
|
||||
|
||||
<div v-else-if="registeredEvents.length" class="space-y-4">
|
||||
<div v-else-if="registeredEvents.length" class="event-list">
|
||||
<NuxtLink
|
||||
v-for="evt in registeredEvents"
|
||||
:key="evt._id"
|
||||
:to="`/events/${evt.slug || evt._id}`"
|
||||
class="block p-4 border border-guild-700 hover:border-candlelight-500 transition-colors"
|
||||
class="event-item"
|
||||
>
|
||||
<div class="flex items-start gap-4">
|
||||
<div
|
||||
v-if="
|
||||
evt.featureImage &&
|
||||
(evt.featureImage.publicId || evt.featureImage.url)
|
||||
"
|
||||
class="flex-shrink-0 w-20 h-20 overflow-hidden"
|
||||
>
|
||||
<img
|
||||
:src="getEventImageUrl(evt.featureImage)"
|
||||
:alt="evt.title"
|
||||
class="w-full h-full object-cover"
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
v-else
|
||||
class="flex-shrink-0 w-20 h-20 bg-guild-800 border border-guild-600 flex items-center justify-center"
|
||||
>
|
||||
<Icon
|
||||
name="heroicons:calendar-days"
|
||||
class="w-8 h-8 text-candlelight-400"
|
||||
/>
|
||||
</div>
|
||||
<div class="flex-1 min-w-0">
|
||||
<h3 class="font-semibold text-guild-100 mb-1">
|
||||
{{ evt.title }}
|
||||
</h3>
|
||||
<div class="flex items-center gap-4 text-ui-mono text-guild-400">
|
||||
<span class="flex items-center gap-1">
|
||||
<Icon name="heroicons:calendar" class="w-4 h-4" />
|
||||
{{ formatEventDate(evt.startDate) }}
|
||||
</span>
|
||||
<span class="flex items-center gap-1">
|
||||
<Icon name="heroicons:clock" class="w-4 h-4" />
|
||||
{{ formatEventTime(evt.startDate) }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-shrink-0">
|
||||
<Icon
|
||||
name="heroicons:chevron-right"
|
||||
class="w-5 h-5 text-guild-500"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<span class="event-date">{{ formatEventDate(evt.startDate) }}</span>
|
||||
<span class="event-title">{{ evt.title }}</span>
|
||||
<CircleBadge v-if="evt.circle" :circle="evt.circle" />
|
||||
</NuxtLink>
|
||||
|
||||
<!-- Calendar subscription -->
|
||||
<button class="calendar-btn" @click="copyCalendarLink">
|
||||
{{ calendarLinkCopied ? 'Link copied!' : 'Subscribe to calendar' }}
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div v-else class="text-center py-8">
|
||||
<Icon
|
||||
name="heroicons:calendar-days"
|
||||
class="w-12 h-12 text-guild-600 mx-auto mb-3"
|
||||
/>
|
||||
<p class="text-guild-400 mb-4">
|
||||
You haven't registered for any upcoming events
|
||||
</p>
|
||||
<UButton
|
||||
to="/events"
|
||||
size="sm"
|
||||
class="border-guild-600 text-guild-200 hover:bg-guild-800 hover:border-candlelight-500"
|
||||
>
|
||||
Browse Events
|
||||
</UButton>
|
||||
<div v-else class="empty-state">
|
||||
<p>You haven't registered for any upcoming events</p>
|
||||
</div>
|
||||
|
||||
<NuxtLink to="/events" class="section-link">Browse all events →</NuxtLink>
|
||||
|
||||
<!-- Calendar subscription instructions -->
|
||||
<div
|
||||
v-if="registeredEvents.length > 0 && showCalendarInstructions"
|
||||
class="mt-4 p-4 bg-guild-800 border border-guild-600"
|
||||
>
|
||||
<div class="flex items-start justify-between gap-4">
|
||||
<div class="flex-1">
|
||||
<h4 class="text-sm font-semibold text-guild-100 mb-2">
|
||||
How to Subscribe to Your Calendar
|
||||
</h4>
|
||||
<ul
|
||||
class="text-xs text-guild-300 space-y-1 list-disc list-inside"
|
||||
>
|
||||
<li>
|
||||
<strong>Google Calendar:</strong> Click "+" → "From URL" →
|
||||
Paste the link
|
||||
</li>
|
||||
<li>
|
||||
<strong>Apple Calendar:</strong> File → New Calendar
|
||||
Subscription → Paste the link
|
||||
</li>
|
||||
<li>
|
||||
<strong>Outlook:</strong> Add Calendar → Subscribe from web
|
||||
→ Paste the link
|
||||
</li>
|
||||
</ul>
|
||||
<p class="text-xs text-guild-400 mt-2">
|
||||
Your calendar will automatically update when you register or
|
||||
unregister from events.
|
||||
</p>
|
||||
</div>
|
||||
<button
|
||||
@click="showCalendarInstructions = false"
|
||||
class="text-guild-400 hover:text-guild-200"
|
||||
>
|
||||
<Icon name="heroicons:x-mark" class="w-5 h-5" />
|
||||
</button>
|
||||
<div v-if="registeredEvents.length > 0 && showCalendarInstructions" class="calendar-instructions">
|
||||
<div class="ci-header">
|
||||
<strong>How to Subscribe to Your Calendar</strong>
|
||||
<button @click="showCalendarInstructions = false" class="ci-close">×</button>
|
||||
</div>
|
||||
<ul>
|
||||
<li><strong>Google Calendar:</strong> Click "+" then "From URL" then paste the link</li>
|
||||
<li><strong>Apple Calendar:</strong> File then New Calendar Subscription then paste the link</li>
|
||||
<li><strong>Outlook:</strong> Add Calendar then Subscribe from web then paste the link</li>
|
||||
</ul>
|
||||
<p class="ci-note">Your calendar will automatically update when you register or unregister from events.</p>
|
||||
</div>
|
||||
</UCard>
|
||||
</div>
|
||||
|
||||
<div class="content-block">
|
||||
<div class="section-label">Quick Actions</div>
|
||||
<NuxtLink
|
||||
to="/members?peerSupport=true"
|
||||
class="quick-action"
|
||||
:class="{ disabled: !canPeerSupport }"
|
||||
:title="!canPeerSupport ? 'Complete your membership to book peer sessions' : ''"
|
||||
>
|
||||
Book a peer session<span class="arrow">→</span>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/member/profile" class="quick-action">
|
||||
Update your profile<span class="arrow">→</span>
|
||||
</NuxtLink>
|
||||
<a href="https://wiki.ghostguild.org" target="_blank" class="quick-action">
|
||||
Browse the wiki<span class="arrow">→</span>
|
||||
</a>
|
||||
<NuxtLink to="/members" class="quick-action">
|
||||
Browse members<span class="arrow">→</span>
|
||||
</NuxtLink>
|
||||
<NuxtLink to="/member/profile#account" class="quick-action">
|
||||
Manage account<span class="arrow">→</span>
|
||||
</NuxtLink>
|
||||
</div>
|
||||
</div>
|
||||
</UContainer>
|
||||
|
||||
<!-- Membership Summary + Peer Support -->
|
||||
<div class="content-row">
|
||||
<div class="content-block">
|
||||
<div class="section-label">Your Membership</div>
|
||||
<div class="membership-row">
|
||||
<span class="key">Circle</span>
|
||||
<span class="val" :style="{ color: `var(--c-${memberData?.circle || 'community'})` }">
|
||||
{{ memberData?.circle }}
|
||||
</span>
|
||||
</div>
|
||||
<div class="membership-row">
|
||||
<span class="key">Contribution</span>
|
||||
<span class="val">${{ memberData?.contributionTier }} CAD/month</span>
|
||||
</div>
|
||||
<div class="membership-row">
|
||||
<span class="key">Status</span>
|
||||
<span class="val">
|
||||
<span :class="isActive ? 'status-active' : ''">
|
||||
{{ isActive ? 'Active' : statusConfig.label }}
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div v-if="memberData?.createdAt" class="membership-row">
|
||||
<span class="key">Member since</span>
|
||||
<span class="val">{{ formatMemberSince(memberData.createdAt) }}</span>
|
||||
</div>
|
||||
<NuxtLink to="/member/profile#account" class="section-link">
|
||||
Change circle or contribution →
|
||||
</NuxtLink>
|
||||
</div>
|
||||
|
||||
<div class="content-block">
|
||||
<div class="section-label">Peer Support</div>
|
||||
<DashedBox>
|
||||
<p class="peer-text">
|
||||
Interested in offering peer support? Set up your profile to connect with other members who share your interests and experience.
|
||||
</p>
|
||||
<NuxtLink to="/member/profile" class="section-link">
|
||||
Set up peer support →
|
||||
</NuxtLink>
|
||||
</DashedBox>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
|
|
@ -473,7 +280,6 @@ const formatEventDate = (dateString) => {
|
|||
return new Intl.DateTimeFormat("en-US", {
|
||||
month: "short",
|
||||
day: "numeric",
|
||||
year: "numeric",
|
||||
}).format(date);
|
||||
};
|
||||
|
||||
|
|
@ -485,6 +291,14 @@ const formatEventTime = (dateString) => {
|
|||
}).format(date);
|
||||
};
|
||||
|
||||
const formatMemberSince = (dateString) => {
|
||||
const date = new Date(dateString);
|
||||
return new Intl.DateTimeFormat("en-US", {
|
||||
month: "short",
|
||||
year: "numeric",
|
||||
}).format(date);
|
||||
};
|
||||
|
||||
onMounted(() => {
|
||||
loadRegisteredEvents();
|
||||
});
|
||||
|
|
@ -493,6 +307,340 @@ onMounted(() => {
|
|||
useHead({
|
||||
title: "Member Dashboard - Ghost Guild",
|
||||
});
|
||||
|
||||
// Removed middleware - handling auth directly in the page component
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
/* ---- DASHBOARD LAYOUT ---- */
|
||||
.dashboard {
|
||||
max-width: 960px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
/* ---- LOADING / UNAUTH STATES ---- */
|
||||
.loading-state {
|
||||
text-align: center;
|
||||
padding: 80px 24px;
|
||||
color: var(--text-faint);
|
||||
}
|
||||
|
||||
.spinner {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
border: 2px dashed var(--candle);
|
||||
border-top-color: transparent;
|
||||
border-radius: 50%;
|
||||
animation: spin 1s linear infinite;
|
||||
margin: 0 auto 12px;
|
||||
}
|
||||
|
||||
.spinner-sm {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
}
|
||||
|
||||
@keyframes spin {
|
||||
to { transform: rotate(360deg); }
|
||||
}
|
||||
|
||||
.loading-inline {
|
||||
padding: 24px 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.unauth-state {
|
||||
text-align: center;
|
||||
padding: 80px 24px;
|
||||
max-width: 400px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.unauth-state h2 {
|
||||
font-family: 'Brygada 1918', serif;
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
color: var(--text-bright);
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.unauth-state p {
|
||||
color: var(--text-dim);
|
||||
font-size: 12px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
/* ---- WELCOME HEADER ---- */
|
||||
.welcome {
|
||||
padding: 28px 28px;
|
||||
border-bottom: 1px dashed var(--border);
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 16px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.welcome h1 {
|
||||
font-family: 'Brygada 1918', serif;
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
color: var(--text-bright);
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.welcome .meta {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
gap: 12px;
|
||||
font-size: 12px;
|
||||
color: var(--text-dim);
|
||||
}
|
||||
|
||||
/* ---- CONTENT GRID ---- */
|
||||
.content-row {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, minmax(0, 1fr));
|
||||
border-bottom: 1px dashed var(--border);
|
||||
}
|
||||
|
||||
.content-block {
|
||||
padding: 24px 28px;
|
||||
border-right: 1px dashed var(--border);
|
||||
min-width: 0;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
.content-block:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
/* ---- EVENT LIST ---- */
|
||||
.event-list {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
.event-item {
|
||||
display: grid;
|
||||
grid-template-columns: 64px 1fr auto;
|
||||
gap: 12px;
|
||||
align-items: baseline;
|
||||
padding: 10px 0;
|
||||
border-bottom: 1px dashed var(--border);
|
||||
transition: padding-left 0.2s;
|
||||
text-decoration: none;
|
||||
color: inherit;
|
||||
}
|
||||
|
||||
.event-item:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.event-item:hover {
|
||||
padding-left: 4px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.event-date {
|
||||
color: var(--text-faint);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.event-title {
|
||||
color: var(--text);
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
.event-item:hover .event-title {
|
||||
color: var(--candle);
|
||||
}
|
||||
|
||||
/* ---- CALENDAR BUTTON ---- */
|
||||
.calendar-btn {
|
||||
font-family: 'Commit Mono', monospace;
|
||||
font-size: 11px;
|
||||
color: var(--candle-dim);
|
||||
background: none;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
padding: 8px 0 0;
|
||||
}
|
||||
|
||||
.calendar-btn:hover {
|
||||
color: var(--candle);
|
||||
}
|
||||
|
||||
/* ---- CALENDAR INSTRUCTIONS ---- */
|
||||
.calendar-instructions {
|
||||
margin-top: 16px;
|
||||
padding: 16px 20px;
|
||||
border: 1px dashed var(--border);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ci-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: flex-start;
|
||||
margin-bottom: 8px;
|
||||
color: var(--text-bright);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.ci-close {
|
||||
background: none;
|
||||
border: none;
|
||||
color: var(--text-faint);
|
||||
cursor: pointer;
|
||||
font-size: 16px;
|
||||
line-height: 1;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
.ci-close:hover {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.calendar-instructions ul {
|
||||
list-style: disc;
|
||||
padding-left: 16px;
|
||||
color: var(--text-dim);
|
||||
font-size: 11px;
|
||||
line-height: 1.8;
|
||||
}
|
||||
|
||||
.ci-note {
|
||||
font-size: 11px;
|
||||
color: var(--text-faint);
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
/* ---- EMPTY STATE ---- */
|
||||
.empty-state {
|
||||
padding: 16px 0;
|
||||
}
|
||||
|
||||
.empty-state p {
|
||||
color: var(--text-faint);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
/* ---- SECTION LINK ---- */
|
||||
.section-link {
|
||||
display: inline-block;
|
||||
margin-top: 16px;
|
||||
font-size: 12px;
|
||||
color: var(--candle);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.section-link:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
/* ---- QUICK ACTIONS ---- */
|
||||
.quick-action {
|
||||
border: 1px dashed var(--border);
|
||||
padding: 14px 20px;
|
||||
margin-bottom: 8px;
|
||||
transition: border-color 0.2s;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
color: var(--text);
|
||||
font-size: 13px;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.quick-action:hover {
|
||||
border-color: var(--candle-faint);
|
||||
color: var(--candle);
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.quick-action.disabled {
|
||||
opacity: 0.4;
|
||||
pointer-events: none;
|
||||
cursor: not-allowed;
|
||||
}
|
||||
|
||||
.quick-action .arrow {
|
||||
color: var(--text-faint);
|
||||
margin-left: 8px;
|
||||
transition: color 0.2s;
|
||||
}
|
||||
|
||||
.quick-action:hover .arrow {
|
||||
color: var(--candle-faint);
|
||||
}
|
||||
|
||||
/* ---- MEMBERSHIP SUMMARY ---- */
|
||||
.membership-row {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 8px 0;
|
||||
border-bottom: 1px dashed var(--border);
|
||||
font-size: 12px;
|
||||
}
|
||||
|
||||
.membership-row:last-of-type {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.membership-row .key {
|
||||
color: var(--text-faint);
|
||||
}
|
||||
|
||||
.membership-row .val {
|
||||
color: var(--text);
|
||||
text-transform: capitalize;
|
||||
}
|
||||
|
||||
.status-active {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.status-active::before {
|
||||
content: '';
|
||||
display: inline-block;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background: var(--green);
|
||||
}
|
||||
|
||||
/* ---- PEER SUPPORT ---- */
|
||||
.peer-text {
|
||||
color: var(--text-dim);
|
||||
font-size: 12px;
|
||||
line-height: 1.65;
|
||||
}
|
||||
|
||||
/* ---- RESPONSIVE ---- */
|
||||
@media (max-width: 768px) {
|
||||
.content-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.content-block {
|
||||
border-right: none;
|
||||
border-bottom: 1px dashed var(--border);
|
||||
}
|
||||
|
||||
.content-block:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.welcome {
|
||||
padding: 24px 20px;
|
||||
}
|
||||
|
||||
.content-block {
|
||||
padding: 20px;
|
||||
}
|
||||
|
||||
.event-item {
|
||||
grid-template-columns: 56px 1fr auto;
|
||||
gap: 8px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue