feat: redesign landing page with brand system and section blocks
Build & Push Docker Image / build (push) Has been cancelled

Refresh the homepage around new hero/services/roadmap sections, shared design tokens, and updated brand assets.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
ar.badiei
2026-07-23 17:00:55 +03:30
co-authored by Cursor
parent f0c290786e
commit c2376b3b9e
352 changed files with 34442 additions and 2760 deletions
+39
View File
@@ -0,0 +1,39 @@
import type { Transition, Variants } from "motion/react";
/** Standard scroll-reveal ease (ui-ux-pro-max: power2.out-equivalent). */
export const blockEase = [0.22, 1, 0.36, 1] as const;
/** ~400–500ms section entrance — transform + opacity only. */
export const blockRevealTransition: Transition = {
duration: 0.5,
ease: blockEase,
};
/**
* Trigger when the block approaches ~85% from the top of the viewport.
* `once` keeps motion purposeful and avoids reverse jitter on scroll-up.
*/
export const blockViewport = {
once: true,
amount: 0.2,
margin: "0px 0px -10% 0px",
} as const;
export const blockRevealContainer: Variants = {
hidden: {},
visible: {
transition: {
staggerChildren: 0.08,
delayChildren: 0.04,
},
},
};
export const blockRevealItem: Variants = {
hidden: { opacity: 0, y: 24 },
visible: {
opacity: 1,
y: 0,
transition: blockRevealTransition,
},
};
+32
View File
@@ -0,0 +1,32 @@
import { cn } from "@/lib/utils";
/**
* Global layout tokens for Amin Rayan.
* All page sections must use these — do not invent ad-hoc max-widths or gutters.
*
* Base was max-w-5xl (64rem); +20% → 76.8rem for a wider content column.
*/
export const layout = {
/** Outer horizontal gutter (full-bleed backgrounds stay outside this). */
gutter: "px-6",
/** Main content max width (64rem × 1.2). */
maxWidth: "max-w-[76.8rem]",
/** Shared content shell: centered, capped, padded. */
container: "mx-auto w-full max-w-[76.8rem] px-6",
/**
* Vertical rhythm for major sections.
* Adjacent sections always meet as `pb + pt` from this token
* (`py-16` → 8rem gap, `md:py-20` → 10rem) — including hero → خدمات ما.
*/
sectionY: "py-16 md:py-20",
/** Top offset under fixed header for first section (incl. homepage hero). */
sectionTopWithHeader: "pt-28 pb-16 md:pt-32 md:pb-20",
/** Anchor scroll offset under fixed header. */
scrollMargin: "scroll-mt-28",
/** Soft visual cue between bands — no hard template break. */
sectionBandDivider: "border-t border-border/30",
} as const;
export function containerClassName(className?: string) {
return cn(layout.container, className);
}
+33
View File
@@ -0,0 +1,33 @@
const LATIN_TO_PERSIAN: Record<string, string> = {
"0": "۰",
"1": "۱",
"2": "۲",
"3": "۳",
"4": "۴",
"5": "۵",
"6": "۶",
"7": "۷",
"8": "۸",
"9": "۹",
};
/**
* Convert Latin digits in a string to Persian digits.
* Leaves non-digit characters unchanged. Use for UI labels, stats,
* dates, and counters — not for technical IDs or code.
*/
export function toPersianDigits(value: string | number): string {
return String(value).replace(/[0-9]/g, (digit) => LATIN_TO_PERSIAN[digit] ?? digit);
}
/**
* Format a number for Persian UI (locale grouping + Persian digits).
*/
export function formatPersianNumber(
value: number,
options?: Intl.NumberFormatOptions
): string {
return toPersianDigits(
new Intl.NumberFormat("fa-IR", options).format(value)
);
}
+105 -52
View File
@@ -4,62 +4,92 @@ import { cn } from "@/lib/utils";
/**
* Site-wide typography scale optimized for Persian (RTL) readability.
*
* Hierarchy (requested → variant):
* - Heading 1 → `h1` / `display`
* - Heading 2 → `h2`
* - Heading 3 → `h3`
* - Body Large → `body-lg`
* - Body → `body`
* - Small Text → `body-sm`
* - Caption → `caption`
* - Button Text → `button` / `button-lg`
* - Navigation → `nav` / `nav-mobile`
*
* Alignment: prefer `text-start` (right in RTL).
* Section captions (`section-intro`) use justify + last-line start for 2+ lines.
* Reading measure: keep paragraphs within `typeMeasure.*` max-widths.
*
* Use via `typography({ variant })`, `type.*` shorthand, or `<Typography>`.
*/
export const typographyVariants = cva("tracking-normal", {
variants: {
variant: {
/** Large marketing hero titles */
/** Large marketing hero titles — may be centered via className */
display:
"text-3xl font-semibold leading-relaxed text-balance sm:text-4xl lg:text-5xl",
"text-start text-3xl font-bold leading-[1.55] text-balance sm:text-4xl lg:text-5xl",
/** Main page titles */
h1: "text-3xl font-bold leading-snug text-balance md:text-4xl lg:text-5xl",
h1: "text-start text-3xl font-extrabold leading-[1.45] text-balance md:text-4xl lg:text-5xl",
/** Major section headings */
h2: "text-2xl font-semibold leading-snug text-balance md:text-3xl lg:text-4xl",
h2: "text-start text-2xl font-bold leading-[1.45] text-balance md:text-3xl lg:text-4xl",
/** Subsection / feature block headings */
h3: "text-lg font-semibold leading-snug md:text-xl",
h3: "text-start text-lg font-bold leading-[1.5] md:text-xl",
/** Compact block headings, mini sections */
h4: "text-base font-semibold leading-snug md:text-lg",
/** Prominent intro paragraphs */
"body-lg": "text-lg leading-relaxed md:text-xl",
h4: "text-start text-base font-bold leading-[1.5] md:text-lg",
/** Prominent intro paragraphs — same size as section captions */
"body-lg": "text-start text-lg leading-[1.8]",
/** Standard paragraphs */
body: "text-base leading-relaxed",
body: "text-start text-base leading-[1.8]",
/** Secondary / denser copy */
"body-sm": "text-sm leading-relaxed",
/** Metadata, timestamps, footnotes */
caption: "text-xs leading-normal text-muted-foreground",
"body-sm": "text-start text-sm leading-[1.75]",
/** Metadata, timestamps, footnotes — fixed size site-wide */
caption: "text-start text-xs leading-[1.6] text-muted-foreground",
/** Dense UI chrome (mockups, compact badges, timeline steps) — prefer caption when possible */
micro: "text-start text-[0.6875rem] leading-[1.5]",
/** Section eyebrow / badge labels */
eyebrow: "text-sm font-medium leading-normal text-muted-foreground",
eyebrow:
"text-start text-sm font-medium leading-normal text-muted-foreground",
/** Form labels, settings labels */
label: "text-sm font-medium leading-none",
label: "text-start text-sm font-medium leading-none",
/** Header / menu items (desktop) */
nav: "text-sm font-medium",
nav: "text-start text-sm font-medium leading-none",
/** Mobile navigation items */
"nav-mobile": "text-base font-medium",
"nav-mobile": "text-start text-base font-medium leading-snug",
/** Default / sm button labels — optically centered in the control */
button: "text-sm font-medium leading-none",
/** Large button labels (hero / marketing CTAs) */
"button-lg": "text-base font-medium leading-none",
/** Titles inside cards and panels */
"card-title": "text-base font-semibold leading-snug",
"card-title": "text-start text-base font-bold leading-snug",
/** Supporting copy inside cards */
"card-desc": "text-sm leading-relaxed text-muted-foreground",
"card-desc":
"text-start text-sm leading-[1.75] text-muted-foreground",
/** Chat message bubbles */
chat: "text-sm leading-relaxed",
chat: "text-start text-sm leading-[1.75]",
/** Log panels, JSON, technical output */
code: "font-mono text-xs leading-relaxed",
code: "text-start font-mono text-xs leading-relaxed",
/** Large stat numbers */
stat: "text-4xl font-bold leading-none text-primary md:text-5xl",
stat: "text-start text-4xl font-bold leading-none text-primary md:text-5xl",
/** Inline nav / footer links */
link: "text-sm text-muted-foreground",
/** Section intro paragraphs (muted) */
"section-intro": "text-lg leading-relaxed text-muted-foreground",
link: "text-start text-sm leading-normal text-muted-foreground",
/**
* Section captions under headings (muted).
* Multi-line: justify; last line stays start (right in RTL).
* Single-line: justify has no visual stretch — stays start-aligned.
*/
"section-intro":
"text-justify text-lg leading-[1.8] text-muted-foreground [text-align-last:start]",
/** Pull quotes / emphasis blocks */
emphasis: "text-base font-medium leading-relaxed text-foreground",
emphasis:
"text-start text-base font-medium leading-[1.8] text-foreground",
/** Accordion / list item titles */
"list-title": "text-base font-medium leading-snug",
"list-title": "text-start text-base font-medium leading-snug",
/** CTA section headings (slightly larger than h2) */
"cta-title":
"text-2xl font-semibold leading-snug text-balance md:text-3xl lg:text-4xl",
"text-start text-2xl font-bold leading-[1.45] text-balance md:text-3xl lg:text-4xl",
/** Decorative error page numbers */
"display-mono":
"text-[5rem] font-black leading-none sm:text-[6rem] md:text-[8rem]",
"text-start text-[5rem] font-black leading-none sm:text-[6rem] md:text-[8rem]",
},
},
defaultVariants: {
@@ -74,34 +104,57 @@ export type TypographyVariant = NonNullable<
/** Shorthand class strings for inline use: `className={type.h2}` */
export const type: Record<TypographyVariant, string> = {
display:
"text-3xl font-semibold leading-relaxed tracking-normal text-balance sm:text-4xl lg:text-5xl",
h1: "text-3xl font-bold leading-snug tracking-normal text-balance md:text-4xl lg:text-5xl",
h2: "text-2xl font-semibold leading-snug tracking-normal text-balance md:text-3xl lg:text-4xl",
h3: "text-lg font-semibold leading-snug tracking-normal md:text-xl",
h4: "text-base font-semibold leading-snug tracking-normal md:text-lg",
"body-lg": "text-lg leading-relaxed tracking-normal md:text-xl",
body: "text-base leading-relaxed tracking-normal",
"body-sm": "text-sm leading-relaxed tracking-normal",
caption: "text-xs leading-normal tracking-normal text-muted-foreground",
eyebrow: "text-sm font-medium leading-normal tracking-normal text-muted-foreground",
label: "text-sm font-medium leading-none tracking-normal",
nav: "text-sm font-medium tracking-normal",
"nav-mobile": "text-base font-medium tracking-normal",
"card-title": "text-base font-semibold leading-snug tracking-normal",
"card-desc": "text-sm leading-relaxed tracking-normal text-muted-foreground",
chat: "text-sm leading-relaxed tracking-normal",
code: "font-mono text-xs leading-relaxed tracking-normal",
stat: "text-4xl font-bold leading-none tracking-normal text-primary md:text-5xl",
link: "text-sm tracking-normal text-muted-foreground",
"section-intro": "text-lg leading-relaxed tracking-normal text-muted-foreground",
emphasis: "text-base font-medium leading-relaxed tracking-normal text-foreground",
"list-title": "text-base font-medium leading-snug tracking-normal",
"text-3xl font-bold leading-[1.55] tracking-normal text-balance text-start sm:text-4xl lg:text-5xl",
h1: "text-3xl font-extrabold leading-[1.45] tracking-normal text-balance text-start md:text-4xl lg:text-5xl",
h2: "text-2xl font-bold leading-[1.45] tracking-normal text-balance text-start md:text-3xl lg:text-4xl",
h3: "text-lg font-bold leading-[1.5] tracking-normal text-start md:text-xl",
h4: "text-base font-bold leading-[1.5] tracking-normal text-start md:text-lg",
"body-lg": "text-lg leading-[1.8] tracking-normal text-start",
body: "text-base leading-[1.8] tracking-normal text-start",
"body-sm": "text-sm leading-[1.75] tracking-normal text-start",
caption:
"text-xs leading-[1.6] tracking-normal text-start text-muted-foreground",
micro: "text-[0.6875rem] leading-[1.5] tracking-normal text-start",
eyebrow:
"text-sm font-medium leading-normal tracking-normal text-start text-muted-foreground",
label: "text-sm font-medium leading-none tracking-normal text-start",
nav: "text-sm font-medium leading-none tracking-normal text-start",
"nav-mobile": "text-base font-medium leading-snug tracking-normal text-start",
button: "text-sm font-medium leading-none tracking-normal",
"button-lg": "text-base font-medium leading-none tracking-normal",
"card-title":
"text-base font-bold leading-snug tracking-normal text-start",
"card-desc":
"text-sm leading-[1.75] tracking-normal text-start text-muted-foreground",
chat: "text-sm leading-[1.75] tracking-normal text-start",
code: "font-mono text-xs leading-relaxed tracking-normal text-start",
stat: "text-4xl font-bold leading-none tracking-normal text-start text-primary md:text-5xl",
link: "text-sm leading-normal tracking-normal text-start text-muted-foreground",
"section-intro":
"text-lg leading-[1.8] tracking-normal text-justify text-muted-foreground [text-align-last:start]",
emphasis:
"text-base font-medium leading-[1.8] tracking-normal text-start text-foreground",
"list-title":
"text-base font-medium leading-snug tracking-normal text-start",
"cta-title":
"text-2xl font-semibold leading-snug tracking-normal text-balance md:text-3xl lg:text-4xl",
"text-2xl font-bold leading-[1.45] tracking-normal text-balance text-start md:text-3xl lg:text-4xl",
"display-mono":
"text-[5rem] font-black leading-none tracking-tighter sm:text-[6rem] md:text-[8rem]",
"text-[5rem] font-black leading-none tracking-tighter text-start sm:text-[6rem] md:text-[8rem]",
};
/**
* Comfortable reading widths for Persian body copy.
* Prefer these over stretching lines across the full container.
*/
export const typeMeasure = {
/** Short support line under a heading */
narrow: "max-w-md",
/** Standard paragraph / section intro */
prose: "max-w-2xl",
/** Longer multi-paragraph blocks */
wide: "max-w-3xl",
} as const;
/** Text-related spacing tied to typography hierarchy */
export const typeSpacing = {
/** Eyebrow → heading */