# ABACO INFRA — Design System

This is the design system of record for the website. It applies to all frontend work unless a
page-level requirement in `docs/SOW.md` explicitly overrides it.

The site is an **engineering consultancy / infrastructure organisation website**. The visual
language communicates engineering expertise, institutional credibility, technical precision,
sustainability, and human impact. It is not a SaaS dashboard, not a generic corporate template,
and not the school-website template the SOW was adapted from.

**Direction:** premium institutional + modern editorial + engineering visualisation.
Clean, structured, spacious, technical, confident, contemporary.

**Avoid:** excessive gradients, heavy glassmorphism, neon, bubble-rounded UI, floating-card soup,
generic SaaS aesthetics, cartoon illustrations, stock handshake/boardroom photography, constant
animation, decoration without semantic purpose.

---

## 1. Tokens

All tokens live in `resources/css/app.css` under `@theme`. **Never hardcode a hex value in a Blade
template.** If a new colour seems necessary, first check whether an existing semantic token fits.

### Brand

The palette comes from the ABACO INFRA brand board and the logo artwork: ABACO orange as the
mark, charcoal as the structural neutral, light grey as the ground.

| Token | Value | Use |
| --- | --- | --- |
| `--color-primary` / `-400` | `#FF9A2E` | ★ Brand orange. Button and pill surfaces, the logo mark, rules, indicators |
| `--color-primary-500` | `#F08300` | Hover on an orange surface |
| `--color-primary-700` | `#A35600` | **Interactive text** — 4.6:1 on white |
| `--color-primary-50` | `#FFF6EC` | Orange wash behind panels and active navigation |
| `--color-secondary` / `-700` | `#333333` | ★ Brand charcoal. Dark bands, footer, navbar, the dark button |
| `--color-secondary-400` | `#8C8C8C` | Brand board mid grey |
| `--color-secondary-600` | `#4C4C4C` | The logo wordmark grey |
| `--color-accent` | `#A35600` | Alias of `primary-700`, for interactive text |

**The contrast rule that shapes everything.** `#FF9A2E` on white is roughly 2:1 — it fails for body
text at any size. Orange is therefore a *surface* colour, never a text colour on white:

- Orange background with near-black text (`.btn-primary`, `.pill-active`) — the way the brand board
  uses it on the business card and hard hat.
- Interactive text, link arrows and eyebrows use `text-text-brand` (`#A35600`).
- On charcoal, orange text is fine, and is used for icons and accents.

### Status

| Token | Value |
| --- | --- |
| `--color-success` | `#16803C` |
| `--color-warning` | `#B45309` |
| `--color-error` / `--color-danger` | `#C2261D` |
| `--color-info` | `#0369A1` |

The warning tone is deliberately deeper than the brand orange so the two never read as one signal.

Status must never be communicated by colour alone — always pair with a label or icon.

### Neutrals

| Token | Value | Use |
| --- | --- | --- |
| `--color-background` | `#F4F4F4` | Page ground (brand board light grey) |
| `--color-surface` | `#FFFFFF` | Cards, panels, modals |
| `--color-surface-muted` | `#F0F0F0` | Alternating sections, inputs |
| `--color-surface-tint` | `#FFF6EC` | Orange-tinted surface |
| `--color-border` | `#E0E0E0` | Hairlines, card borders |
| `--color-text` | `#1A1A1A` | Body and headings |
| `--color-text-secondary` | `#4C4C4C` | Supporting copy |
| `--color-text-muted` | `#8C8C8C` | Metadata, captions |
| `--color-text-brand` | `#A35600` | Links, eyebrows, hover states |
| `--color-dark` | `#333333` | Footer, navbar, dark bands |
| `--color-dark-elevated` | `#1A1A1A` | Deepest dark |

### Gradients

`--gradient-primary`, `-primary-deep`, `-brand-fusion`, `-dark`, `-dark-page`, `-surface`,
`-warm-fade`, `-hero-overlay`, each with a matching `.bg-gradient-*` utility.

### Colour hierarchy

1. White / light-grey ground
2. Near-black typography
3. Orange for the primary action and the brand mark — one clear orange per view
4. Charcoal for structure and dark bands
5. Status colours for small signals only

Whole pages are never orange. Orange earns attention precisely because it is rationed.

