- Mobile: a hamburger nav with a dropdown, and ≤767/720px breakpoints across pages that collapse multi-column grids to one column and cut the 112px desktop side padding down for phones; admin gets a phone pass too. - Readability: bump the type-scale tokens and the small hardcoded sizes across user-facing pages (roadmap route excepted — already enlarged). - Pulse votes now sit in a warm terracotta-tinted panel so they stand out. - Header: 50% larger Fenja AI logo, the dot vertically centred to it, and a rebalanced "Project Bifrost" lockup (smaller, matched cap heights). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
160 lines
4.9 KiB
Text
160 lines
4.9 KiB
Text
---
|
|
import AppLayout from '../../layouts/AppLayout.astro';
|
|
import { getPastEvents, getEventRsvpCount } from '../../lib/db';
|
|
import { pigmentForId } from '../../lib/format';
|
|
|
|
const user = Astro.locals.user;
|
|
const past = getPastEvents(500);
|
|
|
|
function parseUtc(s: string): Date {
|
|
if (/T.*[Zz]$/.test(s) || /[+-]\d{2}:?\d{2}$/.test(s)) return new Date(s);
|
|
return new Date(s.replace(' ', 'T') + 'Z');
|
|
}
|
|
function fmt(part: Intl.DateTimeFormatOptions, iso: string): string {
|
|
return new Intl.DateTimeFormat('en-GB', { ...part, timeZone: 'Europe/Copenhagen' }).format(parseUtc(iso));
|
|
}
|
|
---
|
|
<AppLayout title="Past gatherings" user={user}>
|
|
<div class="page">
|
|
|
|
<header class="head">
|
|
<h1 class="head-title">The archive.</h1>
|
|
<p class="head-sub">Everything the council has gathered around so far.</p>
|
|
<a href="/events" class="section-link back-link">← Back to upcoming</a>
|
|
</header>
|
|
|
|
{past.length === 0 ? (
|
|
<p class="body-md empty">No past events yet.</p>
|
|
) : (
|
|
<ul class="past-list">
|
|
{past.map(ev => {
|
|
const monthCode = fmt({ month: 'short' }, ev.starts_at).toUpperCase();
|
|
const attended = getEventRsvpCount(ev.slug).going;
|
|
const hasNotes = !!ev.notes_url;
|
|
const pigA = pigmentForId(ev.id);
|
|
const pigB = pigmentForId(ev.id + 1);
|
|
return (
|
|
<li class="past-card">
|
|
{ev.photo_url ? (
|
|
<img class="past-thumb" src={ev.photo_url} alt="" loading="lazy" />
|
|
) : hasNotes ? (
|
|
<a href={ev.notes_url!} class="past-thumb past-thumb--notes" aria-label="Read the notes">
|
|
<span class="past-thumb-month">{monthCode}</span>
|
|
</a>
|
|
) : (
|
|
<div
|
|
class="past-thumb past-thumb--gradient"
|
|
style={`background: linear-gradient(135deg, ${pigA.hex}, ${pigB.hex});`}
|
|
aria-hidden="true"
|
|
>
|
|
<span class="past-thumb-month">{monthCode}</span>
|
|
</div>
|
|
)}
|
|
<div class="past-text">
|
|
<h3 class="past-title">{ev.title}</h3>
|
|
<p class="past-meta">
|
|
{fmt({ day: 'numeric', month: 'long', year: 'numeric' }, ev.starts_at)}
|
|
{ev.location && ` · ${ev.location}`}
|
|
</p>
|
|
<p class="past-foot label-sm">
|
|
{attended} attended · {hasNotes ? 'Notes shared' : 'No notes'}
|
|
</p>
|
|
</div>
|
|
</li>
|
|
);
|
|
})}
|
|
</ul>
|
|
)}
|
|
|
|
</div>
|
|
</AppLayout>
|
|
|
|
<style>
|
|
.page {
|
|
padding: var(--space-12) var(--space-20) var(--space-16);
|
|
max-width: var(--content-max);
|
|
margin: 0 auto;
|
|
display: flex;
|
|
flex-direction: column;
|
|
gap: var(--space-8);
|
|
}
|
|
.head { max-width: 46rem; }
|
|
.head-eyebrow {
|
|
letter-spacing: var(--tracking-wider);
|
|
text-transform: uppercase;
|
|
color: var(--on-surface-variant);
|
|
margin-bottom: var(--space-3);
|
|
}
|
|
.head-title {
|
|
font-family: var(--font-serif);
|
|
font-weight: 400;
|
|
font-size: var(--text-display-md);
|
|
letter-spacing: var(--tracking-tight);
|
|
line-height: var(--leading-tight);
|
|
color: var(--on-surface);
|
|
margin: 0;
|
|
}
|
|
.head-sub { color: var(--on-surface-variant); margin-top: var(--space-3); max-width: 32rem; }
|
|
.back-link { margin-top: var(--space-4); }
|
|
|
|
.empty { color: var(--on-surface-muted); }
|
|
|
|
.past-list {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
display: grid;
|
|
grid-template-columns: 1fr 1fr;
|
|
gap: var(--space-5);
|
|
}
|
|
.past-card {
|
|
display: grid;
|
|
grid-template-columns: 56px 1fr;
|
|
gap: var(--space-4);
|
|
align-items: start;
|
|
}
|
|
.past-thumb {
|
|
width: 56px;
|
|
height: 56px;
|
|
border-radius: var(--radius-md);
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: center;
|
|
overflow: hidden;
|
|
text-decoration: none;
|
|
border: none;
|
|
}
|
|
.past-thumb--notes {
|
|
background: color-mix(in oklab, var(--pigment-copper) 18%, transparent);
|
|
color: var(--pigment-copper);
|
|
}
|
|
.past-thumb-month {
|
|
font-family: var(--font-sans);
|
|
font-size: var(--text-label-sm);
|
|
letter-spacing: var(--tracking-wider);
|
|
text-transform: uppercase;
|
|
font-weight: 600;
|
|
color: rgba(250, 246, 238, 0.6);
|
|
}
|
|
.past-thumb--notes .past-thumb-month { color: var(--pigment-copper); }
|
|
|
|
.past-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
|
|
.past-title {
|
|
font-family: var(--font-serif);
|
|
font-weight: 400;
|
|
font-size: 1.0625rem;
|
|
color: var(--on-surface);
|
|
margin: 0;
|
|
}
|
|
.past-meta { font-size: 0.75rem; color: var(--on-surface-variant); margin: 0; }
|
|
.past-foot {
|
|
color: var(--on-surface-muted);
|
|
letter-spacing: var(--tracking-wide);
|
|
margin: 0;
|
|
}
|
|
|
|
@media (max-width: 720px) {
|
|
.page { padding: var(--space-8) var(--space-5) var(--space-12); }
|
|
.past-list { grid-template-columns: 1fr; }
|
|
}
|
|
</style>
|