225 lines
7.7 KiB
CSS
225 lines
7.7 KiB
CSS
/* ============================================================================
|
|||
|
|
TYPE ROLES (tier 2 for typography)
|
||
|
|
----------------------------------------------------------------------------
|
||
|
|
Composes tier-1 primitives into the named roles published in Figma
|
||
|
|
(Display/Small, Heading/H2, Body/*, Label/Medium) plus the two headings the
|
||
|
|
scale needs but Figma has not drawn yet (H1, H3), derived from the same ramp.
|
||
|
|
|
||
|
|
Components use the utilities below - `display-sm`, `heading-h2`, `body-md`,
|
||
|
|
`label-md` - never a raw font-size / line-height / letter-spacing.
|
||
|
|
|
||
|
|
Panton (EN) and Montserrat Arabic (AR) are the brand faces, both supplied
|
||
|
|
and present in apps/web/public/fonts/. Licensed to the project, not to this
|
||
|
|
repository - .gitignore keeps every woff2 out of version control.
|
||
|
|
See ./README.md for the filename of every face.
|
||
|
|
========================================================================= */
|
||
|
|
|
||
|
|
/* ---------------------------------------------------------------------------
|
||
|
|
@font-face - Panton (English / Latin)
|
||
|
|
Regular and Bold are supplied and live in public/fonts/. A SemiBold cut has
|
||
|
|
not been supplied, so Label/Medium (weight 500) resolves to Panton Regular
|
||
|
|
through normal CSS font matching - see ./README.md to upgrade it.
|
||
|
|
------------------------------------------------------------------------ */
|
||
|
|
@font-face {
|
||
|
|
font-family: "Panton";
|
||
|
|
src: url("/fonts/Panton-Regular.woff2") format("woff2");
|
||
|
|
font-weight: 400;
|
||
|
|
font-style: normal;
|
||
|
|
font-display: swap;
|
||
|
|
}
|
||
|
|
|
||
|
|
@font-face {
|
||
|
|
font-family: "Panton";
|
||
|
|
src: url("/fonts/Panton-Bold.woff2") format("woff2");
|
||
|
|
font-weight: 700;
|
||
|
|
font-style: normal;
|
||
|
|
font-display: swap;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ---------------------------------------------------------------------------
|
||
|
|
@font-face - Arabic
|
||
|
|
|
||
|
|
"Montserrat Arabic" is THE Arabic brand face. The communication guideline
|
||
|
|
PDF names "Montaser Arabic", but that is a typo in the guideline - confirmed
|
||
|
|
with the client on 2026-09-11. Do not reintroduce a "Montaser Arabic"
|
||
|
|
family: it does not exist and would silently shadow the real one, because it
|
||
|
|
would sit ahead of Montserrat in --font-ar and match any similarly-named
|
||
|
|
face a visitor happens to have installed.
|
||
|
|
|
||
|
|
Three weights are supplied in public/fonts/. unicode-range keeps every
|
||
|
|
Arabic file off English pages entirely.
|
||
|
|
------------------------------------------------------------------------ */
|
||
|
|
@font-face {
|
||
|
|
font-family: "Montserrat Arabic";
|
||
|
|
src: url("/fonts/Montserrat-Arabic-Regular.woff2") format("woff2");
|
||
|
|
font-weight: 400;
|
||
|
|
font-style: normal;
|
||
|
|
font-display: swap;
|
||
|
|
unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+08A0-08FF,
|
||
|
|
U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+2010-2011, U+204F, U+2E41,
|
||
|
|
U+0660-0669;
|
||
|
|
}
|
||
|
|
|
||
|
|
@font-face {
|
||
|
|
font-family: "Montserrat Arabic";
|
||
|
|
src: url("/fonts/Montserrat-Arabic-Medium.woff2") format("woff2");
|
||
|
|
font-weight: 500 600;
|
||
|
|
font-style: normal;
|
||
|
|
font-display: swap;
|
||
|
|
unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+08A0-08FF,
|
||
|
|
U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+2010-2011, U+204F, U+2E41,
|
||
|
|
U+0660-0669;
|
||
|
|
}
|
||
|
|
|
||
|
|
@font-face {
|
||
|
|
font-family: "Montserrat Arabic";
|
||
|
|
src: url("/fonts/Montserrat-Arabic-Bold.woff2") format("woff2");
|
||
|
|
font-weight: 700;
|
||
|
|
font-style: normal;
|
||
|
|
font-display: swap;
|
||
|
|
unicode-range: U+0600-06FF, U+0750-077F, U+0870-088E, U+08A0-08FF,
|
||
|
|
U+FB50-FDFF, U+FE70-FEFF, U+200C-200F, U+2010-2011, U+204F, U+2E41,
|
||
|
|
U+0660-0669;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ---------------------------------------------------------------------------
|
||
|
|
TYPE SEMANTIC TOKENS
|
||
|
|
The EN/AR switch is a token rebind, not a second set of utilities: every
|
||
|
|
role below reads --font-heading / --font-body and the role tracking tokens,
|
||
|
|
so `<html lang="ar">` - or any Arabic subtree - re-points them once and the
|
||
|
|
whole scale follows.
|
||
|
|
|
||
|
|
Latin tracking is negative on display sizes and positive on labels; Arabic
|
||
|
|
is a joined script where letter-spacing breaks the connections, so all
|
||
|
|
Arabic tracking resets to normal.
|
||
|
|
------------------------------------------------------------------------ */
|
||
|
|
:root {
|
||
|
|
--font-heading: var(--font-en);
|
||
|
|
--font-body: var(--font-en);
|
||
|
|
--font-ui: var(--font-en);
|
||
|
|
|
||
|
|
--type-tracking-display: var(--tracking-tighter);
|
||
|
|
--type-tracking-h1: var(--tracking-tight);
|
||
|
|
--type-tracking-h2: var(--tracking-snug);
|
||
|
|
--type-tracking-h3: var(--tracking-snug);
|
||
|
|
--type-tracking-body: var(--tracking-normal);
|
||
|
|
--type-tracking-label: var(--tracking-wide);
|
||
|
|
}
|
||
|
|
|
||
|
|
[lang="ar"],
|
||
|
|
:lang(ar) {
|
||
|
|
--font-heading: var(--font-ar);
|
||
|
|
--font-body: var(--font-ar);
|
||
|
|
--font-ui: var(--font-ar);
|
||
|
|
|
||
|
|
--type-tracking-display: var(--tracking-normal);
|
||
|
|
--type-tracking-h1: var(--tracking-normal);
|
||
|
|
--type-tracking-h2: var(--tracking-normal);
|
||
|
|
--type-tracking-h3: var(--tracking-normal);
|
||
|
|
--type-tracking-body: var(--tracking-normal);
|
||
|
|
--type-tracking-label: var(--tracking-normal);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* ---------------------------------------------------------------------------
|
||
|
|
TYPE ROLE UTILITIES
|
||
|
|
------------------------------------------------------------------------ */
|
||
|
|
|
||
|
|
/* Display/Small - Bold 44/52, ls -1 [figma] */
|
||
|
|
@utility display-sm {
|
||
|
|
font-family: var(--font-heading);
|
||
|
|
font-size: var(--text-4xl);
|
||
|
|
line-height: var(--leading-11);
|
||
|
|
letter-spacing: var(--type-tracking-display);
|
||
|
|
font-weight: var(--font-weight-bold);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Heading/H1 - Bold 36/44 (derived - not yet drawn in Figma) */
|
||
|
|
@utility heading-h1 {
|
||
|
|
font-family: var(--font-heading);
|
||
|
|
font-size: var(--text-3xl);
|
||
|
|
line-height: var(--leading-10);
|
||
|
|
letter-spacing: var(--type-tracking-h1);
|
||
|
|
font-weight: var(--font-weight-bold);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Heading/H2 - Bold 28/36, ls -0.3 [figma] */
|
||
|
|
@utility heading-h2 {
|
||
|
|
font-family: var(--font-heading);
|
||
|
|
font-size: var(--text-2xl);
|
||
|
|
line-height: var(--leading-9);
|
||
|
|
letter-spacing: var(--type-tracking-h2);
|
||
|
|
font-weight: var(--font-weight-bold);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Heading/H3 - Bold 22/30 (derived - not yet drawn in Figma) */
|
||
|
|
@utility heading-h3 {
|
||
|
|
font-family: var(--font-heading);
|
||
|
|
font-size: var(--text-xl);
|
||
|
|
line-height: var(--leading-8);
|
||
|
|
letter-spacing: var(--type-tracking-h3);
|
||
|
|
font-weight: var(--font-weight-bold);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Body/Large - 18/28 */
|
||
|
|
@utility body-lg {
|
||
|
|
font-family: var(--font-body);
|
||
|
|
font-size: var(--text-lg);
|
||
|
|
line-height: var(--leading-7);
|
||
|
|
letter-spacing: var(--type-tracking-body);
|
||
|
|
font-weight: var(--font-weight-regular);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Body/Large Bold - Bold 18/28 [figma] */
|
||
|
|
@utility body-lg-bold {
|
||
|
|
font-family: var(--font-body);
|
||
|
|
font-size: var(--text-lg);
|
||
|
|
line-height: var(--leading-7);
|
||
|
|
letter-spacing: var(--type-tracking-body);
|
||
|
|
font-weight: var(--font-weight-bold);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Body/Medium - 16/24 */
|
||
|
|
@utility body-md {
|
||
|
|
font-family: var(--font-body);
|
||
|
|
font-size: var(--text-md);
|
||
|
|
line-height: var(--leading-6);
|
||
|
|
letter-spacing: var(--type-tracking-body);
|
||
|
|
font-weight: var(--font-weight-regular);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Body/Medium Bold - Bold 16/24 [figma] */
|
||
|
|
@utility body-md-bold {
|
||
|
|
font-family: var(--font-body);
|
||
|
|
font-size: var(--text-md);
|
||
|
|
line-height: var(--leading-6);
|
||
|
|
letter-spacing: var(--type-tracking-body);
|
||
|
|
font-weight: var(--font-weight-bold);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Body/Small - Regular 14/20 [figma] */
|
||
|
|
@utility body-sm {
|
||
|
|
font-family: var(--font-body);
|
||
|
|
font-size: var(--text-sm);
|
||
|
|
line-height: var(--leading-5);
|
||
|
|
letter-spacing: var(--type-tracking-body);
|
||
|
|
font-weight: var(--font-weight-regular);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Body/Small Bold - Bold 14/20 [figma] */
|
||
|
|
@utility body-sm-bold {
|
||
|
|
font-family: var(--font-body);
|
||
|
|
font-size: var(--text-sm);
|
||
|
|
line-height: var(--leading-5);
|
||
|
|
letter-spacing: var(--type-tracking-body);
|
||
|
|
font-weight: var(--font-weight-bold);
|
||
|
|
}
|
||
|
|
|
||
|
|
/* Label/Medium - SemiBold 12/16, ls 0.5 [figma] */
|
||
|
|
@utility label-md {
|
||
|
|
font-family: var(--font-ui);
|
||
|
|
font-size: var(--text-xs);
|
||
|
|
line-height: var(--leading-4);
|
||
|
|
letter-spacing: var(--type-tracking-label);
|
||
|
|
font-weight: var(--font-weight-medium);
|
||
|
|
}
|