---

## 2. Typography

One brand family, plus a mono face for technical metadata.

- **Headings and body:** Poppins — the typeface named on the brand board
- **Technical metadata:** Fira Code (`.meta-label`: project numbers, coordinates, dimensions)

Scale (fluid, defined as tokens):

| Role | Size |
| --- | --- |
| Hero | `clamp(2.75rem, 6vw, 5.5rem)` |
| H1 | `clamp(2.25rem, 4vw, 4rem)` |
| H2 | `clamp(1.8rem, 3vw, 3rem)` |
| H3 | `1.5rem – 2rem` |
| Body | `1rem – 1.125rem` |
| Small / meta | `0.75rem – 0.875rem` |

Large type is used selectively — not every heading is oversized. Body copy uses `max-w-[65ch]`,
comfortable line height, strong contrast, short paragraphs.

---

## 3. Layout & spacing

- Container: `max-w-7xl mx-auto` with responsive horizontal padding (`.container-page`).
- Section rhythm: mobile `py-12`–`py-20`, tablet `py-16`–`py-24`, desktop `py-20`–`py-32`
  (`.section`, `.section-lg`, `.section-tight`).
- Prefer asymmetric editorial layouts over three identical columns wherever the content allows.
- Avoid full-width text blocks unless the block is deliberately editorial.

### Radius

Buttons `rounded-lg` · cards `rounded-xl`/`rounded-2xl` · large media `rounded-2xl` ·
status pills `rounded-full`. No bubble UI.

### Shadows

Used sparingly. Prefer borders and surface contrast. Every card must still read correctly with
its shadow removed.

---

## 4. Images

Images carry the brand. Use real project, infrastructure, field and team photography:
roads, bridges, hydropower, water systems, urban development, irrigation, GIS/survey work,
engineering teams, field inspections, community impact, construction progress.

Never use handshake photos, generic boardrooms, people pointing at screens, or stock skyscrapers.

Rules:

- Images must communicate scale, expertise, location, impact or technical work — never decoration.
- Consistent aspect ratios (`aspect-16/10` cards, `aspect-3/4` portraits, `aspect-21/9` banners).
- `object-cover`, responsive sizing, `loading="lazy"` below the fold.
- The hero/LCP image is never lazy-loaded; it gets `fetchpriority="high"`.
- Always meaningful `alt` text; decorative images get `alt=""`.

### The sanctioned techniques

There are dozens of ways to use an image well; using all of them makes a site look like a demo
reel. These twenty are the site's vocabulary. Anything outside this list needs a reason, and if it
recurs it becomes a component before it becomes a second instance.

| # | Technique | Where it lives |
| --- | --- | --- |
| 1 | Full-screen cinematic hero | `public/partials/hero.blade.php` |
| 2 | Split editorial hero / band | `<x-split-media>` — About introduction |
| 3 | Cinematic overlay (scrim) | `.scrim`, `.scrim-side` |
| 4 | Gradient background | `<x-immersive-band>`, footer CTA |
| 5 | Classic parallax | `data-parallax="0.08"` |
| 6 | Multi-layer parallax | several `data-parallax` depths inside one `data-parallax-scope` |
| 7 | Sticky scroll storytelling | `data-pin-media` + `data-pin-scope` — project, sector, About |
| 8 | Horizontal scroll gallery | `<x-scroll-gallery>` — project detail, 4+ photos |
| 9 | Bento grid | homepage gallery section |
| 10 | Masonry gallery | `<x-masonry>` — album detail, gallery blocks |
| 11 | Editorial grid | sector, project and media card grids |
| 12 | Hover reveal cards | team card, partner grid |
| 13 | Image hotspots | `<x-hotspot-image>` — `hotspots` page block |
| 14 | Before / after slider | `<x-compare-slider>` — `compare` page block |
| 15 | Lightbox gallery | `public/partials/lightbox.blade.php` |
| 16 | Ken Burns | `.ken-burns` — first hero slide |
| 17 | Clip-path reveal | `data-mask-reveal` |
| 18 | Drone / aerial full-bleed band | `<x-immersive-band>` — sector pages, `immersive` block |
| 19 | Blueprint texture | `.bg-blueprint`, `.bg-blueprint-dark` |
| 20 | Topographic background | `.bg-topographic`, `.bg-dot-grid` |

