Najjar\NajjarV02 729ab71c2c
Some checks are pending
CI/CD / test-and-build (push) Waiting to run
CI/CD / deploy (push) Blocked by required conditions
Refactor code structure for improved readability and maintainability; removed redundant code blocks and optimized function calls.
2026-05-20 18:03:42 +04:00

6.1 KiB

Design System

Reusable design tokens + scales extracted from the Luxam reference build. Drop into globals.css (Tailwind v4 @theme) of any new project to start with the same DNA.


Color palette

@theme {
  /* Backgrounds obsidian → graphite layering */
  --color-obsidian: #08080A;   /* page background */
  --color-graphite: #15161A;   /* dark glass card */
  --color-graphite-2: #1C1D22; /* slightly lifted card variant */

  /* Foreground */
  --color-bone: #F4F0E6;       /* primary text on dark */
  --color-mist: #C7C2B5;       /* secondary/muted text */

  /* Brand gold spectrum (use sparingly + structurally) */
  --color-gold: #D4A437;       /* core brand gold */
  --color-gold-light: #F2C25B; /* hover, highlight, gradient stops */
  --color-gold-deep: #7A4A12;  /* gradient base */
  --color-ember: #B5731A;      /* warm secondary */

  /* Sustainability accent (use only where ecology theme applies) */
  --color-emerald: #1F8F6B;
  --color-emerald-glow: #3FD8A4;
}

Usage rules

  • Background: bg-obsidian body, bg-graphite/40 backdrop-blur-sm cards.
  • Borders: border-bone/10 default, border-gold/30 on hover, border-gold/40 active.
  • Text: text-bone titles, text-mist body/secondary, text-gold-light brand accents.
  • Never use raw #fff or pure #000. Always bone or obsidian.
  • Gradients: single-axis brand gradient from-gold-light via-gold to-gold-deep. No rainbow.

Typography

// app/layout.tsx
import { Cormorant_Garamond, Geist, Geist_Mono } from "next/font/google";

const display = Cormorant_Garamond({
  subsets: ["latin"],
  variable: "--font-display",
  weight: ["400", "500", "600"],
  display: "swap",
});
const sans = Geist({ subsets: ["latin"], variable: "--font-sans", display: "swap" });
const mono = Geist_Mono({ subsets: ["latin"], variable: "--font-mono", display: "swap" });

Hierarchy

Role Font Size
Hero H1 font-display (serif) text-[clamp(2.6rem,7vw,6.4rem)] leading-[1.0] tracking-[-0.02em]
Section H2 font-display text-[clamp(2.4rem,5vw,4.6rem)] leading-[1.02] tracking-[-0.02em]
Card H3/H4 font-display text-2xl md:text-3xl
Body font-sans (inherited default) text-base md:text-lg leading-[1.7]
UI label font-sans text-[10px] md:text-[11px] font-medium uppercase tracking-[0.22em]
Nav link font-sans text-sm font-medium tracking-[0.005em]
Stats number font-display text-5xl md:text-6xl (responsive smaller on mobile)

Avoid

  • font-mono on long values or body text.
  • tracking-[0.3em]+ on small labels.
  • leading-[0.95] on serif headlines (clips ascenders).

Helper class for one-color brand text:

.gold-text {
  background: linear-gradient(90deg, #FFEFC5, #F2C25B 40%, #D4A437 80%, #7A4A12);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
}

Spacing scale

Section padding lives only on the Section primitive:

// components/ui/Section.tsx
className={cn("relative scroll-mt-24 py-16 md:scroll-mt-28 md:py-20 lg:py-24", className)}
  • Mobile: py-16 (64 px)
  • Tablet: md:py-20 (80 px)
  • Desktop: lg:py-24 (96 px)
  • All anchored sections get scroll-mt-24 md:scroll-mt-28 for sticky-nav clearance.

Don't override per-section unless there's a structural reason. Centralize.

Card padding: p-6 md:p-7 standard, p-7 md:p-10 for hero/feature cards.

Grid gaps: gap-4 md:gap-5 standard, gap-6 md:gap-8 for large cards.


Border radius scale

--radius-xs: 4px;
--radius-sm: 8px;
--radius-md: 14px;
--radius-lg: 22px;
--radius-xl: 32px;

Tailwind shortcuts to match: rounded-2xl (cards), rounded-3xl (hero panels), rounded-full (pills + buttons).


Motion

// shared variants
const cardGrid: Variants = {
  hidden: {},
  visible: { transition: { staggerChildren: 0.08, delayChildren: 0.15 } },
};
const cardCell: Variants = {
  hidden: { opacity: 0, y: 24, filter: "blur(6px)" },
  visible: {
    opacity: 1, y: 0, filter: "blur(0px)",
    transition: { duration: 0.8, ease: [0.16, 1, 0.3, 1] },
  },
};
  • Entrance ease: [0.16, 1, 0.3, 1] (cubic-bezier "out-quart-ish").
  • Duration: hero 1.3s, cards 0.8s, hover 0.3-0.5s.
  • Hover lift: -translate-y-1 max. No -translate-y-2+ (jumpy).
  • Halo pulse: [0.5, 0.85, 0.5] opacity, 6s loop. Wrap in !reduce && (...).
  • useReducedMotion() must be read in any animated component.

Forbidden

  • Bouncy springs (stiffness > 200) on entrance.
  • Scale jumps > 1.05 on hover for cards.
  • Parallax > 200 px translate range.
  • Marquees without mask-image edge fade.

Visual textures

Class Purpose
noise-bg Subtle film-grain background overlay
grain Animated grain (use sparingly on cards)
metallic-divider Thin gold-tinted divider line
radial-gold Faint amber radial wash (positioned absolute, blur-3xl)
radial-emerald Same, emerald variant
hairline-t, hairline-b 1 px top/bottom hairline borders
mask-fade-y, mask-fade-x Edge fade masks

Define these as utilities in globals.css per the Luxam reference.


Hover state pattern

Every card/button uses the same hover vocabulary:

  1. -translate-y-1 lift (cards) or -translate-y-0.5 (buttons).
  2. Border step up: border-bone/10 → border-gold/30 (or /35 /40).
  3. Background step up: bg-graphite/40 → bg-graphite/60.
  4. Amber radial glow bottom-right: radial-gradient(circle, rgba(212,164,55,0.28), transparent 70%) blurred.
  5. Gold underline sweep (cards): absolute bottom-0 left-0 h-px w-0 ... group-hover:w-full.
  6. Optional: top hairline gold gradient fade-in.
  7. Icon disc gets rotate-[8deg] + amber halo shadow.

Apply via group + group-hover: Tailwind variants never per-element JS listeners.


Container widths

// components/ui/Container.tsx three variants
size="default"  max-w-7xl
size="wide"     max-w-[1480px]
size="narrow"   max-w-3xl

All variants: mx-auto px-6 md:px-10.


When in doubt

  • More dark, less gold.
  • More space, less content.
  • Less motion, more restraint.
  • Real photography > illustration.
  • Editorial typography > corporate sans.