Skip to content

Perchford design system

Internal, noindex

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.

Back to contents

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

Authority navy --authority-navy Dark fields and primary button hover 15.1:1 with white text
Trust blue --trust-blue Primary actions, links, and active controls 7.3:1 with white text
Slate ink --slate-ink Body text, headings, and structural rules 15.9:1 on white
Architectural copper --architectural-copper Feature accent on dark fields and selected actions 5.15:1 with slate ink
Clear blue --clear-blue Supporting accent and current-year state 6.24:1 with slate ink
Mist --mist Quiet tint and supporting surface 13.3:1 with slate ink
Architectural copper is the feature accent. It appears selectively on authority navy, never as text on white, and only as a large fill when paired with slate ink. Clear blue supports it in diagrams, status markers, and quiet interactive details.

Surfaces

White --white Default field
Paper --paper Alternating field, register cells
Warm --warm Third field, image placeholder base
Mist --mist Quiet tint and accent field. Once per page maximum.

Text

Slate ink --slate-ink Headings and primary text 15.9:1 on white
Muted slate --muted Body copy, captions, secondary text 6.3:1 on white
On dark --rp-on-dark Text on slate ink and authority navy fields
On dark muted --rp-on-dark-muted Body copy on dark fields 9.9:1 on authority navy

Rules and borders

Line --line Quiet internal rules inside a component
Line strong --line-strong Register grids, ledger rows, section edges
Rule inverse --rp-rule-inverse All rules on dark fields

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.

Now --rp-state-now Needs timely attention
This year --rp-state-year In the current annual plan
Plan next --rp-state-next Needs budget or a dependency first
Monitor --rp-state-monitor Tracked, not yet funded

Approved field combinations

Approved text, rule, and accent colours for each field
FieldHeadingBodyRulesAccent
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--mutedtrust blue at 24%--trust-blue fill
Slate inkwhite--rp-on-dark-muted--rp-rule-inverse--architectural-copper
Authority navywhite--rp-on-dark-muted--rp-rule-inverse--architectural-copper
Contrast requirement. WCAG 2.2 AA: 4.5:1 for body text, 3:1 for text at 24px or above and for interface borders. Every combination above clears it. The one to watch is --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.
Back to contents

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

Type scale tokens, sizes, and where each belongs
TokenSizeWhere it belongs
--rp-display-1clamp(48px, 7.4vw, 92px)Homepage hero only. Once per site section.
--rp-display-2clamp(38px, 5.6vw, 66px)Section headings and secondary heroes
--rp-display-3clamp(28px, 3.6vw, 42px)Sub-section headings inside a dense pattern
--rp-statementclamp(21px, 2.9vw, 30px)Serif statement paragraphs and pull quotes
--rp-text-leadclamp(17px, 1.7vw, 20px)Lead paragraph beside a display heading
--rp-text-body16pxRunning prose
--rp-text-sm14pxLedger values, register body, dense rows
--rp-text-xs13pxCaptions, notes, metadata
--rp-text-2xs11pxTable 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.

Long-form article typography. Journal body copy uses --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
Back to contents

04Layout and spacing

Six spacing steps and four breakpoints. A value between steps is a mistake rather than a nuance.

Containers

Container and gutter tokens
TokenValueUse
--rp-container1240pxStandard section width
--rp-container-narrow880pxArticle body, in-article patterns
--rp-gutter24pxPage gutter, both sides
--rp-gutter-sm16pxGutter below 560px

Spacing scale

Spacing scale tokens and their uses
TokenValueUse
--rp-space-3xs4pxBetween a label and the value directly beneath it
--rp-space-2xs8pxList item gaps, button gaps
--rp-space-xs14pxLedger row padding, tight cell padding
--rp-space-sm22pxRegister cell padding, standard row padding
--rp-space-md34pxBetween blocks inside a section
--rp-space-lgclamp(44px, 5vw, 64px)Between a section heading and its content
--rp-space-xlclamp(64px, 7vw, 96px)Tight section padding
--rp-space-sectionclamp(76px, 9vw, 124px)Standard section padding

Breakpoints

Breakpoints and what changes at each
WidthWhat changes
1180pxWide. Three and five column layouts begin to compress.
980pxDesktop. Primary two-column splits stack.
760pxTablet. Four-up registers become two-up.
560pxPhone. 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.

Statement column, 1fr
Substance column, 0.82fr

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.

Back to contents

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

Rule weights, colours, and their meanings
WeightColourMeaning
2px--inkThe top edge of a structural block. Opens a table, sequence, or register.
1px--line-strongBetween peer rows or cells. The system’s default rule.
1px--lineQuiet internal divisions inside a single component.
2px left--line-strongMargin 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.

Shadows. The system ships one, --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.
Back to contents

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

