Files
libra/docs/tasks/24-1.md
T
2026-10-31 19:23:46 +02:00

9.6 KiB
Raw Blame History

id, title, status, date, parent
id title status date parent
24-1 24-1 Public Design Foundation (Stylesheet, Script, Fonts, Layout) Done 2026-10-31 24

Description

Create the shared foundation every later redesign subtask builds on. It must be loaded only by the public layout (and, for the stylesheet only, by the auth layouts in task 24-9), and every rule must be scoped under body.site so the admin and client dashboards are unaffected.

The approved visual reference is the mockup file docs/ux-mockup.html (committed in caec396). Where this task says "port lines X–Y", copy those CSS rules from that file and prefix every selector with body.site (for example .btn-gold → body.site .btn-gold; :root{…} → body.site{…}; body{…} → body.site{…}; html[dir=ltr] .x → html[dir=ltr] body.site .x; html[lang=en] .x → html[lang=en] body.site .x). The mockup's lines contain no images, so line numbers are exact.

Files to create

  1. resources/css/public.css — contains, in this order:
    • Tokens on body.site (from mockup lines 12–29): --forest:#2D3624; --forest-2:#232A1C; --gold:#A68966; --gold-ink:#8A7555; --gold-lt:#C4A882; --cream:#F4F1EA; --olive:#4A5D23; --ink:#1E2219; --muted:#5B6152; --line:rgba(45,54,36,.14); --display:"Markazi Text","Times New Roman",serif; --body:"IBM Plex Sans Arabic",system-ui,sans-serif; --r:10px; --ease:cubic-bezier(.2,.7,.2,1); --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);
    • Page ground and type on body.site (port lines 32–39): font-family:var(--body); color:var(--ink); font-size:17px; line-height:1.75; background-color:var(--cream) plus the linen weave background-image: 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). This overrides the inline style="font-family: var(--font-…)" on the body, so the layout's inline style is removed (see layout changes below).
    • Port lines 40–50 (img, links, .wrap, skip link, focus-visible, h1–h3, .eyebrow, .art-no). .wrap = max-width:1200px; margin-inline:auto; padding-inline:28px. Focus = outline:2px solid var(--gold); outline-offset:3px; border-radius:4px.
    • Buttons: port lines 52–68 (.btn, .btn-gold with shimmer ::after, .btn-ghost, .on-dark .btn-ghost, .btn .arr and LTR mirroring). Class names .btn, .btn-gold, .btn-ghost do not exist in resources/css/app.css (which uses .btn-primary, .btn-secondary), and they are scoped under body.site, so there is no collision.
    • Progress rule: port lines 70–73 (#hem → rename to .site-progress; fixed, top 0, z 60, height 2px, gradient linear-gradient(90deg,#8A7555,#E2CDA4,#A68966), transform:scaleX(0), origin right; html[dir=ltr] origin left).
    • Sections: port lines 139–144 (section{position:relative}, .sec{padding:120px 0}, .sec-head, .sec-head h2, .sec-head p).
    • Reveal: port lines 286–290, changed so content is hidden only when JavaScript runs: body.site.js [data-reveal]{opacity:0;transform:translateY(28px);transition:opacity .9s var(--ease),transform .9s var(--ease)}, body.site.js [data-reveal].in{opacity:1;transform:none}, and the data-d 1–5 delays (.08s, .16s, .24s, .32s, .4s).
    • Responsive base: at max-width:760px: body.site{font-size:16px}, body.site .wrap{padding-inline:18px}, body.site .sec{padding:80px 0}.
    • Reduced motion (port lines 324–327): under @media (prefers-reduced-motion:reduce), body.site *, body.site *::before, body.site *::after{animation:none!important; transition:none!important; scroll-behavior:auto!important} and body.site [data-reveal]{opacity:1;transform:none}.
    • html:has(body.site){scroll-behavior:smooth}.
  2. resources/js/public.js — imports ./site/reveal.js and ./site/progress.js, and calls each module's init() on the livewire:navigated document event (Livewire 3 dispatches it on the first page load and after every wire:navigate), and each module's destroy() on livewire:navigating. On init it adds the class js to document.body.
  3. resources/js/site/reveal.js — exports init()/destroy(). If matchMedia('(prefers-reduced-motion: reduce)').matches, add class in to every [data-reveal] and return. Otherwise create one IntersectionObserver with rootMargin: '0px 0px -8% 0px'; when an observed element intersects, add class in and unobserve it. destroy() disconnects the observer.
  4. resources/js/site/progress.js — exports init()/destroy(). Adds a passive scroll listener on window that sets .site-progress style.transform = scaleX(p) where p = max > 0 ? scrollY / max : 1 and max = document.documentElement.scrollHeight - innerHeight, and toggles class scrolled on #site-nav when scrollY > 8 (if that element exists; it is added in task 24-2). Runs once on init. destroy() removes the listener.
  5. resources/views/partials/site-fonts.blade.php — exactly:
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Markazi+Text:wght@400;500;600;700&family=IBM+Plex+Sans+Arabic:wght@300;400;500;600&display=swap" rel="stylesheet">
    
  6. lang/ar/site.php and lang/en/site.php — each <?php return [ ... ]; with the keys progress_label (ar 'تقدّم القراءة', en 'Reading progress'). Later subtasks add keys to these files.

Files to modify

  1. vite.config.js — input becomes ['resources/css/app.css', 'resources/js/app.js', 'resources/css/public.css', 'resources/js/public.js'].
  2. resources/views/components/layouts/public.blade.php:
    • After @include('partials.head') add @include('partials.site-fonts') and @vite(['resources/css/public.css', 'resources/js/public.js']).
    • <body> becomes <body class="site min-h-screen flex flex-col"> (remove bg-background and the inline style="font-family: …").
    • Immediately after the skip link add <div class="site-progress" aria-hidden="true"></div>.
    • Remove the spacer <div class="h-16"></div> (the navigation becomes sticky in 24-2; until then the existing fixed navigation may overlap the first 64px — acceptable only between 24-1 and 24-2).
    • <main> keeps id="main-content" role="main" class="flex-1" tabindex="-1" but its child <div class="max-w-[1200px] mx-auto px-4 sm:px-6 lg:px-8 py-6 sm:py-8"> is removed, so {{ $slot }} is rendered directly inside <main>.
  3. Because the wrapper is gone, wrap the root content of each existing public page that is not yet redesigned in <div class="wrap py-8">…</div> so these pages keep a contained width until their own subtask restyles them:
    • resources/views/livewire/pages/home.blade.php
    • resources/views/livewire/pages/about.blade.php (also remove the negative margins -mx-4 sm:-mx-6 lg:-mx-8 -mt-6 sm:-mt-8 from its first <section>)
    • resources/views/livewire/pages/booking.blade.php
    • resources/views/livewire/pages/booking-success.blade.php
    • resources/views/livewire/pages/posts/index.blade.php
    • resources/views/livewire/pages/posts/show.blade.php
    • resources/views/pages/legal.blade.php
    • resources/views/pages/terms.blade.php
    • resources/views/pages/privacy.blade.php (resources/views/pages/booking.blade.php is a dead placeholder — /booking is served by the Volt page — and is left untouched.) For a Volt page whose root is a single element, put the wrapper inside the root element so the component keeps one root.
  4. resources/views/partials/head.blade.php — change <meta name="theme-color" content="#4A4A42"> to <meta name="theme-color" content="#2D3624">. Change nothing else in this file (the dashboards share it).

Do not modify resources/css/app.css or any file under resources/views/livewire/admin/, resources/views/livewire/client/, resources/views/components/layouts/app*.

Acceptance Criteria

  • npm run build succeeds and public/build/manifest.json contains entries for resources/css/public.css and resources/js/public.js.
  • Every selector in resources/css/public.css is scoped under body.site (or html[...] body.site, or html:has(body.site)), verify: grep -nE '^[^@/ }].*\{' resources/css/public.css | grep -v 'body.site' returns nothing.
  • The HTML of / contains <body class="site, the Markazi+Text font link, a public.css and a public.js asset, and <div class="site-progress".
  • The HTML of /admin/dashboard (logged in as admin) and /client/dashboard (logged in as a client) contains neither public.css, public.js, Markazi nor class="site.
  • resources/css/app.css is unchanged: git diff --quiet BASE -- resources/css/app.css.
  • On / with the browser at 390px wide, the document has no horizontal scroll, and every public page listed in item 9 still renders its content inside a 1200px-max container.
  • Scrolling / changes the .site-progress element's transform from scaleX(0) toward scaleX(1); with prefers-reduced-motion: reduce emulated, every [data-reveal] element is visible without scrolling.
  • partials/head.blade.php contains content="#2D3624" and no #4A4A42.

Sub-tasks

None.