Zoom-on-scroll (`data-zoom-scroll`) supports #18 and is not counted separately.

### Where each area uses them

| Area | Image treatment |
| --- | --- |
| Home hero | Full-screen cinematic image or muted video, Ken Burns on the first slide |
| About | Split layout with one editorial image, then a pinned narrative column |
| Sectors | Large image cards; full-bleed band on the sector page |
| Projects | Portfolio cards with technical metadata |
| Project detail | Pinned sidebar + grid, and a horizontal scroll story when the set is large |
| Achievements | Documentary photography in a timeline |
| Team | Portraits, 3:4, hover reveals contact detail |
| Media | Editorial thumbnails |
| Gallery | Masonry + lightbox |
| Footer CTA | Background photograph under a brand gradient |

### Rejected by default

Fixed/`background-attachment` backgrounds, blurred decorative photography, duotone treatments,
polaroid and collage compositions, 360° panoramas, image morph and full-screen page transitions,
scroll-jacked narratives, 3D tilt, and wave/arch/organic masks. They fight the institutional
register, the performance budget, or both. Revisit only with a specific brief.

---

## 5. Motion

GSAP + ScrollTrigger, loaded once in `resources/js/motion.js`. Animation must communicate
hierarchy, progress, spatial relationship or content discovery — never decorate.

Approved: hero text reveal, image mask/clip reveal, card stagger, statistic count-up, section
entrance, pinned project storytelling, navigation state transition, marquee, micro-interactions.

Forbidden: constant floating loops, heavy parallax, long page transitions, animating every card
independently, anything that delays access to content.

`prefers-reduced-motion: reduce` disables every non-essential animation — elements are shown in
their final state immediately. This is enforced centrally in `motion.js`.

---

## 6. Components

Reusable UI lives in `resources/views/components/`. Before creating a component, check whether an
existing one fits. Buttons, cards, badges, breadcrumbs, filters, pagination, modals, alerts,
tables and empty states must look identical everywhere.

Current set: `button`, `badge`, `card`, `breadcrumbs`, `icon`, `image`, `empty-state`,
`section-heading`, `page-hero`, `project-card`, `media-card`, `stat-counter`, `marquee`,
`lightbox`, `alert`, `form/*`, `admin/*`.

---

## 7. States

Every dynamic surface needs:

- **Loading** — skeletons or a lightweight placeholder, never a bare spinner on content areas.
- **Empty** — explains what is missing, e.g. "No projects are currently available for this sector."
- **Error** — a recovery message. Never expose framework, PHP or database errors publicly.

---

## 8. Accessibility (non-negotiable)

Semantic HTML · correct heading order · full keyboard operation · visible focus rings · ARIA only
where native semantics fall short · labelled form controls · accessible validation messages ·
alt text · sufficient contrast · skip-to-content · reduced motion · accessible modals, dropdowns
and navigation. Hover is never the only route to important information; touch targets stay large.

---

## 9. Performance

Target: usable page load under 3 seconds.

WebP/AVIF where available · responsive images · lazy loading below the fold · optimised hero media
· Vite production build · font preconnect · eager loading and query caching to avoid N+1 ·
pagination · deferred non-critical JS. No large JS library for something CSS or Alpine can do.

---

## 10. Internationalisation

English and Nepali. User-facing strings go through `__()` / `lang/` files rather than being
inlined in Blade. Keep translation calls out of complex markup.

---

## 11. Definition of done

**Frontend feature:** desktop, tablet and mobile layouts work · keyboard navigation works · forms
validate · empty and error states exist · images optimised with alt text · SEO metadata present ·
animation respects reduced motion · no unnecessary JS · Tailwind conventions followed · reusable
components used · matches this system.

**Full module:** migration · model · relationships · validation · authorisation · admin CRUD ·
public frontend · search/filtering · file handling · SEO · responsive UI · accessibility checked ·
tests · seeder/factory · no SOW requirement silently omitted.

---

## 12. Content rules

Concise, professional, technically credible. No marketing filler, no "world-class/leading/
innovative" claims, no invented statistics, clients, certifications, awards or dates. Where real
content is unavailable, use clearly marked placeholder copy — never fabricated facts. All counters
and statistics come from admin-managed data.
