Typography overhaul: Inter Tight display headings, Belleza confined to wordmark

Belleza (single-weight decorative face) read thin and informal against
the dense data UI. Headings now use Inter Tight semibold with negative
tracking; hero metrics join the display face at proper optical sizes.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
pull/29/head
Talha Ahmed 2026-08-27 11:31:19 +05:00
parent abc8bffb81
commit 9df3b46aa9
4 changed files with 41 additions and 35 deletions

View File

@ -16,15 +16,16 @@
<meta name="theme-color" content="#004d43" media="(prefers-color-scheme: light)" /> <meta name="theme-color" content="#004d43" media="(prefers-color-scheme: light)" />
<meta name="theme-color" content="#0e1d1f" media="(prefers-color-scheme: dark)" /> <meta name="theme-color" content="#0e1d1f" media="(prefers-color-scheme: dark)" />
<!-- Utopia brand type: Belleza (main headings) + Inter as the metric- <!-- Type: Inter Tight (headings) + Inter as the metric-compatible
compatible stand-in for Neue Montreal, which is a licensed face. stand-in for Neue Montreal, which is a licensed face; if Neue
If Neue Montreal is installed locally it wins via the CSS stack. --> Montreal is installed locally it wins via the CSS stack.
Belleza is loaded for the wordmark only. -->
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Belleza&family=Inter:wght@400;500;600;700;800&display=swap" /> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Belleza&family=Inter:wght@400;500;600;700;800&family=Inter+Tight:wght@500;600;700&display=swap" />
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect width='100' height='100' rx='22' fill='%23004d43'/><g transform='translate(14 32) scale(0.72)'><path d='M100 3.65C97.86 20.99 91.89 43.03 79.48 55.33 76 58.77 71.84 61.46 66.96 62.14 50.4 64.46 41.84 47.5 29.07 42.7 21.85 39.98 14.5 42.02 9.66 47.95 6.54 51.78 4.49 56.35 2.97 61.13 2.41 61.64 0.97 61.66 0 61.31L0 0.13C1.05 0 2.27 0.02 3.09 0.28 14.9 15.86 26.77 30.82 40.15 45.28L60.79 24.7C67.38 18.22 74.41 12.74 82.59 8.51 88.11 5.83 93.64 3.93 100 3.65Z' fill='%23ceff71'/></g></svg>" /> <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect width='100' height='100' rx='22' fill='%23004d43'/><g transform='translate(14 32) scale(0.72)'><path d='M100 3.65C97.86 20.99 91.89 43.03 79.48 55.33 76 58.77 71.84 61.46 66.96 62.14 50.4 64.46 41.84 47.5 29.07 42.7 21.85 39.98 14.5 42.02 9.66 47.95 6.54 51.78 4.49 56.35 2.97 61.13 2.41 61.64 0.97 61.66 0 61.31L0 0.13C1.05 0 2.27 0.02 3.09 0.28 14.9 15.86 26.77 30.82 40.15 45.28L60.79 24.7C67.38 18.22 74.41 12.74 82.59 8.51 88.11 5.83 93.64 3.93 100 3.65Z' fill='%23ceff71'/></g></svg>" />
<script type="module" crossorigin src="/assets/index-CxWyqo2y.js"></script> <script type="module" crossorigin src="/assets/index-Nz9mKrAc.js"></script>
<link rel="stylesheet" crossorigin href="/assets/index-C-yWe0Um.css"> <link rel="stylesheet" crossorigin href="/assets/index-B2bX4le4.css">
</head> </head>
<body> <body>
<div id="root"></div> <div id="root"></div>

View File

