---
version: alpha
name: Greengrocer
description: Pink awning, acid green produce, amber price. Nothing can be rendered without its unit price.
meta:
  id: "theme-greengrocer"
  model: "Claude Opus 5"
  author: "Claude Code"
  createdAt: "2026-09-02T00:58:17+09:00"
  updatedAt: "2026-09-02T00:58:17+09:00"
  version: "1.0.0"
  isNew: false
lookbook:
  tagline: Per kilo, or it does not go on the shelf.
  bestFor: Grocery and produce, food markets, wholesale ordering, meal-kit and box schemes
  avoidFor: Luxury goods, professional services, anything priced per seat or per month
  defaultMode: light
  surfaceStyle: filled
  accentUse: bar
  caseStyle: all-upper
  borderWidth: 2px
  imageTreatment: bright
  motion:
    intensity: 3
    duration: 160ms
    ease: "cubic-bezier(0.2, 0, 0, 1)"
    signature: "Quantity steppers respond instantly with no easing at all. A market transaction should feel like a hand on a scale."
  displayFont: Anton
  displayKind: sans
  bodyFont: Chivo
  monoFont: Sono
colors:
  background: "#ECE0F4"
  foreground: "#1C131C"
  card: "#E3D2EE"
  card-foreground: "#1C131C"
  popover: "#E3D2EE"
  popover-foreground: "#1C131C"
  primary: "#768000"
  primary-foreground: "#120917"
  secondary: "#D8C2E7"
  secondary-foreground: "#1C131C"
  muted: "#D8C2E7"
  muted-foreground: "#5D505E"
  accent: "#946300"
  accent-foreground: "#FCF8FF"
  destructive: "#B6322D"
  destructive-foreground: "#FCF8FF"
  border: "#C9B5D6"
  input: "#C9B5D6"
  ring: "#768000"
  chart-1: "#7C8700"
  chart-2: "#27A107"
  chart-3: "#008B67"
  chart-4: "#AE8900"
  chart-5: "#A05C00"
colorsDark:
  background: "#130D17"
  foreground: "#E2D5E2"
  card: "#21132A"
  card-foreground: "#E2D5E2"
  popover: "#21132A"
  popover-foreground: "#E2D5E2"
  primary: "#A6B300"
  primary-foreground: "#120917"
  secondary: "#301B3C"
  secondary-foreground: "#E2D5E2"
  muted: "#301B3C"
  muted-foreground: "#968797"
  accent: "#EBA000"
  accent-foreground: "#120917"
  destructive: "#FF7A6E"
  destructive-foreground: "#120917"
  border: "#3D2A49"
  input: "#3D2A49"
  ring: "#A6B300"
  chart-1: "#A5B200"
  chart-2: "#46BA32"
  chart-3: "#00CE9B"
  chart-4: "#B68F00"
  chart-5: "#FF9B28"
typography:
  display-lg:
    fontFamily: Anton
    fontSize: 76px
    fontWeight: 400
    lineHeight: 0.94
    letterSpacing: -0.02em
  headline-lg:
    fontFamily: Anton
    fontSize: 40px
    fontWeight: 400
    lineHeight: 1.02
    letterSpacing: -0.01em
  headline-md:
    fontFamily: Anton
    fontSize: 22px
    fontWeight: 700
    lineHeight: 1.24
    letterSpacing: 0.005em
  body-lg:
    fontFamily: Chivo
    fontSize: 16px
    fontWeight: 400
    lineHeight: 1.55
  body-md:
    fontFamily: Chivo
    fontSize: 14.5px
    fontWeight: 400
    lineHeight: 1.52
  body-sm:
    fontFamily: Chivo
    fontSize: 13px
    fontWeight: 600
    lineHeight: 1.45
  label-caps:
    fontFamily: Chivo
    fontSize: 11px
    fontWeight: 700
    lineHeight: 1.1
    letterSpacing: 0.1em
  label-mono:
    fontFamily: Sono
    fontSize: 13px
    fontWeight: 600
    lineHeight: 1.4
  numeral-xl:
    fontFamily: Sono
    fontSize: 56px
    fontWeight: 700
    lineHeight: 1
    letterSpacing: -0.03em
rounded:
  none: 0px
  sm: 0px
  md: 0px
  lg: 2px
  xl: 2px
  full: 9999px
spacing:
  base: 16px
  xs: 4px
  sm: 8px
  md: 16px
  lg: 24px
  xl: 44px
  gutter: 14px
  margin: 24px
  measure: 60ch
