Files
anwar-pi-website/DESIGN_SYSTEM.md
T

5.5 KiB
Raw Permalink Blame History

DESIGN_SYSTEM — anwarpy.ai

Canonical tokens live in web/src/app/design.css. This file documents them and the rules for using them. If CSS and this file disagree, fix one of them in the same PR.

1. Design personality

Editorial, calm, premium-dark. Ink surfaces, champagne accents, generous whitespace, Arabic-first typography. Restraint is the brand: one accent color, used sparingly; motion is short and soft; nothing blinks, nothing bounces.

2. Color tokens

Token Value Role
--ink #131519 page background (--bg)
--ink-2 #17191d raised background
--basalt #1c1f24 card/surface (--surface)
--seam #2b2f36 hairline borders (--border)
--seam-2 #3a3f47 hover border, stronger seam
--mist #ece9e3 primary text (--fg)
--stone #a3a09a muted text (--muted)
--dim #7b7974 faintest text (meta only)
--champagne #d4b47c THE accent (--accent) — badges, CTAs, highlights
--champagne-ink #1a150c text/icons on champagne (--accent-ink)

Rules:

  • Never introduce a new hue. Semantic aliases (--bg, --surface, --fg, --muted, --border, --accent) are the only tokens components may use — raw hex is for design.css only.
  • Champagne on ink or champagne-ink on champagne. Never champagne text on basalt for body copy (contrast), never stone below 14px.
  • Success/warning/error states (form errors, honest 503s) use --mist/--stone + wording first; reserve red only where the CSS already defines it. Do not invent traffic-light colors.

3. Typography

  • Readex Pro (Arabic + Latin, single family), loaded in layout.tsx via next/font/google, weights 300–700. --font-display: var(--font-sans), "Segoe UI", sans-serif.
  • Scale: hero H1 ~2.5rem/700; section H2 ~1.5rem/600; body 1rem/400 with line-height ≥1.8 for Arabic; meta/captions 0.875rem --stone.
  • Arabic-first: direction: rtl at the page root; Arabic quotes «»; numerals via formatNumber (Arabic-Indic where the site does).
  • LTR islands inside RTL text use <bdi dir="ltr">: anwarpy.ai, $10, code, identifiers, agent names (GPTBot…). Never let a raw Latin token break RTL flow.
  • No <br> for spacing; use margins. No font-size below 0.75rem.

4. Spacing & shape

  • Space scale: 4 / 8 / 12 / 16 / 24 / 32 / 48 / 64px. Section padding 48–64px; card padding 16–24px; page max-width container per existing layout (centered, ≥24px gutters).
  • Radii: cards/pills 8–12px; badges/buttons pill (999px) where the existing CSS does; inputs match buttons.
  • Borders: 1px --seam everywhere; hover → --seam-2. No heavy shadows; elevation = --ink-2/--basalt layering, not blur.

5. Component inventory (build from these, extend the list, never fork it)

Existing, in src/components/ + route CSS: topnav.tsx, site-menu.tsx, nav-links.tsx, footer.tsx, anwarpi-background.tsx, set-body-attr.tsx.

Recurring patterns (CSS classes are the contract):

  • Buttons: .btn, .btn.btn-primary (champagne bg, --accent-ink text), disabled/coming-soon state = «قريباً» pill, wired to subscribe-button.tsx comingSoon prop. Disabled buttons are visually disabled from first paint and explain why in Arabic.
  • Badges/pills: access badge «مجاني» / «للأعضاء»; content-type badge (note/tutorial/case_study/comparison); «وصول مبكر مجاني» champagne strip.
  • Notice strip: the early-access notice on articles — champagne-tinted band, verbatim copy from PRD §3.2, never a modal.
  • Guide card: surface card, dek line, meta row (category · reading minutes · «حُدّث»), champagne hover seam. Topic hubs and «ابدأ من هنا» reuse it.
  • Article body: headings, paragraphs, lists, blockquote, code (LTR island, scrollable), real <table> for tabular data (never screenshot/ASCII), links --champagne underline.
  • Forms: label above input, input bg --ink-2, border --seam, error text = the API's Arabic sentence verbatim, loading state disables + keeps label, success replaces form state («تم! سنراسلك عند تفعيل العضوية.»).
  • Tables renderer: for Lexical table nodes — mobile-safe overflow wrapper.

New components: reuse an existing class first, then extend design.css (or the route's CSS) — do not add a component library (no shadcn/radui/MUI) and no Tailwind (decision, 2026-10-11).

6. Motion

  • Durations 150–250ms, ease-out. Hover: border color + 1–2px translate. Entrances: fade/rise ≤8px.
  • No parallax, no infinite loops, no scroll-hijack. Reduced-motion: honor prefers-reduced-motion for any added animation.
  • Micro-interactions (like button) may pulse once on success — once, not looping.

7. Accessibility floor (enforced by npx hyperframes check on the brag video; treat as the site bar too)

  • Contrast: body text ≥ 4.5:1, large text ≥ 3:1 (--stone on --basalt passes; --dim only ≥1.5rem or decorative).
  • Focus visible: 2px --champagne outline on interactive elements.
  • Every image has meaningful Arabic alt (covers: the guide title); icon buttons have aria-label.
  • Landmarks: header/nav/main/footer; one H1 per page; heading order never skips.
  • Forms: <label for>, aria-live="polite" status regions (existing pattern: #notify-done).

8. Cover images

Generated via npm run covers (scripts/generate-covers.mjs) — 1200×630, ink/champagne system, Arabic title shaping checked. og:image dimensions are asserted in tests/evidence (1200×630). Don't hand-drop covers of other sizes.