---
version: alpha
name: Spring Doorstep
description: "Calm, botanical UI for home-service booking: spring-water blue actions on cool green-grey neutrals, soft serif headlines, steady contrast."
colors:
  background: "#f4f7f6"
  foreground: "#141b19"
  card: "#ffffff"
  card-foreground: "#141b19"
  popover: "#ffffff"
  popover-foreground: "#141b19"
  primary: "#1f7599"
  primary-foreground: "#ffffff"
  secondary: "#e6ecea"
  secondary-foreground: "#2a3431"
  muted: "#e6ecea"
  muted-foreground: "#505d59"
  accent: "#dcf0f7"
  accent-foreground: "#173d51"
  destructive: "#b92a4c"
  destructive-foreground: "#ffffff"
  success: "#19684b"
  success-foreground: "#ffffff"
  warning: "#f5dd95"
  warning-foreground: "#452e08"
  border: "#cfd9d5"
  input: "#b1bfba"
  ring: "#1f7599"
  dark-background: "#141b19"
  dark-foreground: "#f4f7f6"
  dark-card: "#1c2523"
  dark-card-foreground: "#f4f7f6"
  dark-popover: "#212b29"
  dark-popover-foreground: "#f4f7f6"
  dark-primary: "#55b1d2"
  dark-primary-foreground: "#0c2633"
  dark-secondary: "#2a3533"
  dark-secondary-foreground: "#e6ecea"
  dark-muted: "#26302e"
  dark-muted-foreground: "#b1bfba"
  dark-accent: "#173d51"
  dark-accent-foreground: "#dcf0f7"
  dark-destructive: "#f5677f"
  dark-destructive-foreground: "#370a14"
  dark-success: "#4fb88a"
  dark-success-foreground: "#082a1f"
  dark-warning: "#ddac42"
  dark-warning-foreground: "#2a1b04"
  dark-border: "#3d4845"
  dark-input: "#505d59"
  dark-ring: "#55b1d2"
typography:
  display-lg:
    fontFamily: Fraunces
    fontSize: 48px
    fontWeight: 600
    lineHeight: 1.08
    letterSpacing: -0.025em
  display-md:
    fontFamily: Fraunces
    fontSize: 38px
    fontWeight: 600
    lineHeight: 1.12
    letterSpacing: -0.02em
  heading-lg:
    fontFamily: Fraunces
    fontSize: 30px
    fontWeight: 500
    lineHeight: 1.2
    letterSpacing: -0.015em
  heading-md:
    fontFamily: Instrument Sans
    fontSize: 24px
    fontWeight: 600
    lineHeight: 1.3
    letterSpacing: -0.01em
  heading-sm:
    fontFamily: Instrument Sans
    fontSize: 20px
    fontWeight: 600
    lineHeight: 1.35
    letterSpacing: -0.005em
  body-lg:
    fontFamily: Instrument Sans
    fontSize: 18px
    fontWeight: 400
    lineHeight: 1.6
  body-md:
    fontFamily: Instrument Sans
    fontSize: 16px
    fontWeight: 400
    lineHeight: 1.6
  body-sm:
    fontFamily: Instrument Sans
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.5
  label:
    fontFamily: Instrument Sans
    fontSize: 14px
    fontWeight: 500
    lineHeight: 1.25
    letterSpacing: 0.005em
  caption:
    fontFamily: Instrument Sans
    fontSize: 12px
    fontWeight: 500
    lineHeight: 1.4
    letterSpacing: 0.01em
  code:
    fontFamily: JetBrains Mono
    fontSize: 14px
    fontWeight: 400
    lineHeight: 1.5
rounded:
  sm: 4px
  md: 8px
  lg: 12px
  xl: 16px
  full: 9999px
spacing:
  xs: 4px
  sm: 8px
  md: 16px
  lg: 24px
  xl: 32px
  2xl: 48px
  3xl: 64px
