Style Guide
The foundations every Perchford page is built from: colour, type, spacing, shape, interaction, photography, motion, and the nine shared motifs. The Pattern Lab holds the 62 sections composed from them.
The visual thesis is the standing record. A well-managed home has a record, so the system speaks in the language of an ordered, living document of a property: ruled lines, sequence marks, horizons, and a visible boundary between what is decided and what is still open. Warm paper surfaces and a quiet serif keep it residential rather than administrative.
01Brand principles
Five distinctions do most of the work. Each one has a near neighbour that is easy to drift into and hard to come back from.
Premium, not pretentious
Premium here means restraint and precision: generous space, one typeface doing display work, no ornament that carries no information. Pretentious is abstraction for its own sake. If a sentence sounds impressive but leaves the reader less certain about what happens next, it has crossed over.
Residential, not commercial
This is somebody’s house, not a facility. Warm paper surfaces, a serif that belongs on a letter rather than a dashboard, and copy addressed to one person. Anything that would look at home in a B2B software product has drifted.
Architectural, not cold
Structure is visible: rules, alignment, a real grid, honest hierarchy. Cold is when structure is the only thing present. Every dense ruled section needs warmth nearby, which is what the paper and mist fields are for.
Editorial, not decorative
Editorial means the layout follows the argument: a lead, a measure, a caption that adds something. Decorative means a shape was added because the space looked empty. Empty space is not a problem to solve.
Reusable, not repetitive
A motif used three times on a page is a system. The same composition used three times is a template. The composition rules in section 12 exist because this is the failure the system is most likely to produce.
The one-line test
If a section could appear unchanged on a SaaS marketing site, a financial app, or a generic home-services template, it is wrong regardless of how good it looks. Redesign it.
02Colour
CSS custom properties in src/styles/global.css and
src/styles/design-system.css are the only source of truth. A pattern that
introduces a colour is a bug.
Brand
Surfaces
Text
Rules and borders
Condition states
Four states, used by the condition marker. Each one must always be accompanied by its text label. Colour never carries meaning on its own.
Approved field combinations
| Field | Heading | Body | Rules | Accent |
|---|---|---|---|---|
| White | --slate-ink | --muted | --line-strong | --trust-blue |
| Paper | --slate-ink | --muted | --line-strong | --trust-blue |
| Warm | --slate-ink | --muted | --line-strong | --trust-blue |
| Mist | --slate-ink | --muted | trust blue at 24% | --trust-blue fill |
| Slate ink | white | --rp-on-dark-muted | --rp-rule-inverse | --architectural-copper |
| Authority navy | white | --rp-on-dark-muted | --rp-rule-inverse | --architectural-copper |
--muted on --mist, which measures 5.26:1. Keep the muted slate mix at
72% so secondary text retains a comfortable margin above the requirement.
03Typography
Two families. A serif for display and statements, a sans for everything else. Adding a third face requires a documented reason.
Display and statement
--font-serif, currently Georgia. Set at 500 weight, tight tracking between -0.03em and -0.055em, and leading near 1.0. The tight tracking is what makes it read as designed rather than as a default serif.
Interface and body
--font, Plus Jakarta Sans with a system fallback. Known gap: the webfont is declared but never actually loaded, so every page currently renders in the system fallback. Either self-host it or remove it from the stack.
Scale
Display 1
Display 2, the section heading size
Display 3, for headings inside a dense pattern
Statement. A serif paragraph used where a claim needs more weight than body copy gives it.
Lead. The supporting paragraph that sits beside a display heading in a held column.
Body. Running prose, capped at 68 characters so a line never becomes hard to track back from.
Body small. Register cells, ledger values, and anywhere density genuinely helps the reader.
Caption. Image provenance, metadata, and row detail.
01 02 03 · 0% · 1994 · Feb to Mar
| Token | Size | Where it belongs |
|---|---|---|
--rp-display-1 | clamp(48px, 7.4vw, 92px) | Homepage hero only. Once per site section. |
--rp-display-2 | clamp(38px, 5.6vw, 66px) | Section headings and secondary heroes |
--rp-display-3 | clamp(28px, 3.6vw, 42px) | Sub-section headings inside a dense pattern |
--rp-statement | clamp(21px, 2.9vw, 30px) | Serif statement paragraphs and pull quotes |
--rp-text-lead | clamp(17px, 1.7vw, 20px) | Lead paragraph beside a display heading |
--rp-text-body | 16px | Running prose |
--rp-text-sm | 14px | Ledger values, register body, dense rows |
--rp-text-xs | 13px | Captions, notes, metadata |
--rp-text-2xs | 11px | Table labels and row states. Never running prose. |
Measure
Reading
68ch. The hard limit for any running prose.
Lead
56ch. Supporting paragraphs beside a heading.
Display
18ch. Forces display headings to break where you intend.
--rp-text-body at
--rp-leading-body inside .rp-container-narrow, which lands close to
the 68 character measure at every width. Article headings step down through display 3 and the
.rp-heading size. Do not use display 1 or 2 inside article body copy.
Type rules
- Serif for display, statements, quotes, and numerals
- Sans for everything else
- Tighten tracking as size increases, never the reverse
- Cap every prose block at a documented measure
- Use tabular numerals for anything in a column
Type mistakes
- All-caps text anywhere except table column labels
- Letter-spacing added to body copy
- Serif at small sizes for running prose
- A third typeface
- Type sizes between the documented steps
04Layout and spacing
Six spacing steps and four breakpoints. A value between steps is a mistake rather than a nuance.
Containers
| Token | Value | Use |
|---|---|---|
--rp-container | 1240px | Standard section width |
--rp-container-narrow | 880px | Article body, in-article patterns |
--rp-gutter | 24px | Page gutter, both sides |
--rp-gutter-sm | 16px | Gutter below 560px |
Spacing scale
| Token | Value | Use |
|---|---|---|
--rp-space-3xs | 4px | Between a label and the value directly beneath it |
--rp-space-2xs | 8px | List item gaps, button gaps |
--rp-space-xs | 14px | Ledger row padding, tight cell padding |
--rp-space-sm | 22px | Register cell padding, standard row padding |
--rp-space-md | 34px | Between blocks inside a section |
--rp-space-lg | clamp(44px, 5vw, 64px) | Between a section heading and its content |
--rp-space-xl | clamp(64px, 7vw, 96px) | Tight section padding |
--rp-space-section | clamp(76px, 9vw, 124px) | Standard section padding |
Breakpoints
| Width | What changes |
|---|---|
1180px | Wide. Three and five column layouts begin to compress. |
980px | Desktop. Primary two-column splits stack. |
760px | Tablet. Four-up registers become two-up. |
560px | Phone. Two-up registers become one-up, gutters tighten. |
Asymmetry
Symmetric grids are the exception. The held column defaults to a 1 to 0.82 split; registers prefer an uneven lead column where the content has a genuine lead item. Equal columns are correct only when the items are true peers, which is rarer than it looks.
Image proportions
3:2 elevation
The default. A house seen from the street.
4:5 portrait
People, and vertical architectural detail.
16:9 wide
Full-bleed context views only.
1:1 square
Detail crops inside a register cell.
05Shape and depth
This is a rule-led system, not a radius-led one. Most content sits directly on the page surface, separated by hairlines.
A card is warranted when
- The object represents a real artifact, such as the plan excerpt or a visit record
- It genuinely floats above the field, such as a navigation panel
- Its edges carry meaning, such as a bounded document
Content stays on the page surface when
- It is a list of peer items. Use a register.
- It is a heading with a paragraph. That is just content.
- The only reason is that the section looked empty
- Every sibling already has one. Then none of them need one.
Rules and dividers
| Weight | Colour | Meaning |
|---|---|---|
| 2px | --ink | The top edge of a structural block. Opens a table, sequence, or register. |
| 1px | --line-strong | Between peer rows or cells. The system’s default rule. |
| 1px | --line | Quiet internal divisions inside a single component. |
| 2px left | --line-strong | Margin note. Trust blue or copper when the note is a commitment. |
Radius
0 (default)
Registers, ledgers, tables, fields, images, and every structural edge.
10px
Small interface objects only.
16px
The ceiling. Nothing in this system is rounder than this except pill buttons.
--shadow-subtle, and it is used only where
something genuinely floats above the page. A shadow on a static section is decoration.
Coloured shadows and glows are prohibited.
06Interactive elements
Buttons and links are inherited from the existing production stylesheet unchanged. Form controls are new: the site had no shared field styling before this system.
Buttons
Form controls
Form rules
- A visible label above every control, always
- Help text linked with aria-describedby
- Errors stated as what to do, not what went wrong
- Error and success carry an icon-free text message, never colour alone
- Minimum 44px target height on every control
Form mistakes
- Placeholder text used as the label
- Validation on blur before the user has finished
- Red border with no message
- Disabled submit buttons as the primary validation strategy
- Custom controls where a native one would work
07Photography
The current library combines real property context with planning and adviser imagery. Keep additions consistent with the calm, credible direction established here.
Photograph
- The house from the street, square to the facade, at eye level
- Systems as they actually are: the mechanical room, the panel, the water heater
- Work in progress and the record being made
- Real people who work here, in real conditions
- Overcast or early-evening light. Flat light reads as honest.
Never photograph
- Stock imagery of any kind
- AI-generated properties, interiors, or people
- Staged handshakes, clipboards, or hard hats
- Heavily styled interiors that imply a renovation service
- Wide-angle distortion that flatters a room dishonestly
Composition
Square to the subject. Level horizon. Verticals kept vertical. The camera should feel placed rather than found.
Cropping
3:2 for property views, 4:5 for people. Mobile crops centre on the subject, never on empty sky or lawn.
Overlays
None. No text over images, no tints, no scrims. The frame provides the structure instead.
Captions
Required. Location in bold, then what the image shows. A caption that only repeats the heading should be replaced or removed.
Alt text
Describe what matters for the argument the section is making, not the whole scene. Decorative placeholders take an empty alt.
People
Only real team members and only consenting customers. No customer property is published without written permission.
08Shared motifs
Nine devices, defined in src/styles/design-system.css. They are what make the
system recognisable. A section uses at most three.
Register
01
Scattered information
Records live in different places.
02
Reactive decisions
The loudest problem wins.
03
Accented cell
At most one per register.
Horizon and condition marker
Do now
Safety and property preservation.
Do this year
The current annual plan.
Monitor
Tracked, not yet funded.
Drawing motifs
Motifs 1 to 9 are typographic conventions. Correct, but a ruled table and a numbered list are not inventions, and on their own they produced a system nobody would recognise as this company. These five come from surveyor’s and architect’s drawing language, which is the native visual world of a property record. The mono face carries all of them.
Level datum. The triangle rests on the line the level is measured from.
Hatch. Out of scope, always with a text label beside it.
- Sheet
- Care plan
- Revision
- Aug 2026
- Scope
- One property
- Status
- Illustrative
00+00
00+40
00+80
Station spine. A datum down the edge of a long section so its parts can be located against each other. The rail is hidden below 640px and the content stacks.
| Motif | Class | Purpose |
|---|---|---|
| M10 Dimension line | .rp-dim | A measured span with tick ends and the value in a break in the line. |
| M11 Station spine | .rp-station | A ticked and numbered datum running down the edge of a section, like chainage on a survey. |
| M12 Title block | .rp-titleblock | The metadata corner of a drawing sheet. Short mono key and value pairs in a ruled grid. |
| M13 Hatch | .rp-hatch | Diagonal fill marking a zone that is deliberately out of scope. |
| M14 Level datum | .rp-datum | The elevation symbol from a building section: a triangle resting on a line with the level value beside it. |
M10 Dimension line
Use it when
- Something has a start, an end, and a real extent
- Measuring a horizon, a timeline, or the reach of a level
Do not use it when
- It is only a label. A dimension line that measures nothing looks like information and is not.
M11 Station spine
Use it when
- A long section has ordered parts worth locating against each other
Do not use it when
- The section is short. A spine with two stations is just a line.
M12 Title block
Use it when
- An artifact needs provenance: revision, scope, what it illustrates
Do not use it when
- The values would be invented to fill the cells. Every field has to be true.
M13 Hatch
Use it when
- Marking something genuinely excluded or unavailable
Do not use it when
- The content is merely secondary. Hatch means not this, not less important.
M14 Level datum
Use it when
- Denoting a service level, a tier, or a threshold
Do not use it when
- The items are not ordered. A datum implies height.
Ledger pair, sequence, and margin note
- IncludedA term on the left, its consequence on the right.
- Not includedExcluded rows strike the term, never the explanation.
- 01
A sequence mark sits in its own column and is never enclosed in a shape.
- 02
Ordinals are serif, tabular, and trust blue on light fields.
A margin note carries a boundary, a caveat, or provenance. Forest border when it is a commitment.
| Motif | Class | Purpose |
|---|---|---|
| M1 Register | .rp-register | Content on hairlines instead of inside cards. The primary anti-card device. |
| M2 Sequence mark | .rp-seq | A serif ordinal in its own column, marking order, priority, or step. |
| M3 Horizon | .rp-horizon | The labelled time axis. Now, this year, plan next, monitor, later. |
| M4 Condition marker | .rp-marker | A 9px square carrying one of five states. Square rather than circle, because a circle reads as a dashboard status dot. |
| M5 Elevation frame | .rp-frame | Photography as a deliberate architectural view: a hairline inset from the image edge, and a ruled caption beneath. |
| M6 Held column | .rp-held | Asymmetric section opening. A short held statement, then the substance, on a shared baseline. |
| M7 Ledger pair | .rp-ledger | Two-part ruled rows. A term on the left, its consequence on the right. |
| M8 Quiet field | .rp-field | A flat tinted band segmenting page rhythm. Flat colour only. |
| M9 Margin note | .rp-note | A small annotation flush to a rule, carrying a boundary, caveat, or provenance statement. |
M1 Register
Use it when
- Listing peer items
- Comparing scopes side by side
- Showing a grouped checklist
Do not use it when
- A single item needs lifting for emphasis
- Items have a strict ranking, which needs the sequence mark instead
M2 Sequence mark
Use it when
- Order genuinely carries meaning
- Steps in a process
- A positional register where the reader may want to reference an item
Do not use it when
- Items are peers with no sequence, since a number implies a ranking readers will try to read
- Inside a circle, square, or tinted chip. Never.
M3 Horizon
Use it when
- Showing when work happens
- Explaining how priority is assigned
Do not use it when
- The content has no time dimension
- The stops would need renaming to fit, which means it is not a horizon
M4 Condition marker
Use it when
- A row has a real condition or completion state
- Reinforcing a horizon label already present as text
Do not use it when
- The state is invented for decoration
- It would be the only indication of the state. Colour never carries meaning alone.
M5 Elevation frame
Use it when
- Showing a property, a system, or a person
- Any image that needs provenance
Do not use it when
- The image is a screenshot or a diagram
- There is no caption. Every framed image needs one.
M6 Held column
Use it when
- Opening a section
- A heading that needs a supporting paragraph
Do not use it when
- The previous section also opened with a held column. Alternate.
- The section has only one short line of content
M7 Ledger pair
Use it when
- Pairing a term with its meaning
- Included against not included
- What you do against what we do
Do not use it when
- The right side runs longer than about three lines. That is a register.
- There is no meaningful left-hand term
M8 Quiet field
Use it when
- Separating a section from its neighbours
- Marking a section as a different kind of content
Do not use it when
- The neighbouring section uses the same field
- A gradient, blur, or texture is being considered. Flat only.
M9 Margin note
Use it when
- A claim needs a stated limit
- A visual needs provenance
- Pricing or availability needs a clear boundary
Do not use it when
- The note is really the main point. Promote it.
- It would bury something the reader needs before deciding.
design-system.css. Registers collapse to one column,
ledgers stack term above value, and the horizon drops its label column. The condition marker
is aria-hidden in every use, because its state is always present as text in the
same row.
09Motion
Motion is calm and never load-bearing. No information waits for an animation to finish.
| Use | Duration | Behaviour |
|---|---|---|
| Section reveal | 360ms | Opacity plus a 10px rise. Content is readable before it runs. |
| Hover and focus | 200ms | Colour, border, and underline only. No transform on containers. |
| Text link arrow | 200ms | 3px horizontal shift. Directional, not decorative. |
| Disclosure | 200ms | The FAQ plus mark rotating to a minus. Native details handles the rest. |
| Form feedback | 120ms | Border and message colour. Never a shake. |
| Navigation feedback | 200ms | Background and colour change on the active item. |
Permitted
- Opacity and small translation
- Colour and border transitions
- A one-time reveal per section
- Motion that shows direction, such as a link arrow
Prohibited
- Bouncing, elastic, or spring easing
- Parallax of any depth
- Spinning, pulsing, or looping animation
- Hover-lift on cards or sections
- Animated counters
- Anything that delays the reader seeing content
global.css already reduces every animation and transition
to 0.01ms under prefers-reduced-motion: reduce. Patterns with their own
transitions repeat the query locally so the intent survives a refactor. The reveal animation
is defined only inside prefers-reduced-motion: no-preference, so it never runs at
all rather than running instantly.
10Accessibility
WCAG 2.2 AA is the standard. These are the specific commitments this system makes.
Contrast
4.5:1 for body text, 3:1 for large text and interface borders. Every documented field combination is measured in section 2.
Focus
A 3px ring at 3px offset, trust blue on light fields and copper on dark. Never removed, never replaced with a colour change alone.
Keyboard
Everything interactive is a native button, link, input, details, or select. No custom widgets, no tabindex above 0.
Semantics
One h1 per page. Headings step without skipping. Comparison data uses real tables with scoped headers and a caption.
Colour independence
Condition markers are aria-hidden and always accompanied by text. Table ticks carry visually hidden alternatives.
Touch targets
44px minimum on every control, including FAQ summaries and filter buttons.
Reduced motion
Honoured globally and repeated locally in any pattern that adds its own transition.
Alt text
Describes what matters to the argument. Decorative and placeholder images take an empty alt.
ContactLauncher component is fixed to
the viewport on every page and has not been audited against this standard.
11Anti-slop rules
Binding. A pattern that breaks one of these does not ship, regardless of how good it looks in isolation.
What this system refuses
Each of these is a shortcut that makes a page look finished without making it clearer. Most of them are what a design produces when nobody decided what the section was for.
- Equal-width three-card grids as the default answer
- Icons inside tinted rounded squares
- Gradients used decoratively
- Glassmorphism and backdrop blur
- Glow effects and coloured drop shadows
- Abstract blobs and floating rounded rectangles
- Pill labels and decorative badges
- Eyebrows, kickers, and all-caps section labels
- The eyebrow, heading, paragraph, three-card formula
- A centred heading at the top of every section
- Bento grids
- Hover-lift card effects
- Border radii above 16px
- Shadows that carry no elevation meaning
- Animated counters
- Motion that delays comprehension
- A card container around every piece of content
- Stock or AI-generated photography
- New colours, radii, or shadows invented inside a pattern
- Statistics the business has not actually earned
The two hardest to hold
The three-card grid
It will always be the fastest way to fill a section, and it is almost never the most informative. Before using an equal register, check whether the items really are peers. If one leads, use an uneven register. If they are sequential, use a sequence. If each has a consequence, use a ledger.
Five patterns in the library use an equal register, and each one has to justify it: four frictions with no ranking, four seasons, three parties to a project, four commitments, and the three service levels. The levels are the weakest case, since they are cumulative rather than peer. They carry sequence marks so the ordering is still visible.
The card container
A border around content does not organise it, it just draws a box. The register motif exists so that peer content can be separated by a hairline instead. Reach for a card only when the object represents a real artifact, and be able to name what artifact it is.
12Composition rules
How foundations and motifs combine into a page. These limits exist because the most likely failure of any pattern library is a site where every page reads the same.
| Rule | Limit | Why |
|---|---|---|
| Adjacent layout archetypes | Never the same twice | This is the rule that actually stops a page feeling templated. Everything else is secondary to it. |
| Motifs per section | Three maximum | A fourth device stops being structure and becomes texture. |
| Dark fields per page | Two maximum, never adjacent | Dark marks a change in register. Three makes it the default. |
| Mint field per page | One | Mint is the only accent surface. A second one spends the emphasis. |
| Neighbouring fields | Must differ | Two white sections in a row read as one long section. |
| Held columns in a row | Never two consecutive | This is how a page starts to feel templated. |
| Equal registers per page | One | The second one is almost always disguising a ranking. |
| Primary actions per section | One | Two primaries means neither is. |
| Heroes per page | One | Non-negotiable. |
| Patterns per page | Six to nine | Below six the page is thin. Above nine nothing is remembered. |
Field rhythm
A workable homepage rhythm. Note that no two adjacent sections share a field, and the dark fields are separated by at least two light ones.
- Hero. Ink field.
- Problem framing. White.
- Priority board. Mist, the one accent field.
- Service levels. White.
- Differentiation. Ink, the second and last dark field.
- Record anatomy. Paper.
- Process. White.
- FAQ. Paper.
- Call to action. Authority navy, closing the page.
Photography and copy hierarchy
In any section pairing an image with copy, one of them leads and the other supports. A 50/50 split makes the reader choose, and they will choose neither. Where the image leads, the copy caps at the lead measure. Where the copy leads, the image sits at 4:5 or smaller and carries a caption that adds information the copy does not.
Back to contents