feat(pulse): 'also coming up' strip + editorial row (dispatch + pulse)

Below the indigo hero, two new sections replace the previous fenja-section
two-box layout.

ALSO-COMING-UP STRIP — plain text on cream, not a card. Flex
justify-between, 4px vertical padding. Up to 2 upcoming events on the
left, each rendered as a 22px serif day number beside a stacked
column: 9px tracked 'MONTH · KIND' label on top, 13px event title on
bottom. A 1px × 28px vertical divider in rgba(0,0,0,0.08) between the
two items. Right side carries the lone 'All gatherings →' link in 11px
terracotta tracked uppercase.

EDITORIAL ROW — 1.7fr / 1fr grid with a 56px column gap. Asymmetric
on purpose; the dispatch column carries the weight.

Dispatch column (left, wider, no card chrome):
  - Byline row: 26px deterministic-pigment avatar + 12px author first
    name + 11px relative time + kind pill (9px tracked, 2/8 padding,
    3px radius, pigment-tinted background, margin-left: auto).
  - 32px serif headline, line-height 1.15.
  - 14px lead paragraph, line-height 1.7 (via dispatchLongPreview).
  - 'Read the full dispatch' link — 11px terracotta tracked uppercase
    with a hard 1px terracotta underline (not the global .section-link
    italic treatment — this one's a button-ish affordance).
  - Margin-top 48px, padding-top 28px, 0.5px on-surface-border line,
    then the EARLIER list. Rows are 15px serif title left, 10px tracked
    '{KIND} · {N}D' right. Day count is rounded UTC delta.

Pulse column (right, narrower, no card chrome):
  - 10px tracked 'this week's pulse' eyebrow with a 5px terracotta dot
    prefix. The only return of an eyebrow on /pulse.
  - 22px serif question.
  - 11px tracked status line: 'CLOSES {DAY} · {N} OF {TOTAL} VOTED'.
  - Options stack with 6px gap. Each option has no top/right/bottom
    border, only a 2px left border. Default left-border is rgba(0,0,0,
    0.1); selected option flips to terracotta and gains a 5% terracotta
    background tint. Letter prefix (A/B/C/D) is tracked, 10px, muted
    by default and terracotta when chosen.
  - Vote action POST handler unchanged — same /pulse?action=vote path
    introduced in v2.

If the featured dispatch has no attached poll, the right column
doesn't render and the dispatch column takes the full row (the spec's
single-column collapse case).

Stale CSS for the old events-card / hero-* / coming-up-* / fenja-* /
fenja-poll-* class names all deleted in the same pass.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jonathan Hvid 2026-05-12 10:53:39 +02:00
parent 29fe1b7c92
commit 4219cda7b6

View file