components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.primary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 16px
    height: 40px
  button-secondary:
    backgroundColor: "{colors.secondary}"
    textColor: "{colors.secondary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 16px
    height: 40px
  button-destructive:
    backgroundColor: "{colors.destructive}"
    textColor: "{colors.destructive-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 16px
    height: 40px
  input:
    backgroundColor: "{colors.background}"
    textColor: "{colors.foreground}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.md}"
    padding: 0 12px
    height: 40px
  card:
    backgroundColor: "{colors.card}"
    textColor: "{colors.card-foreground}"
    rounded: "{rounded.lg}"
    padding: 24px
  popover:
    backgroundColor: "{colors.popover}"
    textColor: "{colors.popover-foreground}"
    rounded: "{rounded.lg}"
    padding: 12px
  helper-text:
    backgroundColor: "{colors.background}"
    textColor: "{colors.muted-foreground}"
    typography: "{typography.body-sm}"
  table-row-alt:
    backgroundColor: "{colors.muted}"
    textColor: "{colors.muted-foreground}"
    typography: "{typography.body-sm}"
    height: 44px
  badge:
    backgroundColor: "{colors.accent}"
    textColor: "{colors.accent-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
  badge-success:
    backgroundColor: "{colors.success}"
    textColor: "{colors.success-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
  badge-warning:
    backgroundColor: "{colors.warning}"
    textColor: "{colors.warning-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
  badge-destructive:
    backgroundColor: "{colors.destructive}"
    textColor: "{colors.destructive-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
  button-primary-dark:
    backgroundColor: "{colors.dark-primary}"
    textColor: "{colors.dark-primary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 16px
    height: 40px
  button-secondary-dark:
    backgroundColor: "{colors.dark-secondary}"
    textColor: "{colors.dark-secondary-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 16px
    height: 40px
  button-destructive-dark:
    backgroundColor: "{colors.dark-destructive}"
    textColor: "{colors.dark-destructive-foreground}"
    typography: "{typography.label}"
    rounded: "{rounded.md}"
    padding: 0 16px
    height: 40px
  input-dark:
    backgroundColor: "{colors.dark-background}"
    textColor: "{colors.dark-foreground}"
    typography: "{typography.body-sm}"
    rounded: "{rounded.md}"
    padding: 0 12px
    height: 40px
  card-dark:
    backgroundColor: "{colors.dark-card}"
    textColor: "{colors.dark-card-foreground}"
    rounded: "{rounded.lg}"
    padding: 24px
  popover-dark:
    backgroundColor: "{colors.dark-popover}"
    textColor: "{colors.dark-popover-foreground}"
    rounded: "{rounded.lg}"
    padding: 12px
  helper-text-dark:
    backgroundColor: "{colors.dark-background}"
    textColor: "{colors.dark-muted-foreground}"
    typography: "{typography.body-sm}"
  table-row-alt-dark:
    backgroundColor: "{colors.dark-muted}"
    textColor: "{colors.dark-muted-foreground}"
    typography: "{typography.body-sm}"
    height: 44px
  badge-dark:
    backgroundColor: "{colors.dark-accent}"
    textColor: "{colors.dark-accent-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
  badge-success-dark:
    backgroundColor: "{colors.dark-success}"
    textColor: "{colors.dark-success-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
  badge-warning-dark:
    backgroundColor: "{colors.dark-warning}"
    textColor: "{colors.dark-warning-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
  badge-destructive-dark:
    backgroundColor: "{colors.dark-destructive}"
    textColor: "{colors.dark-destructive-foreground}"
    typography: "{typography.caption}"
    rounded: "{rounded.full}"
    padding: 0 8px
    height: 22px
---

# Spring Doorstep

## Overview

Spring Doorstep is for homeowners booking gardeners, cleaners, plumbers and handypeople, often while dealing with a problem in their house. Instead of urgent orange or red, the system uses one spring-water blue (brand, hue about 200) for action. Structure comes from cool green-grey neutrals (hue about 160). Fraunces is used only for titles of 30px and larger. Every text pair clears 4.5:1 in both modes, and most pairs clear 5:1.

Moods: calm, natural, trustworthy, gentle. Built for: home-services, property-maintenance, landscaping. Density: comfortable.

Every color has a light value and a dark value. Tokens named `dark-*` are the dark-mode counterparts of the token with the same role name.

## Colors

Fernmark Blue carries every primary button, link and focus ring. Light mode uses primary brand.600 #1f7599 with white text (5.2:1) and ring brand.600 (4.8:1 on background). Dark mode uses brand.400 #55b1d2 with brand.950 text (6.5:1). Neutrals hold a steady green tint from 50 to 950. Neutral.950 is set to #141b19 so dark surfaces stay deep but tinted. Destructive is crimson (hue about 345), roughly 145° away from the blue, so cancellations can't be mistaken for primary actions. Success uses a cool teal-leaning green (hue about 155) to sit beside the blue. Warning uses a muted ochre fill (warning.200 with warning.900 text, 9.7:1) so it reads as caution, not alarm. Muted-foreground is neutral.700 in light mode (6.4:1 on background, 5.8:1 on muted) and neutral.300 in dark mode (7.2:1 on muted #26302e).

- **Primary** `#1f7599` / dark `#55b1d2`: the single action color. Primary buttons, links, focus ring.
- **Background / Foreground** `#f4f7f6` / dark `#141b19` on `#141b19` / dark `#f4f7f6`: page surface and body text.
- **Card** `#ffffff` / dark `#1c2523`: raised surfaces.
- **Secondary** `#e6ecea` / dark `#2a3533`: secondary buttons and quiet controls.
- **Muted** `#e6ecea` / dark `#26302e` with **muted-foreground** `#505d59` / dark `#b1bfba`: helper text, table stripes, disabled-looking surfaces.
- **Accent** `#dcf0f7` / dark `#173d51`: highlights, selected rows, badges.
- **Destructive** `#b92a4c` / dark `#f5677f`, **Success** `#19684b` / dark `#4fb88a`, **Warning** `#f5dd95` / dark `#ddac42`: status only, always paired with an icon or label.
- **Border** `#cfd9d5` / dark `#3d4845`, **Input** `#b1bfba` / dark `#505d59`, **Ring** `#1f7599` / dark `#55b1d2`.

