style: drop eyebrows + body italics across editorial pages

Applies the v3 rules globally: italics reserved for the Bifrost wordmark
and section-links; uppercase tracked eyebrows removed from page heads
and content sections.

Pages updated:
- /members: drops the 'MEMBERS' eyebrow + italic on h1 + italic on member
  name + italic on pull-quote.
- /events: drops the head eyebrow + 'Next up · Members only' /
  'Invitation by hand' hero eyebrows + 'Also coming up' / 'Past
  gatherings' sub-section eyebrows + italics on hero day, hero title,
  also-row titles, past-card titles. The past-gatherings header-row
  'View all →' link migrates to the bottom of the section as a
  section-link.
- /events/past: drops the eyebrow + italic h1; back-link uses
  .section-link.
- /dispatches/: drops the 'DISPATCHES' eyebrow + italic h1 + dispatch-row
  title italic + date column italic.
- /dispatches/[slug]: drops italic on the article title + h2/h3 inside
  rendered markdown + blockquote italic + adjacent prev/next title
  italic. Back-link migrates to .section-link.
- /roadmap: drops the 'ROADMAP' eyebrow and the .lead class on the
  subtitle.

Orphaned eyebrow class rules left in place; harmless and the next
visual pass can sweep them with the rest of the unused CSS.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Jonathan Hvid 2026-05-12 09:52:29 +02:00
parent 637055a73e
commit 66c3f6492f
7 changed files with 47 additions and 70 deletions

View file

@ -12,7 +12,39 @@
"Bash(node scripts/seed.js)", "Bash(node scripts/seed.js)",
"Bash(pnpm typecheck *)", "Bash(pnpm typecheck *)",
"Bash(pnpm build *)", "Bash(pnpm build *)",
"Bash(identify /home/jonathan/Documents/DEV/Project-Bifrost/public/innofounder-logo.png)" "Bash(identify /home/jonathan/Documents/DEV/Project-Bifrost/public/innofounder-logo.png)",
"Bash(pnpm dev *)",
"Bash(awk '{print $1}')",
"Bash(pnpm db:migrate *)",
"Bash(sqlite3 bifrost.db \".schema users\")",
"Bash(sqlite3 bifrost.db \".schema attendance\")",
"Bash(sqlite3 bifrost.db \"SELECT name FROM sqlite_master WHERE type='table' ORDER BY name;\")",
"Bash(sqlite3 bifrost.db \"SELECT id, name, slug FROM users;\")",
"Bash(node *)",
"Bash(pnpm db:seed:roadmap)",
"Bash(pnpm test *)",
"Bash(curl -sI http://localhost:4321/pulse -b \"bifrost_session=test\")",
"Bash(curl -sI http://localhost:4321/admin)",
"Bash(pnpm db:seed:demo *)",
"Bash(curl -s -c /tmp/jar.txt -b /tmp/jar.txt -d \"email=lars@rigspolitiet.dk&password=cab123\" http://localhost:4321/login -i)",
"Bash(curl -sI -b /tmp/jar.txt http://localhost:4321/)",
"Bash(curl -s -b /tmp/jar.txt http://localhost:4321/pulse)",
"Bash(curl -s -c /tmp/jonjar.txt -b /tmp/jonjar.txt -d \"email=jonathan@fenja.ai&password=fenja123\" http://localhost:4321/login -i)",
"Bash(curl -s -b /tmp/jonjar.txt \"http://localhost:4321/admin?tab=pulses\")",
"Bash(curl -s -b /tmp/jonjar.txt \"http://localhost:4321/admin?tab=roadmap\")",
"Bash(curl -s -b /tmp/jonjar.txt \"http://localhost:4321/admin?tab=events\")",
"Bash(curl -s -b /tmp/jonjar.txt \"http://localhost:4321/admin?tab=activity\")",
"Bash(awk NR>=107 && NR<=117 *)",
"Bash(awk 'NR==111' src/lib/format.ts)",
"Bash(curl -s -c /tmp/jar.txt -d \"email=lars@rigspolitiet.dk&password=cab123\" http://localhost:4321/login -o /dev/null -i)",
"Bash(curl -sI -b /tmp/jar.txt http://localhost:4321/pulse)",
"Bash(curl -s -b /tmp/jar.txt http://localhost:4321/members)",
"Bash(curl -s -b /tmp/jar.txt http://localhost:4321/events)",
"Bash(curl -s -b /tmp/jar.txt http://localhost:4321/dispatches)",
"Bash(curl -s -b /tmp/jar.txt http://localhost:4321/dispatches/1-we-are-deprioritising-public-cloud-parity-for-q3)",
"Bash(pnpm db:seed)",
"Bash(curl -s -c /tmp/jar.txt -d \"email=lars@virk2.dk&password=cab123\" http://localhost:4321/login -o /dev/null -i)",
"Bash(curl -s -c /tmp/jar.txt -d \"email=lars@virk2.dk&password=cab123\" http://localhost:4321/login -o /dev/null)"
] ]
} }
} }

View file

@ -38,7 +38,7 @@ const bodyHtml = renderMd(d.body);
<AppLayout title={d.title} user={user}> <AppLayout title={d.title} user={user}>
<article class="page"> <article class="page">
<a href="/dispatches" class="back-link label-sm">← All dispatches</a> <a href="/dispatches" class="section-link back-link">← All dispatches</a>
<header class="head"> <header class="head">
<div class="head-meta"> <div class="head-meta">
@ -50,7 +50,7 @@ const bodyHtml = renderMd(d.body);
</time> </time>
</div> </div>
<h1 class="title"><em>{d.title}</em></h1> <h1 class="title">{d.title}</h1>
<div class="byline"> <div class="byline">
<Avatar id={d.author_id} name={d.author_name} size={32} /> <Avatar id={d.author_id} name={d.author_name} size={32} />
@ -103,15 +103,7 @@ const bodyHtml = renderMd(d.body);
gap: var(--space-6); gap: var(--space-6);
} }
.back-link { .back-link { align-self: flex-start; }
color: var(--on-surface-muted);
text-decoration: none;
border-bottom: none;
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
align-self: flex-start;
}
.back-link:hover { color: var(--on-surface-variant); border-bottom: none; }
.head { display: flex; flex-direction: column; gap: var(--space-4); } .head { display: flex; flex-direction: column; gap: var(--space-4); }
@ -145,7 +137,6 @@ const bodyHtml = renderMd(d.body);
color: var(--on-surface); color: var(--on-surface);
margin: 0; margin: 0;
} }
.title em { font-style: italic; }
.byline { .byline {
display: flex; display: flex;
@ -168,7 +159,6 @@ const bodyHtml = renderMd(d.body);
.body :global(p) { margin: 0 0 var(--space-4); } .body :global(p) { margin: 0 0 var(--space-4); }
.body :global(h2) { .body :global(h2) {
font-family: var(--font-serif); font-family: var(--font-serif);
font-style: italic;
font-weight: 400; font-weight: 400;
font-size: 1.5rem; font-size: 1.5rem;
margin: var(--space-6) 0 var(--space-3); margin: var(--space-6) 0 var(--space-3);
@ -183,7 +173,6 @@ const bodyHtml = renderMd(d.body);
border-left: 2px solid color-mix(in oklab, var(--pigment-terracotta) 40%, transparent); border-left: 2px solid color-mix(in oklab, var(--pigment-terracotta) 40%, transparent);
padding-left: var(--space-4); padding-left: var(--space-4);
color: var(--on-surface-variant); color: var(--on-surface-variant);
font-style: italic;
margin: var(--space-5) 0; margin: var(--space-5) 0;
} }
.body :global(code) { .body :global(code) {
@ -245,7 +234,6 @@ const bodyHtml = renderMd(d.body);
.adj-next .adj-kind-pill { align-self: flex-end; } .adj-next .adj-kind-pill { align-self: flex-end; }
.adj-title { .adj-title {
font-family: var(--font-serif); font-family: var(--font-serif);
font-style: italic;
color: var(--on-surface); color: var(--on-surface);
} }
.adj-empty {} /* placeholder for missing prev/next slot */ .adj-empty {} /* placeholder for missing prev/next slot */

View file

@ -24,8 +24,7 @@ function fmt(iso: string): string {
<div class="page"> <div class="page">
<header class="head"> <header class="head">
<p class="label-sm head-eyebrow">Dispatches</p> <h1 class="head-title">Notes from the studio.</h1>
<h1 class="head-title"><em>Notes from the studio.</em></h1>
<p class="head-sub">Decisions, half-built ideas, and things we've changed our mind about.</p> <p class="head-sub">Decisions, half-built ideas, and things we've changed our mind about.</p>
</header> </header>
@ -92,7 +91,6 @@ function fmt(iso: string): string {
color: var(--on-surface); color: var(--on-surface);
margin: 0; margin: 0;
} }
.head-title em { font-style: italic; }
.head-sub { color: var(--on-surface-variant); margin-top: var(--space-3); max-width: 32rem; } .head-sub { color: var(--on-surface-variant); margin-top: var(--space-3); max-width: 32rem; }
.empty { color: var(--on-surface-muted); } .empty { color: var(--on-surface-muted); }
@ -141,7 +139,6 @@ function fmt(iso: string): string {
} }
.d-title { .d-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.25rem;
line-height: 1.3; line-height: 1.3;

View file

@ -55,19 +55,13 @@ const heroAudience = hero?.audience ?? 'Members only';
<div class="page"> <div class="page">
<header class="head"> <header class="head">
<p class="label-sm head-eyebrow">Events</p> <h1 class="head-title">Where the council gathers.</h1>
<h1 class="head-title"><em>Where the council gathers.</em></h1>
<p class="head-sub">Dinners, working sessions, the occasional summit. Always small, always off the record.</p> <p class="head-sub">Dinners, working sessions, the occasional summit. Always small, always off the record.</p>
</header> </header>
<!-- ── Hero invitation ─────────────────────────────────────── --> <!-- ── Hero invitation ─────────────────────────────────────── -->
{hero ? ( {hero ? (
<article class="hero" aria-label={`Next up: ${hero.title}`}> <article class="hero" aria-label={`Next up: ${hero.title}`}>
<header class="hero-top">
<span class="hero-eyebrow">Next up · {heroAudience}</span>
<span class="hero-eyebrow">Invitation by hand</span>
</header>
<div class="hero-body"> <div class="hero-body">
<div class="hero-date"> <div class="hero-date">
<span class="hero-weekday">{weekday(hero.starts_at)}</span> <span class="hero-weekday">{weekday(hero.starts_at)}</span>
@ -109,7 +103,7 @@ const heroAudience = hero?.audience ?? 'Members only';
) : ( ) : (
<article class="hero hero--empty"> <article class="hero hero--empty">
<p class="hero-empty-line"> <p class="hero-empty-line">
<em>Nothing scheduled yet — when we have something, you'll be the first to know.</em> Nothing scheduled yet — when we have something, you'll be the first to know.
</p> </p>
</article> </article>
)} )}
@ -117,7 +111,6 @@ const heroAudience = hero?.audience ?? 'Members only';
<!-- ── Also coming up ──────────────────────────────────────── --> <!-- ── Also coming up ──────────────────────────────────────── -->
{alsoUpcoming.length > 0 && ( {alsoUpcoming.length > 0 && (
<section class="also"> <section class="also">
<p class="label-sm section-eyebrow">Also coming up</p>
<ul class="also-list"> <ul class="also-list">
{alsoUpcoming.map(ev => ( {alsoUpcoming.map(ev => (
<li class="also-row"> <li class="also-row">
@ -148,10 +141,6 @@ const heroAudience = hero?.audience ?? 'Members only';
<!-- ── Past gatherings ─────────────────────────────────────── --> <!-- ── Past gatherings ─────────────────────────────────────── -->
{past.length > 0 && ( {past.length > 0 && (
<section class="past"> <section class="past">
<header class="past-head">
<p class="label-sm section-eyebrow">Past gatherings</p>
<a href="/events/past" class="past-all">View all →</a>
</header>
<ul class="past-grid"> <ul class="past-grid">
{past.map(ev => { {past.map(ev => {
const monthCode = monthShort(ev.starts_at); const monthCode = monthShort(ev.starts_at);
@ -187,6 +176,7 @@ const heroAudience = hero?.audience ?? 'Members only';
); );
})} })}
</ul> </ul>
<a href="/events/past" class="section-link">View all past gatherings →</a>
</section> </section>
)} )}
@ -220,7 +210,7 @@ const heroAudience = hero?.audience ?? 'Members only';
color: var(--on-surface); color: var(--on-surface);
margin: 0; margin: 0;
} }
.head-title em { font-style: italic; }
.head-sub { .head-sub {
color: var(--on-surface-variant); color: var(--on-surface-variant);
margin-top: var(--space-3); margin-top: var(--space-3);
@ -278,7 +268,6 @@ const heroAudience = hero?.audience ?? 'Members only';
} }
.hero-day { .hero-day {
font-family: var(--font-serif); font-family: var(--font-serif);
font-style: italic;
font-size: 2.75rem; font-size: 2.75rem;
line-height: 1; line-height: 1;
color: var(--ink-text); color: var(--ink-text);
@ -287,7 +276,6 @@ const heroAudience = hero?.audience ?? 'Members only';
.hero-detail { padding-left: var(--space-5); } .hero-detail { padding-left: var(--space-5); }
.hero-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;
@ -377,7 +365,6 @@ const heroAudience = hero?.audience ?? 'Members only';
margin: auto; margin: auto;
max-width: 32rem; max-width: 32rem;
} }
.hero-empty-line em { font-style: italic; }
/* ── Section eyebrow shared ──────────────────────────────────── */ /* ── Section eyebrow shared ──────────────────────────────────── */
.section-eyebrow { .section-eyebrow {
@ -406,7 +393,6 @@ const heroAudience = hero?.audience ?? 'Members only';
} }
.also-day { .also-day {
font-family: var(--font-serif); font-family: var(--font-serif);
font-style: italic;
font-size: 1.5rem; font-size: 1.5rem;
line-height: 1; line-height: 1;
color: var(--on-surface); color: var(--on-surface);
@ -423,7 +409,6 @@ const heroAudience = hero?.audience ?? 'Members only';
.also-body { display: flex; flex-direction: column; gap: 4px; } .also-body { display: flex; flex-direction: column; gap: 4px; }
.also-title { .also-title {
font-family: var(--font-serif); font-family: var(--font-serif);
font-style: italic;
font-weight: 400; font-weight: 400;
font-size: 1.0625rem; font-size: 1.0625rem;
color: var(--on-surface); color: var(--on-surface);
@ -506,7 +491,6 @@ const heroAudience = hero?.audience ?? 'Members only';
.past-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; } .past-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.past-title { .past-title {
font-family: var(--font-serif); font-family: var(--font-serif);
font-style: italic;
font-weight: 400; font-weight: 400;
font-size: 1.0625rem; font-size: 1.0625rem;
color: var(--on-surface); color: var(--on-surface);

View file

@ -18,10 +18,9 @@ function fmt(part: Intl.DateTimeFormatOptions, iso: string): string {
<div class="page"> <div class="page">
<header class="head"> <header class="head">
<p class="label-sm head-eyebrow">Past gatherings</p> <h1 class="head-title">The archive.</h1>
<h1 class="head-title"><em>The archive.</em></h1>
<p class="head-sub">Everything the council has gathered around so far.</p> <p class="head-sub">Everything the council has gathered around so far.</p>
<a href="/events" class="back-link label-sm">← Back to upcoming</a> <a href="/events" class="section-link back-link">← Back to upcoming</a>
</header> </header>
{past.length === 0 ? ( {past.length === 0 ? (
@ -95,18 +94,8 @@ function fmt(part: Intl.DateTimeFormatOptions, iso: string): string {
color: var(--on-surface); color: var(--on-surface);
margin: 0; margin: 0;
} }
.head-title em { font-style: italic; }
.head-sub { color: var(--on-surface-variant); margin-top: var(--space-3); max-width: 32rem; } .head-sub { color: var(--on-surface-variant); margin-top: var(--space-3); max-width: 32rem; }
.back-link { .back-link { margin-top: var(--space-4); }
display: inline-block;
margin-top: var(--space-4);
color: var(--on-surface-muted);
text-decoration: none;
border-bottom: none;
letter-spacing: var(--tracking-wide);
text-transform: uppercase;
}
.back-link:hover { color: var(--on-surface-variant); border-bottom: none; }
.empty { color: var(--on-surface-muted); } .empty { color: var(--on-surface-muted); }
@ -152,7 +141,6 @@ function fmt(part: Intl.DateTimeFormatOptions, iso: string): string {
.past-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; } .past-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.past-title { .past-title {
font-family: var(--font-serif); font-family: var(--font-serif);
font-style: italic;
font-weight: 400; font-weight: 400;
font-size: 1.0625rem; font-size: 1.0625rem;
color: var(--on-surface); color: var(--on-surface);

View file

@ -19,8 +19,7 @@ function memberSinceLabel(member: { cab_joined_date: string | null; created_at:
<div class="page"> <div class="page">
<header class="members-head"> <header class="members-head">
<p class="label-sm members-eyebrow">Members</p> <h1 class="members-title">The council.</h1>
<h1 class="members-title"><em>The council.</em></h1>
<p class="members-sub"> <p class="members-sub">
An invited circle of operators shaping what Project Bifrost becomes. An invited circle of operators shaping what Project Bifrost becomes.
</p> </p>
@ -82,13 +81,6 @@ function memberSinceLabel(member: { cab_joined_date: string | null; created_at:
.members-head { margin-bottom: var(--space-6); max-width: 46rem; } .members-head { margin-bottom: var(--space-6); max-width: 46rem; }
.members-eyebrow {
letter-spacing: var(--tracking-wider);
text-transform: uppercase;
color: var(--on-surface-variant);
margin-bottom: var(--space-3);
}
.members-title { .members-title {
font-family: var(--font-serif); font-family: var(--font-serif);
font-weight: 400; font-weight: 400;
@ -98,7 +90,6 @@ function memberSinceLabel(member: { cab_joined_date: string | null; created_at:
color: var(--on-surface); color: var(--on-surface);
margin: 0; margin: 0;
} }
.members-title em { font-style: italic; }
.members-sub { .members-sub {
color: var(--on-surface-variant); color: var(--on-surface-variant);
@ -140,7 +131,6 @@ function memberSinceLabel(member: { cab_joined_date: string | null; created_at:
.m-name { .m-name {
font-family: var(--font-serif); font-family: var(--font-serif);
font-style: italic;
font-weight: 400; font-weight: 400;
font-size: 1.375rem; font-size: 1.375rem;
line-height: 1.2; line-height: 1.2;
@ -174,8 +164,7 @@ function memberSinceLabel(member: { cab_joined_date: string | null; created_at:
padding-left: 12px; padding-left: 12px;
border-left: 2px solid color-mix(in oklab, var(--row-pigment) 40%, transparent); border-left: 2px solid color-mix(in oklab, var(--row-pigment) 40%, transparent);
font-family: var(--font-serif); font-family: var(--font-serif);
font-style: italic; font-size: 0.9375rem;
font-size: 0.875rem;
line-height: 1.5; line-height: 1.5;
color: var(--on-surface); color: var(--on-surface);
max-width: 38rem; max-width: 38rem;

View file

@ -52,9 +52,8 @@ const horizonColors: Record<string, string> = {
<div class="page"> <div class="page">
<header class="page-header"> <header class="page-header">
<p class="label-sm eyebrow">Roadmap</p>
<h1 class="display-md page-title">What we are building.</h1> <h1 class="display-md page-title">What we are building.</h1>
<p class="lead subtitle"> <p class="subtitle">
Three horizons. What is in progress now, what comes next, Three horizons. What is in progress now, what comes next,
and what is further out. This is the live picture. and what is further out. This is the live picture.
</p> </p>