# MoPricer UI patterns (Phase 1 foundation — read before Phase 2)

Phase 1 added shared building blocks. Every Phase 2 page agent MUST reuse these
instead of inventing its own, so the app looks and behaves consistently.

## 1. Page header (title + purpose)
Add to the top of each page's `@section('content')`:
```blade
@include('includes.page_header', [
    'title'   => 'Ferries',
    'purpose' => 'One sentence: what this page is for, in plain English.',
    'help'    => url('/logs'),   // optional; omit if none
])
```
Purpose copy about pricing behaviour MUST be verified against `PRICING_GUIDE.md`.
Do not invent how pricing works.

## 2. Flash / validation messages — already automatic
`includes/flash.blade.php` is rendered by the layout above every page's content.
It shows `session('success')`, `session('status')`, `session('error')`, and the
validation error bag. To give feedback after a create/update/delete, have the
controller redirect `->with('success', 'Ferry added.')` — no per-page markup
needed. Only controller *display* redirects may be added; do not touch pricing
logic.

## 3. Consistent action buttons
Use these classes for every entity table's row actions (see `mo-ui.css`):
```html
<a href="..."      class="mo-btn mo-btn--edit">Edit</a>
<button type="..." class="mo-btn mo-btn--delete">Delete</button>
```
Replace ad-hoc icon-only buttons (e.g. the exception page's trash/pencil icons)
with these so all tables match.

## 4. Delete confirmation
Reuse the existing confirm modal partial `includes/confirm.blade.php`
(`@include('includes.confirm', ['title'=>..., 'message'=>..., 'formId'=>..., 'fieldId'=>...])`).
Delete buttons should open it rather than deleting immediately.

## 5. "Any" for blank origin/destination cells
Where a blank country cell means "applies to any country" (waypoint, exception,
customs tables), render it as:
```blade
{{ $row->from_country ?: '' }}  →  @if($row->from_country){{ $row->from_country }}@else<span class="mo-any">Any</span>@endif
```
This is display-only. Do NOT change stored values or field `name=` attributes.

## 6. Units & currency in labels
Every quantity/price label carries its unit: `Mass (kg)`, `Volume (m³)`,
`Distance (km)`, `Price (EUR)`. Confirm the currency against `PRICING_GUIDE.md`.
Wrap the unit in `<span class="mo-unit">(kg)</span>` if you want it muted.

## 7. Map defaults (Europe)
`window.MO_MAP_DEFAULTS = { center:{lat:50.0,lng:9.0}, zoom:4 }` is loaded
app-wide via `js/mapDefaults.js`. Map/zone page scripts should use it as the
initial centre when there is no saved/user centre to restore. Do not hardcode
Australia/Caribbean coordinates.

## 8. Where CSS goes
`public/css/app.css` is a legacy Bootstrap dump and is NOT loaded — ignore it.
Shared styles live in `public/css/mo-ui.css` (linked in the layout). Page-only
styles go in a page `<style>` block or `@push('head') ... @endpush`.

## 9. Hard rules (all agents)
- Never change routes or form field `name=` attributes.
- Never change pricing math / controller calculation logic / the formula engine.
- Never commit `.env`, `vendor/`, secrets.
- UI/copy/layout/presentation only.
