88c0a65aa9
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
457 lines
30 KiB
Markdown
457 lines
30 KiB
Markdown
# UX Design Spec: Libra for Rights — Public-Site Redesign
|
||
**Version:** 2.0
|
||
**Date:** 2026-10-31
|
||
**Status:** Approved (client approved mockup v3 on 2026-10-31)
|
||
**Visual mockup:** `docs/ux-mockup.html` (open in a browser to view; v3, commit `caec396`)
|
||
|
||
This file has two parts:
|
||
|
||
- **Part A — Public site (redesign, approved 2026-10-31).** Governs every page rendered through
|
||
`resources/views/components/layouts/public.blade.php` and the auth layouts' type and controls.
|
||
- **Part B — Dashboards, emails and the Nablus form (unchanged).** The retrospective record of the
|
||
design system as built before the redesign. It still governs the admin and client dashboards,
|
||
the emails and `/forms/nablus-workshop`, none of which the redesign touches.
|
||
|
||
Where Part A and Part B disagree about a public page, Part A wins.
|
||
|
||
---
|
||
|
||
# Part A — Public site
|
||
|
||
## Design Direction
|
||
|
||
Arabic-first, editorial and quiet: the firm reads like a well-bound legal document, not a tech
|
||
product. The brand palette (forest, gold, cream, olive) is kept and used with more confidence —
|
||
large forest bands, gold as thread and rule, cream as linen. Headlines are set in an editorial
|
||
naskh serif (Markazi Text); body in IBM Plex Sans Arabic. Sections are numbered like articles of
|
||
a statute ("المادة ٠١ — المؤسِّسة"). The signature is an engraved-gold balance over olive-tree
|
||
photography that settles into level on load and is weighed by the visitor's pointer. Tatreez
|
||
appears only inside real photography — Naser ruled out drawn cross-stitch ("drawing using xxx and
|
||
other symbols is more of a tech stuff not lawyers", 2026-10-31). Every claim on the page is backed
|
||
by the code (code-fit check, 2026-10-31): no availability promises, no response-time promises, no
|
||
article images.
|
||
|
||
**Layout default:** desktop-first; every layout works at 768px and 390px with no horizontal scroll.
|
||
|
||
**Scope:** public pages only — home `/`, about `/about`, posts `/posts` and `/posts/{post}`,
|
||
booking `/booking` and `/booking/success`, legal `/page/{slug}` (terms, privacy), and the auth
|
||
pages (type and controls only, see *Auth pages*). Out of scope: admin and client dashboards,
|
||
emails, PDFs, `/forms/nablus-workshop`.
|
||
|
||
## Layout & Navigation
|
||
|
||
- **Containment.** The public layout no longer wraps pages in one padded 1200px container; each
|
||
page section is full-bleed and places its own content in a `.wrap` container:
|
||
`max-width: 1200px; margin-inline: auto; padding-inline: 28px` (18px at ≤760px).
|
||
- **Section rhythm.** Standard section padding 120px top and bottom (80px at ≤760px). Section
|
||
header (`.sec-head`): flex row, items aligned to the end, space-between, gap 32px, wrap,
|
||
margin-bottom 54px; left side holds the article label and h2, right side a muted lede
|
||
(max-width 30em).
|
||
- **Article label** (`.art-no`): display font, 1.15rem, weight 600, `--gold-ink`. Format
|
||
`المادة ٠N — <name>` / `Article 0N — <Name>` (Arabic-Indic digits in Arabic).
|
||
- **Eyebrow** (`.eyebrow`): 0.82rem, weight 600, `--gold-ink`, preceded by a 22×2px rule in
|
||
currentColor with 10px gap; in English 0.74rem, uppercase, letter-spacing .16em. Arabic text
|
||
never gets letter-spacing (it breaks joining).
|
||
- **Navigation** (sticky, top 0, z 50, height 72px): background `rgba(244,241,234,.82)` with
|
||
`backdrop-filter: blur(14px) saturate(1.2)`; bottom border transparent until the page has
|
||
scrolled more than 8px, then `1px solid var(--line)` plus shadow `0 8px 24px -18px
|
||
rgba(30,34,25,.5)`. Order (start → end): brand (seal + wordmark), links, then tools (language
|
||
toggle, client login, gold "Book a consultation" button). Links: Home, About, Services (→
|
||
`/#services`), Articles (→ `/posts`), Booking (→ `/booking`). Link style: 10px 14px padding,
|
||
weight 500, .95rem; hover colour `--olive`; a 2px dashed gold underline (4px dash, 3px gap)
|
||
scales in from the inline-start edge on hover and stays on the current page's link
|
||
(`aria-current="page"`). Logged-in visitors see "Dashboard" (to their role's dashboard) and
|
||
"Log out" in place of "Client login", as today.
|
||
- **Brand mark:** a 46×46px "seal" — `public/images/logo.png` as a cover background on white,
|
||
2px solid `#1A1A1A` border, shadow `3px 3px 5px rgba(26,26,26,.35)` — followed by the wordmark:
|
||
«ليبرا» (display font, 1.35rem) over «للحقوق» (.72rem, muted). English: "Libra" over
|
||
"FOR RIGHTS" (letter-spacing .12em).
|
||
- **Mobile (≤1100px):** links hide; a 44×44px menu button (1.5px `--line` border, radius 10px,
|
||
white) opens the existing Alpine mobile menu, restyled as a cream sheet below the nav with
|
||
full-width 48px rows. At ≤760px the nav's gold button and the client-login link also hide (both
|
||
remain inside the sheet).
|
||
- **Reading progress rule:** a fixed 2px bar at the very top of the viewport (z 60), gradient
|
||
`#8A7555 → #E2CDA4 → #A68966`, `transform: scaleX(p)` where p = scrollY / (scrollHeight −
|
||
innerHeight); origin is the inline-start edge (right in RTL, left in LTR). Decorative
|
||
(`aria-hidden`).
|
||
- **Footer:** background `--forest-2` (#232A1C), text `--gold-lt`, margin-top 120px, padding 72px 0
|
||
28px, .92rem. A 1px top hairline: horizontal gradient transparent → `rgba(196,168,130,.7)` →
|
||
transparent. Four columns (1.4fr 1fr 1fr 1fr, gap 40px; 2 columns ≤1100px; 1 column ≤760px):
|
||
(1) brand mark with cream wordmark and the tagline «ملتزمون بالعدالة – متجذرون بالكرامة – مدفوعون
|
||
للدفاع»; (2) "Explore": About, Services, Articles, Booking; (3) "Clients": Client login, Terms of
|
||
use, Privacy policy; (4) "Contact": phone (LTR), email, address. Column headings: display font,
|
||
1.15rem, cream. Links: 10px vertical padding, hover → cream and a 3px nudge toward the
|
||
inline-start. Bottom row: copyright, top border `rgba(244,241,234,.1)`, .8rem. No photography
|
||
credit line.
|
||
|
||
## Visual Style
|
||
|
||
### Color Palette
|
||
|
||
| Token | Hex | Use |
|
||
|---|---|---|
|
||
| `--forest` | `#2D3624` | hero frame ground, pillar band, booking card, hover fill of service rows |
|
||
| `--forest-2` | `#232A1C` | footer only (depth) |
|
||
| `--gold` | `#A68966` | gold buttons, rules, row numbers, focus ring |
|
||
| `--gold-ink` | `#7A6648` | gold text on cream (labels, dates) — darkened from the brand gold-hover `#8A7555` on 2026-10-31 so small text meets WCAG AA (4.9:1 on cream, 5.5:1 on white) |
|
||
| `--gold-lt` | `#C4A882` | small gold text on forest |
|
||
| `--cream` | `#F4F1EA` | page ground |
|
||
| `--olive` | `#4A5D23` | link hover, emphasis word in the hero, active accents |
|
||
| `--ink` | `#1E2219` | body and heading text |
|
||
| `--muted` | `#5B6152` | secondary text |
|
||
| `--line` | `rgba(45,54,36,.14)` | hairlines and borders |
|
||
| fabric ground | `#ECE7DC` | background of the Vision section |
|
||
|
||
The palette is the brand's own (`docs/brand.md`); `--ink`, `--muted`, `--forest-2` and the fabric
|
||
ground are darker/lighter steps of it, added for contrast and depth. Status colours (success,
|
||
danger, warning) are unchanged from Part B.
|
||
|
||
**Page ground:** `--cream` with a linen weave —
|
||
`repeating-linear-gradient(0deg, rgba(45,54,36,.025) 0 1px, transparent 1px 3px),
|
||
repeating-linear-gradient(90deg, rgba(45,54,36,.022) 0 1px, transparent 1px 4px)`.
|
||
|
||
**Shadows:** `--shadow-1: 0 1px 2px rgba(30,34,25,.06), 0 4px 14px rgba(30,34,25,.06)`;
|
||
`--shadow-2: 0 2px 4px rgba(30,34,25,.08), 0 18px 40px -12px rgba(30,34,25,.28)`.
|
||
**Easing:** `--ease: cubic-bezier(.2,.7,.2,1)`. **Radius:** cards 16px, buttons and chips 999px,
|
||
inputs 12px.
|
||
|
||
### Typography
|
||
|
||
- **Display** (h1–h3, article labels, blockquotes, numbers): **Markazi Text**, weights 400–700,
|
||
fallback `"Times New Roman", serif`. Headings weight 700, line-height 1.25.
|
||
- **Body and UI:** **IBM Plex Sans Arabic**, weights 300–600, fallback `system-ui, sans-serif`.
|
||
17px, line-height 1.75 (16px at ≤760px). Both families carry Latin glyphs, so English uses the
|
||
same two families.
|
||
- Loaded from Google Fonts with `display=swap`, on the public and auth layouts only. The dashboards
|
||
keep Cairo/Montserrat.
|
||
- Sizes: hero h1 `clamp(2.6rem, 4.6vw, 4.1rem)`, line-height 1.12, word-spacing .08em (English:
|
||
letter-spacing −.02em); section h2 `clamp(2rem, 3.4vw, 3rem)`; row h3 1.65rem; card h3 1.4rem;
|
||
post h3 1.35rem; lede 1.15rem.
|
||
|
||
### Tone & Style
|
||
|
||
Editorial, warm, unhurried. Real photography only (olive tree, embroidery on a hoop, olives,
|
||
hills, the founder's portrait). No drawn cross-stitch, no gradient blobs, no carousels. Depth comes
|
||
from layered shadows, gold hairlines and the engraved balance.
|
||
|
||
### Buttons
|
||
|
||
- **Gold** (`.btn-gold`): pill (radius 999px), min-height 48px, padding 12px 26px, weight 600,
|
||
background `--gold`, text `--ink`, shadow `0 1px 0 rgba(255,255,255,.35) inset, 0 8px 22px -8px
|
||
rgba(166,137,102,.8)`. Hover: lift 2px, deeper glow plus a 6px `rgba(166,137,102,.14)` halo, and
|
||
a white shimmer (105° gradient, 30–70%) sweeps across in .7s.
|
||
- **Ghost** (`.btn-ghost`): transparent, 1.5px inset `--forest` ring, text `--ink`. Hover: fills
|
||
`--forest`, text cream, lift 2px. On dark grounds: cream text and a `rgba(244,241,234,.6)` ring;
|
||
hover fills cream with forest text.
|
||
- An arrow icon inside a button nudges 4px toward the reading direction on hover; it is mirrored
|
||
in LTR.
|
||
- Focus (all controls): `outline: 2px solid var(--gold); outline-offset: 3px`.
|
||
|
||
## Key Screens / Flows
|
||
|
||
### Home `/`
|
||
|
||
Top to bottom (content is real; copy keys are listed in the tasks):
|
||
|
||
1. **Hero** — two columns (1fr : 1.08fr, gap 56px; one column ≤1100px). Start column: eyebrow
|
||
«ليبرا للحقوق · فلسطين»; h1 «العدالة *ممارسةٌ يومية*، لا مبدأٌ نظري.» with the emphasised phrase
|
||
in `--olive` and a dashed gold underline; lede (the existing `home.intro`); gold "Book a
|
||
consultation" (→ `#book`) and ghost "Our services" (→ `#services`); a trust strip of three
|
||
items separated from the CTAs by a hairline: «أفراد وشركات / استشارات وتمثيل», «المرأة والأسرة /
|
||
دعم قانوني متخصص», «عربي · English / خدمة بلغتين». End column: the **balance frame** (see
|
||
Signature Moment): an arched frame (aspect 4:4.6, radius 999px 999px 18px 18px) holding the
|
||
olive-tree photo under a forest gradient veil, a soft gold glow, the gold balance, and the
|
||
italic caption «لكلّ حقٍّ وزنُه». A cream tag with a pulsing olive dot overlaps the frame edge:
|
||
«استشارات حضورية أو عن بُعد».
|
||
2. **Pillars band** — full-bleed forest band, three columns divided by cream hairlines: Justice,
|
||
Dignity, Advocacy, each with a gold gem (12px rotated square) and a one-line gloss in
|
||
`--gold-lt`. Hover lightens the column background.
|
||
3. **Founder** (Article 01) — portrait (aspect 4:5, radius 18px, greyscale, an inset dashed gold
|
||
frame, a cream name card «هدى عرموش / المؤسِّسة · محامية»), h2 «تعرّف على المؤسِّسة», a pull
|
||
quote «العدالة ممارسة يومية، وليست مجرد مبدأ نظري.» (display font, gold inline-start rule), the
|
||
two bio paragraphs, and a ghost "Read our story" → `/about`. Hover on the portrait restores some
|
||
colour and scales it 3%.
|
||
4. **Services docket** (Article 02) — four rows, each a link to `#book`: big gold number, title,
|
||
chips of the service's items, a round arrow button. Hover: the row fills forest, text turns
|
||
cream, chips go gold-light, the arrow fills gold, a dashed gold inner border appears, lift 2px.
|
||
5. **Vision** (Article 03, fabric ground `#ECE7DC`) — text column (h2 «منسوجةٌ من نسيج المجتمع»
|
||
and a display-font paragraph) beside the embroidery-hoop photo (circular, two gold ring
|
||
shadows). Below it, three cards: "For our institution" (forest panel with a static balance),
|
||
"For society" (olives photo), "For Palestinians in the diaspora" (hills photo); each with an
|
||
italic label on the image, a title and one line.
|
||
6. **Values** (Article 04) — six cards in a row (3 ≤1100px, 2 ≤760px): a gold-ringed medallion
|
||
with a fine-line icon, and the value name. Hover: card lifts and tilts −0.6°, the medallion
|
||
rotates −8°, gains a gold glow, the icon turns olive.
|
||
7. **Latest articles** (Article 05) — the three most recent published posts as text-only cards
|
||
(date, title, excerpt, "Read more"), gold top border turning olive on hover, a large faint
|
||
quotation mark in the corner; "View all articles" ghost button → `/posts`. No post → the
|
||
existing "Articles coming soon" line in place of the grid.
|
||
8. **Booking card** (Article 06, `id="book"`) — one rounded (28px) forest card in two columns:
|
||
start panel with h2 "Book a consultation", the lede «اختر يوماً ووقتاً متاحَين، وأخبرنا باختصار
|
||
عن قضيتك. نراجع كل طلب ونؤكّد الموعد بالبريد الإلكتروني — دون الحاجة إلى حساب.», phone, email,
|
||
address, and the finale balance (190px); end panel is a cream inset form (see *Booking flow*).
|
||
|
||
### Booking flow (home card and `/booking`)
|
||
|
||
Both surfaces run the existing guest-booking component and its rules unchanged: name, email,
|
||
phone (all required), a case summary (required, minimum 20 characters), the math captcha, one
|
||
booking per email per day, slots from `AvailabilityService`, the existing confirm step, and the
|
||
redirect to `/booking/success`. Logged-in visitors see the existing "you are logged in" message,
|
||
restyled, in place of the form.
|
||
|
||
- **Home card (compact):** fields in this order — name and phone side by side, email, a **day
|
||
strip**, a **slot row**, the case summary, the captcha, the gold submit "Request this
|
||
appointment" (full width), and the note «ملاحظة: يمكنك حجز استشارة واحدة كحدّ أقصى في اليوم.».
|
||
The day strip shows the next 14 calendar days that have at least one available slot, as
|
||
66×72px buttons (weekday name over the day number), horizontally scrollable; the first is
|
||
pre-selected. Selected day: forest fill, cream number. The slot row shows that day's available
|
||
slots as pill buttons (min-height 44px); selected slot: gold fill. Both use `aria-pressed`.
|
||
Submit opens the existing confirm step inside the same card (summary of date, time and contact,
|
||
with Confirm and Back).
|
||
- **`/booking` page:** the same two-panel forest card, full page; the end panel keeps the month
|
||
calendar (the existing component, restyled: cream ground, 44px day cells, selected day forest,
|
||
available days with a gold dot, unavailable days muted), then the fields and confirm step.
|
||
- **Inputs:** min-height 48px, padding 12px 16px, radius 12px, 1.5px border `rgba(45,54,36,.18)`,
|
||
white; focus: border `--gold` plus a 4px `rgba(166,137,102,.2)` ring. Labels .85rem, weight 600.
|
||
Errors: the existing message under the field, in the danger colour.
|
||
- **`/booking/success`:** a centred cream card on the linen ground with a small level balance, the
|
||
existing success copy and a ghost button home.
|
||
|
||
### About `/about`
|
||
|
||
The same system, existing content only (no new copy beyond section labels): hero (eyebrow, h1
|
||
from `about.title`, the tagline, the identity statement), Vision and Mission (the fabric section
|
||
pattern; the three mission cards with the olives, hills and static-balance panels), Values (the
|
||
medallion row), Goals (a numbered docket list: gold display numbers, no chips, no links), Legal
|
||
services (the docket rows, linking to `/booking`), closing gold CTA to `/booking`.
|
||
|
||
### Articles `/posts` and `/posts/{post}`
|
||
|
||
- **Index:** page head (article label, h2 "Articles"), the existing search field restyled as a
|
||
pill input, the text-only post cards in a three-column grid (2 ≤1100px, 1 ≤760px), the existing
|
||
pagination restyled (pill buttons, current page forest).
|
||
- **Show:** a reading column max-width 720px; date in `--gold-ink`; title in the display font
|
||
`clamp(2rem, 3.4vw, 3rem)`; body in the existing prose styles with headings in the display font
|
||
and links in `--olive`; a "Back to articles" ghost button.
|
||
|
||
### Legal pages `/page/{slug}`
|
||
|
||
Reading column max-width 720px, display-font title, existing prose body.
|
||
|
||
### Auth pages (login, forgot/reset password, confirm password, verify email)
|
||
|
||
Type and controls only: the auth layouts load the two new families and apply the input, focus and
|
||
gold-button styles above. The split composition (forest panel with the logo, cream form panel) and
|
||
the existing auth pattern stay as they are.
|
||
|
||
## Signature Moment
|
||
|
||
**Element:** an engraved-gold balance (scales of justice) drawn as layered SVG — gradient-filled
|
||
beam, pillar, olive-leaf finial, base and two pans with a drop shadow — standing over the
|
||
olive-tree photograph in the hero frame. A second instance (the "finale", 190px) sits in the
|
||
booking card; a static instance fills the "For our institution" card.
|
||
**Built from:** the firm's own name — Libra, the balance — and the olive tree of the region; the
|
||
photograph is real.
|
||
**Trigger:** page load; pointer movement over the hero frame (fine pointers only); scroll position
|
||
for the finale.
|
||
**Mapping:**
|
||
- Load: the hero beam starts tilted 14° and, after 450ms, a damped spring settles it to 0°
|
||
(per frame: `v += (target − a) × 0.028; v ×= 0.935; a += v`; stop when |v| < 0.002 and
|
||
|target − a| < 0.01).
|
||
- Pointer: x = (clientX − frame.left) / frame.width; target = clamp((x − 0.5) × 2.4, −1, 1) × 9°.
|
||
The gold glow follows the pointer; the photo pans opposite the pointer by
|
||
`(pointer − centre) / −40` px at scale 1.08. Pointer leave → target 0°, photo resets.
|
||
- Pans hang from the beam ends: for beam angle θ, pan centres are at (200 ∓ 142·cos θ,
|
||
110 ∓ 142·sin θ) in the 400×400 viewBox, so they stay vertical while the beam tips.
|
||
- Finale: with p the page progress, q = clamp((p − 0.7) / 0.25, 0, 1); target = −12° × (1 − q), so
|
||
the balance comes level as the reader reaches the booking card.
|
||
**Tech suggestion:** an inline SVG Blade component and a small vanilla JS module
|
||
(`requestAnimationFrame`); no library.
|
||
**Reduced-motion fallback:** all balances render level (0°), no spring, no pointer response, no
|
||
glow movement; the photo stays still.
|
||
|
||
## Interaction Patterns (secondary)
|
||
|
||
- **Entrance choreography:** elements marked `data-reveal` start at opacity 0 and translateY 28px
|
||
and transition (.9s, `--ease`) to rest when 8% inside the viewport (IntersectionObserver,
|
||
`rootMargin: 0px 0px -8% 0px`, observe once). Delays by `data-d` 1–5: .08s steps. Content stays
|
||
visible if JavaScript fails (the hidden state applies only once the script adds a `js` class).
|
||
- **Hover depth:** cards lift 6px with `--shadow-2` and a gold border `rgba(166,137,102,.55)`;
|
||
card images scale 1.05–1.06 over .8s.
|
||
- **Language toggle:** the existing `/language/{locale}` route; a 48×44px pill showing "EN" in
|
||
Arabic and "ع" in English.
|
||
- **Reduced motion:** `@media (prefers-reduced-motion: reduce)` disables every animation and
|
||
transition on the public pages and shows all `data-reveal` content at rest.
|
||
- **Touch targets:** every interactive element at least 44×44px.
|
||
- **RTL/LTR:** logical properties throughout; arrows and the progress rule's origin mirror.
|
||
|
||
## Design Decisions & Rationale
|
||
|
||
- **Markazi Text + IBM Plex Sans Arabic** — Amiri's calligraphic ligatures broke in large
|
||
headlines; Markazi is an editorial naskh with a matching Latin serif (brand.md asks for a serif
|
||
headline); Plex Arabic is highly legible at body size. Two families total.
|
||
- **Balance over olive photography, no drawn tatreez** — Naser rejected the cross-stitch drawings
|
||
as "tech stuff"; the balance is the firm's name and reads as law at a glance.
|
||
- **Article numbering** — frames the firm's content in the language of a statute; costs nothing.
|
||
- **Text-only article cards** — posts have no image field (code-fit check); no images are promised.
|
||
- **Copy limited to what the code backs** — no availability or response-time claims; booking copy
|
||
is drawn from the existing lang strings.
|
||
- **Public-only scope** — the dashboards share global tokens and `.btn` classes; the redesign is
|
||
scoped to the public layout so no dashboard screen changes.
|
||
- **Compact booking on the home page** — the client approved a one-screen form; it reuses the same
|
||
component and rules, so the backend does not change.
|
||
|
||
## Open Questions
|
||
|
||
None blocking. Rulings taken for the build (ledger, 2026-10-31):
|
||
|
||
1. **Photography** — the mockup's four Unsplash photos (olive tree, embroidery hoop, olives, hills)
|
||
ship as the production images; the Unsplash licence allows commercial use without attribution.
|
||
The client may replace them later with their own.
|
||
2. **Home day strip** — the next 14 calendar days with an available slot; `/booking` keeps the
|
||
month calendar.
|
||
3. **Pages the mockup does not show** (about, articles, booking page, success, legal) — composed
|
||
from the homepage's components with their existing content; no new sections.
|
||
4. **Auth pages** — type and controls only; composition unchanged.
|
||
|
||
---
|
||
|
||
# Part B — Dashboards, emails and the Nablus form (pre-redesign record)
|
||
|
||
|
||
Retrospective documentation of the design system as it is currently **built and live**. This
|
||
is not a proposal — it describes what shipped, so a dev/QA agent picking up a new task can match
|
||
existing patterns rather than invent new ones. Synthesized from `docs/brand.md`, epics 9/10/12/13/14/16,
|
||
and the root `CLAUDE.md`.
|
||
|
||
## Brand colors (current — source of truth: `docs/brand.md`)
|
||
|
||
The palette has changed twice since the original PRD. **Use the values below**, from `docs/brand.md`,
|
||
for any new work — they are the most recent and match what Epic 12 shipped.
|
||
|
||
| Token | Hex | Usage |
|
||
|---|---|---|
|
||
| Primary — Dark Forest Green | `#2D3624` | Header/footer backgrounds |
|
||
| CTA — Warm Gold | `#A68966` | Buttons, links, accents |
|
||
| Background — Warm Cream | `#F4F1EA` | Main page background |
|
||
| Text — Forest Green | `#2D322A` | Headings, body text |
|
||
| Card — Pure White | `#FFFFFF` | Card backgrounds |
|
||
| Active — Olive Green | `#4A5D23` | Active states, language toggle |
|
||
| Primary Light | `#3D4634` | Primary hover state |
|
||
| CTA Hover | `#8A7555` | Button hover state |
|
||
| CTA Light | `#C4A882` | Light accents |
|
||
| Active Hover | `#5A7030` | Active-state hover |
|
||
| Deep Black | `#1A1A1A` | Logo artwork, headline emphasis |
|
||
|
||
**History (do not use these for new work, they are superseded):**
|
||
- Epic 1 / PRD / Epic 9 originally specified **Navy Blue `#0A1F44` + Gold `#D4AF37`**.
|
||
- Epic 10 ("Brand Color Refresh") replaced that with **Charcoal `#4A4A42` + Warm Gray `#C9C4BA`**.
|
||
- Epic 12 ("Branding Refresh") replaced *that* with the **Dark Forest Green + Warm Gold** palette
|
||
above, which is what `docs/brand.md` documents and what is currently live. Epic 9's own stories
|
||
(button/form/card specs) still reference the original Navy+Gold hex values — treat those as
|
||
structural/pattern guidance only (border-radius, padding, states) and substitute the current
|
||
hex values from the table above.
|
||
|
||
## Typography
|
||
|
||
- **Arabic:** Cairo or Tajawal (Google Fonts), weights Light 300 / Regular 400 / SemiBold 600 / Bold 700.
|
||
- **English:** Montserrat or Lato, same weight set.
|
||
- `docs/brand.md` additionally suggests a serif (Playfair Display / Libre Baskerville) for the
|
||
organization name/headline treatment and an italic serif for taglines, with a sans body
|
||
(Source Sans Pro / Open Sans / Inter) — this is brand-identity guidance; the app itself
|
||
implements the Cairo/Tajawal + Montserrat/Lato pairing from Epic 9.2.
|
||
- **Hierarchy:** H1 Bold 2.5rem/40px · H2 SemiBold 2rem/32px · H3 SemiBold 1.5rem/24px ·
|
||
Body Regular 1rem/16px · Small Regular 0.875rem/14px.
|
||
- Line height: 1.6 body, 1.3 headings.
|
||
- `font-display: swap`, critical fonts preloaded, loaded via Google Fonts + Tailwind `font-family`
|
||
config with `@font-face` fallbacks.
|
||
|
||
## Layout system
|
||
|
||
- Container max-width: **1200px**.
|
||
- Card padding: 24px; card border-radius: 8px; card shadow `0 2px 8px rgba(0,0,0,0.1)`, with a
|
||
subtle lift + shadow increase on hover.
|
||
- Button padding 12px 24px, border-radius 6px; input/textarea padding 12px 16px, border-radius 6px,
|
||
textarea min-height 120px.
|
||
- **Breakpoints:** Mobile `<576px` · Tablet `576–991px` · Desktop `992–1199px` · Large Desktop `>=1200px`.
|
||
Mobile-first: single-column + collapsible sections on mobile, two-column/collapsible sidebar on
|
||
tablet, full multi-column grid + sidebars on desktop. Touch targets >= 44px. Tables scroll
|
||
horizontally on small screens; calendar and forms must remain usable on mobile.
|
||
- Transitions are short and subtle: button hover 150ms ease, card hover 200ms ease, modal
|
||
open/close 200ms, all under 300ms — and must respect `prefers-reduced-motion` (no auto-playing
|
||
animations).
|
||
|
||
## Component patterns (Epic 9 stories 9.4–9.7)
|
||
|
||
- **Buttons:** primary = CTA-gold background / dark text, hover to CTA-hover; secondary =
|
||
transparent with gold border + gold text, hover fills gold with dark text; disabled = flat gray
|
||
background/text, no hover, `cursor: not-allowed`; danger = solid red (`#E74C3C`) with white text.
|
||
Loading state shows a spinner; all buttons have a visible focus state. Built by extending Flux UI's
|
||
button component with Tailwind component classes.
|
||
- **Forms:** inputs/textareas/selects share consistent border + radius, gold border on focus;
|
||
selects and checkboxes/radios are custom-styled (not native) with gold accents on
|
||
checked/selected state; labels are SemiBold with a `*` required indicator; errors show a red
|
||
border plus a message rendered directly below the field. Built on Flux UI form components with
|
||
explicit RTL alignment handling.
|
||
- **Cards/containers:** off-white/cream background, optional gold top/left accent border for
|
||
featured or important cards; dashboard stat cards add a gold-accented icon, a large number, and
|
||
a trend indicator; list cards use consistent item spacing and clear click targets. Implemented as
|
||
a reusable Blade card component with variant props.
|
||
- **Navigation/footer:** fixed-top nav, brand-primary background, logo left on desktop / centered
|
||
on mobile, gold link text with an active-link indicator, styled language toggle, and a full-width
|
||
slide/dropdown mobile menu (Alpine.js) with 44px+ touch targets. Footer shares the brand-primary
|
||
background and carries logo + firm info, contact details, Terms/Privacy links, and copyright; it
|
||
stays pinned to the bottom of short pages (sticky footer).
|
||
|
||
## Bilingual / RTL–LTR rules
|
||
|
||
- Arabic is primary and renders RTL; English is secondary, LTR. `dir="rtl"` is set on `<html>` for
|
||
Arabic; layout uses Tailwind's RTL support and logical properties (`start`/`end` rather than
|
||
`left`/`right`) so components flip automatically rather than needing per-direction overrides.
|
||
- In RTL: text aligns right, navigation mirrors (logo moves to the right), form labels sit on the
|
||
right, directional icons/arrows flip, and margins/paddings swap sides.
|
||
- Switching language must not break layout — calendars and tables must render correctly in both
|
||
directions, and every component is expected to be tested in both.
|
||
- All user-facing strings live in language files (`ar`/`en`); there is no hardcoded UI copy.
|
||
|
||
## Key page layouts
|
||
|
||
- **Home** (Epic 14): Navigation → Hero (tagline + intro + CTA buttons, Warm Cream background) →
|
||
About (Huda Armouche's photo + bio) → Services (4 cards: Consultations, Representation,
|
||
Litigation, Contracts) → Values (6 icon cards) → Latest Posts (3 most recent published posts,
|
||
pulled live via `Post::where('status','published')->latest()->take(3)->get()`, with a "View All"
|
||
link) → Footer (phone + address + links). Sections alternate between Warm Cream and White
|
||
backgrounds; CTAs use Warm Gold.
|
||
- **About Us** (Epic 16, new page at `/about`): Navigation → Hero (title + identity statement) →
|
||
Vision & Mission (three-fold: For Itself / For Society / For Diaspora, card layout) → Values
|
||
(6 core values: Integrity, Justice, Knowledge, Women's Empowerment, Professionalism, Social
|
||
Innovation) → Goals (7 goals, numbered/scannable) → Legal Services (grouped by category:
|
||
consultations, litigation, family law, business services) → Footer. (A Scholarship Aspiration
|
||
section was built under this epic but removed from `/about` entirely on 2026-01-11 at Naser's
|
||
request — do not re-add without confirming; see `docs/tasks/16-6.md`.)
|
||
- **Auth pages** (Epic 13 — login, forgot/reset password, confirm-password, email verify): the
|
||
2FA challenge page exists in code but is currently dormant — 2FA has been disabled in production
|
||
since 2026-01-17 (see root `CLAUDE.md` Authentication section). Split-screen layout. Left panel: Dark Forest Green (`#2D3624`) background with the
|
||
LIBRA logo centered. Right panel: Warm Cream background with a subtle SVG botanical/geometric
|
||
background pattern (low-opacity brand colors) behind the form. On mobile, only the form side
|
||
shows, with the logo displayed above it. The language toggle's `light` variant was darkened
|
||
(`text-primary` instead of `text-body/70`) specifically for visibility on this light panel,
|
||
without changing its appearance on the dark public-nav background.
|
||
- **Dashboards** (Epics 6 admin / 7 client): standard authenticated-app shell — nav/sidebar +
|
||
content area using the same card, button, and table components as the rest of the app. Admin
|
||
dashboard emphasizes stat cards, Chart.js analytics, and data tables with export actions; client
|
||
dashboard is read-mostly (consultations, timelines, profile) with a single primary action
|
||
(submit new booking) and a booking-limit indicator.
|
||
|
||
## Accessibility (WCAG AA — Epic 9.10)
|
||
|
||
- Color contrast: body text >= 4.5:1, large text (18px+ bold or 24px+ regular) >= 3:1, UI elements
|
||
(buttons, borders, icons) >= 3:1. The gold-on-dark-forest-green and text-on-cream combinations
|
||
must be verified against these ratios whenever a color changes.
|
||
- Focus indicators must be visible (a gold outline), never conveyed by color change alone.
|
||
- Full keyboard navigation: every interactive element reachable, logical tab order, a skip-to-main-content
|
||
link.
|
||
- Screen readers: correct heading hierarchy (h1 > h2 > h3), alt text on all images, ARIA labels
|
||
where needed, form labels programmatically associated with their fields.
|
||
- Motion: respect `prefers-reduced-motion`; no auto-playing animations.
|