← Back to Index

Typography Font Mapping

Every type style the working Figma file declares, mapped onto the two licensed Futura PT files

ALPA Mobile · UI Refresh Epic AB#1821 · Updated: 2026-07-30 17:52 ET · Audited: 2026-07-30 11:57 ET

Primary source: live Figma file owEYzHf7FrHRvWC2u82UOl (ALPA mobile app) — typography read from Figma variable definitions via get_variable_defs, 2026-07-30. Every node id cited below was resolved against that file on that date. Font-file facts read directly from the shipped binaries' name and OS/2 tables. Render behaviour measured on the iOS simulator in the Blazor WebView.
Direction. The app ships two licensed font files only. No other family may be added, fetched, or substituted. Every type style the design declares must therefore resolve to one of those two faces. This document records the census and the mapping; it does not change any CSS.

1 · The provided font files

Read from the binaries themselves, not from filenames — the filename is not authoritative and had previously been recorded incorrectly.

FileFamily (name ID 1)Subfamily (name ID 2)usWeightClassPath
FuturaPT-Book.otfFutura PTBook400ALPAMobile.Presentation/wwwroot/fonts/
FuturaPT-Bold.otfFutura PTBold700ALPAMobile.Presentation/wwwroot/fonts/

Registered via @font-face in alpa-components.css (two rules, one per weight). The native side registers the .ttf equivalents in MauiProgram.cs as FuturaPTBook / FuturaPTBold.

2 · Census — what the design declares

The design system defines 8 type styles across 4 families. Family is itself tokenised for three roles; Body and Button carry their family as a literal inside the type style rather than as a token.

Type styleFamilyStyleWeightSizeLine heightLetter spacing
Display/MLora (token Font Family/Heading)SemiBold600 (token Font Weight/Heading)241.20
Display/SLora (token Font Family/Heading)SemiBold600201.20
Body/Body LFutura (literal)Medium500201.30
Body/Body MFutura (literal)Medium500181.20
Body/Body SFutura (literal)Medium500121.20
Other/EyebrowInter (token Font Family/Eyebrow)Bold700121.45 %
Other/CaptionInter (token Font Family/Caption)Regular400 (token Font Weight/Caption)141.50
Other/ButtonLeague Spartan (literal)Regular400151.04 %

Line heights are ratios and letter spacing is a percentage. Both reproduce the values observed in Figma Dev Mode exactly: 20 × 1.2 = 24, 18 × 1.2 = 21.6, 12 × 1.4 = 16.8; 5 % of 12px = 0.6px.

2.1 · Node provenance

Each type style below was read from the variable definitions attached to these component nodes in owEYzHf7FrHRvWC2u82UOl.

Node idComponentType styles / font variables observed
4033:1436card-lgFont Family/Heading=Lora · Font Weight/Heading=600 · Display/S · Font Family/Eyebrow=Inter · Other/Eyebrow · Body/Body M
4153:8817profileDisplay/M · Display/S · Body/Body L · Body/Body M · Other/Button (League Spartan)
4718:11125card-mdOther/Eyebrow · Display/S · Body/Body M
4864:31901card-notificationOther/Eyebrow · Display/S · Body/Body L
5172:15482listy card genericFont Family/Caption=Inter · Font Weight/Caption=400 · Other/Caption · Body/Body M
4047:4230horizontal scrolling feedDisplay/S · Body/Body M · Other/Eyebrow
4737:13038card-btnBody/Body M
5512:12925bannerBody/Body S
4245:5754button pillOther/Button
4361:8479tab groupOther/Button
4450:9884flight card-saved & recent searchesOther/Button
4537:14830progress bar & labelsBody/Body M

Queried and returned no typography variables (size tokens only, or colour/spacing only): 4128:7717 button-sm · 4128:7690 profile info block · 4555:7483 flight segment card · 4596:11818 section title · 4038:1037 navBar-bottom · 5251:15088 button link.

