style(pulse): drop date + tenure line, italic-noun section titles, more air, new active nav cue
Greeting (1, 2): the tracked date label above the greeting and the
milestone tenure line below it both come out. The greeting is now just
'Good morning, Jonathan.' alone on the left, with the MEMBER · NNN /
'Founding circle' stamp on the right. tenureMilestone helper + test stay
in place — they're still useful for future surfaces but no longer
rendered on /pulse.
Section titles (3): the noun in each section title gets serif italic +
a trailing period — 'On the <em>roadmap.</em>' and 'The <em>council.</em>'.
The two-word framing reads better visually than the previous flat
sans-serif title.
Spacing (6): bumped the major section transitions. Greeting → hero now
80px (was 56), also-coming-up → editorial 96px, editorial → roadmap
96px, roadmap → council 96px. The hero → also-coming-up gap stays at
the deliberate 18px because they're a pair, and the dispatch column's
internal margin-top 48px to its 'Earlier' list stays unchanged because
they belong to the same story.
Footer (7): 'Council manifesto' link removed from the footer for all
pages. The standalone /council-manifesto route stays in the codebase
(orphaned, not linked) so it isn't a 404 when someone has the URL.
Active nav link (8): the previous 4px terracotta dot below the active
link is gone. The active link now reads in a different typographic
register entirely:
- terracotta colour
- serif italic Newsreader (vs sans uppercase for inactive)
- sentence case (text-transform: none — the label appears as 'Pulse'
instead of 'PULSE')
- leading '· ' prefix dot for an additional 'you are here' marker
Four cues at once, no positioned overlay, no floating elements. The
typography shift alone tells you which page you're on.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
cde98f9454
commit
89688d605d
3 changed files with 32 additions and 49 deletions
|
|
@ -41,7 +41,7 @@ const hasArrows = items.length > 3;
|
|||
---
|
||||
<section class="roadmap-section" aria-label="On the roadmap">
|
||||
<header class="roadmap-header">
|
||||
<h2 class="roadmap-title">On the roadmap</h2>
|
||||
<h2 class="roadmap-title">On the <em>roadmap.</em></h2>
|
||||
<div class="roadmap-actions">
|
||||
<a href="/roadmap" class="roadmap-all">See the full roadmap →</a>
|
||||
{hasArrows && (
|
||||
|
|
@ -138,6 +138,7 @@ const hasArrows = items.length > 3;
|
|||
color: var(--on-surface);
|
||||
margin: 0;
|
||||
}
|
||||
.roadmap-title em { font-style: italic; }
|
||||
.roadmap-actions {
|
||||
display: flex;
|
||||
align-items: baseline;
|
||||
|
|
|
|||
|
|
@ -15,8 +15,7 @@ const navLinks = [
|
|||
];
|
||||
|
||||
const footerLinks = [
|
||||
{ href: '/vision', label: 'Vision' },
|
||||
{ href: '/council-manifesto', label: 'Council manifesto' },
|
||||
{ href: '/vision', label: 'Vision' },
|
||||
];
|
||||
|
||||
const currentPath = Astro.url.pathname;
|
||||
|
|
@ -190,20 +189,24 @@ const year = new Date().getFullYear();
|
|||
color: var(--on-surface);
|
||||
border-bottom: none;
|
||||
}
|
||||
/* Active nav link: terracotta color + a serif italic "·" bracket. The
|
||||
prefix dot acts as a 'you are here' marker without floating below
|
||||
the link the way the previous indicator did. Switching from sans
|
||||
uppercase to terracotta serif italic also doubles as a typography
|
||||
cue, so the active state reads even before colour processes. */
|
||||
.nav-link.active {
|
||||
color: var(--on-surface);
|
||||
color: var(--pigment-terracotta);
|
||||
font-family: var(--font-serif);
|
||||
font-style: italic;
|
||||
font-weight: 400;
|
||||
letter-spacing: var(--tracking-snug);
|
||||
text-transform: none;
|
||||
font-size: 15px;
|
||||
}
|
||||
/* 4px terracotta dot under the active link, 22px below its baseline. */
|
||||
.nav-link.active::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: 50%;
|
||||
bottom: -22px;
|
||||
width: 4px;
|
||||
height: 4px;
|
||||
border-radius: 50%;
|
||||
background: var(--pigment-terracotta);
|
||||
transform: translateX(-50%);
|
||||
.nav-link.active::before {
|
||||
content: '·';
|
||||
margin-right: 6px;
|
||||
color: var(--pigment-terracotta);
|
||||
}
|
||||
|
||||
/* ── User zone ──────────────────────────────────────────────────── */
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ import {
|
|||
getAllCabMembers, getPulseById, getUserVote, castVote,
|
||||
} from '../lib/db';
|
||||
import {
|
||||
timeOfDay, pulseDateLabel, daysSince, tenureMilestone, relativeTime,
|
||||
timeOfDay, relativeTime,
|
||||
eventKindLabel,
|
||||
dispatchSlug, dispatchKindLabel, dispatchKindPigment, dispatchLongPreview,
|
||||
} from '../lib/format';
|
||||
|
|
@ -54,12 +54,6 @@ if (Astro.request.method === 'POST') {
|
|||
// ── Greeting ───────────────────────────────────────────────────────
|
||||
const firstName = user.name.split(' ')[0];
|
||||
const greetingPrefix = `Good ${timeOfDay()}, `; // "Good morning, "
|
||||
const dateLabel = pulseDateLabel(); // "MONDAY, 11 MAY"
|
||||
|
||||
const tenureAnchor = user.role === 'cab' && user.cab_joined_date
|
||||
? user.cab_joined_date
|
||||
: user.created_at;
|
||||
const tenureCopy = tenureMilestone(daysSince(tenureAnchor));
|
||||
|
||||
const memberNumberLabel = user.member_number != null
|
||||
? `MEMBER · ${String(user.member_number).padStart(3, '0')}`
|
||||
|
|
@ -112,9 +106,7 @@ const members = getAllCabMembers();
|
|||
<!-- ── Greeting ─────────────────────────────────────────────── -->
|
||||
<section class="cascade greeting">
|
||||
<div class="greeting-left">
|
||||
<p class="greeting-date">{dateLabel}</p>
|
||||
<h1 class="greeting-line">{greetingPrefix}<em class="greeting-first">{firstName}</em>.</h1>
|
||||
<p class="greeting-tenure">{tenureCopy}</p>
|
||||
</div>
|
||||
{memberNumberLabel && (
|
||||
<div class="greeting-right">
|
||||
|
|
@ -236,7 +228,7 @@ const members = getAllCabMembers();
|
|||
{members.length > 0 && (
|
||||
<section class="cascade council-section" aria-label="The council">
|
||||
<header class="council-header">
|
||||
<h2 class="council-title">The council</h2>
|
||||
<h2 class="council-title">The <em>council.</em></h2>
|
||||
<a href="/members" class="council-all">See who our council is made up of →</a>
|
||||
</header>
|
||||
|
||||
|
|
@ -274,14 +266,16 @@ const members = getAllCabMembers();
|
|||
flex-direction: column;
|
||||
}
|
||||
|
||||
/* Per-section spacing table (no shared gap — each transition is tuned).
|
||||
Read top-down: greeting → hero → also → editorial → roadmap → council. */
|
||||
.greeting { margin-top: 48px; } /* below nav */
|
||||
.hero-slot { margin-top: 56px; } /* greeting → hero */
|
||||
.also-coming-up { margin-top: 18px; } /* hero → also (tight; related) */
|
||||
.editorial-row { margin-top: 72px; } /* also → editorial */
|
||||
.roadmap-wrap { margin-top: 72px; } /* editorial → roadmap */
|
||||
.council-section{ margin-top: 72px; } /* roadmap → council */
|
||||
/* Per-section spacing table. More air between sections than before
|
||||
(96px between editorial / roadmap / council); editorial-row internal
|
||||
dispatch → 'Earlier' gap stays tight at the original 48px because
|
||||
they're the same story. */
|
||||
.greeting { margin-top: 64px; } /* below nav */
|
||||
.hero-slot { margin-top: 80px; } /* greeting → hero */
|
||||
.also-coming-up { margin-top: 18px; } /* hero → also (tight; pair) */
|
||||
.editorial-row { margin-top: 96px; } /* also → editorial */
|
||||
.roadmap-wrap { margin-top: 96px; } /* editorial → roadmap */
|
||||
.council-section{ margin-top: 96px; } /* roadmap → council */
|
||||
|
||||
/* ── Cascade entry (first paint only) ─────────────────────────── */
|
||||
.cascade {
|
||||
|
|
@ -309,7 +303,6 @@ const members = getAllCabMembers();
|
|||
.greeting-left {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
max-width: 30rem;
|
||||
}
|
||||
.greeting-right {
|
||||
|
|
@ -318,14 +311,6 @@ const members = getAllCabMembers();
|
|||
align-items: flex-end;
|
||||
gap: 6px;
|
||||
}
|
||||
.greeting-date {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 11px;
|
||||
letter-spacing: var(--tracking-wider);
|
||||
text-transform: uppercase;
|
||||
color: var(--on-surface-variant);
|
||||
margin: 0;
|
||||
}
|
||||
.greeting-line {
|
||||
font-family: var(--font-serif);
|
||||
font-weight: 400;
|
||||
|
|
@ -336,13 +321,6 @@ const members = getAllCabMembers();
|
|||
margin: 0;
|
||||
}
|
||||
.greeting-first { font-style: italic; }
|
||||
.greeting-tenure {
|
||||
font-size: 13px;
|
||||
color: var(--on-surface-variant);
|
||||
margin: 0;
|
||||
max-width: 380px;
|
||||
line-height: var(--leading-relaxed);
|
||||
}
|
||||
.greeting-member {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 11px;
|
||||
|
|
@ -641,6 +619,7 @@ const members = getAllCabMembers();
|
|||
color: var(--on-surface);
|
||||
margin: 0;
|
||||
}
|
||||
.council-title em { font-style: italic; }
|
||||
.council-all {
|
||||
font-family: var(--font-sans);
|
||||
font-size: 11px;
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue