# Build a practice area page with the Counsel theme

You are building one page in an existing project: the page for one practice area of a commercial law firm, with what the team does, the matters it typically takes on, three recent matters, the two partners who lead it and its related briefings. Follow this brief closely. `DESIGN.md` decides the tokens: colors, type, spacing steps and corners. This brief decides the layout, its widths included, and which token goes where. If this brief names a color, a type size, a spacing step or a corner that `DESIGN.md` does not have, `DESIGN.md` wins.

## Before you start

1. **Check the theme is installed.** The project should have `DESIGN.md` in its root and the Counsel variables in its global CSS. If not, run `npx shadcn@latest add https://strictthemes.com/r/counsel.json` and save https://strictthemes.com/themes/counsel/DESIGN.md as `DESIGN.md` in the project root. In a project without shadcn, use https://strictthemes.com/themes/counsel/tailwind.css instead. If the global CSS still imports a font the theme does not use (a new shadcn project imports Geist), remove that import, and uninstall its package if nothing else uses it. Keep every font import the theme's install added, also one for a style no page uses yet.
2. **Read `DESIGN.md` from start to finish.** It is the source of truth for every visual decision.
3. **Look at the project before writing code.** Use its framework, router and file layout. For controls (buttons, inputs, tabs, menus, dialogs, accordions, data tables) use the components in `components/ui`, and add a missing one with `npx shadcn@latest add <name>` rather than writing your own, unless this brief names a plain element. Layout is plain elements with theme classes: sections, panels, figures and lists need no component.
4. **Teach `cn()` the theme's type classes.** shadcn's class merger does not know `text-display` or `text-h1`. It takes them for colors, so `cn("text-label text-muted-foreground")` silently drops one of the two, and a type class passed to a stock component does not replace its size. In a new shadcn project, `lib/utils.ts` only passes `cn` on from the `cn` package. Unless the file already holds the lines below, change it to:

   ```ts
   import { createCn } from "cn/config"

   // The theme's type classes are font sizes, not colors.
   export const cn = createCn({
     extend: {
       classGroups: {
         "font-size": [{ text: ["display", "h1", "h2", "body", "label"] }],
       },
     },
   })
   ```

   Then make every file in `components/ui` use it: where one has `import { cn } from "cn"`, change that line to import `cn` from the project's utils file (`@/lib/utils` in a default setup). Do the same for each component you add later. If the project uses `tailwind-merge` instead of the `cn` package, its components already import from the utils file: pass the same object to `extendTailwindMerge` and keep `clsx`.
5. **Write real content.** If the user gave you details about their product, use them. Otherwise use the sample product in this brief and write the rest of the copy yourself: specific and plain, the way the samples read. Invent the company and people names; do not use real ones. Never use lorem ipsum. A link with no destination yet points to `#`. Set the page's `<title>` and meta description.

## The theme in short

- **Fonts:** Marcellus for headings, Jost for body text, Courier Prime for labels and code.
- **Type scale** (size/weight; each class also sets line height and tracking): `text-display` 60px/400, `text-h1` 40px/400, `text-h2` 24px/400, `text-body` 17px/400, `text-label` 13px/400.
- **Font per size:** a type class does not set the font family. Headings (`<h1>` to `<h6>`) get the heading font on their own; on any other element add the font class: `font-heading` with `text-display`, `text-h1`, `text-h2`; `font-mono` with `text-label`.
- **Spacing scale**, with the Tailwind step in brackets: 4px (`1`), 8px (`2`), 16px (`4`), 32px (`8`), 56px (`14`), 112px (`28`).
- **Corners:** `rounded-sm` 1px, `rounded-md` 2px, `rounded-xl` 4px (the `lg` corner in `DESIGN.md`). `rounded-lg` is 2px as well: it is shadcn's name for the base corner, the one its stock buttons and inputs use.
- **Colors (light mode):** primary #14213D, on-primary #FFFFFF, secondary #000000, on-secondary #FFFFFF, tertiary #FCA311, on-tertiary #000000, neutral #5B6170, background #FFFFFF, surface #F6F6F6, foreground #000000, border #E5E5E5, error #B3261E.

### How Counsel pages are laid out