3 · The mapping decision

Figma declaresWeightMaps toRationale
Lora SemiBold — Display/M, Display/S600Futura PT Bold 700Nearest available above. Title emphasis is carried by weight once the serif is gone.
Futura Medium — Body L, Body M, Body S500Futura PT Book 400Nearest available below. Bold would overshoot a light emphasis.
Inter Bold — Other/Eyebrow700Futura PT Bold 700Exact weight match.
Inter Regular — Other/Caption400Futura PT Book 400Exact weight match.
League Spartan Regular — Other/Button400Futura PT Book 400Exact weight match.
Rule: requested weight ≤ 500 → Book 400 · ≥ 600 → Bold 700.
The rule is family-agnostic, so it also covers any family a future design revision introduces. Size, line height, letter spacing, casing and colour are unaffected — only family and weight collapse.

All values belong in alpa-components.css and must route through the family tokens (--font-heading-family, --font-body-family, --alpa-eyebrow). No inline style= attributes and no literal family stacks in component rules.

3.1 · Why the mapping is visually safe

Measured on device by rendering identical text at each weight in Futura PT and comparing rendered widths:

Requested weightRendered widthFace actually used
300 · 400 · 500516.960 pxBook 400
600 · 700 · 800 · 900579.400 pxBold 700

The browser already applies exactly this mapping through CSS font matching. Writing it into the stylesheet makes explicit what already happens at render time — it does not change how anything looks.

3.2 · Hierarchy check

Verified against the My MEC card, whose three roles exercise three different families.

RoleFigmaMappedRemains distinct by
EyebrowInter Bold 700 · 12px · uppercase · ls 0.6px · opacity 0.5Bold 700size, casing, letter-spacing, secondary colour
Card titleLora SemiBold 600 · 20 / 24Bold 70020px, primary colour
BodyFutura Medium 500 · 18 / 21.6Book 400weight contrast against the title

Serif/sans contrast is lost. The title-versus-body hierarchy survives, re-expressed as Bold-versus-Book. Title and eyebrow both land on Bold 700 but stay clearly separated by size, casing and colour.

4 · Where the code departs findings

4.1 · Non-provided families in use

FamilyWhereActually renders?
Inter — Google Fonts--alpa-eyebrow, consumed by 34 rulesYes — eyebrow text is currently drawn in a non-provided typeface
Georgia, serif — literal.alpa-radar-titleYes
"Futura LT Pro" — literal.alpa-profile-label, .alpa-profile-nav-row-labelNo — falls through to Futura PT
Lora — Google Fontsfetched; referenced by zero rulesNo — also fails to resolve (document.fonts.check = false)
Roboto — Google Fontsfetched; unreferencedNo
Network dependency. ALPAMobile/wwwroot/index.html:13,15 and home.html:17 fetch Lora, Inter and Roboto from fonts.googleapis.com at runtime. Typography therefore depends on connectivity, and the app makes third-party requests on launch. Futura PT is correctly self-hosted via @font-face.
League Spartan is declared by the design for every button but appears nowhere in the codebase — buttons render Futura PT today. Under the two-file direction that is the correct outcome; it is recorded here so the substitution reads as a decision rather than an oversight.

4.2 · Off-palette weight declarations — 109

Declarations asking for a weight with no corresponding file. Each already resolves to Book 400 or Bold 700 by the rule in §3.

Filefont-weight declarationsOff-palette
ALPAMobile.Presentation/wwwroot/css/alpa-components.css13371
ALPAMobile/wwwroot/css/ftdt.css4636
ALPAMobile/wwwroot/css/widget.css72
Total186109

The /dev/font-specimen demo ladder is excluded from these counts — it declares 300/500/600/800 deliberately, to demonstrate the gap.

4.3 · Cost of closing each gap