@ -16,12 +16,13 @@
<meta name="theme-color" content="#004d43" media="(prefers-color-scheme: light)" /> <meta name="theme-color" content="#004d43" media="(prefers-color-scheme: light)" />
<meta name="theme-color" content="#0e1d1f" media="(prefers-color-scheme: dark)" /> <meta name="theme-color" content="#0e1d1f" media="(prefers-color-scheme: dark)" />
<!-- Utopia brand type: Belleza (main headings) + Inter as the metric- <!-- Type: Inter Tight (headings) + Inter as the metric-compatible
compatible stand-in for Neue Montreal, which is a licensed face. stand-in for Neue Montreal, which is a licensed face; if Neue
If Neue Montreal is installed locally it wins via the CSS stack. --> Montreal is installed locally it wins via the CSS stack.
Belleza is loaded for the wordmark only. -->
<link rel="preconnect" href="https://fonts.googleapis.com" /> <link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Belleza&family=Inter:wght@400;500;600;700;800&display=swap" /> <link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Belleza&family=Inter:wght@400;500;600;700;800&family=Inter+Tight:wght@500;600;700&display=swap" />
<link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect width='100' height='100' rx='22' fill='%23004d43'/><g transform='translate(14 32) scale(0.72)'><path d='M100 3.65C97.86 20.99 91.89 43.03 79.48 55.33 76 58.77 71.84 61.46 66.96 62.14 50.4 64.46 41.84 47.5 29.07 42.7 21.85 39.98 14.5 42.02 9.66 47.95 6.54 51.78 4.49 56.35 2.97 61.13 2.41 61.64 0.97 61.66 0 61.31L0 0.13C1.05 0 2.27 0.02 3.09 0.28 14.9 15.86 26.77 30.82 40.15 45.28L60.79 24.7C67.38 18.22 74.41 12.74 82.59 8.51 88.11 5.83 93.64 3.93 100 3.65Z' fill='%23ceff71'/></g></svg>" /> <link rel="icon" href="data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'><rect width='100' height='100' rx='22' fill='%23004d43'/><g transform='translate(14 32) scale(0.72)'><path d='M100 3.65C97.86 20.99 91.89 43.03 79.48 55.33 76 58.77 71.84 61.46 66.96 62.14 50.4 64.46 41.84 47.5 29.07 42.7 21.85 39.98 14.5 42.02 9.66 47.95 6.54 51.78 4.49 56.35 2.97 61.13 2.41 61.64 0.97 61.66 0 61.31L0 0.13C1.05 0 2.27 0.02 3.09 0.28 14.9 15.86 26.77 30.82 40.15 45.28L60.79 24.7C67.38 18.22 74.41 12.74 82.59 8.51 88.11 5.83 93.64 3.93 100 3.65Z' fill='%23ceff71'/></g></svg>" />
</head> </head>
<body> <body>

View File

@ -52,9 +52,9 @@
.auth-aside-copy h1 { .auth-aside-copy h1 {
font-family: var(--font-display); font-family: var(--font-display);
font-size: clamp(32px, 4vw, 44px); font-size: clamp(32px, 4vw, 44px);
line-height: 1.15; line-height: 1.12;
font-weight: 400; font-weight: 600;
letter-spacing: -0.02em; letter-spacing: -0.025em;
margin: 0 0 14px; margin: 0 0 14px;
color: #fff; color: #fff;
} }
@ -115,7 +115,7 @@
} }
.auth-brand .brand-name { .auth-brand .brand-name {
font-family: var(--font-display); font-family: var(--font-brand);
font-weight: 400; font-weight: 400;
letter-spacing: 0.2px; letter-spacing: 0.2px;
} }

View File

@ -7,8 +7,9 @@
Secondary #25e9a5 mint · #8e92ff periwinkle Secondary #25e9a5 mint · #8e92ff periwinkle
Neutral #ffffff · #000000 Neutral #ffffff · #000000
Typography Typography
Display / main headings ....... Belleza Display / main headings ....... Inter Tight (semibold, tight tracking)
UI, body & sub-headings ....... Neue Montreal (Inter fallback) UI, body & sub-headings ....... Neue Montreal (Inter fallback)
Wordmark only ................. Belleza
Theme model Theme model
Light white/mint surfaces, deep green as the action colour. Light white/mint surfaces, deep green as the action colour.
@ -84,7 +85,8 @@
--topbar-h: 64px; --topbar-h: 64px;
--font: 'Neue Montreal', 'PP Neue Montreal', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; --font: 'Neue Montreal', 'PP Neue Montreal', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
--font-display: 'Belleza', 'Neue Montreal', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; --font-display: 'Inter Tight', 'Neue Montreal', 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
--font-brand: 'Belleza', 'Inter Tight', 'Inter', sans-serif;
--mono: 'SF Mono', ui-monospace, 'Cascadia Code', Menlo, monospace; --mono: 'SF Mono', ui-monospace, 'Cascadia Code', Menlo, monospace;
/* Type scale 9 steps that the 20-size census collapses onto. /* Type scale 9 steps that the 20-size census collapses onto.
@ -97,9 +99,9 @@
--fs-lg: 18px; /* section headings, empty states */ --fs-lg: 18px; /* section headings, empty states */
--fs-xl: 22px; /* modal titles */ --fs-xl: 22px; /* modal titles */
--fs-2xl: 25px; /* profile hero name, mobile page title */ --fs-2xl: 25px; /* profile hero name, mobile page title */
--fs-3xl: 30px; /* page title (Belleza) */ --fs-3xl: 30px; /* page title (Inter Tight) */
--lh-display: 1.15; /* Belleza display headings */ --lh-display: 1.15; /* display headings */
--lh-heading: 1.25; /* h2h6, card titles */ --lh-heading: 1.25; /* h2h6, card titles */
--lh-body: 1.5; /* running copy */ --lh-body: 1.5; /* running copy */
--lh-label: 1.35; /* eyebrows, form labels, table headers */ --lh-label: 1.35; /* eyebrows, form labels, table headers */
@ -261,30 +263,32 @@ img, svg, video, canvas { max-width: 100%; }
/* ============================================================ /* ============================================================
BRAND TYPOGRAPHY BRAND TYPOGRAPHY
Guideline: "main heading always in main typeface belleza / Display face is Inter Tight a headline grotesque that shares
content & sub-heading always in neue montreal". Inter's skeleton, so titles read as the same voice as the UI,
Belleza is a display face reserved for page-level and modal only set semibold with negative tracking. Belleza (the brand
titles, hero numbers and the wordmark. Everything structural guideline's decorative face) is confined to the wordmark: at
(labels, tables, controls) stays in the UI face for legibility. text sizes and weight 400 it read thin and informal against a
dense data UI. Everything structural (labels, tables, controls)
stays in the UI face for legibility.
============================================================ */ ============================================================ */
.page-title, .page-title,
.modal-head h2, .modal-head h2,
.brand-name,
.ph-name, .ph-name,
.ai-hero h2, .ai-hero h2,
.empty-state h3 { .empty-state h3 {
font-family: var(--font-display); font-family: var(--font-display);
font-weight: 400; font-weight: 600;
letter-spacing: 0; letter-spacing: -0.015em;
} }
.page-title { font-size: var(--fs-3xl); line-height: var(--lh-display); } .page-title { font-size: var(--fs-3xl); line-height: var(--lh-display); letter-spacing: -0.02em; }
.page-title-sm { font-size: var(--fs-xl); } /* embedded sub-page titles (h2) */ .page-title-sm { font-size: var(--fs-xl); letter-spacing: -0.015em; } /* embedded sub-page titles (h2) */
.modal-head h2 { font-size: var(--fs-xl); } .modal-head h2 { font-size: var(--fs-xl); }
.ph-name { font-size: var(--fs-2xl); } .ph-name { font-size: var(--fs-2xl); }
.brand-name { font-size: var(--fs-lg); font-weight: 400; letter-spacing: .2px; } .brand-name { font-family: var(--font-brand); font-size: var(--fs-lg); font-weight: 400; letter-spacing: .2px; }
/* Metrics read as data, not prose keep them in the UI face, /* Metrics read as data hero numbers use the display face (Inter
tabular-lining so digits don't jitter as values update. */ Tight keeps Inter's figures), everything else stays in the UI face;
all tabular-lining so digits don't jitter as values update. */
.kpi-value, .stat-mini-val, .ats-ring .ats-num, .cell-mono, .mono, .kpi-value, .stat-mini-val, .ats-ring .ats-num, .cell-mono, .mono,
table.data td, .k-count, .nav-badge { table.data td, .k-count, .nav-badge {
font-variant-numeric: tabular-nums; font-variant-numeric: tabular-nums;
@ -295,7 +299,7 @@ table.data td, .k-count, .nav-badge {
bolder than the styled card titles beside them). Component rules bolder than the styled card titles beside them). Component rules
(.page-title, .modal-head h2, .card-head h3, ) win by specificity. */ (.page-title, .modal-head h2, .card-head h3, ) win by specificity. */
h1, h2, h3, h4, h5, h6 { line-height: var(--lh-heading); } h1, h2, h3, h4, h5, h6 { line-height: var(--lh-heading); }
h1 { font-family: var(--font-display); font-weight: 400; font-size: var(--fs-3xl); line-height: var(--lh-display); } h1 { font-family: var(--font-display); font-weight: 600; font-size: var(--fs-3xl); line-height: var(--lh-display); letter-spacing: -0.02em; }
h2 { font-size: var(--fs-xl); font-weight: 600; } h2 { font-size: var(--fs-xl); font-weight: 600; }
h3 { font-size: var(--fs-md); font-weight: 600; } h3 { font-size: var(--fs-md); font-weight: 600; }
h4 { font-size: var(--fs-base); font-weight: 600; } h4 { font-size: var(--fs-base); font-weight: 600; }
@ -583,7 +587,7 @@ table.data thead th, .rbac-matrix th, .cal-dow, .info-item .il,
.kpi-label { font-size: var(--fs-sm); color: var(--text-2); font-weight: 500; } .kpi-label { font-size: var(--fs-sm); color: var(--text-2); font-weight: 500; }
.kpi-icn { width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center; } .kpi-icn { width: 40px; height: 40px; border-radius: 11px; display: grid; place-items: center; }
.kpi-icn svg { width: 20px; height: 20px; } .kpi-icn svg { width: 20px; height: 20px; }
.kpi-value { font-size: 28px; font-weight: 700; letter-spacing: -1px; line-height: 1; } .kpi-value { font-family: var(--font-display); font-size: 28px; font-weight: 600; letter-spacing: -0.02em; line-height: 1; }
.kpi-foot { display: flex; align-items: center; gap: 6px; margin-top: 10px; font-size: var(--fs-sm); } .kpi-foot { display: flex; align-items: center; gap: 6px; margin-top: 10px; font-size: var(--fs-sm); }
.trend { display: inline-flex; align-items: center; gap: 3px; font-weight: 600; padding: 2px 7px; border-radius: var(--radius-sm); font-size: var(--fs-xs); } .trend { display: inline-flex; align-items: center; gap: 3px; font-weight: 600; padding: 2px 7px; border-radius: var(--radius-sm); font-size: var(--fs-xs); }
.trend svg { width: 13px; height: 13px; } .trend svg { width: 13px; height: 13px; }
@ -830,7 +834,7 @@ canvas { width: 100%; max-width: 100%; display: block; }
.more-count { width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; background: var(--bg-sunken); color: var(--text-2); font-size: 11px; font-weight: 700; border: 2px solid var(--bg-elev); margin-left: -8px; } .more-count { width: 30px; height: 30px; border-radius: 50%; display: grid; place-items: center; background: var(--bg-sunken); color: var(--text-2); font-size: 11px; font-weight: 700; border: 2px solid var(--bg-elev); margin-left: -8px; }
.stat-mini { display: flex; flex-direction: column; gap: 4px; } .stat-mini { display: flex; flex-direction: column; gap: 4px; }
.stat-mini-val { font-size: 22px; font-weight: 700; letter-spacing: -.5px; } .stat-mini-val { font-family: var(--font-display); font-size: 22px; font-weight: 600; letter-spacing: -0.015em; }
.stat-mini-lbl { font-size: var(--fs-sm); color: var(--text-3); } .stat-mini-lbl { font-size: var(--fs-sm); color: var(--text-3); }
.divider { height: 1px; background: var(--border); margin: 16px 0; } .divider { height: 1px; background: var(--border); margin: 16px 0; }
@ -1055,7 +1059,7 @@ canvas { width: 100%; max-width: 100%; display: block; }
background: conic-gradient(var(--c) calc(var(--pct)*1%), var(--bg-sunken) 0); } background: conic-gradient(var(--c) calc(var(--pct)*1%), var(--bg-sunken) 0); }
.ats-ring::after { content: ''; position: absolute; inset: 12px; border-radius: 50%; background: var(--bg-elev); } .ats-ring::after { content: ''; position: absolute; inset: 12px; border-radius: 50%; background: var(--bg-elev); }
.ats-ring .ats-val { position: relative; z-index: 1; text-align: center; } .ats-ring .ats-val { position: relative; z-index: 1; text-align: center; }
.ats-ring .ats-num { font-size: 30px; font-weight: 800; letter-spacing: -1px; line-height: 1; } .ats-ring .ats-num { font-family: var(--font-display); font-size: 30px; font-weight: 700; letter-spacing: -0.02em; line-height: 1; }
.ats-ring .ats-lbl { font-size: 11px; color: var(--text-3); font-weight: 600; } .ats-ring .ats-lbl { font-size: 11px; color: var(--text-3); font-weight: 600; }
.skill-pill { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-xs); font-weight: 600; padding: 4px 10px; border-radius: var(--radius-sm); } .skill-pill { display: inline-flex; align-items: center; gap: 5px; font-size: var(--fs-xs); font-weight: 600; padding: 4px 10px; border-radius: var(--radius-sm); }
.skill-pill svg { width: 12px; height: 12px; } .skill-pill svg { width: 12px; height: 12px; }