- **Container:** one `<div>` wraps the whole page and is the container: `mx-auto max-w-[1200px] px-4 md:px-8`, plus `text-body`. This width is the one arbitrary value allowed. Inside it sit the `<header>`, a `<main>` holding everything between the two, and the `<footer>`.
- **Grid:** a section's content sits in a grid: `grid grid-cols-1 md:grid-cols-12 md:gap-x-8`. The grid sets columns only, never `gap-y-*`: every vertical distance comes from the rhythm rule. Below `md` every grid item takes the full width. Leave the columns this brief does not fill empty; an empty column is part of the design, so center nothing to fill it. From `md` up every grid item gets `md:col-span-*`, because an item without one takes a single column: "columns 1–12" is `md:col-span-12`. It also gets `md:col-start-*` when it starts after column 1, and `md:col-start-1` when it must start a new row under an item that leaves room beside it; or the grid puts it in that room. An item whose columns overlap those of the item before it always starts a new row. Where a brief puts "a section's content in columns 5–12", the `<section>` is the grid and the content is one `<div>` with those column classes. Where a list "is itself the grid", the `<section>` is not a grid: the heading above the list sits directly in it at the full width.
- **Text and note:** running text sits in seven of the twelve columns (`md:col-span-7`, or the columns this brief gives). Beside it, where this brief asks for one, sits one short note in columns 9–12 (`md:col-start-9 md:col-span-4`), with `mt-14 md:mt-0` on a phone, so it comes after the text. Nothing else stands beside the text.
- **Vertical rhythm:** written as a top margin on the lower element (`mt-*`), never as `space-y-*`, `gap-y-*`, a bottom margin or padding, except the padding a section gets around its hairline (see Sections) and the padding of a card or a list entry, which these notes give. Between a label and the one thing it names (a form label and its field, a name and the role under it, a term and its value when they stack): `mt-2`. Between a heading and the text under it, and between paragraphs: `mt-4`. A label line above a heading, and a label heading above its text, its `<address>` or its `<dl>`, count as headings: `mt-4` to what follows. Between blocks inside a section (a paragraph and a button, a heading and a list, a card and the text after it, two parts of a side column): `mt-8`. Between two parts of a section that each have their own `<h2>`: `mt-14`. Where two grid items share a row from `md` up, the second has its phone margin and `md:mt-0`, unless this brief gives a margin from `md` up. Inside a flex row (the header, a label line with a badge, a group of buttons) the space is the row's `gap-*` as this brief states it. Where this brief gives an element its own margin, it replaces the one from this list.
- **Sections:** `<main>` holds a stack of `<section>` elements. The first has `mt-14 md:mt-28` and no border: the header's hairline is above it. Every other section is divided from the one before it by one hairline, with white space on both sides of it: `mt-8 border-t border-border pt-8 md:mt-14 md:pt-14`, which is 112px from section to section on a large screen and 64px on a phone, with the line in the middle. That is the whole gap and the only padding a section has; the section's first element takes no top margin of its own.
- **Header:** the `<header>` is itself the row, with `border-b border-border py-8`: `flex flex-col items-start gap-4 md:flex-row md:items-baseline md:justify-between`. On the left the firm's name, `Harrow & Vane`, a link to `/` in `font-heading text-h2`, styled as a header link and never marked as the current page. It is not a heading element, and it has no weight class. On the right a `<nav>` with the `aria-label` "Main" and no classes, holding a `<ul>` with `flex flex-wrap gap-x-4 gap-y-2 md:gap-x-8` of four links as labels, in this order: "Practice" (`/practice/commercial-disputes`), "People" (`/people/ruth-calloway`), "Insights" (`/insights/notice-clauses`) and "Contact" (`/contact`). Each brief names the current one, if any. Below `md` the links sit under the name and may wrap onto a second line; there is no "Menu" button.
- **Footer:** a `<footer>` with `mt-14 md:mt-28`, a 1px `border-border` top border and `py-8`. Inside it a grid like the one above, with three parts:
  - Columns 1–4 (`md:col-span-4`): the firm's full name as plain text in `font-heading text-h2`, `Harrow & Vane LLP`, then with `mt-2` the office's address: one `<address>` with `not-italic font-mono text-label uppercase text-muted-foreground` holding two `<p>` lines with no margin between them, `4 Chancery Row` and `Wexcombe WX1 2LN`.
  - Columns 5–8 (`md:col-start-5 md:col-span-4`, with `mt-8 md:mt-0`): two `<p>` label lines, the second with `mt-2`: the telephone number `01632 960 214` as a `tel:01632960214` link, and the email address `enquiries@harrowvane.example` as a `mailto:` link in `normal-case`. Both styled as footer links.
  - Columns 9–12 (`md:col-start-9 md:col-span-4`, with `mt-8 md:mt-0`): a `<nav>` with the `aria-label` "Footer" holding a `<ul>` of the header's four links, in the same order, as labels, `mt-2` between items. The current page is marked here too, with `aria-current="page"` and `underline`.
  - Under the grid, with `mt-8`, a label line in `text-muted-foreground`: `© 2026 Harrow & Vane LLP · Registered in England and Wales`.