ChangeVisual impact
Normalise the 109 weight declarationsNone — proven by measurement (§3.1)
Drop the Lora + Roboto fetchesNone — unreferenced
Route the literal Futura LT Pro stacks through tokensNone — already falls back
Drop InterVisible — 34 eyebrow rules change typeface
.alpa-radar-title Georgia → tokenVisible — 1 rule

5 · Documentation staleness action needed

The captured spec set reads the wrong Figma file. docs/ui-refresh-1821/figma-component-specs.json records _resync.source.file = psH738AqHDxuMyFm897f9r, revision 2026-06-17. The working file is owEYzHf7FrHRvWC2u82UOl. Every typography claim derived from that capture is therefore unverified against current design.

25 docs carry family claims inherited from that capture — Lora ×51, Inter ×47, Futura LT Pro ×23, SF Pro ×2, Hind ×3 (counts exclude each document's own <style> block, so these are content assertions, not page styling). Highest-authority affected: design-tokens.html, design-questions.html, home-page-audit.html, the card-* and button-* specs, list-component.html, naming-decisions-record.html.

5.1 · Families to retire from the docs

The census found no Futura LT Pro and no SF Pro anywhere in the working file's typography. Both should be treated as obsolete in the documentation.

This retires an earlier concern: the docs' apparent "two Futura cuts in one design" is a stale-capture artifact, not a real design inconsistency. All three components the old capture attributed to Futura LT Pro — search bar, mobile nav, mobile hero — no longer resolve at their captured node ids.

5.2 · A family the docs have never recorded

League Spartan is absent from every document in /docs, yet it is the current, live font for every button in the design system (Other/Button, five components in §2.1). The documentation gap is real even though the mapping outcome is unchanged.

5.3 · Dead captured node ids — 7 of 39

Captured node idComponent
4055:6042search bar
4021:668mobile nav
4055:5564mobile hero
4038:221card-sm
5452:679flight card-og
4864:32242topNav
5452:434card-button
Read this precisely. A dead node id means the captured id no longer resolves — not necessarily that the component was deleted. flight card-og is the counter-example: captured id 5452:679 is invalid, yet a frame named flight card-og resolves at 4713:19868. Specs derived from the dead ids should be re-sourced before being relied on, not assumed removed.

5.4 · Typography scale in design-tokens.html

Resolved 2026-07-30. Design confirmed Body/Body M (18px) is the page default, settling which source is authoritative. design-tokens.html has been corrected: body L 16→20px, body M 14→18px, body line-height 1.6→1.2, button 12→15px, plus a missing --font-caption-size (14px). --font-title-lg-size (28px) remains unconfirmed — see the last row. Design also answered the paired scaling question (DQ-21): the app should honour the OS text-size setting, tracked on AB#2391.

design-tokens.html predated this census and its typography scale did not correspond to the current type-style set. The differences found are below.

design-tokens.htmlValueNearest census styleValueStatus
--font-eyebrow-size / -weight / -ls12px / 700 / 0.05emOther/Eyebrow12 / 700 / 5 %matches
--font-title-md-size20pxDisplay/S20matches
--font-body-sm-size12pxBody/Body S12matches
--font-body-md-size14pxBody/Body M18differs
--font-body-lg-size16pxBody/Body L20differs
--font-body-lh1.6Body/*1.2 – 1.3differs
--font-button-size12pxOther/Button15differs
--font-title-lg-size28pxDisplay/M = 2424unconfirmed

The last row is marked unconfirmed rather than differing: a larger display style (Display/L or above) may exist that this census did not surface, in which case 28px may map to it correctly.

6 · Method and coverage limits

Typography was read from Figma variable definitions (get_variable_defs), which are reachable remotely and return the design system's type styles directly. That makes this census authoritative for the type-style set.

7 · Scope

In scope for this document — the mapping (§3), the census (§2), and the record of code and documentation departures (§4, §5).

Not in scope — applying the mapping. No CSS has been changed. Weight normalisation, Inter/Georgia removal, the design-tokens.html scale reconciliation, and correcting the 25 affected docs are follow-on work.