# Harbor Ledger design.md

Harbor Ledger is fictional. It is a bookkeeping service for independent contractors. The prices, the city, and the call offer below are example facts for this file. Do not publish them as a real business. Replace them when you copy the clean template.

This file is judgment. The stylesheet is what the browser paints. If a hex here disagrees with the custom property, the custom property wins until someone edits it on purpose.

## Reader and page job

- Reader: an independent contractor who sends their own invoices and wants someone else to keep the monthly books.
- Decision: whether to book a 20-minute call this week.
- Primary action: Book a 20-minute call. Destination: /book.
- Approved example facts: monthly books are $89. A tax-ready year is $640. The service is for contractors, not for companies with a finance team.
- Proposals, not yet approved: any headline about saving time.
- Gaps: no customer quotes, no logo permissions, no measured hours saved. Leave those out.

## Refusals

- Do not add a logo cloud. There are no approved logos.
- Do not invent a testimonial or a contractor's name.
- Do not put a product dashboard in the hero. The product is a service.
- Do not change $89 or $640 while editing layout.
- Do not add a third offer to make a pricing grid look even.

## Tokens

Declared on :root in src/styles/tokens.css. Use var(). Do not copy the hex into a component.

- --background: #f6f4ef. Page canvas.
- --foreground: #1c1915. Text.
- --muted: #5e584f. Secondary text. Check it against --background before you use it for a price.
- --accent: #0f6e56. Primary button fill.
- --accent-foreground: #ffffff. Text on the button.
- --danger: #9f2d20. Form errors, with text, not color alone.
- Spacing steps: 4, 8, 12, 16, 24, 32, 48, 64.
- Type: Source Serif for the page title only. The rest is the already loaded sans. Do not add a third family for a quote.

These names are examples for the fictional project. A real project should point at the properties it already has.

## Layout

- The home page opening is left aligned: who it is for, the price, and one button. A photograph, if you have a real one, comes after that stack on a phone.
- Reading text stays within about 65 characters. Do not shrink the type to make a long headline fit.
- Desktop content width is 1120px with 24px of side padding. At 390px the side padding is 16px.
- One primary button in the opening. The pricing page may repeat that same action once, under the two prices.

## Components and states

- Button, src/components/button.tsx. Primary is filled --accent. Secondary is a border. States that exist: default, hover, focus-visible, disabled. The label says the result.
- Price row. Shows the amount, the period, and one line of what is included. Do not invent a crossed-out price.
- Field. Visible label, not a placeholder standing in for the label. Error text names the field and how to fix it. Valid input remains after a failed submit.
- Shell, src/components/site-shell.tsx. Header, skip link, current page, footer. New marketing routes use this shell. Do not paste a second header.

## Assets

- A photograph must show a contractor's own workspace or be omitted. The example brief is a kitchen table, a laptop, and invoices, 3:2, no readable client names.
- Alt text for that photo, if used: "Laptop and invoices on a kitchen table."
- Decorative lines get an empty alt attribute.
- No stock handshake, no generated logo, no chart with a made-up result.

## Motion

- Default is still.
- A focus ring does not need animation.
- If a disclosure opens, it may fade in under 200ms. Honor prefers-reduced-motion by skipping that fade.
- Do not autoplay a carousel of quotes. There are no quotes.

## Accessibility and responsive behavior

- House convention: use one h1 for the main page topic. Later sections use h2 in order.
- The call link is in the tab order and shows a visible ring.
- Body text is at least 16px.
- In a 390 × 844 px viewport captured from the top at 100% zoom, the price and the button are visible before any tall image.
- Contrast for the price and the button label meets WCAG 2.1 AA for normal text, 4.5:1, against the surface they sit on.

## Do and do not

Do: reuse the shell, the button, and the custom properties. Keep the two approved prices. Say who the service is for in the first screen.

Do not: fill a missing quote, copy another firm's palette from a screenshot, or treat this fictional file as proof that a page was reviewed.

## Checks

- Desktop: the first screen shows contractors, a price, and Book a 20-minute call.
- 390 × 844 px, captured from the top at 100% zoom: those three are still visible before a tall image.
- The button is the existing component.
- No testimonial and no logo row.
- The stylesheet and this file name the same custom properties.
