docs: client-approved public-site redesign — PRD 1.4, UX spec v2.0, architecture §6.2, tasks 24-x Ready for Dev

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
This commit is contained in:
Naser Mansour
2026-10-31 18:23:02 +02:00
parent caec396fa4
commit 3d1fe40be6
17 changed files with 1761 additions and 5 deletions
+196
View File
@@ -0,0 +1,196 @@
---
id: 24-4
title: 24-4 Home Page Sections (Hero to Latest Articles)
status: Ready for Dev
date: 2026-10-31
parent: 24
---
## Description
Rebuild `resources/views/livewire/pages/home.blade.php` as the approved redesign, sections 1–7
(hero, pillars, founder, services, vision, values, latest articles). Section 8, the booking card,
is task 24-5; leave a placeholder comment `{{-- booking card: task 24-5 --}}` where it goes. Keep
the component's PHP class as it is (`#[Layout('components.layouts.public')]`, `with()` returning
`latestPosts` = `Post::published()->latest('published_at')->take(3)->get()`). Remove the
temporary `<div class="wrap py-8">` wrapper added in 24-1: each section is full-bleed and holds a
`<div class="wrap">`.
The visual reference is `docs/ux-mockup.html` (commit `caec396`). Port the CSS for each section
from the line ranges below into `resources/css/public.css`, every selector prefixed with
`body.site `, and port the matching responsive rules from lines 293–323. Put `data-reveal` and
`data-d` attributes on the same elements as the mockup (lines 358–506).
### Photography — create `public/images/site/`
Extract these JPEG data URIs from `docs/ux-mockup.html` and save them, decoded, as files (a short
script reading the file and base64-decoding the `src="data:image/jpeg;base64,…"` value on each
line is enough; do not commit the script):
| Mockup line | `<img>` | Save as |
|---|---|---|
| 377 | hero olive tree | `public/images/site/olive-tree.jpg` |
| 447 | embroidery hoop | `public/images/site/embroidery-hoop.jpg` |
| 455 | olives on a branch | `public/images/site/olives.jpg` |
| 459 | hills and road | `public/images/site/hills.jpg` |
The founder portrait uses the existing `public/images/huda-armouche.jpg`. The images are from
Unsplash (licence permits commercial use without attribution); show no credit line.
### Sections (in order, inside the root `<div>`)
1. **Hero** — `<section class="hero" id="top">`; CSS lines 100–125. Two-column grid
(`1fr 1.08fr`, gap 56px; one column ≤1100px). Start column: `.eyebrow` = `site.hero_eyebrow`;
`<h1>` = `{{ __('site.hero_title_a') }}<em>{{ __('site.hero_title_em') }}</em>{{ __('site.hero_title_b') }}`
(the `em` is upright, `--olive`, with `text-decoration: underline dashed var(--gold) .07em;
text-underline-offset:.28em`); `<p class="lede">` = `home.intro`; CTA row: gold button
`home.cta_book` → `#book` with the arrow SVG (mockup line 366), ghost button
`home.cta_services` → `#services`; `.trust` strip with three items, each
`<strong>` + `<span>`: (`site.trust_1_title`, `site.trust_1_text`), (`site.trust_2_title`,
`site.trust_2_text`), (`site.trust_3_title`, `site.trust_3_text`). End column `.hero-art`:
`<figure class="frame">` (aspect 4/4.6, radius `999px 999px 18px 18px`, forest ground,
gradient veil `::before` from `rgba(35,42,28,.35)` to `.9`), containing
`<img src="/images/site/olive-tree.jpg" alt="{{ __('site.alt_olive_tree') }}">` (filter
`saturate(.75) contrast(1.05)`, `scale(1.08)`), `<span class="glow">` (420px radial gold
glow), `<x-site.balance mode="hero" :label="__('site.balance_label')" id="scales" />`
positioned `inset:10% 8% 12%`, and `<figcaption>` = `site.frame_caption` (display italic,
cream .78). Then `<div class="tag">` with `<span class="dot">` (olive, pulsing) and
`site.frame_tag`.
2. **Pillars band** — `<section class="band on-dark" aria-label="{{ __('site.pillars_label') }}">`;
CSS lines 127–137. Three `.pillar` columns: (`site.pillar_justice`, `site.pillar_justice_text`),
(`site.pillar_dignity`, `site.pillar_dignity_text`), (`site.pillar_advocacy`,
`site.pillar_advocacy_text`), each title preceded by `<span class="gem">` (CSS line 210).
3. **Founder** — `<section class="sec" id="founder">`; CSS lines 146–157. Portrait
`/images/huda-armouche.jpg` (alt `home.lawyer_name`) with `.namecard`
(`<b>` `home.lawyer_name`, `<span>` `site.founder_role`). Text column: `.art-no`
`site.art_founder`; `<h2>` `home.about_title`; `<blockquote>` `site.founder_quote`;
paragraphs `home.lawyer_bio` and `home.lawyer_bio_2`; ghost button `site.founder_cta` →
`route('about')`.
4. **Services docket** — `<section class="sec" id="services" style="padding-top:40px">`;
CSS lines 159–174. `x-site.section-head` (see below) with label `site.art_services`, title
`home.services_subtitle`, lede `site.services_lede`. Four `<a class="row" href="#book">` rows:
number `01`–`04` (`.n`), `<h3>` title, `.chips` of the items, `.go` arrow circle. Rows in order:
(`home.service_consultation_title`, `home.service_consultation_items`),
(`home.service_family_title`, `home.service_family_items`),
(`home.service_civil_title`, `home.service_civil_items`),
(`home.service_business_title`, `home.service_business_items`). Items are arrays — render each
as `<span class="chip">`.
5. **Vision** — `<section class="sec fabric" id="mission">`; CSS lines 176–197. Text column:
`.art-no` `site.art_vision`, `<h2>` `site.vision_title`, `<p class="big">` `site.vision_text`;
beside it `.hoop` with `/images/site/embroidery-hoop.jpg` (alt `site.alt_hoop`; filter
`hue-rotate(-140deg) saturate(.55) sepia(.25)`). Below, `.three` grid of `<article class="card">`:
(a) `.ph.motif-ph` containing `<x-site.balance mode="static" />` (150×150px) and label
`site.card_institution_label`, title `site.card_institution_title`, text
`site.card_institution_text`; (b) `.ph` with `/images/site/olives.jpg` (alt `site.alt_olives`),
label `site.card_society_label`, title `site.card_society_title`, text `site.card_society_text`;
(c) `.ph` with `/images/site/hills.jpg` (alt `site.alt_hills`), label
`site.card_diaspora_label`, title `site.card_diaspora_title`, text `site.card_diaspora_text`.
6. **Values** — `<section class="sec" id="values">`; CSS lines 199–212. Section head: label
`site.art_values`, title `home.values_title`, lede `home.values_subtitle`. `.sampler` grid of six
`.val` cards, each `<span class="medal">` with the line icon and `<b>` =
`home.values.<key>.title`, keys in order `integrity`, `justice`, `knowledge`, `empowerment`,
`professionalism`, `innovation`. Icons: the inline SVGs on mockup lines 474–479 in the same
order (24×24 viewBox, `aria-hidden="true"`, stroke `--gold-ink` 1.5, no fill). Replace the
current `flux:icon` usage.
7. **Latest articles** — `<section class="sec" id="posts" style="padding-top:20px">`; CSS lines
214–234. Head: label `site.art_articles`, title `home.posts_title`, and in place of the lede a
ghost button `home.view_all_posts` → `route('posts.index')`. If `$latestPosts` is not empty:
`.posts` grid of `<x-site.post-card :post="$post" />`; otherwise a `<p>` with
`home.posts_empty` (muted, centred).
### Components to create
- **`resources/views/components/site/section-head.blade.php`** — props `label`, `title`,
`lede` (nullable); renders
`<div class="sec-head"><div><span class="art-no" data-reveal>{{ $label }}</span><h2 data-reveal data-d="1">{{ $title }}</h2></div>`
then either `<p data-reveal data-d="2">{{ $lede }}</p>` or the `$slot` (for the button), then
`</div>`.
- **`resources/views/components/site/post-card.blade.php`** — prop `post` (App\Models\Post);
`<a class="post" href="{{ route('posts.show', $post) }}" wire:navigate data-reveal>` →
`<div class="bd">` with `<span class="meta">` = the published date
(`$post->published_at?->translatedFormat('j F Y')`), `<h3>` = `$post->getTitle()`, `<p>` = an
excerpt of `strip_tags($post->getBody())` limited to 140 characters (`Str::limit`), and
`<span class="more">` = `home.read_more`. Text-only: no image element.
### Language keys — add to `lang/ar/site.php` and `lang/en/site.php`
| Key | ar | en |
|---|---|---|
| `hero_eyebrow` | ليبرا للحقوق · فلسطين | Libra for Rights · Palestine |
| `hero_title_a` | العدالة␠ | Justice is a␠ |
| `hero_title_em` | ممارسةٌ يومية | daily practice |
| `hero_title_b` | ، لا مبدأٌ نظري. | , not a theory. |
| `trust_1_title` | أفراد وشركات | Individuals & companies |
| `trust_1_text` | استشارات وتمثيل | Consultations and representation |
| `trust_2_title` | المرأة والأسرة | Women & family |
| `trust_2_text` | دعم قانوني متخصص | Specialised legal support |
| `trust_3_title` | عربي · English | Arabic · English |
| `trust_3_text` | خدمة بلغتين | Bilingual service |
| `alt_olive_tree` | شجرة زيتون معمّرة بين صخور كلسية | An ancient olive tree among limestone rocks |
| `balance_label` | ميزان العدالة | The scales of justice |
| `frame_caption` | لكلّ حقٍّ وزنُه | Every right carries its weight |
| `frame_tag` | استشارات حضورية أو عن بُعد | Consultations in person or remotely |
| `pillars_label` | ركائزنا | Our pillars |
| `pillar_justice` | العدالة | Justice |
| `pillar_justice_text` | الإنصاف، والمساءلة، وسيادة القانون. | Fairness, accountability and the rule of law. |
| `pillar_dignity` | الكرامة | Dignity |
| `pillar_dignity_text` | القيمة الأصيلة لكل إنسان. | The inherent worth of every person. |
| `pillar_advocacy` | الدفاع | Advocacy |
| `pillar_advocacy_text` | انخراطٌ فاعل، وقولُ الحق في وجه السلطة. | Active engagement, and speaking truth to power. |
| `art_founder` | المادة ٠١ — المؤسِّسة | Article 01 — The founder |
| `founder_role` | المؤسِّسة · محامية | Founder · Attorney at Law |
| `founder_quote` | «العدالة ممارسة يومية، وليست مجرد مبدأ نظري.» | “Justice is a daily practice, not merely a theoretical principle.” |
| `founder_cta` | اقرأ قصتنا | Read our story |
| `art_services` | المادة ٠٢ — الخدمات | Article 02 — Services |
| `services_lede` | ممارسة قانونية أصيلة، تقوم على البحث والمعرفة الميدانية. | Traditional legal practice, combined with research-driven insight. |
| `art_vision` | المادة ٠٣ — الرؤية | Article 03 — Vision |
| `vision_title` | منسوجةٌ من نسيج المجتمع | Woven from the fabric of society |
| `vision_text` | ليبرا نسيجٌ أصيل من المجتمع، تتقصّى مشكلاته وتوثّقها وتكشف جذورها، وتقدّم حلولاً عملية لرأب أوجاعه مهما صغرت، عبر العمل التشاركي والبحث الميداني الحقيقي. | Libra investigates society's problems, documents them, uncovers their roots, and offers practical solutions to mend social pains — however small — through collaborative work and genuine field research. |
| `alt_hoop` | تطريز بغرزة الصليب مشدود على طارة خشبية | Cross-stitch embroidery stretched on a wooden hoop |
| `card_institution_label` | لمؤسستنا | For our institution |
| `card_institution_title` | القانون والبحث والميدان | Law, research and fieldwork |
| `card_institution_text` | نلتقط نبض المجتمع ونحوّل تحدياته إلى معرفة وحلول قانونية مبتكرة. | Capturing society's pulse and turning its challenges into knowledge and innovative legal solutions. |
| `alt_olives` | ثمار زيتون على غصن | Olives ripening on a branch |
| `card_society_label` | للمجتمع | For society |
| `card_society_title` | شريكٌ موثوق للقضاء | A trusted partner to the judiciary |
| `card_society_text` | نعيد وصل المجتمع بتاريخه وإرثه القانوني. | Reconnecting society with its history and legal heritage. |
| `alt_hills` | تلال وطريق متعرّج عند الغروب | Hills and a winding road at sunset |
| `card_diaspora_label` | لفلسطينيي الشتات | For Palestinians in the diaspora |
| `card_diaspora_title` | عودةٌ إلى الأرض والعائلة | Back to the land and the family |
| `card_diaspora_text` | نساعد الفلسطينيين في الخارج على البحث في عائلاتهم وتاريخهم وأراضيهم. | Helping Palestinians abroad research their families, their history and their land. |
| `art_values` | المادة ٠٤ — القيم | Article 04 — Values |
| `art_articles` | المادة ٠٥ — المقالات | Article 05 — Articles |
`␠` marks a trailing space that must be kept in the value.
### Files
- Create: `public/images/site/olive-tree.jpg`, `public/images/site/embroidery-hoop.jpg`,
`public/images/site/olives.jpg`, `public/images/site/hills.jpg`,
`resources/views/components/site/section-head.blade.php`,
`resources/views/components/site/post-card.blade.php`.
- Modify: `resources/views/livewire/pages/home.blade.php`, `resources/css/public.css`,
`lang/ar/site.php`, `lang/en/site.php`.
- Do not edit `lang/*/home.php`.
## Acceptance Criteria
- [ ] `/` renders, in order, sections with ids `top`, (the pillars band), `founder`, `services`,
`mission`, `values`, `posts`, each with its content from the keys above in both Arabic and
English (switch with `/language/en`).
- [ ] `/` has exactly one `<h1>`, and every `<img>` has a non-empty `alt` in both languages.
- [ ] The four files in `public/images/site/` exist, are valid JPEGs (`file` reports JPEG image
data) and load with HTTP 200 on `/`.
- [ ] The hero balance renders inside the hero frame and settles level (task 24-3 behaviour).
- [ ] Each services row links to `#book`; each row shows the item chips from `home.php`.
- [ ] With three or more published posts, three post cards show date, title, excerpt and "Read
more", link to `/posts/{post}`, and contain no `<img>`; with no published posts, the
`home.posts_empty` text shows instead of the grid.
- [ ] At 1440, 768 and 390px wide, `/` has no horizontal scroll (`document.documentElement.scrollWidth <= innerWidth`).
- [ ] Hovering a service row fills it forest with cream text; hovering a value card lifts it and
rotates its medallion; hovering a post card lifts it.
- [ ] The page contains no "Unsplash" text and `lang/*/home.php` is unchanged against BASE.
## Sub-tasks
None.