One primary action per section. Two primaries beside each other means neither is primary. Every button clears the 44px minimum touch target.

Form controls

We confirm availability address by address.

Enter an email address including the part after the @ symbol.

We currently serve this area.

How long do you expect to own the home
What do you already have

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
Back to contents

07Photography

The current library combines real property context with planning and adviser imagery. Keep additions consistent with the calm, credible direction established here.

Use approved home-management photography only. A pattern may still ship with a labelled placeholder when no approved image fits. Do not fill the gap with generic stock photography.
Photography pending
Minnetonka Placeholder. Replace with a real property view.

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.

Back to contents

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.

Year one 3 to 5 year roadmap Ongoing
Level 03 · +2

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.

The five drawing motifs, their classes, and purposes
MotifClassPurpose
M10 Dimension line.rp-dimA measured span with tick ends and the value in a break in the line.
M11 Station spine.rp-stationA ticked and numbered datum running down the edge of a section, like chainage on a survey.
M12 Title block.rp-titleblockThe metadata corner of a drawing sheet. Short mono key and value pairs in a ruled grid.
M13 Hatch.rp-hatchDiagonal fill marking a zone that is deliberately out of scope.
M14 Level datum.rp-datumThe 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.
  1. 01

    A sequence mark sits in its own column and is never enclosed in a shape.

  2. 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.

The nine shared motifs, their classes, and purposes
MotifClassPurpose
M1 Register.rp-registerContent on hairlines instead of inside cards. The primary anti-card device.
M2 Sequence mark.rp-seqA serif ordinal in its own column, marking order, priority, or step.
M3 Horizon.rp-horizonThe labelled time axis. Now, this year, plan next, monitor, later.
M4 Condition marker.rp-markerA 9px square carrying one of five states. Square rather than circle, because a circle reads as a dashboard status dot.
M5 Elevation frame.rp-framePhotography as a deliberate architectural view: a hairline inset from the image edge, and a ruled caption beneath.
M6 Held column.rp-heldAsymmetric section opening. A short held statement, then the substance, on a shared baseline.
M7 Ledger pair.rp-ledgerTwo-part ruled rows. A term on the left, its consequence on the right.
M8 Quiet field.rp-fieldA flat tinted band segmenting page rhythm. Flat colour only.
M9 Margin note.rp-noteA 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.
Mobile and accessibility. Every motif has documented behaviour at 560px, defined alongside its rules in 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.
Back to contents

09Motion

Motion is calm and never load-bearing. No information waits for an animation to finish.

Motion uses, durations, and behaviours
UseDurationBehaviour
Section reveal360msOpacity plus a 10px rise. Content is readable before it runs.
Hover and focus200msColour, border, and underline only. No transform on containers.
Text link arrow200ms3px horizontal shift. Directional, not decorative.
Disclosure200msThe FAQ plus mark rotating to a minus. Native details handles the rest.
Form feedback120msBorder and message colour. Never a shake.
Navigation feedback200msBackground 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
Reduced motion. 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.
Back to contents

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.

Known gaps. The level comparison matrix scrolls horizontally below 640px, which is acceptable for a genuine data table but should be verified with a screen reader before it ships on a production page. The production ContactLauncher component is fixed to the viewport on every page and has not been audited against this standard.
Back to contents

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 test. If a section could appear unchanged on a SaaS startup, a marketing agency, a financial app, or a generic home-services template, redesign it. Looking good is not the bar. Looking like this specific company is.

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.

Back to contents

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.

Composition limits and the reason for each
RuleLimitWhy
Adjacent layout archetypesNever the same twiceThis is the rule that actually stops a page feeling templated. Everything else is secondary to it.
Motifs per sectionThree maximumA fourth device stops being structure and becomes texture.
Dark fields per pageTwo maximum, never adjacentDark marks a change in register. Three makes it the default.
Mint field per pageOneMint is the only accent surface. A second one spends the emphasis.
Neighbouring fieldsMust differTwo white sections in a row read as one long section.
Held columns in a rowNever two consecutiveThis is how a page starts to feel templated.
Equal registers per pageOneThe second one is almost always disguising a ranking.
Primary actions per sectionOneTwo primaries means neither is.
Heroes per pageOneNon-negotiable.
Patterns per pageSix to nineBelow 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.

  1. Hero. Ink field.
  2. Problem framing. White.
  3. Priority board. Mist, the one accent field.
  4. Service levels. White.
  5. Differentiation. Ink, the second and last dark field.
  6. Record anatomy. Paper.
  7. Process. White.
  8. FAQ. Paper.
  9. Call to action. Authority navy, closing the page.
Nine sections, three of them dark or accented, no two neighbours alike. 13 of the 62 patterns in the library render on a dark field, which is roughly the right proportion. If that number grows much past a third, dark stops signalling anything.

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