@ -152,42 +152,75 @@ const members = getAllCabMembers();
/> />
</section> </section>
<!-- 'Also coming up' strip lands in step 6 — temporarily empty --> <!-- ── 'Also coming up' strip (plain text on cream) ─────────── -->
<section class="cascade also-coming-up" aria-label="Also coming up">
<div class="also-list">
{comingUp.slice(0, 2).map((ev, i) => (
<>
{i > 0 && <span class="also-divider" aria-hidden="true"></span>}
<div class="also-item">
<span class="also-day">{dayNum(ev.starts_at)}</span>
<div class="also-meta-col">
<span class="also-month-kind">{monthShort(ev.starts_at)} · {eventKindLabel(ev.kind).toUpperCase()}</span>
<span class="also-title">{ev.title}</span>
</div>
</div>
</>
))}
</div>
<a href="/events" class="also-link">All gatherings →</a>
</section>
<!-- ── Editorial row: dispatch (1.7fr) + pulse (1fr) ─────────── -->
<!-- ── Latest from Fenja: 2-box article + poll, plus 2 below ── -->
{featured && ( {featured && (
<section class="cascade fenja-section" aria-label="Latest from Fenja"> <section class="cascade editorial-row" aria-label="Latest from Fenja">
<div class:list={['fenja-row', { 'fenja-row--with-poll': !!featured.poll }]}>
<article class="fenja-article-box"> <article class="dispatch-col">
<header class="fenja-byline"> <header class="dispatch-byline">
<Avatar id={featured.author_id} name={featured.author_name} size={28} /> <Avatar id={featured.author_id} name={featured.author_name} size={26} />
<span class="fenja-byline-name">{featured.author_name}</span> <span class="dispatch-byline-name">{featured.author_name.split(' ')[0]}</span>
{featured.author_title && <span class="fenja-byline-title">· {featured.author_title}</span>} <span class="dispatch-byline-time">{relativeTime(featured.published_at ?? featured.created_at)}</span>
<span class="fenja-byline-time">{relativeTime(featured.published_at ?? featured.created_at)}</span> <span class="dispatch-kind-pill" style={`--pill: ${dispatchKindPigment(featured.kind)}`}>
<span class="fenja-kind-pill" style={`--pill: ${dispatchKindPigment(featured.kind)}`}> {dispatchKindLabel(featured.kind).toUpperCase()}
{dispatchKindLabel(featured.kind)}
</span> </span>
</header> </header>
<h2 class="fenja-title">{featured.title}</h2> <h2 class="dispatch-headline">{featured.title}</h2>
<p class="fenja-body">{featuredPreview}</p>
<a href={`/dispatches/${dispatchSlug(featured)}`} class="section-link fenja-read">Read the full dispatch</a> <p class="dispatch-para-lead">{featuredPreview}</p>
<a href={`/dispatches/${dispatchSlug(featured)}`} class="dispatch-read">Read the full dispatch</a>
{moreDispatches.length > 0 && (
<div class="earlier-block">
<p class="earlier-label">Earlier</p>
<ul class="earlier-list">
{moreDispatches.map(d => (
<li class="earlier-row">
<a href={`/dispatches/${dispatchSlug(d)}`} class="earlier-link">
<span class="earlier-title">{d.title}</span>
<span class="earlier-meta">{dispatchKindLabel(d.kind).toUpperCase()} · {Math.max(1, Math.round((Date.now() - new Date((d.published_at ?? d.created_at).replace(' ', 'T') + 'Z').getTime()) / 86400000))}D</span>
</a>
</li>
))}
</ul>
</div>
)}
</article> </article>
{featured.poll && ( {featured.poll && (
<aside class="fenja-poll-box" aria-label="Attached poll"> <aside class="pulse-col" aria-label="This week's pulse">
<p class="fenja-poll-question">{featured.poll.question}</p> <p class="pulse-eyebrow"><span class="pulse-eyebrow-dot" aria-hidden="true"></span>This week's pulse</p>
<p class="pulse-question">{featured.poll.question}</p>
<p class="pulse-status">
Closes {closeDayLabel(featured.poll.closes_at).toUpperCase()} · {featured.poll.votes_total} of {members.length} voted
</p>
<form method="POST" class="fenja-poll-options" novalidate> <form method="POST" class="pulse-options" novalidate>
<input type="hidden" name="action" value="vote" /> <input type="hidden" name="action" value="vote" />
<input type="hidden" name="pulse_id" value={featured.poll.id} /> <input type="hidden" name="pulse_id" value={featured.poll.id} />
{featured.poll.options.map((opt, i) => { {featured.poll.options.map((opt, i) => {
const chosen = featured.poll!.my_vote === i; const chosen = featured.poll!.my_vote === i;
const count = featured.poll!.votes_by_option[i] ?? 0;
const pct = featured.poll!.votes_total > 0 ? (count / featured.poll!.votes_total) * 100 : 0;
const locked = featured.poll!.my_vote !== null || featured.poll!.status !== 'open'; const locked = featured.poll!.my_vote !== null || featured.poll!.status !== 'open';
const letter = String.fromCharCode(65 + i); const letter = String.fromCharCode(65 + i);
return ( return (
@ -195,46 +228,18 @@ const members = getAllCabMembers();
type="submit" type="submit"
name="option_index" name="option_index"
value={i} value={i}
class:list={['fenja-poll-option', { chosen, locked }]} class:list={['pulse-option', { chosen, locked }]}
disabled={locked && !chosen} disabled={locked && !chosen}
aria-pressed={chosen} aria-pressed={chosen}
> >
<span class="fenja-poll-letter">{letter}</span> <span class="pulse-option-letter">{letter}</span>
<span class="fenja-poll-text">{opt}</span> <span class="pulse-option-text">{opt}</span>
{locked && (
<span class="fenja-poll-bar" aria-hidden="true">
<span class="fenja-poll-bar-fill" style={`width:${pct.toFixed(1)}%`}></span>
</span>
)}
</button> </button>
); );
})} })}
</form> </form>
<p class="fenja-poll-count">
{featured.poll.votes_total} of {members.length} have weighed in
{featured.poll.status === 'open'
? ` · closes ${closeDayLabel(featured.poll.closes_at)}`
: ' · closed'}
</p>
</aside> </aside>
)} )}
</div>
{moreDispatches.length > 0 && (
<ul class="fenja-more">
{moreDispatches.map(d => (
<li class="fenja-more-row">
<a href={`/dispatches/${dispatchSlug(d)}`} class="fenja-more-link">
<span class="fenja-more-title">{d.title}</span>
<span class="fenja-more-meta">{dispatchKindLabel(d.kind)} · {relativeTime(d.published_at ?? d.created_at)}</span>
</a>
</li>
))}
</ul>
)}
<a href="/dispatches" class="section-link fenja-all">All updates from Fenja</a>
</section> </section>
)} )}
@ -372,376 +377,264 @@ const members = getAllCabMembers();
.greeting-right { align-items: flex-start; } .greeting-right { align-items: flex-start; }
} }
/* ── Events card (--ink) — more air, prominent hero ───────────── */ /* ── 'Also coming up' strip (plain text on cream) ─────────────── */
.events-card { .also-coming-up {
background: var(--ink);
color: var(--ink-text);
border-radius: var(--radius-lg);
padding: var(--space-10) var(--space-10);
display: flex;
flex-direction: column;
gap: var(--space-7);
}
.events-card--empty {
align-items: flex-start;
text-align: left;
min-height: 200px;
justify-content: space-between;
}
.events-empty-line {
color: var(--ink-text);
font-family: var(--font-serif);
font-size: 1.25rem;
margin: 0;
max-width: 32rem;
opacity: 0.92;
}
.hero-body {
display: grid;
grid-template-columns: 150px 1fr;
gap: var(--space-8);
align-items: center; /* vertically align date + detail */
padding: var(--space-3) 0;
position: relative;
}
.hero-body::after {
content: '';
position: absolute;
left: 150px;
top: 0; bottom: 0;
width: 0.5px;
background: rgba(232, 224, 208, 0.18);
}
.hero-date {
display: flex;
flex-direction: column;
gap: 6px;
padding-right: var(--space-4);
}
.hero-weekday, .hero-month {
font-family: var(--font-sans);
font-size: var(--text-label-sm);
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
color: rgba(232, 224, 208, 0.75);
}
.hero-day {
font-family: var(--font-serif);
font-weight: 400;
font-size: 3.5rem;
line-height: 1;
color: var(--ink-text);
margin: 2px 0;
}
.hero-detail { padding-left: var(--space-7); }
.hero-title {
font-family: var(--font-serif);
font-weight: 400;
font-size: 2rem;
line-height: 1.2;
color: var(--ink-text);
margin: 0 0 var(--space-4);
}
.hero-desc {
color: rgba(232, 224, 208, 0.92);
margin: 0 0 var(--space-4);
max-width: 50rem;
line-height: var(--leading-relaxed);
}
.hero-meta {
color: rgba(232, 224, 208, 0.7);
font-size: var(--text-body-sm);
margin: 0;
}
/* Hero foot */
.hero-foot {
border-top: 0.5px solid rgba(232, 224, 208, 0.18);
padding-top: var(--space-5);
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
gap: var(--space-4); padding: 4px 0;
flex-wrap: wrap; gap: var(--space-5);
} }
.hero-foot-left { display: flex; align-items: center; gap: var(--space-4); } .also-list {
.hero-foot-stat { display: flex;
color: rgba(232, 224, 208, 0.7); align-items: center;
gap: 18px;
min-width: 0;
}
.also-divider {
display: inline-block;
width: 1px;
height: 28px;
background: rgba(0, 0, 0, 0.08);
transform: scaleX(1);
}
.also-item {
display: flex;
align-items: center;
gap: 12px;
}
.also-day {
font-family: var(--font-serif);
font-weight: 400;
font-size: 22px;
line-height: 1;
color: var(--on-surface);
}
.also-meta-col {
display: flex;
flex-direction: column;
gap: 2px;
min-width: 0;
}
.also-month-kind {
font-family: var(--font-sans); font-family: var(--font-sans);
font-size: var(--text-label-sm); font-size: 9px;
letter-spacing: var(--tracking-wider); letter-spacing: var(--tracking-wider);
text-transform: uppercase; text-transform: uppercase;
color: var(--on-surface-variant);
} }
.hero-foot-right { display: flex; align-items: center; gap: var(--space-3); } .also-title {
.hero-cta { font-size: 13px;
background: var(--ink-text); color: var(--on-surface);
color: var(--ink); white-space: nowrap;
border: none; overflow: hidden;
padding: 10px 20px; text-overflow: ellipsis;
border-radius: 999px; max-width: 16rem;
font-family: var(--font-sans);
font-size: var(--text-label-md);
font-weight: 600;
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
cursor: pointer;
transition: opacity var(--duration-fast) var(--ease-standard);
} }
.hero-cta:hover { opacity: 0.85; } .also-link {
.hero-confirmed {
color: var(--ink-text);
font-family: var(--font-sans); font-family: var(--font-sans);
font-size: var(--text-label-md); font-size: 11px;
font-weight: 600; letter-spacing: var(--tracking-wider);
letter-spacing: var(--tracking-wide);
text-transform: uppercase; text-transform: uppercase;
padding: 10px 16px; color: var(--pigment-terracotta);
border: 0.5px solid rgba(232, 224, 208, 0.4); text-decoration: none;
border-radius: 999px; border-bottom: none;
} }
.hero-change { .also-link:hover { opacity: 0.8; border-bottom: none; }
background: transparent;
border: none; /* ── Editorial row: dispatch (1.7fr) + pulse (1fr) ────────────── */
color: rgba(232, 224, 208, 0.75); .editorial-row {
font-family: var(--font-sans); display: grid;
font-size: var(--text-label-sm); grid-template-columns: 1.7fr 1fr;
letter-spacing: var(--tracking-wide); gap: 56px;
text-transform: uppercase; align-items: start;
cursor: pointer;
text-decoration: underline;
} }
/* Bundled coming-up sub-cards (no RSVP) */ /* Dispatch column */
.coming-up-grid { .dispatch-col { display: flex; flex-direction: column; gap: var(--space-3); }
.dispatch-byline {
display: flex;
align-items: center;
gap: 10px;
}
.dispatch-byline-name {
font-family: var(--font-sans);
font-size: 12px;
font-weight: 600;
color: var(--on-surface);
}
.dispatch-byline-time {
font-family: var(--font-sans);
font-size: 11px;
color: var(--on-surface-variant);
}
.dispatch-kind-pill {
background: color-mix(in oklab, var(--pill) 14%, transparent);
color: var(--pill);
padding: 2px 8px;
border-radius: 3px;
font-family: var(--font-sans);
font-size: 9px;
letter-spacing: var(--tracking-wider);
font-weight: 600;
margin-left: auto;
}
.dispatch-headline {
font-family: var(--font-serif);
font-weight: 400;
font-size: 32px;
line-height: 1.15;
color: var(--on-surface);
margin: 8px 0 0;
letter-spacing: var(--tracking-snug);
}
.dispatch-para-lead {
margin: var(--space-2) 0 0;
font-size: 14px;
line-height: 1.7;
color: var(--on-surface);
}
.dispatch-read {
margin-top: var(--space-2);
align-self: flex-start;
font-family: var(--font-sans);
font-size: 11px;
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
color: var(--pigment-terracotta);
text-decoration: none;
border-bottom: 1px solid var(--pigment-terracotta);
padding-bottom: 1px;
}
.dispatch-read:hover { opacity: 0.78; border-bottom: 1px solid var(--pigment-terracotta); }
.earlier-block {
margin-top: 48px;
padding-top: 28px;
border-top: 0.5px solid rgba(0, 0, 0, 0.08);
display: flex;
flex-direction: column;
gap: 14px;
}
.earlier-label {
font-family: var(--font-sans);
font-size: 11px;
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
color: var(--on-surface-variant);
margin: 0;
}
.earlier-list {
list-style: none; list-style: none;
padding: 0; padding: 0;
margin: 0; margin: 0;
display: grid;
grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
gap: var(--space-3);
}
.coming-up-card {
background: rgba(232, 224, 208, 0.06);
border: 0.5px solid rgba(232, 224, 208, 0.14);
border-radius: var(--radius-md);
padding: var(--space-5);
display: flex; display: flex;
gap: var(--space-4); flex-direction: column;
align-items: flex-start; gap: 14px;
} }
.cu-date { display: flex; flex-direction: column; gap: 2px; min-width: 36px; } .earlier-link {
.cu-day { display: flex;
justify-content: space-between;
align-items: baseline;
gap: 16px;
color: var(--on-surface);
text-decoration: none;
border-bottom: none;
}
.earlier-link:hover { border-bottom: none; opacity: 0.7; }
.earlier-title {
font-family: var(--font-serif); font-family: var(--font-serif);
font-size: 1.5rem; font-size: 15px;
line-height: 1; line-height: 1.3;
color: var(--ink-text);
} }
.cu-month { .earlier-meta {
font-family: var(--font-sans); font-family: var(--font-sans);
font-size: var(--text-label-sm); font-size: 10px;
letter-spacing: var(--tracking-wider); letter-spacing: var(--tracking-wider);
text-transform: uppercase; text-transform: uppercase;
color: rgba(232, 224, 208, 0.7); color: var(--on-surface-variant);
} white-space: nowrap;
.cu-body { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.cu-title {
font-family: var(--font-serif);
font-weight: 400;
font-size: 1rem;
line-height: 1.25;
color: var(--ink-text);
margin: 0;
}
.cu-meta {
font-size: 0.75rem;
color: rgba(232, 224, 208, 0.65);
margin: 0;
} }
.hero-see-all { align-self: flex-start; color: var(--ink-text); } /* Pulse column */
.section-link--ink { text-decoration-color: rgba(232, 224, 208, 0.5); } .pulse-col { display: flex; flex-direction: column; gap: 14px; }
.pulse-eyebrow {
/* ── Latest from Fenja: two boxes + 2 minimalist rows below ──── */
.fenja-section {
display: flex;
flex-direction: column;
gap: var(--space-6);
}
.fenja-row {
display: grid;
grid-template-columns: 1fr;
gap: var(--space-5);
}
.fenja-row--with-poll {
grid-template-columns: 1.6fr 1fr;
}
.fenja-article-box,
.fenja-poll-box {
background: var(--surface-card);
border: 0.5px solid var(--surface-card-border);
border-radius: var(--radius-lg);
padding: var(--space-7) var(--space-8);
display: flex;
flex-direction: column;
gap: var(--space-4);
}
.fenja-byline {
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--space-2); gap: 8px;
flex-wrap: wrap;
font-size: var(--text-body-sm);
}
.fenja-byline-name { font-weight: 600; color: var(--on-surface); }
.fenja-byline-title { color: var(--on-surface-variant); }
.fenja-byline-time {
color: var(--on-surface-muted);
font-size: var(--text-label-sm);
letter-spacing: var(--tracking-wide);
margin-left: auto;
}
.fenja-kind-pill {
background: color-mix(in oklab, var(--pill) 14%, transparent);
color: var(--pill);
padding: 2px 9px;
border-radius: 999px;
font-family: var(--font-sans); font-family: var(--font-sans);
font-size: var(--text-label-sm); font-size: 10px;
letter-spacing: var(--tracking-wide); letter-spacing: var(--tracking-wider);
font-weight: 600; text-transform: uppercase;
color: var(--pigment-terracotta);
margin: 0;
} }
.fenja-title { .pulse-eyebrow-dot {
width: 5px;
height: 5px;
border-radius: 50%;
background: var(--pigment-terracotta);
}
.pulse-question {
font-family: var(--font-serif); font-family: var(--font-serif);
font-weight: 400; font-weight: 400;
font-size: 1.75rem; font-size: 22px;
line-height: 1.25; line-height: 1.25;
color: var(--on-surface); color: var(--on-surface);
margin: 0; margin: 0;
letter-spacing: var(--tracking-snug);
} }
.fenja-body { .pulse-status {
color: var(--on-surface); font-family: var(--font-sans);
line-height: var(--leading-relaxed); font-size: 11px;
margin: 0; letter-spacing: var(--tracking-wider);
font-size: var(--text-body-lg); text-transform: uppercase;
} color: var(--on-surface-variant);
.fenja-read { margin-top: var(--space-2); align-self: flex-start; }
/* Poll box */
.fenja-poll-question {
font-family: var(--font-serif);
font-weight: 400;
font-size: 1.125rem;
line-height: 1.3;
color: var(--on-surface);
margin: 0; margin: 0;
} }
.fenja-poll-options { .pulse-options {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: var(--space-2); gap: 6px;
margin-top: 6px;
} }
.fenja-poll-option { .pulse-option {
position: relative;
display: flex; display: flex;
align-items: center; align-items: center;
gap: var(--space-3); gap: 8px;
padding: var(--space-3) var(--space-4); padding: 10px 14px;
background: var(--background); background: transparent;
border: 0.5px solid var(--surface-card-border); border: none;
border-radius: var(--radius-md); border-left: 2px solid rgba(0, 0, 0, 0.1);
font-family: var(--font-sans); font-family: var(--font-sans);
font-size: var(--text-body-sm); font-size: 13px;
color: var(--on-surface); color: var(--on-surface);
text-align: left; text-align: left;
cursor: pointer; cursor: pointer;
transition: border-color var(--duration-fast) var(--ease-standard), transition: border-color var(--duration-fast) var(--ease-standard),
background var(--duration-fast) var(--ease-standard); background var(--duration-fast) var(--ease-standard);
overflow: hidden;
} }
.fenja-poll-option:hover:not(.locked) { .pulse-option:hover:not(.locked) { border-left-color: rgba(0, 0, 0, 0.25); }
border-color: var(--outline); .pulse-option.chosen {
border-left-color: var(--pigment-terracotta);
background: rgba(185, 107, 88, 0.05);
} }
.fenja-poll-option.chosen { .pulse-option.locked:not(.chosen) {
border-color: var(--pigment-terracotta);
background: color-mix(in oklab, var(--pigment-terracotta) 6%, var(--surface-card));
}
.fenja-poll-option.locked:not(.chosen) {
cursor: default; cursor: default;
color: var(--on-surface-variant); color: var(--on-surface-variant);
} }
.fenja-poll-option:disabled { opacity: 0.85; } .pulse-option:disabled { opacity: 0.85; }
.fenja-poll-letter { .pulse-option-letter {
color: var(--on-surface-variant);
font-family: var(--font-sans);
font-size: 10px;
font-weight: 600; font-weight: 600;
color: var(--on-surface-muted); letter-spacing: var(--tracking-wider);
font-size: var(--text-label-sm); text-transform: uppercase;
margin-right: 8px;
flex-shrink: 0; flex-shrink: 0;
} }
.fenja-poll-option.chosen .fenja-poll-letter { color: var(--pigment-terracotta); } .pulse-option.chosen .pulse-option-letter { color: var(--pigment-terracotta); }
.fenja-poll-text { flex: 1; } .pulse-option-text { flex: 1; }
.fenja-poll-bar {
position: absolute;
left: 0; right: 0; bottom: 0;
height: 2px;
background: var(--surface-container);
}
.fenja-poll-bar-fill {
display: block;
height: 100%;
background: var(--pigment-terracotta);
opacity: 0.55;
transition: width 600ms var(--ease-standard);
}
.fenja-poll-count {
color: var(--on-surface-muted);
font-size: var(--text-label-sm);
letter-spacing: var(--tracking-wide);
margin: 0;
}
/* 2 minimalist rows below the article */
.fenja-more {
list-style: none;
padding: 0;
margin: 0;
display: flex;
flex-direction: column;
}
.fenja-more-row {
border-bottom: 0.5px solid var(--surface-card-border);
}
.fenja-more-row:last-child { border-bottom: none; }
.fenja-more-link {
display: flex;
justify-content: space-between;
align-items: baseline;
gap: var(--space-4);
padding: var(--space-3) 0;
color: var(--on-surface);
text-decoration: none;
border-bottom: none;
}
.fenja-more-link:hover {
border-bottom: none;
opacity: 0.75;
}
.fenja-more-title {
font-family: var(--font-serif);
font-size: var(--text-body-md);
color: var(--on-surface);
}
.fenja-more-meta {
color: var(--on-surface-muted);
font-size: var(--text-label-sm);
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
white-space: nowrap;
}
.fenja-all { align-self: flex-start; }
/* ── Roadmap horizontal cards ─────────────────────────────────── */ /* ── Roadmap horizontal cards ─────────────────────────────────── */
.roadmap-section { .roadmap-section {
@ -848,10 +741,7 @@ const members = getAllCabMembers();
/* ── Responsive ───────────────────────────────────────────────── */ /* ── Responsive ───────────────────────────────────────────────── */
@media (max-width: 880px) { @media (max-width: 880px) {
.roadmap-grid { grid-template-columns: 1fr; } .roadmap-grid { grid-template-columns: 1fr; }
.hero-body { grid-template-columns: 1fr; gap: var(--space-5); } .editorial-row { grid-template-columns: 1fr; gap: var(--space-8); }
.hero-body::after { display: none; } .also-coming-up { flex-direction: column; align-items: flex-start; gap: var(--space-3); }
.hero-detail { padding-left: 0; }
.fenja-row--with-poll { grid-template-columns: 1fr; }
.events-card { padding: var(--space-7) var(--space-6); }
} }
</style> </style>