All text/background pairs above pass WCAG AA (4.5:1) in both modes; this is checked automatically at build time.

## Typography

The type scale is a major third (ratio of about 1.25) anchored at 16px: 12, 14, 16, 18, 20, 24, 30, 38 and 48. Fraunces covers display-lg 48/600, display-md 38/600 and heading-lg 30/500. Letter spacing tightens from -0.015em to -0.025em as size grows. Instrument Sans covers heading-md 24, heading-sm 20, all body styles, labels and captions at weights 400, 500 and 600. Body line height is 1.5 to 1.6 so instructions stay readable. JetBrains Mono at 14/400 is reserved for booking references, postcodes in tables and code in developer docs.

- Display: **Fraunces** (fallback Georgia, serif)
- Interface: **Instrument Sans** (fallback system-ui, sans-serif)
- Mono: **JetBrains Mono** (fallback ui-monospace, monospace)

| Token | Font | Size | Line height | Weight |
|---|---|---|---|---|
| display-lg | Fraunces | 48px | 1.08 | 600 |
| display-md | Fraunces | 38px | 1.12 | 600 |
| heading-lg | Fraunces | 30px | 1.2 | 500 |
| heading-md | Instrument Sans | 24px | 1.3 | 600 |
| heading-sm | Instrument Sans | 20px | 1.35 | 600 |
| body-lg | Instrument Sans | 18px | 1.6 | 400 |
| body-md | Instrument Sans | 16px | 1.6 | 400 |
| body-sm | Instrument Sans | 14px | 1.5 | 400 |
| label | Instrument Sans | 14px | 1.25 | 500 |
| caption | Instrument Sans | 12px | 1.4 | 500 |
| code | JetBrains Mono | 14px | 1.5 | 400 |

## Layout

Comfortable density on a 4px base grid. Content columns cap at 1152px. Buttons and inputs are 40px tall. Schedule and quote rows are at least 48px tall, with space.4 (16px) horizontal cell padding.

Spacing uses a 4px base: xs = 4px, sm = 8px, md = 16px, lg = 24px, xl = 32px, 2xl = 48px, 3xl = 64px.

## Elevation & Depth

Mostly flat. Cards use a 1px border token plus shadow.sm. Shadow.md is for popovers and date pickers, and shadow.lg is for confirmation dialogs only. In dark mode, elevation comes from surface lift: background #141b19, then card #1c2523, then popover #212b29.

- sm: `0 1px 2px rgba(20, 27, 25, 0.06)`
- md: `0 4px 12px -2px rgba(20, 27, 25, 0.12)`
- lg: `0 16px 40px -8px rgba(20, 27, 25, 0.20)`

## Shapes

Soft but tidy rounding. Buttons and inputs use radius.md (8px), and cards and sheets use radius.lg (12px). Radius.full pills are used only for status badges such as 'Booked' or 'On the way' (22px tall, caption type).

Radius scale: sm 4px, md 8px, lg 12px, xl 16px, full 9999px.

## Components

Components ending in `-dark` are the dark-mode versions. Button: 40px tall, 16px horizontal padding, label type. Input: 40px tall with a 1px input-colored border; focus shows a 2px ring in the ring color. Card: 24px padding, 1px border, sm shadow. Badge: pill, caption type.

## Do's and Don'ts

- **Do:** Use the primary token for exactly one main action per screen, such as 'Book visit'. Give other actions the secondary or ghost button variant.
- **Do:** Show focus with a 2px ring token outline at a 2px offset on buttons, inputs, date-picker cells and time-slot chips, in both modes.
- **Do:** Set prices and durations in Instrument Sans with font-feature-settings: 'tnum', right-aligned, in quote and schedule tables.
- **Do:** Use Fraunces only for display-lg (48px), display-md (38px) and heading-lg (30px). Use weight 600 for display styles and 500 for heading-lg.
- **Do:** Pair every status color with an icon or text label, such as 'Confirmed' with a check, so meaning never relies on hue alone.
- **Do:** Keep schedule and quote rows at least 48px tall, and use the muted token as the alternate row fill in lists longer than 10 rows.
- **Do:** Use the accent token only for selected rows, highlighted time slots and selected chips. Put accent-foreground text on it.
- **Do:** In dark mode, layer surfaces as background, then card, then popover. Add shadow.md only to popovers and date pickers.
- **Don't:** Don't use the primary token for errors, cancellations or failed payments. Use destructive with destructive-foreground for those states.
- **Don't:** Don't put body text longer than three lines on the accent or warning surfaces. Keep it on background or card.
- **Don't:** Don't give cards a shadow above shadow.sm. Separation comes from the 1px border token.
- **Don't:** Don't use #000000 or untinted greys for text, borders or surfaces. Draw them from the neutral ramp or the dark surface tokens.
- **Don't:** Don't set Fraunces below heading-lg (30px) or in all caps, and don't use it for form labels, buttons or table content.
- **Don't:** Don't place muted-foreground text on the secondary or accent surfaces. Use secondary-foreground or accent-foreground there.
- **Don't:** Don't use destructive or warning fills as decoration behind non-status content.
