Portfolio · card deep-dive · v7 · final · 2026-04-12

Unified sizing +
Geist vs Fraunces

Two last things from v6. (1) Sizing — the centred marks were matching each other in weight but not in footprint. Numeral 120px, icon 88px, monogram 72px meant the three marks occupied visibly different amounts of the strip, and the breathing room around each was inconsistent. v7 pins all three to a 120px reference size, so the bounding boxes are structurally identical and the breathing around the visible content reads the same for every type.

(2) Geist vs Fraunces — the weight decision in v6 settled the sizing problem but not the family question. v5's original move was to drop Fraunces because lucide couldn't visually match a transitional serif with a geometric sans icon library. v7 puts both families side by side at the new matched sizes, with lucide's stroke weight tuned to approximate each, so the trade-off is visible rather than argued.

§1 · unified sizing

All three marks at 120px reference

In v6 the numeral was 120px, the icon was 88px, and the monogram was 72px. The weights matched (Geist 400 + lucide 2) but the footprints didn't — visible cap-heights came out to roughly 84px for the numeral, 80px for the icon, and 52px for the monogram. The monogram especially looked cramped in the same frame.

v7 pins all three to a 120px reference: numeral 120px font-size, icon 120px × 120px, monogram 120px font-size. Because font cap-height is ~0.7 × em and lucide content fills ~0.67 × its viewBox, the visible content heights come out at ~84px, ~80px, and ~84px respectively — now within 5px of each other instead of a 30px spread. Visible breathing room (from top of strip content area to top of rendered mark) is now ~38–40px for all three.

v6 — Numeral 120px, Icon 88px, Monogram 72px. Different footprints, uneven breathing. The monogram especially feels small.
01
SELECTED WORK · 01

Planner App

v6 numeral: 120px. Anchor size.

  • v6
SELECTED WORK · 03

MOB analysis

v6 icon: 88px. Slightly smaller than numeral footprint.

  • v6
PLN
SELECTED WORK · 01

Planner App

v6 monogram: 72px. Clearly smaller; feels cramped.

  • v6
v7 — All three at 120px reference. Identical bounding boxes, identical visible breathing. Numeral and monogram grow to the same font-size; icon grows to a 120px × 120px box.
01
SELECTED WORK · 01

Planner App

v7 numeral: 120px Geist 400. Unchanged from v6.

  • v7
SELECTED WORK · 03

MOB analysis

v7 icon: 120px lucide stroke 2. Grown from 88px.

  • v7
PLN
SELECTED WORK · 01

Planner App

v7 monogram: 120px Geist 400. Grown from 72px; tighter tracking (-0.05em) keeps PLN compact.

  • v7
Why this works structurally. Font cap-height is a fixed fraction of em-size (~0.7 for Geist). Lucide icon content fills a fixed fraction of its viewBox (~0.67 for most icons). At the same reference size, both render at roughly the same visible extent. The difference between the two ratios is ~4%, which over a 120px reference is ~5px — small enough that the eye reads the three marks as sitting at the same scale. The v6 spread was 32px, which read as "three different sizes." v7 is 5px, which reads as "one size, three flavours."
§2 · typography family — Geist vs Fraunces

Both families at the matched 120px size

v5's argument for Geist was that lucide (geometric sans) couldn't visually match Fraunces (transitional serif) without swapping the icon library. That still applies. But at the matched sizes, and with lucide's stroke-width tuned per family, it's worth seeing the side-by-side before the family locks for good.

Row A — Geist 400 + lucide stroke 2. Numeral and monogram in Geist Regular; lucide at medium stroke. The family matches — sans text marks, sans icon strokes.
01
SELECTED WORK · 01

Planner App

Geist 400 numeral. Clean lining figures, tight tracking, tabular-nums locked.

  • Geist
SELECTED WORK · 03

MOB analysis

Lucide stroke 2 — matches Geist 400 glyph weight.

  • Geist
PLN
SELECTED WORK · 01

Planner App

Geist 400 monogram. Geometric caps, no serifs, flat terminals.

  • Geist
Row B — Fraunces 300 + lucide stroke 1.25. Numeral and monogram in Fraunces Light at display optical size; lucide stroke reduced to approximate Fraunces's thinner modulated strokes. This is as close as lucide can visually get to a transitional serif.
01
SELECTED WORK · 01

Planner App

Fraunces 300 numeral. Serif terminals, bracketed feet, editorial character.

  • Fraunces
SELECTED WORK · 03

MOB analysis

Lucide stroke 1.25 — thinner to approximate Fraunces's modulated strokes. Still geometric linework, still recognisably lucide.

  • Fraunces
PLN
SELECTED WORK · 01

Planner App

Fraunces 300 monogram. Bracketed serifs on the P and N; the serif-family DNA is unmistakable.

  • Fraunces
Row C — Writing register, Geist side. Same typography as Row A, violet register, to confirm the family holds on the writing side.
Row D — Writing register, Fraunces side. Same typography as Row B, violet register.
The trade-off, laid out. Geist wins on family coherence — numeral, monogram, and icon all read as drawn by the same hand. The icon's geometric linework matches the sans text marks' constant stroke weight. Nothing jars. The downside: Geist is a functional interface sans, and at 120px it reads as clean but impersonal. On a portfolio whose whole personality is "typography and system design," Geist as the hero mark says "UI, not editorial."
Fraunces wins on character — the 01 reads as a confident editorial mark, PLN reads as a typographic lockup, and the whole card feels like it came from a design portfolio rather than a dashboard. The cost is the icon. At stroke-width 1.25 lucide gets closer to Fraunces's thin stroke, but the icon's geometric rigidity still reads as a different family than the serif marks. On a card row where one card is an icon and the other two are Fraunces text marks, the icon will always be the odd one out. How often that matters depends on how many icon cards the portfolio ends up with — if icons are rare (one or two per grid at most), the cost is low; if they're frequent, the cost is high.
My read. If the portfolio uses icons as a common visual type (alongside screenshots and diagrams), go Geist — the family coherence matters more than the editorial character. If icons are reserved for rare cases and most cards use screenshots, diagrams, numerals, or monograms, go Fraunces — the editorial weight is a real quality signal on a typography-focused portfolio, and the rare icon card can wear the mismatch. Which one depends on how you expect to use the icon type. If you don't know yet, Geist is the safer default because it doesn't put a family-mismatch tax on any future icon usage.
§3 · featured treatment at v7 sizes

Confirm the featured system still works

Featured treatment is unchanged from v6 — gradient border (2px), "FEATURED" gradient kicker pill, gradient effect on the visual element. Below: one featured card per mark type at the new v7 sizes, Geist side. Confirming that the larger sizes don't break the featured treatment.

Same three, Fraunces side. Featured treatment applied to the serif typography variant. All gradient mechanisms (background-clip for text, SVG url for icon strokes) work identically.
§4 · decisions locked

Card spec freeze

Everything below is final once you pick the family. No other open items — border is 2px from v6, featured treatment is unchanged from v6, Q2 is unchanged from v5.

Locked

Sizing 120px reference for all centred marks

Numeral, icon, and monogram all use a 120px reference size. Numeral and monogram: font-size: 120px. Icon: width: 120px; height: 120px (up from 88px). Monogram tracking tightens to -0.05em to keep three-letter lockups compact at the new size. Shared shell from v4 still centres all three in the same frame; visible breathing around rendered content is now uniform within ~5px.

Family Geist vs Fraunces — pick one

Last open item on the card spec. Both are viable at the v7 matched sizes, and the trade-off is visible in §2. My recommendation is Geist unless icons are deliberately rare — but this is the one call I don't want to make for you. Both options include:

  • Geist option: Numeral + monogram in Geist 400, icon lucide stroke 2.
  • Fraunces option: Numeral + monogram in Fraunces 300 (optical-size auto), icon lucide stroke 1.25.

Featured Unchanged from v6

Every featured card gets three things together: 2px gradient border, "FEATURED" gradient kicker pill, and a gradient effect on the visual element adapted to type (overlay for screenshot/diagram, background-clip for numeral/monogram, SVG stroke reference for icon). Card prop: featured?: boolean. At most one per grid, enforced by review. The v5 gradient-mark strip type stays dropped — the gradient is an effect applied to the chosen visual type, never a visual type on its own.

Visual types Five final

Final visual-type pool: screenshot, diagram, numeral, icon, monogram. Card prop: kind: "screenshot" | "diagram" | "numeral" | "icon" | "monogram".

Q2 Screenshot helper variant API (unchanged from v5)

M5 (meta split) and M6 (detail zoom) live in the <Screenshot> helper as a variant prop. Default variant="detail" (M6); M5 is explicit opt-in. Hierarchy rule ("max one M5 per grid") lives in the style guide, enforced by review.

§5 · next

Pick a family, lock the spec, resume foundation work

Tell me Geist or Fraunces and the card component spec is frozen. Nothing else on the card side until chunk 4c.1 (page layout mockups), when the component gets built straight from this doc. The iteration trail (v1 → v7) stays preserved as the spine of a future design-system case study.

Next work on the critical path: chunk 4a.4 — synthesising voice research, diary audit, and imagery standards into .claude/rules/writing-style.md at the workspace root. Foundation work (4a.4 → 4a.5 → 4a.6) still gates chunk 4b.