- **Headings:** the `<h1>` is `text-h1`, and `text-display` from `md` up where this brief says so (`text-h1 md:text-display`). An `<h2>` in the heading font is `text-h2`, and so is an `<h3>`. Nothing in the heading font is smaller than `text-h2`: a smaller heading is a label heading. Headings keep the regular weight their type class gives them: add no weight class, never `font-bold` or `font-semibold`. Sentence case, no full stop.
- **No bold, no italics:** Marcellus has one weight and no italic, and nothing on these pages fakes either. No `<em>`, `<i>`, `<strong>`, `<b>` or `<cite>`, and no `italic` or bold class, in headings or in running text. An `<address>` is italic by default: give every `<address>` `not-italic`.
- **Labels:** nav links, dates, matter numbers, the names of practice areas in a label line, roles under a name, form labels, terms in a `<dl>`, and button and badge text are labels: `font-mono text-label uppercase`. The wide tracking comes with `text-label`; do not add a `tracking-*` class. Write a label as a short fragment, not a sentence. Error lines and helper text use the label's font and size but are sentences, and are not uppercased. Join the parts of a label line with ` · `. A label on its own line is a block element such as a `<p>`. Email addresses and what someone typed are never uppercased: put an email address inside a label in a `<span>` (or give its link) `normal-case`.
- **Label headings:** a heading that is styled as a label (Address, Hours, Contact) is an `<h2>` or `<h3>`, whichever keeps the heading order, with `font-mono text-label uppercase text-foreground`. Keep the `font-mono`: a heading element gets the heading font on its own.
- **Text color:** headings, label headings, body text, nav links, names and form labels are `text-foreground`. A button's or a badge's text color comes from its variant or its classes. Dates, matter numbers, roles under a name, `<dt>` terms, caption lines and helper text are `text-muted-foreground`. Muted text sits only on `bg-background` or `bg-card`. Paragraphs are never muted. No other text colors: gold (`tertiary`) and navy (`primary`) are never text colors.
- **Measure:** a paragraph of body text is at most `max-w-xl` wide (576px, about 70 characters in Jost at this size), however many columns it sits in. A heading may run wider.
- **Figures:** a sum, a count or a year that stands on its own in a label is `font-mono tabular-nums`. A large figure in a row of figures is `font-heading text-h1`, where this brief says so. Sums are written with the pound sign before the number: `£6.2m`, `£48m`, `£1,480`. A date or a year that stands on its own (in a label line, a `<dd>`, a list entry) is a `<time>` with a `dateTime`. A date or a year inside a sentence (running text, a confirmation message, an error line) is plain text, not a `<time>`, unless this brief says otherwise. A date is written `10 November 2026` (`dateTime="2026-11-10"`), a time `08:30`, a year `2026`. The copyright year is plain text.
- **Telephone numbers** are written in groups, `01632 960 214`; a `tel:` link's `href` has the digits with no spaces (`tel:01632960214`).
- **Links:** a link in running text is `text-foreground underline decoration-1 underline-offset-4 hover:text-muted-foreground`, and inherits its size and font. A link in the header or the footer, and a name or a title that is a link, is `text-foreground decoration-1 underline-offset-4 hover:underline`; the link for the current page has `aria-current="page"` and `underline`. Mark one only where this brief names the current page. Links are never colored, and get `transition-colors duration-150`. A link whose destination this brief does not give points to `#`; the firm's name always points to `/`.
- **Onward links:** a link that stands alone at the end of a part ("All partners", "All briefings") is a `<p>` holding the link (also where a brief puts it in a heading's row), as a label (`font-mono text-label uppercase`) styled as a link in running text, in `inline-flex items-center gap-2`, followed by the `ArrowRight` icon.
- **Buttons:** the shadcn `Button` with `className="h-auto px-8 py-2 font-mono text-label font-normal uppercase"`: `font-normal` because the labels are regular. The default variant (navy, gold in dark mode) is for the page's one main action: one on a page, unless this brief gives a second. Any other button is `variant="secondary"` (black, near-white in dark mode). In `components/ui/button.tsx`, replace that variant's stock `hover:bg-[color-mix(in_oklch,var(--secondary),var(--foreground)_5%)]` with `hover:bg-secondary/80`, once, not beside it: the 5% mix cannot be told from the resting color. Make this change even on a page with no secondary button, so every page's `button.tsx` is the same. Do not use the `outline`, `ghost`, `link` or `destructive` variants, or the `xs`, `sm` or icon sizes. A button that sends a form needs `type="submit"`: this `Button` is `type="button"` unless told otherwise. A call to action that goes to another page, or a `mailto:` or `tel:` link styled as a button, is an `<a>` with the same classes: write `cn(buttonVariants({ variant }), "…")`, because `buttonVariants` alone does not merge classes. Button text is at most four words.
- **Inputs:** the shadcn `Input` and `Textarea` (`npx shadcn@latest add input textarea`) with `className="h-auto border-muted-foreground px-4 py-2 text-body md:text-body"`. The stock `border-input` is too faint against the page and the card; `border-muted-foreground` reaches 3:1 in both modes. They keep their stock 2px corner, the fill they ship with (in dark mode too), the stock `focus-visible:border-ring` and the stock `aria-invalid:border-destructive`. Every field has a visible `<label>` above it with `block`, tied to it with `htmlFor` and styled as a label in `text-foreground`; the field has `mt-2`. Fields follow each other with `mt-8`, on the wrapper `<div>` that holds a label, its field and its error. Optional fields say so in the label: `Telephone (optional)`.
- **Selects:** a choice from a short list is a native `<select>` with `h-auto w-full rounded-md border border-muted-foreground bg-transparent px-4 py-2 text-body text-foreground dark:bg-input/30 aria-invalid:border-destructive dark:aria-invalid:border-destructive/50 focus-visible:border-ring` and the four `focus-visible:outline-*` classes from the rules: the fill, border and error classes are the ones the stock `Input` ships, so the two look alike in both modes; these two `dark:` classes are the one exception to the rules' "no `dark:` color overrides". It takes the same label, margins and error line as any field, and shows an error with `aria-invalid` and its red border, like an `Input`. Its first option is a prompt with an empty value.
- **Checkboxes:** the shadcn `Checkbox` (`npx shadcn@latest add checkbox`). In `components/ui/checkbox.tsx`, change its `rounded-[4px]` to `rounded-md` and its `border-input` to `border-muted-foreground`, once, so it has the inputs' corner and border (where the file ships another corner or border class, change that one). Its stock size, check icon and checked fill (`bg-primary`) stay. Its row is `flex items-start gap-4`, with `mt-1` on the checkbox so it lines up with the first line of its label, and the `<label>` in `text-body text-foreground`, not uppercased: it is a sentence, not a label. Give the `Checkbox` an `id` and the `<label>` `htmlFor` with it, so a click on the words ticks the box; give the `<label>` an `id` too, and the `Checkbox` `aria-labelledby` naming it, because in a Base UI project the `Checkbox`'s `id` lands on a hidden input and the visible box would otherwise have no name.
- **Errors:** an error is a line under its field with `mt-2`: a `<p>` with an `id`, `flex items-start gap-2 font-mono text-label text-destructive`, not uppercased, holding the `CircleAlert` icon (`shrink-0`, no margin) and a sentence that says what to do. The field gets `aria-invalid` and points to the line with `aria-describedby` (beside any helper line it already names). Fields are checked in code when the form is sent, with `noValidate` on the `<form>`, and focus moves to the first field with an error. Render the error lines first and move focus after that render, in an effect or a `requestAnimationFrame`, so the field's description is there when it is read. An error line and its field's `aria-invalid` are removed when that field changes (on `input` or `change`; for the checkbox, on `onCheckedChange`). Every other error stays until the next send.
- **Forms:** a form sits on the pale grey: the `<form>` is `rounded-xl bg-card p-8`, with no border and no shadow. The send button sits under the last field with `mt-8`.
- **Confirmations:** a message that replaces a form goes into an element with `role="status"` that is on the page from the start, empty. The form and the status element share one wrapper, and the wrapper carries the top margin and the column classes, so the message stands where the form stood. The status element has no classes and no margin, so empty it takes no space; never hide it. Inside it, rendered only once there is a message, a `<div>` with `rounded-xl bg-card p-8`, like the form: an `<h2>` or `<h3>` in `text-h2` (whichever keeps the heading order), then with `mt-4` one or two sentences in `text-body`, then whatever this brief adds. A button that follows the message sits after the status element in the same wrapper, not inside it, with `mt-8`. Give the heading `tabIndex={-1}` and move focus to it, because the button that had focus is gone.
- **Badges:** exactly one badge on a page, where this brief puts it, and it is the page's one use of gold: the shadcn `Badge` (`npx shadcn@latest add badge`) with `className="h-auto rounded-sm border-transparent bg-tertiary px-2 py-1 font-mono text-label font-normal uppercase text-tertiary-foreground"`. One or two words, no icon. Nothing else on the page is `bg-tertiary`. In dark mode the gold moves to the main button and the badge turns pale grey, as `DESIGN.md` says; that needs no code.
- **Cards:** a card is a plain element with `rounded-xl bg-card p-8`: pale grey, no border, no shadow. Not the shadcn `Card`, which ships its own padding and a ring. Inside it, a label comes first, with no top margin. Use one only where this brief asks for it, never a card inside a card, and nothing with a border or a fill inside a card except the fields of a form.
- **Portraits:** there are no image files. A portrait is a rectangle, never a circle: a plain `<div>` with `aspect-3/4 w-full rounded-xl border border-border bg-card`, `role="img"` and an `aria-label` that describes the photograph in a sentence ("Ruth Calloway in a dark suit, at a window of the firm's library"). It is drawn as a monogram plate: the `<div>` also has `flex items-end p-4` (`p-8` for a portrait this brief calls large), and holds one `<span>` with `aria-hidden="true"`, the person's initials in `font-heading text-h1 text-muted-foreground` (`text-display` for a large portrait). Nothing else is drawn in it: no icon, no gradient, no shape. A portrait never sits inside a card.
- **Lists of people and matters:** a list where this brief gives each item a 1px top border (people, matters, briefings, steps) is a `<ul>` or `<ol>` with `list-none`, no padding, and no space between its items; each item has `border-t border-border py-8`, unless this brief gives `py-4`, and the list a `border-b border-border` that closes it. In each item a name or a title is in the heading font (an `<h3>` in `text-h2`, or the element this brief names), and the role, the date or the matter number is a label line in `text-muted-foreground`, `mt-2` under the name or above the title as this brief says. Where this brief lays an entry out in columns, the `<li>` itself carries the grid classes beside these, and its parts are the grid items.
- **Description lists:** a `<dl>` is a list of rows. Each row is a `<div>` with `grid grid-cols-3 items-baseline gap-x-4 border-t border-border py-4`: the `<dt>` is a label in `text-muted-foreground`, the `<dd>` takes the other two columns (`col-span-2`) in `text-body`. The `<dl>` has `border-b border-border`, so the last row is closed too. This holds at 375px as well, unless this brief stacks the rows.
- **Rules:** every line is 1px and `border-border`. Hairlines, not boxes, divide a page. No shadows, no blur, no gradients, no colored backgrounds behind sections.
- **Corners:** `rounded-sm` (1px) for the badge, `rounded-md` (2px) for the select and the checkbox, the stock 2px of the `Button`, `Input` and `Textarea` (their `rounded-lg`, which this theme sets to 2px), and `rounded-xl` (4px, the `lg` corner in `DESIGN.md`) for cards, forms and portraits. Nothing is a pill or a circle: no portrait, no badge, no dot and no switch is round.
- **Icons:** from the project's icon set, `lucide-react`, with `size-4`, `strokeWidth={1.5}` and `aria-hidden="true"`. Use them only where this brief or these notes name one. Never emoji.
- **Surfaces:** flat. A stock component that floats over the page (a menu, a dialog) keeps the one short shadow it ships with; these pages use none.
- **Motion:** in the code you write, the only transition is color, and nothing moves on scroll. Stock components keep the motion they ship with, the `Button`'s included.

## The page

Where this section and the layout notes above differ, this section wins.

Sample firm, if the user gave none: **Harrow & Vane LLP**, an invented commercial law firm in Wexcombe, an invented English city, founded in 1952, with 14 partners and 86 lawyers in one office at 4 Chancery Row, Wexcombe WX1 2LN. This page is for its **Commercial disputes** team: 4 partners and 16 lawyers, led by David Achterberg (head of commercial disputes, partner since 2007; `01632 960 231`, d.achterberg@harrowvane.example) and Ruth Calloway (partner since 1 May 2026; `01632 960 237`, r.calloway@harrowvane.example). The team acts for owner-managed companies, their buyers and sellers, and their lenders, in the courts, in arbitration and at mediation, and settles most claims before trial. It is ranked in the first band for commercial disputes in the region by the Northern Legal Review, 2026, an invented directory. Every name, client and matter is invented: name no real firm, person, case or court ruling. Write the rest of the copy yourself, plain and exact.

Build these parts in order.

### 1. Header

The header from the layout notes. "Practice" is the current page, in the header and in the footer.

### 2. Opening

The first section, in the grid:

- A row in columns 1–12 (`md:col-span-12`), a `<div>` with `flex flex-wrap items-center gap-x-4 gap-y-2`: a label line in `text-muted-foreground`, `Practice area · 4 partners · 16 lawyers`, and beside it the page's one badge, "Ranked 2026". 16px between them on one line, 8px when the badge wraps under the label.
- With `mt-4`, the `<h1>` in `text-h1 md:text-display`, columns 1–9 (`md:col-span-9`): "Commercial disputes".
- With `mt-8`, a `<p>` in columns 1–7 (`md:col-start-1 md:col-span-7`, which overlap the `<h1>`'s, so it starts a row under it), at most `max-w-xl`, in `text-body`. Sample: "When a contract, a sale or a partnership goes wrong, we work out what the claim is worth before anyone spends money on it, and then we pursue it or defend it to the end."

### 3. What we do

A section in the grid, with two parts:

**The text**, in columns 1–7 (`md:col-span-7`):

- An `<h2>` in `text-h2`: "What we do".
- With `mt-4`, three paragraphs in `text-body`, each at most `max-w-xl`, the second and third with `mt-4`. Say who the team acts for; how it handles a new dispute in its first two weeks (a partner reads the papers, the client gets a written view of the claim's merits and its likely cost); and how often its claims settle before trial and why. The last paragraph holds one link in running text, "our briefing on notice clauses", to `/insights/notice-clauses`.

**The note**, in columns 9–12 (`md:col-start-9 md:col-span-4`), with `mt-14 md:mt-0`, as the Text and note rule says:

- A label heading "The team", an `<h3>`.
- With `mt-4`, a `<dl>` as the layout notes describe it, with four rows: Partners (`4`), Lawyers (`16`), Head of practice (`David Achterberg`), Ranked (`Band 1, Northern Legal Review, 2026`). The two counts are in `font-mono tabular-nums` inside the `<dd>`.

### 4. Typical matters

A section in the grid:

- An `<h2>` in `text-h2`, columns 1–4 (`md:col-span-4`): "Typical matters".
- In columns 5–12 (`md:col-start-5 md:col-span-8`), with `mt-8 md:mt-0`: a `<ul>` as a list of entries, six entries, each with `py-4` (here, instead of the notes' `py-8`, because the entries are short). Each `<li>` is also `md:grid md:grid-cols-8 md:items-baseline md:gap-x-8`, with two parts: the kind of matter as an `<h3>` in `text-h2` in columns 1–3 (`md:col-span-3`), and one sentence in `text-body` in columns 4–8 (`md:col-span-5`), with `mt-2 md:mt-0`.

  Entries, in this order: Contract and supply claims; Warranty claims after a sale; Shareholder disputes; Professional negligence; Arbitration; Urgent court orders (freezing orders and injunctions, often within a day or two).

### 5. Recent matters

A section that is not a grid:

- An `<h2>` in `text-h2`: "Recent matters".
- With `mt-8`, a `<ul>` as a list of entries, three entries, each with `py-8`. Each `<li>` is also `md:grid md:grid-cols-12 md:items-baseline md:gap-x-8`, with three parts:
  - Columns 1–3 (`md:col-span-3`): a label line in `text-muted-foreground` with the year and the kind of claim, `2026 · Trial`, the year in a `<time dateTime="2026">`.
  - Columns 4–10 (`md:col-span-7`), with `mt-2 md:mt-0`: a `<div>` holding the matter's name as an `<h3>` in `text-h2`, not a link, then with `mt-2` one sentence in `text-body`, at most `max-w-xl`, then with `mt-2` a label line in `text-muted-foreground` naming who led it: `Led by David Achterberg`.
  - Columns 11–12 (`md:col-span-2`), with `mt-2 md:mt-0`: the value, a `<p>` in `font-mono text-label uppercase tabular-nums text-foreground` with `md:text-right`.

  Entries, in this order: "Estley Mills v Brandreth Engineering" (`2026 · Trial`, `£6.2m`, led by David Achterberg with Ruth Calloway): won a claim for a textile mill, after a nine-day trial, over a production line that never ran to its specification. "The sellers of Halden Print" (`2026 · Warranty claim`, `£3.4m`, led by Ruth Calloway): a buyer's warranty claim against our clients was struck out because its notice arrived one day after the contract's deadline. "Marram Logistics" (`2026 · Urgent order`, `£2.1m`, led by David Achterberg): a freezing order against a former director, obtained within 36 hours of the first call.

### 6. Who leads it

A section that is not a grid:

- An `<h2>` in `text-h2`: "Who leads it".
- With `mt-8`, a `<ul>` with `list-none` that is itself the grid (`grid grid-cols-1 md:grid-cols-12 md:gap-x-8`), with two `<li>`: the first in columns 1–6 (`md:col-span-6`), the second in columns 7–12 (`md:col-start-7 md:col-span-6`) with `mt-14 md:mt-0`. Each `<li>` is itself a grid of its own from `md` up, `md:grid md:grid-cols-6 md:gap-x-8`, with two parts:
  - The portrait from the layout notes in columns 1–2 (`md:col-span-2`), with the person's initials. On a phone it is `w-1/2` wide, so it does not fill the screen: write `w-1/2 md:w-full` in place of the notes' `w-full`.
  - In columns 3–6 (`md:col-span-4`), with `mt-4 md:mt-0`, a `<div>` holding: the name as an `<h3>` in `text-h2` holding a link, styled as a name that is a link (Ruth Calloway to `/people/ruth-calloway`, David Achterberg to `#`); with `mt-2` the role, a label line in `text-muted-foreground`; with `mt-4` one sentence in `text-body` on what they handle; with `mt-4` two `<p>` label lines, the second with `mt-2`: the telephone number as a `tel:` link and the email address as a `mailto:` link in `normal-case`, both styled as links in running text.

  People: David Achterberg (`DA`, `Head of commercial disputes`, `01632 960 231`, `d.achterberg@harrowvane.example`): trials and urgent court orders. Ruth Calloway (`RC`, `Partner · Commercial disputes`, `01632 960 237`, `r.calloway@harrowvane.example`): disputes that follow the sale of a company. Each portrait's `aria-label` describes a photograph of that person in one sentence.

### 7. Related briefings

A section that is not a grid:

- An `<h2>` in `text-h2`: "Related briefings".
- With `mt-8`, a `<ul>` as a list of entries, three entries, each with `py-8`. Each `<li>` is also `md:grid md:grid-cols-12 md:items-baseline md:gap-x-8`: in columns 1–3 (`md:col-span-3`) a label line in `text-muted-foreground` with the date as a `<time>` and the reading time, `10 November 2026 · 8 min read`; in columns 4–12 (`md:col-span-9`), with `mt-2 md:mt-0`, the title as an `<h3>` in `text-h2` holding a link, styled as a title that is a link, then with `mt-2` the author, a label line in `text-muted-foreground`.

  Entries, newest first: "Notice clauses after a sale: when a late letter ends a warranty claim" (10 November 2026, 8 min read, Ruth Calloway, to `/insights/notice-clauses`); "Freezing orders: the first forty-eight hours" (29 October 2026, 6 min read, David Achterberg, to `#`); "Earn-outs that end in dispute" (17 September 2026, 6 min read, Ruth Calloway, to `#`).
- With `mt-8`, an onward link from the layout notes: "All briefings", to `#`.

### 8. Speak to the team

A section in the grid, with its content in columns 1–7 (`md:col-span-7`):

- An `<h2>` in `text-h2`: "Speak to the team".
- With `mt-4`, one or two sentences in `text-body`, at most `max-w-xl`: send us the outline of the dispute and any deadline you know of, and a partner replies within one working day.
- With `mt-8`, a `<div>` holding the default button "Speak to the team", an `<a>` styled with `buttonVariants` and the Buttons classes, to `/contact`. The page's one default button.

### 9. Footer

The footer from the layout notes.

### On a phone

Every part is one column. The badge wraps under the label line if the line is too short. The note comes after the three paragraphs, 56px under them. Each list entry stacks: label line, then name or title, then sentence, then value. The two partners stack, each with a half-width portrait above their name.

### Behavior

Nothing on this page has state. Links only.

## Rules

- **Colors:** only the theme's colors, through the semantic classes (`bg-background`, `text-foreground`, `bg-card`, `bg-primary`, `text-primary-foreground`, `text-muted-foreground`, `border-border` and so on). No hex, rgb or named colors in components, and no Tailwind palette classes such as `bg-blue-500` or `text-gray-600`.
- **Spacing:** padding, margin and gap use only the scale's steps (`1`, `2`, `4`, `8`, `14`, `28`) plus 0, 1px and 2px. No arbitrary values such as `p-[18px]`, and no other steps such as `p-3` or `gap-6`. `auto` margins are fine. Widths and heights such as `w-64` or `size-4` are sizes, not spacing. This applies to the code you write: a stock component keeps the spacing inside it, unless this brief changes it.
- **Type:** every piece of text you write gets its size from one of `text-display`, `text-h1`, `text-h2`, `text-body`, `text-label`, set on the element or on a parent it inherits from. Put `text-body` on the outermost element of the page you write. No other sizes. A stock shadcn component keeps the size it ships with, unless `DESIGN.md` or this brief gives that component its own style. A type class does not replace a weight class: where a stock component ships `font-medium` and the text should be regular, add `font-normal`.
- **Fonts:** only the theme's fonts, through `font-sans`, `font-heading` and `font-mono`. Do not add a font.
- **Corners:** only the `rounded-*` classes, which the theme already sets. No arbitrary radius. This theme has no full rounds: do not use `rounded-full`, and give a small mark a corner under half its height or none, because a box whose corner is half its height or more is a full round however it is written.
- **Contrast:** all text meets WCAG AA against its background.
- **Stock components:** a component from `components/ui`, and an `<a>` styled with `buttonVariants`, keeps the hover, pressed and disabled colors and the motion it ships with, unless this brief changes them. They are the theme's colors under other names.
- **Counts:** a number with a noun reads right at one: "1 set", not "1 sets". Where this brief gives the words for only one of the two, write the other the same way.
- **Sizes from data:** a height or a width that comes from data (a chart bar, a meter) is set with an inline `style`. That is the one use for an inline style.
- **Focus:** every link and control shows a 2px outline on keyboard focus: `focus-visible:outline-solid focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ring`. Keep `focus-visible:outline-solid` in it: in Tailwind 4 an `outline-none` on the same element, which stock components carry, otherwise hides the outline. An element that only gets focus from code (a heading or a message with `tabIndex={-1}`) gets the same outline written with `focus:` in place of `focus-visible:` (`focus:outline-solid focus:outline-2 focus:outline-offset-2 focus:outline-ring`): after a mouse click, a browser does not match `:focus-visible` on an element that code focuses. A link, a button or a field that code focuses keeps the `focus-visible:` classes it has: after a mouse click it shows no outline, which is how a browser treats every control, and is right. A stock component that ships its own focus ring (`Button`, `buttonVariants`, `Input`, `Textarea`, `Checkbox`, `Switch`, `AccordionTrigger`, the close button of a `Sheet`) must lose that ring. Do it once, in the component's file in `components/ui`, which is yours to change: replace its `focus-visible:ring-*` classes with the outline classes, and in a field replace its `aria-invalid:ring-*` classes, the `dark:` ones included, with `aria-invalid:ring-0`, or a field with an error shows a tinted ring. `Button` has two more sets. Its base classes also carry `aria-invalid:ring-*` classes: replace them with `aria-invalid:ring-0`, as in a field. Its `destructive` variant carries `focus-visible:ring-*` classes of its own, the `dark:` one included: delete them and put nothing in their place, because the base classes already give every variant the outline. Wherever this rule says replace, change the classes in the file and do not add `ring-0` beside them: an added class only wins where it comes later and passes through `cn`. The stock `focus-visible:border-ring` can stay. These ring changes go only into the files of components that this page uses and that can take focus on it: a `Badge` that is not a link keeps its ring classes. The `cn` import from the setup steps is another matter and goes into every file. A box that scrolls sideways (a code block, a wide table) gets `tabIndex={0}`, `role="region"`, an `aria-label` and the same outline, also at widths where it happens to fit. Where a focusable box touches the edges of a parent that has `overflow-hidden`, draw its outline inside it: `focus-visible:-outline-offset-2` in place of `focus-visible:outline-offset-2`.
- **Not allowed:** purple or multi-color gradients; emoji used as icons or bullets; glows and colored shadows.
- **Avoid:** a card inside a card.
- **Dark mode:** the page must work with the `dark` class on `<html>`. Because every color comes from a semantic class, this needs no extra code; do not write `dark:` color overrides. A new shadcn project follows the system's mode and switches on the `d` key: leave that as it is, and add no mode switch of your own. If the page has a native `<select>` or a date or time field, tell the browser the mode, or its list and its picker stay light in dark mode: in the global CSS, give `:root` `color-scheme: light` and `.dark` `color-scheme: dark`.

From the theme's own do's and don'ts:

- Do use gold once on a page, and let it mean something. The focus outline and a ticked checkbox do not count.
- Do leave wide margins: an empty column is part of the design.
- Do set names and titles in the heading font and the facts about them in labels.
- Don't set Marcellus in bold or italics: it has neither.
- Don't use gradients, glows or photographs with color casts.
- Don't introduce a color, size or radius that is not a token above.

## Check before you finish

Go through this list against the code you wrote, and fix anything that fails.

- [ ] The running text sits in seven of the twelve columns from `md` up, with one short note beside it in columns 9–12 and the columns between them empty.
- [ ] The page has exactly one badge, Ranked 2026, beside the page's label line, and nothing else on the page is `bg-tertiary`; there is exactly one default (navy) button, Speak to the team.
- [ ] The typical matters, the recent matters and the related briefings are lists with a 1px top border on each entry; each briefing's date is a `<time>` with a `dateTime`.
- [ ] Each of the two partners has a rectangular portrait with initials, a name in the heading font, a role in a label, and a telephone link and an email link that are never uppercased.
- [ ] No heading or text on the page is bold or italic, and nothing on the page is round.
- [ ] No color is written as a hex, rgb or Tailwind palette value in the page's code.
- [ ] Every padding, margin and gap in the code you wrote is a step of the spacing scale.
- [ ] Every text element you wrote gets its size from a type-scale class, its own or an inherited one. Visually hidden text is exempt.
- [ ] No file in `components/ui` imports `cn` from `"cn"` directly.
- [ ] Text contrast meets WCAG AA in light and dark mode.
- [ ] The page has one `<h1>`, headings are in order, and every image has alt text.
- [ ] Every interactive element can be reached with the keyboard and shows the focus outline from the rules.
- [ ] At 375px wide the page does not scroll sideways. Wide tables and code blocks scroll inside their own box.
- [ ] The project builds without errors or warnings.

Then tell the user which checks pass, which you could not verify, and anything in this brief you did not do and why.
