feat(pulse): events box lighter + bundled coming-up, unboxed Fenja, horizontal roadmap, bigger council cards
Events card (--ink): - 'Next up · Members only' and 'Invitation by hand' eyebrows removed. - All ink-card text uses cream tones (rgba(232,224,208,...) at 92/75/70/65%) instead of the warm tan --ink-muted; the previous low-contrast labels read 'dark' on the indigo and now read uniformly light. - Italic font removed everywhere on the card (hero day number, hero title, coming-up titles, etc.) — italic is reserved for the Bifrost wordmark and section-links only. - Past gatherings dropped from /pulse entirely; the listing lives on /events and /events/past. - 'Also coming up' is now a grid of small bundled sub-cards inside the blue surface (auto-fit minmax 220px). Each card shows date + title + meta only — no RSVP action, no per-row submit form. - 'See all events →' section-link replaces the old past-gatherings 'View all →' as the sole bottom-of-block link to /events. Latest from Fenja (unboxed): - Card surface dropped. Article sits on the cream page background. - Excerpt extended via new dispatchLongPreview(d, 520) helper — sentence-boundary cut at ~520 chars (was ~200). Title in serif regular, not italic. - 'Read the full dispatch →' section-link at the bottom. Roadmap (horizontal): - Three roadmap items become a 3-column grid of small white cards instead of a vertical list. Each card has status dot + title + status blurb with consistent min-height. - 'See the full roadmap →' section-link at the bottom. Council members (larger cards): - Was a flowing pill row, now an auto-fit grid (minmax 260px) of larger white cards. Each card has a 56px avatar + name + title + company, with generous padding for whitespace. Company name is the new field. - 'See who our council is made up of →' section-link at the bottom. General (eyebrows + italics): all uppercase tracked eyebrow labels gone from /pulse — date label, 'Latest from Fenja', 'From the roadmap', 'The council', etc. Italic body text removed throughout — greeting, titles, member names, dispatch title, roadmap titles. The Bifrost wordmark in the header and the .section-link utility class are the only remaining italics. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ca3686de29
commit
637055a73e
2 changed files with 257 additions and 433 deletions
Binary file not shown.
|
|
@ -3,14 +3,14 @@ import AppLayout from '../layouts/AppLayout.astro';
|
||||||
import Avatar from '../components/Avatar.astro';
|
import Avatar from '../components/Avatar.astro';
|
||||||
import AvatarPile from '../components/AvatarPile.astro';
|
import AvatarPile from '../components/AvatarPile.astro';
|
||||||
import {
|
import {
|
||||||
getUpcomingEvents, getPastEvents, getEventBySlug, getEventAttendees,
|
getUpcomingEvents, getEventBySlug, getEventAttendees,
|
||||||
getEventRsvpCount, getUserRsvp, setEventRsvp, recordActivity,
|
getUserRsvp, setEventRsvp, recordActivity,
|
||||||
getAllRoadmapItems, getLatestPublishedDispatches, getAllCabMembers,
|
getAllRoadmapItems, getLatestPublishedDispatches, getAllCabMembers,
|
||||||
} from '../lib/db';
|
} from '../lib/db';
|
||||||
import {
|
import {
|
||||||
pulseDateLabel, timeOfDay, tenureSince, pigmentForId, relativeTime,
|
pulseDateLabel, timeOfDay, tenureSince, relativeTime,
|
||||||
eventKindLabel, defaultActionLabel,
|
eventKindLabel,
|
||||||
dispatchSlug, dispatchKindLabel, dispatchKindPigment, dispatchExcerptParas,
|
dispatchSlug, dispatchKindLabel, dispatchKindPigment, dispatchLongPreview,
|
||||||
} from '../lib/format';
|
} from '../lib/format';
|
||||||
|
|
||||||
const user = Astro.locals.user;
|
const user = Astro.locals.user;
|
||||||
|
|
@ -36,7 +36,7 @@ if (Astro.request.method === 'POST') {
|
||||||
// ── Greeting ───────────────────────────────────────────────────────
|
// ── Greeting ───────────────────────────────────────────────────────
|
||||||
const firstName = user.name.split(' ')[0];
|
const firstName = user.name.split(' ')[0];
|
||||||
const greeting = `Good ${timeOfDay()}, ${firstName}.`;
|
const greeting = `Good ${timeOfDay()}, ${firstName}.`;
|
||||||
const dateLabel = pulseDateLabel();
|
// (date label dropped per the v3 eyebrow-removal pass; tenure line stays inline)
|
||||||
|
|
||||||
const tenureAnchor = user.role === 'cab' && user.cab_joined_date
|
const tenureAnchor = user.role === 'cab' && user.cab_joined_date
|
||||||
? user.cab_joined_date
|
? user.cab_joined_date
|
||||||
|
|
@ -47,7 +47,6 @@ const tenure = tenureSince(tenureAnchor);
|
||||||
const upcoming = getUpcomingEvents(20);
|
const upcoming = getUpcomingEvents(20);
|
||||||
const hero = upcoming.find(e => e.kind !== 'office_hours') ?? upcoming[0] ?? null;
|
const hero = upcoming.find(e => e.kind !== 'office_hours') ?? upcoming[0] ?? null;
|
||||||
const comingUp = upcoming.filter(e => e.id !== hero?.id).slice(0, 4);
|
const comingUp = upcoming.filter(e => e.id !== hero?.id).slice(0, 4);
|
||||||
const past = getPastEvents(4);
|
|
||||||
|
|
||||||
function parseUtc(s: string): Date {
|
function parseUtc(s: string): Date {
|
||||||
if (/T.*[Zz]$/.test(s) || /[+-]\d{2}:?\d{2}$/.test(s)) return new Date(s);
|
if (/T.*[Zz]$/.test(s) || /[+-]\d{2}:?\d{2}$/.test(s)) return new Date(s);
|
||||||
|
|
@ -64,12 +63,12 @@ const timeStr = (iso: string) => fmt({ hour: '2-digit', minute: '2-digit', ho
|
||||||
const heroAttendees = hero ? getEventAttendees(hero.slug, 'yes') : [];
|
const heroAttendees = hero ? getEventAttendees(hero.slug, 'yes') : [];
|
||||||
const heroConfirmedCount = heroAttendees.length;
|
const heroConfirmedCount = heroAttendees.length;
|
||||||
const heroMyRsvp = hero ? getUserRsvp(user.id, hero.slug) : null;
|
const heroMyRsvp = hero ? getUserRsvp(user.id, hero.slug) : null;
|
||||||
const heroAudience = hero?.audience ?? 'Members only';
|
|
||||||
|
|
||||||
// ── Latest from Fenja (single most recent dispatch) ────────────────
|
// ── Latest from Fenja ──────────────────────────────────────────────
|
||||||
const [latestDispatch] = getLatestPublishedDispatches(1);
|
const [latestDispatch] = getLatestPublishedDispatches(1);
|
||||||
|
const latestPreview = latestDispatch ? dispatchLongPreview(latestDispatch, 520) : '';
|
||||||
|
|
||||||
// ── Roadmap preview (3 most-recently-updated items) ────────────────
|
// ── Roadmap preview (3 most-recently-updated items, horizontal) ────
|
||||||
const roadmapPreview = getAllRoadmapItems()
|
const roadmapPreview = getAllRoadmapItems()
|
||||||
.sort((a, b) => (b.updated_at > a.updated_at ? 1 : -1))
|
.sort((a, b) => (b.updated_at > a.updated_at ? 1 : -1))
|
||||||
.slice(0, 3);
|
.slice(0, 3);
|
||||||
|
|
@ -90,7 +89,7 @@ function roadmapStatusBlurb(item: { status: 'shipping' | 'beta' | 'exploring'; t
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Members strip — all cab users in member-number order ───────────
|
// ── Council members ─────────────────────────────────────────────────
|
||||||
const members = getAllCabMembers();
|
const members = getAllCabMembers();
|
||||||
---
|
---
|
||||||
<AppLayout title="Pulse" user={user}>
|
<AppLayout title="Pulse" user={user}>
|
||||||
|
|
@ -98,44 +97,36 @@ const members = getAllCabMembers();
|
||||||
|
|
||||||
<!-- ── Greeting ─────────────────────────────────────────────── -->
|
<!-- ── Greeting ─────────────────────────────────────────────── -->
|
||||||
<section class="cascade greeting">
|
<section class="cascade greeting">
|
||||||
<p class="label-sm date-label">{dateLabel}</p>
|
<h1 class="greeting-line">{greeting}</h1>
|
||||||
<h1 class="greeting-line">
|
|
||||||
<span class="greeting-italic">{greeting}</span>
|
|
||||||
</h1>
|
|
||||||
<p class="greeting-sub body-md">
|
<p class="greeting-sub body-md">
|
||||||
You've been a member for <em>{tenure}</em>. The team is reading every note you leave.
|
You've been a member for {tenure}. The team is reading every note you leave.
|
||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<!-- ── Events (top, --ink card with hero + coming up + past) ── -->
|
<!-- ── Events (--ink card with hero + bundled coming-up + see all) -->
|
||||||
{hero ? (
|
{hero ? (
|
||||||
<section class="cascade events-card" aria-label="Events">
|
<section class="cascade events-card" aria-label="Events">
|
||||||
|
|
||||||
<!-- Hero -->
|
<!-- Hero -->
|
||||||
<header class="events-hero-top">
|
<div class="hero-body">
|
||||||
<span class="events-eyebrow">Next up · {heroAudience}</span>
|
<div class="hero-date">
|
||||||
<span class="events-eyebrow">Invitation by hand</span>
|
<span class="hero-weekday">{weekday(hero.starts_at)}</span>
|
||||||
</header>
|
<span class="hero-day">{dayNum(hero.starts_at)}</span>
|
||||||
|
<span class="hero-month">{monthShort(hero.starts_at)}</span>
|
||||||
<div class="events-hero-body">
|
|
||||||
<div class="events-date">
|
|
||||||
<span class="events-weekday">{weekday(hero.starts_at)}</span>
|
|
||||||
<span class="events-day">{dayNum(hero.starts_at)}</span>
|
|
||||||
<span class="events-month">{monthShort(hero.starts_at)}</span>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="events-detail">
|
<div class="hero-detail">
|
||||||
<h2 class="events-title">{hero.title}</h2>
|
<h2 class="hero-title">{hero.title}</h2>
|
||||||
<p class="events-desc">{hero.description}</p>
|
<p class="hero-desc">{hero.description}</p>
|
||||||
<p class="events-meta">
|
<p class="hero-meta">
|
||||||
{hero.location}{hero.location && ' · '}{timeStr(hero.starts_at)}{hero.duration_label ? ` · ${hero.duration_label}` : ''}
|
{hero.location}{hero.location && ' · '}{timeStr(hero.starts_at)}{hero.duration_label ? ` · ${hero.duration_label}` : ''}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<footer class="events-hero-foot">
|
<footer class="hero-foot">
|
||||||
<div class="events-foot-left">
|
<div class="hero-foot-left">
|
||||||
<span class="events-foot-stat">
|
<span class="hero-foot-stat">
|
||||||
{hero.capacity ? `${hero.capacity} seats · ` : ''}{heroConfirmedCount} confirmed
|
{hero.capacity ? `${hero.capacity} seats · ` : ''}{heroConfirmedCount} confirmed
|
||||||
</span>
|
</span>
|
||||||
{heroAttendees.length > 0 && (
|
{heroAttendees.length > 0 && (
|
||||||
|
|
@ -143,168 +134,106 @@ const members = getAllCabMembers();
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<form method="POST" class="events-foot-right">
|
<form method="POST" class="hero-foot-right">
|
||||||
<input type="hidden" name="action" value="rsvp" />
|
<input type="hidden" name="action" value="rsvp" />
|
||||||
<input type="hidden" name="event_slug" value={hero.slug} />
|
<input type="hidden" name="event_slug" value={hero.slug} />
|
||||||
{heroMyRsvp === 'yes' ? (
|
{heroMyRsvp === 'yes' ? (
|
||||||
<>
|
<>
|
||||||
<span class="events-confirmed">You're confirmed ✓</span>
|
<span class="hero-confirmed">You're confirmed ✓</span>
|
||||||
<button type="submit" name="status" value="no" class="events-change">Change</button>
|
<button type="submit" name="status" value="no" class="hero-change">Change</button>
|
||||||
</>
|
</>
|
||||||
) : (
|
) : (
|
||||||
<button type="submit" name="status" value="yes" class="events-cta">Save your seat →</button>
|
<button type="submit" name="status" value="yes" class="hero-cta">Save your seat →</button>
|
||||||
)}
|
)}
|
||||||
</form>
|
</form>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
<!-- Coming up (less prominent, same blue card) -->
|
<!-- Bundled coming-up sub-cards (no RSVP buttons) -->
|
||||||
{comingUp.length > 0 && (
|
{comingUp.length > 0 && (
|
||||||
<>
|
<ul class="coming-up-grid">
|
||||||
<hr class="events-divider" />
|
{comingUp.map(ev => (
|
||||||
<p class="events-sub-eyebrow">Also coming up</p>
|
<li class="coming-up-card">
|
||||||
<ul class="events-list">
|
<div class="cu-date">
|
||||||
{comingUp.map(ev => (
|
<span class="cu-day">{dayNum(ev.starts_at)}</span>
|
||||||
<li class="events-list-row">
|
<span class="cu-month">{monthShort(ev.starts_at)}</span>
|
||||||
<span class="events-list-date">
|
</div>
|
||||||
<span class="events-list-day">{dayNum(ev.starts_at)}</span>
|
<div class="cu-body">
|
||||||
<span class="events-list-month">{monthShort(ev.starts_at)}</span>
|
<h3 class="cu-title">{ev.title}</h3>
|
||||||
</span>
|
<p class="cu-meta">{[ev.duration_label, ev.audience, eventKindLabel(ev.kind)].filter(Boolean).join(' · ')}</p>
|
||||||
<span class="events-list-body">
|
|
||||||
<span class="events-list-title">{ev.title}</span>
|
|
||||||
<span class="events-list-meta">{[ev.duration_label, ev.audience, eventKindLabel(ev.kind)].filter(Boolean).join(' · ')}</span>
|
|
||||||
</span>
|
|
||||||
<form method="POST" class="events-list-action-form">
|
|
||||||
<input type="hidden" name="action" value="rsvp" />
|
|
||||||
<input type="hidden" name="event_slug" value={ev.slug} />
|
|
||||||
<button type="submit" name="status" value="yes" class="events-list-action">
|
|
||||||
{ev.action_label ?? defaultActionLabel(ev.kind)}
|
|
||||||
</button>
|
|
||||||
</form>
|
|
||||||
</li>
|
|
||||||
))}
|
|
||||||
</ul>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<!-- Past gatherings (least prominent, same blue card) -->
|
|
||||||
{past.length > 0 && (
|
|
||||||
<>
|
|
||||||
<hr class="events-divider" />
|
|
||||||
<header class="events-past-head">
|
|
||||||
<p class="events-sub-eyebrow">Past gatherings</p>
|
|
||||||
<a href="/events/past" class="events-past-all">View all →</a>
|
|
||||||
</header>
|
|
||||||
<ul class="events-list events-list--past">
|
|
||||||
{past.map(ev => {
|
|
||||||
const attended = getEventRsvpCount(ev.slug).going;
|
|
||||||
const hasNotes = !!ev.notes_url;
|
|
||||||
return (
|
|
||||||
<li class="events-list-row">
|
|
||||||
<span class="events-list-date">
|
|
||||||
<span class="events-list-day">{dayNum(ev.starts_at)}</span>
|
|
||||||
<span class="events-list-month">{monthShort(ev.starts_at)}</span>
|
|
||||||
</span>
|
|
||||||
<span class="events-list-body">
|
|
||||||
<span class="events-list-title">{ev.title}</span>
|
|
||||||
<span class="events-list-meta">{attended} attended · {hasNotes ? 'Notes shared' : 'No notes'}</span>
|
|
||||||
</span>
|
|
||||||
{hasNotes && (
|
|
||||||
<a href={ev.notes_url!} class="events-list-action">Notes ↗</a>
|
|
||||||
)}
|
|
||||||
</li>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</ul>
|
|
||||||
</>
|
|
||||||
)}
|
|
||||||
</section>
|
|
||||||
) : (
|
|
||||||
<section class="cascade events-card events-card--empty">
|
|
||||||
<p class="events-empty-line"><em>Nothing scheduled yet — when we have something, you'll be the first to know.</em></p>
|
|
||||||
</section>
|
|
||||||
)}
|
|
||||||
|
|
||||||
<!-- ── Roadmap + Latest from Fenja ──────────────────────────── -->
|
|
||||||
<section class="cascade combined-card">
|
|
||||||
|
|
||||||
{latestDispatch && (
|
|
||||||
<div class="sub-section">
|
|
||||||
<header class="sub-head">
|
|
||||||
<p class="label-sm sub-eyebrow">Latest from Fenja</p>
|
|
||||||
<a href="/dispatches" class="sub-all">All updates →</a>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<article class="latest-dispatch">
|
|
||||||
<header class="latest-byline">
|
|
||||||
<Avatar id={latestDispatch.author_id} name={latestDispatch.author_name} size={26} />
|
|
||||||
<span class="latest-byline-name">{latestDispatch.author_name}</span>
|
|
||||||
{latestDispatch.author_title && <span class="latest-byline-title">· {latestDispatch.author_title}</span>}
|
|
||||||
<span class="latest-byline-time label-sm">
|
|
||||||
{relativeTime(latestDispatch.published_at ?? latestDispatch.created_at)}
|
|
||||||
</span>
|
|
||||||
<span class="latest-kind-pill" style={`--pill: ${dispatchKindPigment(latestDispatch.kind)}`}>
|
|
||||||
{dispatchKindLabel(latestDispatch.kind)}
|
|
||||||
</span>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<h3 class="latest-title">{latestDispatch.title}</h3>
|
|
||||||
|
|
||||||
<p class="latest-excerpt">{dispatchExcerptParas(latestDispatch).lead}</p>
|
|
||||||
|
|
||||||
<a href={`/dispatches/${dispatchSlug(latestDispatch)}`} class="latest-read">Read the full dispatch →</a>
|
|
||||||
</article>
|
|
||||||
</div>
|
|
||||||
)}
|
|
||||||
|
|
||||||
{latestDispatch && roadmapPreview.length > 0 && <hr class="sub-divider" />}
|
|
||||||
|
|
||||||
<div class="sub-section">
|
|
||||||
<header class="sub-head">
|
|
||||||
<p class="label-sm sub-eyebrow">From the roadmap</p>
|
|
||||||
<a href="/roadmap" class="sub-all">See the full roadmap →</a>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
{roadmapPreview.length === 0 ? (
|
|
||||||
<p class="body-sm muted">No roadmap items yet.</p>
|
|
||||||
) : (
|
|
||||||
<ul class="roadmap-list">
|
|
||||||
{roadmapPreview.map(item => (
|
|
||||||
<li class="roadmap-row">
|
|
||||||
<span
|
|
||||||
class:list={['status-dot', { breathing: item.status === 'shipping' }]}
|
|
||||||
style={`background:${roadmapStatusDot(item.status)}`}
|
|
||||||
aria-hidden="true"
|
|
||||||
></span>
|
|
||||||
<div class="roadmap-row-text">
|
|
||||||
<p class="roadmap-row-title">{item.title}</p>
|
|
||||||
<p class="roadmap-row-blurb label-sm">{roadmapStatusBlurb(item)}</p>
|
|
||||||
</div>
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
|
|
||||||
<!-- ── Members strip ────────────────────────────────────────── -->
|
<a href="/events" class="section-link section-link--ink hero-see-all">See all events →</a>
|
||||||
{members.length > 0 && (
|
|
||||||
<section class="cascade members-card">
|
</section>
|
||||||
<header class="members-head-row">
|
) : (
|
||||||
<p class="label-sm sub-eyebrow">The council</p>
|
<section class="cascade events-card events-card--empty">
|
||||||
<a href="/members" class="sub-all">See who our council is made up of →</a>
|
<p class="events-empty-line">Nothing scheduled yet — when we have something, you'll be the first to know.</p>
|
||||||
|
<a href="/events" class="section-link section-link--ink">See all events →</a>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<!-- ── Latest from Fenja (unboxed, longer excerpt) ──────────── -->
|
||||||
|
{latestDispatch && (
|
||||||
|
<article class="cascade latest-article">
|
||||||
|
<header class="latest-byline">
|
||||||
|
<Avatar id={latestDispatch.author_id} name={latestDispatch.author_name} size={28} />
|
||||||
|
<span class="latest-byline-name">{latestDispatch.author_name}</span>
|
||||||
|
{latestDispatch.author_title && <span class="latest-byline-title">· {latestDispatch.author_title}</span>}
|
||||||
|
<span class="latest-byline-time">{relativeTime(latestDispatch.published_at ?? latestDispatch.created_at)}</span>
|
||||||
|
<span class="latest-kind-pill" style={`--pill: ${dispatchKindPigment(latestDispatch.kind)}`}>
|
||||||
|
{dispatchKindLabel(latestDispatch.kind)}
|
||||||
|
</span>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<ul class="members-strip">
|
<h2 class="latest-title">{latestDispatch.title}</h2>
|
||||||
{members.map(m => (
|
<p class="latest-body">{latestPreview}</p>
|
||||||
<li class="member-pill">
|
|
||||||
<Avatar id={m.id} name={m.name} size={32} />
|
<a href={`/dispatches/${dispatchSlug(latestDispatch)}`} class="section-link">Read the full dispatch →</a>
|
||||||
<span class="member-pill-text">
|
</article>
|
||||||
<span class="member-pill-name">{m.name}</span>
|
)}
|
||||||
{m.title && <span class="member-pill-title label-sm">{m.title}</span>}
|
|
||||||
</span>
|
<!-- ── Roadmap — horizontal cards ───────────────────────────── -->
|
||||||
|
{roadmapPreview.length > 0 && (
|
||||||
|
<section class="cascade roadmap-section" aria-label="From the roadmap">
|
||||||
|
<ul class="roadmap-grid">
|
||||||
|
{roadmapPreview.map(item => (
|
||||||
|
<li class="roadmap-card">
|
||||||
|
<span
|
||||||
|
class:list={['status-dot', { breathing: item.status === 'shipping' }]}
|
||||||
|
style={`background:${roadmapStatusDot(item.status)}`}
|
||||||
|
aria-hidden="true"
|
||||||
|
></span>
|
||||||
|
<div class="roadmap-card-text">
|
||||||
|
<h3 class="roadmap-card-title">{item.title}</h3>
|
||||||
|
<p class="roadmap-card-blurb">{roadmapStatusBlurb(item)}</p>
|
||||||
|
</div>
|
||||||
</li>
|
</li>
|
||||||
))}
|
))}
|
||||||
</ul>
|
</ul>
|
||||||
|
<a href="/roadmap" class="section-link">See the full roadmap →</a>
|
||||||
|
</section>
|
||||||
|
)}
|
||||||
|
|
||||||
|
<!-- ── Council members — larger cards with company ──────────── -->
|
||||||
|
{members.length > 0 && (
|
||||||
|
<section class="cascade council-section" aria-label="The council">
|
||||||
|
<ul class="council-grid">
|
||||||
|
{members.map(m => (
|
||||||
|
<li class="council-card">
|
||||||
|
<Avatar id={m.id} name={m.name} size={56} />
|
||||||
|
<div class="council-card-text">
|
||||||
|
<span class="council-card-name">{m.name}</span>
|
||||||
|
{m.title && <span class="council-card-title">{m.title}</span>}
|
||||||
|
<span class="council-card-org">{m.organisation}</span>
|
||||||
|
</div>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
<a href="/members" class="section-link">See who our council is made up of →</a>
|
||||||
</section>
|
</section>
|
||||||
)}
|
)}
|
||||||
|
|
||||||
|
|
@ -318,7 +247,7 @@ const members = getAllCabMembers();
|
||||||
margin: 0 auto;
|
margin: 0 auto;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-8);
|
gap: var(--space-10);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Cascade entry (first paint only) ─────────────────────────── */
|
/* ── Cascade entry (first paint only) ─────────────────────────── */
|
||||||
|
|
@ -331,20 +260,14 @@ const members = getAllCabMembers();
|
||||||
.cascade:nth-child(2) { animation-delay: 100ms; }
|
.cascade:nth-child(2) { animation-delay: 100ms; }
|
||||||
.cascade:nth-child(3) { animation-delay: 200ms; }
|
.cascade:nth-child(3) { animation-delay: 200ms; }
|
||||||
.cascade:nth-child(4) { animation-delay: 300ms; }
|
.cascade:nth-child(4) { animation-delay: 300ms; }
|
||||||
@keyframes cascade-in {
|
.cascade:nth-child(5) { animation-delay: 400ms; }
|
||||||
to { opacity: 1; transform: translateY(0); }
|
@keyframes cascade-in { to { opacity: 1; transform: translateY(0); } }
|
||||||
}
|
|
||||||
@media (prefers-reduced-motion: reduce) {
|
@media (prefers-reduced-motion: reduce) {
|
||||||
.cascade { opacity: 1; transform: none; animation: none; }
|
.cascade { opacity: 1; transform: none; animation: none; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Greeting ─────────────────────────────────────────────────── */
|
/* ── Greeting ─────────────────────────────────────────────────── */
|
||||||
.greeting { display: flex; flex-direction: column; gap: var(--space-3); }
|
.greeting { display: flex; flex-direction: column; gap: var(--space-3); }
|
||||||
.date-label {
|
|
||||||
letter-spacing: var(--tracking-wider);
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: var(--on-surface-muted);
|
|
||||||
}
|
|
||||||
.greeting-line {
|
.greeting-line {
|
||||||
font-family: var(--font-serif);
|
font-family: var(--font-serif);
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
|
|
@ -354,105 +277,90 @@ const members = getAllCabMembers();
|
||||||
color: var(--on-surface);
|
color: var(--on-surface);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
.greeting-italic { font-style: italic; }
|
|
||||||
.greeting-sub {
|
.greeting-sub {
|
||||||
color: var(--on-surface-variant);
|
color: var(--on-surface-variant);
|
||||||
max-width: 48rem;
|
max-width: 48rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
.greeting-sub em { font-style: italic; color: var(--on-surface); }
|
|
||||||
|
|
||||||
/* ── Events card (top, --ink) ─────────────────────────────────── */
|
/* ── Events card (--ink) ──────────────────────────────────────── */
|
||||||
.events-card {
|
.events-card {
|
||||||
background: var(--ink);
|
background: var(--ink);
|
||||||
color: var(--ink-text);
|
color: var(--ink-text);
|
||||||
border-radius: var(--radius-lg);
|
border-radius: var(--radius-lg);
|
||||||
padding: 1.75rem;
|
padding: var(--space-7) var(--space-8);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-5);
|
gap: var(--space-6);
|
||||||
}
|
}
|
||||||
.events-card--empty {
|
.events-card--empty {
|
||||||
align-items: stretch;
|
align-items: flex-start;
|
||||||
justify-content: center;
|
text-align: left;
|
||||||
text-align: center;
|
min-height: 160px;
|
||||||
min-height: 200px;
|
justify-content: space-between;
|
||||||
}
|
}
|
||||||
.events-empty-line {
|
.events-empty-line {
|
||||||
color: var(--ink-text);
|
color: var(--ink-text);
|
||||||
font-family: var(--font-serif);
|
font-family: var(--font-serif);
|
||||||
font-size: 1.25rem;
|
font-size: 1.25rem;
|
||||||
margin: auto;
|
margin: 0;
|
||||||
max-width: 32rem;
|
max-width: 32rem;
|
||||||
}
|
opacity: 0.92;
|
||||||
.events-empty-line em { font-style: italic; }
|
|
||||||
|
|
||||||
.events-hero-top {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: center;
|
|
||||||
color: var(--ink-muted);
|
|
||||||
}
|
|
||||||
.events-eyebrow {
|
|
||||||
font-family: var(--font-sans);
|
|
||||||
font-size: var(--text-label-sm);
|
|
||||||
letter-spacing: var(--tracking-wider);
|
|
||||||
text-transform: uppercase;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.events-hero-body {
|
/* Hero (lighter, fewer italics) */
|
||||||
|
.hero-body {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 100px 1fr;
|
grid-template-columns: 110px 1fr;
|
||||||
gap: var(--space-6);
|
gap: var(--space-7);
|
||||||
padding: var(--space-4) 0;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
.events-hero-body::after {
|
.hero-body::after {
|
||||||
content: '';
|
content: '';
|
||||||
position: absolute;
|
position: absolute;
|
||||||
left: 100px;
|
left: 110px;
|
||||||
top: 0; bottom: 0;
|
top: 0; bottom: 0;
|
||||||
width: 0.5px;
|
width: 0.5px;
|
||||||
background: rgba(232, 224, 208, 0.2);
|
background: rgba(232, 224, 208, 0.18);
|
||||||
}
|
}
|
||||||
.events-date { display: flex; flex-direction: column; gap: 2px; }
|
.hero-date { display: flex; flex-direction: column; gap: 4px; }
|
||||||
.events-weekday, .events-month {
|
.hero-weekday, .hero-month {
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-size: var(--text-label-sm);
|
font-size: var(--text-label-sm);
|
||||||
letter-spacing: var(--tracking-wider);
|
letter-spacing: var(--tracking-wider);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--ink-text);
|
color: rgba(232, 224, 208, 0.75);
|
||||||
}
|
}
|
||||||
.events-day {
|
.hero-day {
|
||||||
font-family: var(--font-serif);
|
font-family: var(--font-serif);
|
||||||
font-style: italic;
|
font-weight: 400;
|
||||||
font-size: 2.75rem;
|
font-size: 2.75rem;
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
color: var(--ink-text);
|
color: var(--ink-text);
|
||||||
}
|
}
|
||||||
.events-detail { padding-left: var(--space-5); }
|
.hero-detail { padding-left: var(--space-6); }
|
||||||
.events-title {
|
.hero-title {
|
||||||
font-family: var(--font-serif);
|
font-family: var(--font-serif);
|
||||||
font-style: italic;
|
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 1.75rem;
|
font-size: 1.75rem;
|
||||||
line-height: 1.2;
|
line-height: 1.2;
|
||||||
color: var(--ink-text);
|
color: var(--ink-text);
|
||||||
margin: 0 0 var(--space-3);
|
margin: 0 0 var(--space-3);
|
||||||
}
|
}
|
||||||
.events-desc {
|
.hero-desc {
|
||||||
color: rgba(232, 224, 208, 0.85);
|
color: rgba(232, 224, 208, 0.92);
|
||||||
margin: 0 0 var(--space-3);
|
margin: 0 0 var(--space-3);
|
||||||
max-width: 40rem;
|
max-width: 50rem;
|
||||||
}
|
}
|
||||||
.events-meta {
|
.hero-meta {
|
||||||
color: var(--ink-muted);
|
color: rgba(232, 224, 208, 0.7);
|
||||||
font-size: var(--text-body-sm);
|
font-size: var(--text-body-sm);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.events-hero-foot {
|
/* Hero foot */
|
||||||
border-top: 0.5px solid rgba(232, 224, 208, 0.2);
|
.hero-foot {
|
||||||
|
border-top: 0.5px solid rgba(232, 224, 208, 0.18);
|
||||||
padding-top: var(--space-4);
|
padding-top: var(--space-4);
|
||||||
display: flex;
|
display: flex;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
@ -460,17 +368,16 @@ const members = getAllCabMembers();
|
||||||
gap: var(--space-4);
|
gap: var(--space-4);
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
}
|
}
|
||||||
.events-foot-left { display: flex; align-items: center; gap: var(--space-4); }
|
.hero-foot-left { display: flex; align-items: center; gap: var(--space-4); }
|
||||||
.events-foot-stat {
|
.hero-foot-stat {
|
||||||
color: var(--ink-muted);
|
color: rgba(232, 224, 208, 0.7);
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-size: var(--text-label-sm);
|
font-size: var(--text-label-sm);
|
||||||
letter-spacing: var(--tracking-wider);
|
letter-spacing: var(--tracking-wider);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
}
|
}
|
||||||
.events-foot-right { display: flex; align-items: center; gap: var(--space-3); }
|
.hero-foot-right { display: flex; align-items: center; gap: var(--space-3); }
|
||||||
|
.hero-cta {
|
||||||
.events-cta {
|
|
||||||
background: var(--ink-text);
|
background: var(--ink-text);
|
||||||
color: var(--ink);
|
color: var(--ink);
|
||||||
border: none;
|
border: none;
|
||||||
|
|
@ -484,8 +391,8 @@ const members = getAllCabMembers();
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: opacity var(--duration-fast) var(--ease-standard);
|
transition: opacity var(--duration-fast) var(--ease-standard);
|
||||||
}
|
}
|
||||||
.events-cta:hover { opacity: 0.85; }
|
.hero-cta:hover { opacity: 0.85; }
|
||||||
.events-confirmed {
|
.hero-confirmed {
|
||||||
color: var(--ink-text);
|
color: var(--ink-text);
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-size: var(--text-label-md);
|
font-size: var(--text-label-md);
|
||||||
|
|
@ -496,10 +403,10 @@ const members = getAllCabMembers();
|
||||||
border: 0.5px solid rgba(232, 224, 208, 0.4);
|
border: 0.5px solid rgba(232, 224, 208, 0.4);
|
||||||
border-radius: 999px;
|
border-radius: 999px;
|
||||||
}
|
}
|
||||||
.events-change {
|
.hero-change {
|
||||||
background: transparent;
|
background: transparent;
|
||||||
border: none;
|
border: none;
|
||||||
color: var(--ink-muted);
|
color: rgba(232, 224, 208, 0.75);
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-size: var(--text-label-sm);
|
font-size: var(--text-label-sm);
|
||||||
letter-spacing: var(--tracking-wide);
|
letter-spacing: var(--tracking-wide);
|
||||||
|
|
@ -508,152 +415,62 @@ const members = getAllCabMembers();
|
||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sub-sections (Coming up + Past gatherings on the same blue card) */
|
/* Bundled coming-up sub-cards (no RSVP buttons) */
|
||||||
.events-divider {
|
.coming-up-grid {
|
||||||
border: none;
|
|
||||||
height: 0.5px;
|
|
||||||
background: rgba(232, 224, 208, 0.2);
|
|
||||||
margin: var(--space-3) 0 var(--space-2);
|
|
||||||
}
|
|
||||||
.events-sub-eyebrow {
|
|
||||||
font-family: var(--font-sans);
|
|
||||||
font-size: var(--text-label-sm);
|
|
||||||
letter-spacing: var(--tracking-wider);
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: var(--ink-muted);
|
|
||||||
margin: 0 0 var(--space-2);
|
|
||||||
}
|
|
||||||
.events-past-head {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: baseline;
|
|
||||||
gap: var(--space-3);
|
|
||||||
}
|
|
||||||
.events-past-all {
|
|
||||||
font-family: var(--font-sans);
|
|
||||||
font-size: var(--text-label-sm);
|
|
||||||
letter-spacing: var(--tracking-wide);
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: var(--ink-text);
|
|
||||||
text-decoration: none;
|
|
||||||
border-bottom: none;
|
|
||||||
opacity: 0.85;
|
|
||||||
}
|
|
||||||
.events-past-all:hover { opacity: 1; border-bottom: none; }
|
|
||||||
|
|
||||||
.events-list {
|
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
.events-list-row {
|
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: 60px 1fr auto;
|
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
|
||||||
gap: var(--space-4);
|
gap: var(--space-3);
|
||||||
align-items: center;
|
|
||||||
padding: var(--space-3) 0;
|
|
||||||
}
|
}
|
||||||
.events-list-row + .events-list-row { border-top: 0.5px solid rgba(232, 224, 208, 0.1); }
|
.coming-up-card {
|
||||||
|
background: rgba(232, 224, 208, 0.06);
|
||||||
.events-list-date { display: flex; flex-direction: column; gap: 2px; }
|
border: 0.5px solid rgba(232, 224, 208, 0.14);
|
||||||
.events-list-day {
|
border-radius: var(--radius-md);
|
||||||
|
padding: var(--space-4) var(--space-5);
|
||||||
|
display: flex;
|
||||||
|
gap: var(--space-4);
|
||||||
|
align-items: flex-start;
|
||||||
|
}
|
||||||
|
.cu-date { display: flex; flex-direction: column; gap: 2px; min-width: 36px; }
|
||||||
|
.cu-day {
|
||||||
font-family: var(--font-serif);
|
font-family: var(--font-serif);
|
||||||
font-style: italic;
|
font-size: 1.5rem;
|
||||||
font-size: 1.25rem;
|
|
||||||
line-height: 1;
|
line-height: 1;
|
||||||
color: var(--ink-text);
|
color: var(--ink-text);
|
||||||
}
|
}
|
||||||
.events-list-month {
|
.cu-month {
|
||||||
font-family: var(--font-sans);
|
font-family: var(--font-sans);
|
||||||
font-size: var(--text-label-sm);
|
font-size: var(--text-label-sm);
|
||||||
letter-spacing: var(--tracking-wider);
|
letter-spacing: var(--tracking-wider);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
color: var(--ink-muted);
|
color: rgba(232, 224, 208, 0.7);
|
||||||
}
|
}
|
||||||
|
.cu-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
|
||||||
.events-list-body { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
|
.cu-title {
|
||||||
.events-list-title {
|
|
||||||
font-family: var(--font-serif);
|
font-family: var(--font-serif);
|
||||||
font-style: italic;
|
font-weight: 400;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
|
line-height: 1.25;
|
||||||
color: var(--ink-text);
|
color: var(--ink-text);
|
||||||
|
margin: 0;
|
||||||
}
|
}
|
||||||
.events-list-meta {
|
.cu-meta {
|
||||||
font-size: 0.75rem;
|
font-size: 0.75rem;
|
||||||
color: var(--ink-muted);
|
color: rgba(232, 224, 208, 0.65);
|
||||||
}
|
|
||||||
|
|
||||||
.events-list-action-form { justify-self: end; }
|
|
||||||
.events-list-action {
|
|
||||||
background: none;
|
|
||||||
border: none;
|
|
||||||
color: var(--ink-text);
|
|
||||||
font-family: var(--font-sans);
|
|
||||||
font-size: var(--text-label-md);
|
|
||||||
font-weight: 500;
|
|
||||||
letter-spacing: var(--tracking-wide);
|
|
||||||
text-transform: uppercase;
|
|
||||||
cursor: pointer;
|
|
||||||
padding: 0;
|
|
||||||
text-decoration: none;
|
|
||||||
border-bottom: none;
|
|
||||||
opacity: 0.85;
|
|
||||||
}
|
|
||||||
.events-list-action:hover { opacity: 1; border-bottom: none; }
|
|
||||||
|
|
||||||
/* ── Combined card (Roadmap + Latest from Fenja) ──────────────── */
|
|
||||||
.combined-card {
|
|
||||||
background: var(--surface-card);
|
|
||||||
border: 0.5px solid var(--surface-card-border);
|
|
||||||
border-radius: var(--radius-lg);
|
|
||||||
padding: var(--space-6);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: var(--space-4);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-section {
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: var(--space-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-head {
|
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: baseline;
|
|
||||||
gap: var(--space-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.sub-eyebrow {
|
|
||||||
letter-spacing: var(--tracking-wider);
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: var(--on-surface-variant);
|
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sub-all {
|
.hero-see-all { align-self: flex-start; }
|
||||||
font-family: var(--font-sans);
|
|
||||||
font-size: var(--text-label-sm);
|
|
||||||
letter-spacing: var(--tracking-wide);
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: var(--pigment-terracotta);
|
|
||||||
text-decoration: none;
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
.sub-all:hover { opacity: 0.85; border-bottom: none; }
|
|
||||||
|
|
||||||
.sub-divider {
|
/* ── Latest from Fenja (unboxed) ──────────────────────────────── */
|
||||||
height: 1px;
|
.latest-article {
|
||||||
background: var(--surface-card-border);
|
display: flex;
|
||||||
border: none;
|
flex-direction: column;
|
||||||
margin: var(--space-2) 0;
|
gap: var(--space-3);
|
||||||
|
max-width: 56rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Latest from Fenja */
|
|
||||||
.latest-dispatch { display: flex; flex-direction: column; gap: var(--space-3); }
|
|
||||||
.latest-byline {
|
.latest-byline {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
|
@ -665,6 +482,7 @@ const members = getAllCabMembers();
|
||||||
.latest-byline-title { color: var(--on-surface-variant); }
|
.latest-byline-title { color: var(--on-surface-variant); }
|
||||||
.latest-byline-time {
|
.latest-byline-time {
|
||||||
color: var(--on-surface-muted);
|
color: var(--on-surface-muted);
|
||||||
|
font-size: var(--text-label-sm);
|
||||||
letter-spacing: var(--tracking-wide);
|
letter-spacing: var(--tracking-wide);
|
||||||
margin-left: auto;
|
margin-left: auto;
|
||||||
}
|
}
|
||||||
|
|
@ -680,120 +498,126 @@ const members = getAllCabMembers();
|
||||||
}
|
}
|
||||||
.latest-title {
|
.latest-title {
|
||||||
font-family: var(--font-serif);
|
font-family: var(--font-serif);
|
||||||
font-style: italic;
|
|
||||||
font-weight: 400;
|
font-weight: 400;
|
||||||
font-size: 1.25rem;
|
font-size: 1.625rem;
|
||||||
line-height: 1.3;
|
line-height: 1.25;
|
||||||
color: var(--on-surface);
|
color: var(--on-surface);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
letter-spacing: var(--tracking-snug);
|
||||||
}
|
}
|
||||||
.latest-excerpt {
|
.latest-body {
|
||||||
margin: 0;
|
|
||||||
color: var(--on-surface);
|
color: var(--on-surface);
|
||||||
line-height: var(--leading-relaxed);
|
line-height: var(--leading-relaxed);
|
||||||
|
margin: 0;
|
||||||
|
font-size: var(--text-body-lg);
|
||||||
}
|
}
|
||||||
.latest-read {
|
|
||||||
align-self: flex-start;
|
|
||||||
font-family: var(--font-sans);
|
|
||||||
font-size: var(--text-label-md);
|
|
||||||
font-weight: 500;
|
|
||||||
letter-spacing: var(--tracking-wide);
|
|
||||||
text-transform: uppercase;
|
|
||||||
color: var(--pigment-terracotta);
|
|
||||||
text-decoration: none;
|
|
||||||
border-bottom: none;
|
|
||||||
}
|
|
||||||
.latest-read:hover { opacity: 0.85; border-bottom: none; }
|
|
||||||
|
|
||||||
/* Roadmap rows */
|
/* ── Roadmap horizontal cards ─────────────────────────────────── */
|
||||||
.roadmap-list {
|
.roadmap-section {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: var(--space-4);
|
||||||
|
}
|
||||||
|
.roadmap-grid {
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(3, 1fr);
|
||||||
|
gap: var(--space-4);
|
||||||
|
}
|
||||||
|
.roadmap-card {
|
||||||
|
background: var(--surface-card);
|
||||||
|
border: 0.5px solid var(--surface-card-border);
|
||||||
|
border-radius: var(--radius-md);
|
||||||
|
padding: var(--space-5);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
gap: var(--space-3);
|
||||||
|
min-height: 130px;
|
||||||
}
|
}
|
||||||
.roadmap-row {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-start;
|
|
||||||
gap: var(--space-4);
|
|
||||||
padding: var(--space-3) 0;
|
|
||||||
}
|
|
||||||
.roadmap-row + .roadmap-row { border-top: 0.5px solid var(--surface-card-border); }
|
|
||||||
|
|
||||||
.status-dot {
|
.status-dot {
|
||||||
width: 10px;
|
width: 10px;
|
||||||
height: 10px;
|
height: 10px;
|
||||||
border-radius: 50%;
|
border-radius: 50%;
|
||||||
flex-shrink: 0;
|
flex-shrink: 0;
|
||||||
margin-top: 0.4em;
|
|
||||||
}
|
}
|
||||||
@keyframes breathe {
|
@keyframes breathe {
|
||||||
0%, 100% { transform: scale(1); opacity: 1; }
|
0%, 100% { transform: scale(1); opacity: 1; }
|
||||||
50% { transform: scale(1.4); opacity: 0.5; }
|
50% { transform: scale(1.4); opacity: 0.5; }
|
||||||
}
|
}
|
||||||
.status-dot.breathing { animation: breathe 2.4s ease-in-out infinite; }
|
.status-dot.breathing { animation: breathe 2.4s ease-in-out infinite; }
|
||||||
|
.roadmap-card-text { display: flex; flex-direction: column; gap: var(--space-1); }
|
||||||
.roadmap-row-text { flex: 1; display: flex; flex-direction: column; gap: var(--space-1); }
|
.roadmap-card-title {
|
||||||
.roadmap-row-title { margin: 0; font-weight: 500; color: var(--on-surface); }
|
font-family: var(--font-serif);
|
||||||
.roadmap-row-blurb {
|
font-weight: 400;
|
||||||
|
font-size: 1.0625rem;
|
||||||
|
line-height: 1.3;
|
||||||
|
color: var(--on-surface);
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
.roadmap-card-blurb {
|
||||||
color: var(--on-surface-muted);
|
color: var(--on-surface-muted);
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
font-size: var(--text-label-sm);
|
||||||
letter-spacing: var(--tracking-wide);
|
letter-spacing: var(--tracking-wide);
|
||||||
text-transform: uppercase;
|
text-transform: uppercase;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Members strip ────────────────────────────────────────────── */
|
/* ── Council cards — larger, with company ─────────────────────── */
|
||||||
.members-card {
|
.council-section {
|
||||||
background: var(--surface-card);
|
|
||||||
border: 0.5px solid var(--surface-card-border);
|
|
||||||
border-radius: var(--radius-lg);
|
|
||||||
padding: var(--space-6);
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
gap: var(--space-4);
|
gap: var(--space-5);
|
||||||
}
|
}
|
||||||
.members-head-row {
|
.council-grid {
|
||||||
display: flex;
|
|
||||||
justify-content: space-between;
|
|
||||||
align-items: baseline;
|
|
||||||
gap: var(--space-3);
|
|
||||||
}
|
|
||||||
|
|
||||||
.members-strip {
|
|
||||||
list-style: none;
|
list-style: none;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
|
display: grid;
|
||||||
|
grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
|
||||||
|
gap: var(--space-4);
|
||||||
|
}
|
||||||
|
.council-card {
|
||||||
|
background: var(--surface-card);
|
||||||
|
border: 0.5px solid var(--surface-card-border);
|
||||||
|
border-radius: var(--radius-lg);
|
||||||
|
padding: var(--space-6) var(--space-6) var(--space-7);
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
|
||||||
gap: var(--space-3);
|
|
||||||
}
|
|
||||||
.member-pill {
|
|
||||||
display: inline-flex;
|
|
||||||
align-items: center;
|
align-items: center;
|
||||||
gap: var(--space-3);
|
gap: var(--space-5);
|
||||||
padding: var(--space-2) var(--space-4) var(--space-2) var(--space-2);
|
|
||||||
background: var(--surface);
|
|
||||||
border-radius: var(--radius-full);
|
|
||||||
}
|
}
|
||||||
.member-pill-text { display: inline-flex; flex-direction: column; line-height: 1.2; min-width: 0; }
|
.council-card-text {
|
||||||
.member-pill-name { font-size: var(--text-body-sm); color: var(--on-surface); }
|
display: flex;
|
||||||
.member-pill-title {
|
flex-direction: column;
|
||||||
color: var(--on-surface-muted);
|
gap: 4px;
|
||||||
|
min-width: 0;
|
||||||
|
}
|
||||||
|
.council-card-name {
|
||||||
|
font-family: var(--font-serif);
|
||||||
|
font-weight: 400;
|
||||||
|
font-size: 1.125rem;
|
||||||
|
line-height: 1.2;
|
||||||
|
color: var(--on-surface);
|
||||||
|
}
|
||||||
|
.council-card-title {
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
font-size: var(--text-body-sm);
|
||||||
|
color: var(--on-surface-variant);
|
||||||
|
}
|
||||||
|
.council-card-org {
|
||||||
|
font-family: var(--font-sans);
|
||||||
|
font-size: var(--text-label-sm);
|
||||||
letter-spacing: var(--tracking-wide);
|
letter-spacing: var(--tracking-wide);
|
||||||
text-transform: uppercase;
|
color: var(--on-surface-muted);
|
||||||
white-space: nowrap;
|
|
||||||
overflow: hidden;
|
|
||||||
text-overflow: ellipsis;
|
|
||||||
max-width: 14rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ── Responsive: hero column collapse ─────────────────────────── */
|
/* ── Responsive ───────────────────────────────────────────────── */
|
||||||
@media (max-width: 720px) {
|
@media (max-width: 880px) {
|
||||||
.events-hero-body { grid-template-columns: 1fr; }
|
.roadmap-grid { grid-template-columns: 1fr; }
|
||||||
.events-hero-body::after { display: none; }
|
.hero-body { grid-template-columns: 1fr; }
|
||||||
.events-list-row { grid-template-columns: 50px 1fr; }
|
.hero-body::after { display: none; }
|
||||||
.events-list-action-form,
|
.hero-detail { padding-left: 0; }
|
||||||
.events-list-row > a { grid-column: 1 / -1; justify-self: start; padding-top: var(--space-2); }
|
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue