Refresh the homepage around new hero/services/roadmap sections, shared design tokens, and updated brand assets. Co-authored-by: Cursor <cursoragent@cursor.com>
5.4 KiB
Typography
Persian-first typography system using IRANSansX (FaNum — Persian digits baked into the font). Canonical scale: lib/typography.ts. Prefer type.* classes or <Typography variant="…"> over ad-hoc text-* stacks.
Font family
| Role | Stack |
|---|---|
| Sans (UI) | IRANSansX, system-ui, sans-serif |
| Mono | ui-monospace, SF Mono, Menlo, Consolas, monospace |
Loaded via @font-face in app/globals.css. Body applies font-family: "IRANSansX" with text-align: start (right in RTL).
Global base
| Element | Line height | Letter spacing | Alignment |
|---|---|---|---|
body |
1.75 |
normal |
start |
h1–h6 |
1.45 |
normal |
start |
p |
1.8 |
normal |
start |
Tracking is almost always tracking-normal (Persian). Avoid tracking-tight except decorative mono display (display-mono).
Prefer text-start (right in RTL). Section captions (section-intro) use text-justify with text-align-last: start so multi-line captions justify while the last line stays right-aligned. Avoid justify on body paragraphs and titles.
Scale
Use via:
import { type, typeSpacing, typeMeasure } from "@/lib/typography";
import { Typography, SectionTitle } from "@/components/ui/typography";
import { toPersianDigits } from "@/lib/persian-digits";
<h2 className={type.h2}>عنوان بخش</h2>
<Typography variant="section-intro" className={typeMeasure.prose}>
توضیح کوتاه
</Typography>
<span>{toPersianDigits(24)}</span>
| Requested level | Variant | Size / weight | Default element | Use |
|---|---|---|---|---|
| Heading 1 | h1 / display |
3xl→5xl, extrabold / bold | h1 |
Page / hero titles |
| Heading 2 | h2 / cta-title |
2xl→4xl, bold | h2 |
Major sections |
| Heading 3 | h3 |
lg→xl, bold | h3 |
Subsections / features |
| Body Large | body-lg |
lg, leading 1.8 | p |
Prominent intros (same size as captions) |
| Body | body |
base, leading 1.8 | p |
Standard copy |
| Small Text | body-sm |
sm, leading 1.75 | p |
Dense / secondary |
| Caption | caption |
xs, muted | span |
Meta, footnotes |
| Micro | micro |
11px (0.6875rem) | span |
Dense chrome / mockups / step badges |
| Button Text | button / button-lg |
sm / base, medium, leading-none | span |
Wired into Button sizes |
| Navigation | nav / nav-mobile |
sm / base, medium | span |
Header / mobile menu |
| — | eyebrow |
sm medium, muted | p |
Section labels |
| — | label |
sm medium | span |
Form labels |
| — | card-title / card-desc |
base bold / sm | h3 / p |
Cards |
| — | section-intro |
lg muted, justify | p |
Section captions under headings |
| — | stat |
4xl→5xl bold primary | span |
KPI numbers |
Reading measure
| Token | Class | Use |
|---|---|---|
typeMeasure.narrow |
max-w-md |
Short support under a heading |
typeMeasure.prose |
max-w-2xl |
Standard paragraph / intro |
typeMeasure.wide |
max-w-3xl |
Longer multi-paragraph blocks |
Alignment
- Titles: right-aligned (
text-startin RTL). - Section captions (
section-intro): justify with last line start (right in RTL) when 2+ lines. - Body paragraphs: right-aligned; do not justify.
- Hero marketing headlines may use
text-centerwhen the composition requires it — override withclassName="text-center". - Do not inherit
text-centeronto multi-line section captions.
Numbers
- Prefer explicit Persian digits in copy (
۲۴) ortoPersianDigits()/formatPersianNumber(). - IRANSansXFaNum also shapes Latin digits visually; still prefer explicit Persian for dates, counters, stats, and steps.
- Keep Latin only for technical IDs, versions, emails, and code.
Button text
Button sizes pull from type.button (sm/default) and type["button-lg"] (lg). Horizontal padding tokens in globals.css are slightly wider for Persian glyphs. Do not wrap button labels in <Typography> unless building a non-Button control.
Hierarchy rules
- One
h1per page (ordisplayacting as the page title). - Section titles use
h2/cta-title; subsections useh3/h4. - Pair titles with at most one short supporting sentence (
section-introorbody+text-muted-foreground). - Use
text-balanceon large headings (already in scale) for better wrap in Persian. - Blog article prose uses
.blog-contentrules inglobals.css—do not override casually.
Stacking
<div className={typeSpacing.sectionStack}>
<p className={type.eyebrow}>خدمات</p>
<h2 className={cn(type.h2, typeSpacing.eyebrowToHeading)}>…</h2>
<p className={cn(type["section-intro"], typeSpacing.headingToBody, typeMeasure.prose)}>…</p>
</div>
Forbidden
- Inter / Roboto / Arial as primary UI fonts.
- Random
text-[15px]/text-[1.05rem](usetype.microfor dense chrome). tracking-wideston Persian body copy.text-justifyon body paragraphs / titles (section captions are the exception).- Using
font-boldeverywhere—follow the scale weights. - Physical
text-left/mr-/ml-/pr-/pl-when logicaltext-start/ms-/me-/ps-/pe-work. - Overriding scale sizes with
sm:text-5xl/lg:text-6xlontype.display/type.h*. - Using
type.h2on anh3(or vice versa) — keep element level and scale token aligned.