components:
  button-primary:
    backgroundColor: "{colors.primary}"
    textColor: "{colors.primary-foreground}"
    rounded: "{rounded.none}"
    padding: 13px
  button-ghost:
    backgroundColor: transparent
    textColor: "{colors.foreground}"
    rounded: "{rounded.none}"
    padding: 13px
  card-panel:
    backgroundColor: "{colors.card}"
    textColor: "{colors.foreground}"
    rounded: "{rounded.none}"
    padding: 16px
  badge-label:
    backgroundColor: "{colors.secondary}"
    textColor: "{colors.secondary-foreground}"
    typography: "{typography.label-caps}"
    rounded: "{rounded.none}"
---

# Greengrocer

## Overview

Greengrocer is loud and it is honest about money. Its rule is that **no product
renders without a unit price**: every item shows its per-kilo, per-litre or
per-each figure in mono, and a product record without one cannot be displayed —
it renders as a gap with a mono note saying the unit price is missing, rather
than quietly showing a pack price alone.

That is the whole ethic of the system. Grocery UI usually hides the unit price
in 10px grey because comparing is bad for margin. This one puts it at 13px in
semibold mono directly under the pack price, and the crate bar above the card is
the category colour.

Pink awning, acid green produce, amber price. It suits markets, produce and box
schemes. It is wrong for anything priced per seat.

## Colors

A stall: bright ground, loud goods, one price colour.

- **Ground:** pink. Not blush — an awning pink, high enough in chroma to read as
  a decision.
- **Primary (acid green):** add to basket, and the produce itself. It is the
  loudest thing on the page and it is meant to be.
- **Accent (amber):** a **bar** — the 6px crate stripe at the top of every card,
  coloured by category, and the price underline. Solved to 3:1 as a graphical
  object.
- **Neutrals** are pink-tinted; a muted line is still warm.
- Charts are analogous — seasonality and price history in greens and ambers.

## Typography

Anton for the price, Chivo for text, Sono for every unit figure.

- **Display:** Anton at 76px, line-height 0.94. A single-weight condensed poster
  face. It is used for prices and category names — this system's display type is
  a market sign, not a headline.
- **Body:** Chivo at 14.5px, 1.52. Neutral, slightly sturdy, plenty of weight
  range.
- **Sono** carries unit prices, weights and origins. It is a soft mono and it
  keeps a per-kilo figure from looking like a terminal.
- **caseStyle is all-upper.** Category names, buttons, badges, column headers.
  A market is uppercase.

## Layout

**Crates.** Cards are square-cornered, filled, with a 6px accent bar across the
top and a 2px border — a crate seen from the front. They sit in a 5-up grid at
1400px with 14px gutters, and the grid never becomes a list; the density change
between breakpoints is columns, not layout.

The price block is fixed: pack price in Anton at 40px, unit price in Sono at
13px directly beneath it with an accent underline. Both, always, in that order.

Margins are 24px, gutters 14px. Tight — a market stall is not spacious.

## Elevation & Depth

Filled with 2px borders, no shadow. The crate bar does the work a shadow would
do: it separates the card from the pink ground by being a different hue at the
top edge.

Motion is instant. Quantity steppers have no easing at all — 160ms with a hard-
out curve, which at that duration reads as immediate. A scale does not ease.

## Shapes

Zero radius everywhere except the basket pill. Crates are square because crates
are square.

Photography is bright and high-key: produce on white, wet leaves, crates,
hands weighing. Shot flat and lit hard, deliberately not moody — this is not a
farmers-market-at-golden-hour system.

## Components

- **Crate card:** 6px accent top bar in the category colour, 2px border, square
  image, name in uppercase headline-md, price block, stepper. Fixed height.
- **Price block:** Anton 40px pack price, Sono 13px unit price beneath with a
  1px accent underline. Never one without the other.
- **Stepper:** square 36px minus, mono quantity, square 36px plus. No easing.
- **Origin line:** uppercase label-caps, country and grower, muted.
- **Buttons:** acid green fill, zero radius, uppercase. The basket button is the
  one pill in the system.

## Do's and Don'ts

- Do show a unit price on every product, every time.
- Do keep the crate bar coloured by category.
- Do let the type shout; it is a market.
- Don't hide the unit price in small grey text.
- Don't round a crate.
- Don't ease the stepper.
- Don't shoot produce in golden-hour light.
