Skip to content

Principal home

The principal home is the compliance officer’s home screen. It renders at /demo/principal and answers four questions a head of compliance asks before lunch: where are the critical-risk ARs sitting today, what breaches are still owed to the FCA, what file reviews are overdue, and what does my desk look like this morning.

Live: lending-agent-oversight.vercel.app/demo/principal.

Top to bottom, left to right.

  • Skin name (Heritage Mortgage Network) and FRN (412803 for Heritage). Reads as a header chip.
  • Persona pill: Principal · Compliance in amber-soft tint.
  • Mode toggle (Scripted | Free explore).
  • Today’s date, fixed at the demo’s FIXED_NOW of 8 May 2026.

The home does not use a four-up symmetric grid. The composition is grid lg:grid-cols-[minmax(0,1.4fr)_minmax(0,1fr)] — one large headline KPI (RiskHeadline component) on the left at 1.4fr, three supporting tiles stacked on the right at 1fr. The layout signals “here is the one number that matters” rather than “here are four equally-weighted numbers”.

The RiskHeadline component is a Card with a brand-tinted radial wash in the top-left. Inside, in order:

  • Section label Network risk picture.
  • The critical-band count at Fraunces 7-8xl (text-7xl sm:text-8xl font-medium leading-[0.85]), tabular-nums, coloured var(--severity-critical) when nonzero. Animates in over 600ms with a cubic-bezier(0.22, 1, 0.36, 1) curve.
  • Beside it in muted Fraunces 2-3xl: italicised in critical band.
  • Below: a band-distribution bar — a 3-unit-tall pill rendering all five OKLCH severity-coloured segments stacked horizontally, each width-animated in over 700ms with a 60ms stagger.
  • Distribution legend — five dots labelled Low / Moderate / Elevated / High / Critical with their respective counts.
  • Brand-coloured Open the critical-band cohort → link to /demo/principal/register?band=critical.

Three Cards stacked vertically (1-up on lg:, 3-up across sm: to lg:):

TileValueSource
Breaches awaiting FCACount of breaches with an unsatisfied notifyByAtgetDataset(skin).breaches
Overdue file reviewsCount of ARs whose nextReviewDueAt is pastgetDataset(skin).ars
Annual reviews dueCount of ARs with nextReviewDueAt within the next 30 daysgetDataset(skin).ars

Each tile uses KpiTile with the icon container ringed and tinted by the active skin’s var(--brand-primary) for the primary accent variant. Tiles animate in on mount with the existing 350ms ease-out, y:8, staggered 60ms.

The bandDistribution field on the KPI computation (Record<RiskBand, number>) is consumed by the headline; the supporting tiles take the simple counts.

A table at the centre-left. Sorted by riskScore descending, capped at 10 rows. Columns:

  • Trading name (linked to AR detail).
  • Type chip (AR or IAR).
  • Risk score with mini gauge (16px semicircle plus number).
  • Risk band badge.
  • 12-week risk-trajectory sparkline.
  • “Last reviewed” date.

Each row hovers with a 120ms bg-foreground/[0.03] transition. Click navigates to /demo/principal/register/[arId].

Calendar-style grid 14 weeks by 7 days, 90 cells of 14×14px with 2px gap. Background opacity scales with breach count: 0 = slate-100, 1 = var(--brand-primary) 30%, 2 = 55%, 3+ = 85%. Hover tooltip “8 May, 3 breaches”.

Cells fade in stagger top-left to bottom-right over 800ms. A hidden aria-describedby summary reads “90 days, 14 days with breaches, peak day 3 breaches on 22 March” for screen readers.

A 12-week sparkline showing reviews-completed-per-week, with a 4px filled circle on the last data point. Below: “X reviews completed in the last 12 weeks” in muted text.

Bottom of the page. A list of cards surfacing what the compliance officer needs to do today, derived from the fixture set:

  • “Notify FCA on the Pemberton Mortgages breach by Friday.” with a “Open breach” button.
  • “Three file reviews are overdue.” with a “Open review queue” button.
  • “Sign off Holyrood Lending Partners’ annual review packet.” with a “Open packet” button.
  • Loading. The page is server-rendered with fixtures, so first paint is fully populated. Sparkline draws and gauge fills wait for client hydration. Reduced motion skips both.
  • Empty (clean firm). If a skin had zero ARs in the critical band, the tile shows 0 in muted text rather than a destructive tint. The top-10 table degrades gracefully to “No ARs in scope yet” if the register is empty (does not happen in the shipped fixtures).
  • Error. The principal layout wraps the page in an error boundary. On runtime error, a card replaces the broken section with “We couldn’t load this section. Reload to try again.”
  • Action-pending. None on this surface; the home is read-only. Action-pending UI lives on breach detail and annual review packets.
  • Mobile (< 640px). KPI tiles stack 2x2. Top-10 table collapses to a card list, one card per AR with the gauge inline. Heatmap shrinks to 8 weeks horizontally with a small horizontal scroll for the full 14. Next-actions widget stacks full-width.
  • Tablet (640-1024px). KPI tiles in one row of four (smaller). Top-10 and heatmap side by side at narrow widths.
  • Desktop (> 1024px). Full layout. Max-width 1280px container, padded 24px.
  • components/principal/risk-dashboard.tsx (top-level)
  • components/principal/kpi-tile.tsx
  • components/principal/top-risk-table.tsx
  • components/principal/breach-heatmap.tsx
  • components/principal/next-actions.tsx
  • components/principal/sparkline.tsx
  • components/principal/risk-gauge.tsx (mini variant)
  • components/principal/risk-band-badge.tsx
  • Click any AR row to land on AR detail.
  • The “Breaches awaiting FCA notification” KPI deep-links into the breach triage queue.
  • The “Overdue file reviews” KPI deep-links into the file review workspace.
  • The “Annual reviews due this month” KPI deep-links into the annual fitness review packet list.
  • The skin switcher in the chrome re-renders this surface end to end with the new principal firm’s fixtures.