SPROUT · DESIGN SYSTEM v1

A system for tending things that grow.

A warm, lush foundation for a four-channel soil-and-watering controller — built to stay calm at high data density, and to remember that there's something alive on the other end of every reading.

Lush & playful Control-room density Plants with a pulse Light + dark

Color

01 · Foundations

Saturated garden hues over warm, paper-soft neutrals. Greens carry brand and health; water-teal, sun-amber and clay handle states; one true red is reserved for faults.

Brand · Leaf
100#F1F8E6
300#D8EDBF
500#8BD24F
600#34A853
700#247A3A
900#16401F
Accents & status
Water
#17B6C4 · watering
Sun
#F5A623 · dry / warn
Clay
#E8703A · due now
Alert
#E0483D · fault
Iris
#7C5CFF · predicted
Neutrals · light
ink
muted
border
surf-2
surf
Neutrals · dark (soil)
bg
surf
border
leaf
text

Typography

02 · Foundations

Three voices: a rounded display for warmth, a clean grotesk for everything you read, and a mono for every number — so data always looks like data.

Aa
Baloo 2
Display & headings
600 · 700 · 800
Aa
Hanken Grotesk
Body & interface
400 · 500 · 600 · 700
62
JetBrains Mono
Data, labels, codes
400 · 500 · 600
Scale
Display · 64/700Tend a tiny jungle
H1 · 40/700Greenhouse overview
H2 · 28/700Channel 01 · Monstera
Body · 15/400Soil moisture is holding steady; next watering predicted in about eighteen hours.
Data · mono62.4% · 21.4°C · ~18h

Space, radius & elevation

03 · Foundations
Spacing · 4px base
4 · xs
8 · sm
16 · md
24 · lg
40 · xl
Radius
8 · controls
14 · tiles
20 · cards
999 · pills
Elevation
e1 · resting tile
e2 · raised card
e3 · popover

The plant personality system

04 · Signature

The quiet idea that sets this apart: every channel has a mood derived from its data. Not a cartoon mascot — a single designed seedling mark that shifts posture, a color, and one first-person line of copy. Enough to make you feel the plant is doing well (or isn't), never enough to feel like a toy.

Mood states
Thriving
VWC ≥ 70%
“Lush and steady — no action needed.”
Content
VWC 48–69%
“Comfortable, sipping slowly.”
Drinking
pump active
“Having a drink — back shortly.”
Getting thirsty
VWC 34–47%
“Could use a drink before long.”
Thirsty
VWC 18–33%
“Ready for water now.”
Unwell
sensor fault
“Can't feel the soil — check me?”
{{ pct }} soil moisture
{{ moodLabel }}
TRY IT · DRAG THE SOIL DRY
Monstera is {{ moodLabel }}.
{{ moodMicro }}
0% bone dry100% saturated
Voice — do
  • Calm, attentive, first-person-ish: “Ready for water now.”
  • State the fact, then the feeling — data leads, warmth follows.
  • One short line. The plant is a quiet companion, not a chatterbox.
Voice — don't
  • No baby-talk, no pleading, no exclamation pile-ups.
  • No emoji faces or googly eyes on the seedling mark.
  • Never guilt-trip — “you forgot me” is off-limits.

Components

05 · Library

The working parts — pill-shaped, soft-shadowed, color-coded by meaning. Everything below is built from the same tokens.

Buttons
primary · secondary · tonal · danger · disabled · icon  |  hover lifts 1px + deepens shade
Status pills
Optimal Watering Dry Due now Fault Predicted
Pump / relay toggle
Pump 02
ON · 12s
Pump 04
OFF · idle
Moisture gauge · states
82%
Thriving
62%
Content
41%
Thirsty
25%
Due now
Drinking
PREDICTED · NEXT CYCLE
in ~18 hours
Tomorrow, around 09:40 · 92% confidence
SOIL TEMP
21.4°
+0.6° since dawn
HUMIDITY
54%
Comfortable range
RESERVOIR
2.4L
~6 cycles left
Alerts
CH04 sensor not responding
Last good reading 11 min ago. Pump 04 locked out until restored.
Reservoir running low
About 6 watering cycles remain. Top up within 2 days.

Data visualization

06 · Library

Soft 2.5px strokes, gentle area fills, generous gridlines. Each channel keeps its color across every chart so the eye learns it once. Predictions render in dashed iris.

Soil moisture · 24h
● CH1● CH2● CH3┄ pred
00:0006:0012:0018:00now
Watering frequency
CH1 · events / day · 14d
2w agotoday
Trending +18% — drinking more as it grows.

Control room · light

07 · In context

Everything at once, calm under pressure. Four channels, live environment, prediction and an event feed — dense, but never noisy.

GreenhouseMon · 09:42
CHANNELS 4 WATER TODAY 1.2L RESERVOIR 2.4L UPTIME 14d
CH01
Monstera
Thriving
82%
Last 2d ago
Next ~2d
CH02
Ferns
Drinking
75%
Last now
Pump 12s
CH03
Herb box
Due now
29%
Last 5d ago
Next now
CH04
Succulents
Fault
Signal
lost
PUMP LOCKED
All channels · 24h
●CH1●CH2●CH3
00:0006:0012:0018:00now
Recent events
CH2 watering started · 12s
09:41
CH4 sensor signal lost
09:30
CH3 predicted due within 1h
08:55
CH1 finished · 0.3L delivered
Sun 18:20

Control room · dark

08 · After dark

The same screen for your midnight sessions. Surfaces drop to soil-dark, greens glow, every accent stays exactly where it was — no relearning in the dark.

GreenhouseMon · 23:58
CH 4 H2O 1.2L RES 2.4L UP 14d
CH01
Monstera
Thriving
82%
Last 2d
Next ~2d
CH02
Ferns
Drinking
75%
Last now
Pump 12s
CH03
Herb box
Due now
29%
Last 5d
Next now
CH04
Succulents
Fault
Signal
lost
LOCKED
All channels · 24h
●CH1●CH2●CH3
00:0006:0012:0018:00now
Recent events
CH2 watering started · 12s
23:57
CH4 sensor signal lost
23:30
CH3 predicted due within 1h
22:55
CH1 finished · 0.3L delivered
18:20
Instrument & analytics
extension for the dense analytics dashboard

Reading the signal

09 · Data model

A correction the dashboard team is right to insist on: the trustworthy value is raw ADC counts and the calibrated band — not a percentage. A 0–100 figure is shown only as a clearly-labelled relative index between the wet and dry calibration anchors, never dressed up as VWC. Every readout therefore carries three layers.

RAW 1830 counts
Moist
index 68 /100
relative · not VWC
Raw counts — the reading

The instrument value. Inverted ADC (higher = drier). Always available in mono, to 0 decimals. This drives nothing visual on its own but anchors every other layer and the calibration.

Band — the meaning

The plain state. One of seven calibrated bands drives the mood, status color and any automation. Mood is keyed to band, never to %.

The seven bands · wet → dry (raw ranges are placeholders — set per-pin at calibration)
BANDRAW COUNTSINDEXMOOD MAPPING
Saturated≤ 130096–100Soggy · ease off
Wet1300–160080–95Drinking / fresh
Moist1600–190062–79Thriving
Ideal1900–220048–61Content
Drying2200–250032–47Getting thirsty
Dry2500–280016–31Thirsty · due now
Parched≥ 28000–15Parched · urgent
Quality flags
OK
in range · stable
SUSPECT
noisy / out of trend
SATURATED
rail / over-wet clip
NO_SIGNAL
sensor unreachable

Dense data grid

10 · Instrument

The densest item display: sortable columns, mono numerics with aligned decimals, status-tinted band cells, quiet zebra rows, hover highlight. A density toggle trades breathing room for rows-on-screen.

Comfortable Compact
row height 48 → 32 · decimals & alignment preserved
CH PLANT RAW ↓ IDX BAND Δ24H LAST NEXT PUMP QUAL
01 Monstera 1,612 78 Moist +4.2 2d 04h ~2d idle
02 Ferns 1,448 88 Wet +11.0 now 12s ON
03 Herb box 2,690 22 Dry −6.5 5d 11h now idle
04 Succulents — — Fault LOCK
numerics right-aligned, thousands-separated · band cell tinted to its color · hover row → surface-2 · sort caret on active column

Analysis chart

11 · Instrument

The clean trend, instrumented. Zone tints sit behind the curve, day/night bands behind those; threshold + hysteresis deadband, event markers and slope annotations turn a line into a reading you can reason about. Prediction stays dashed iris.

CH01 · Monstera · moisture index · 24h idx (relative)
night night 100 50 0
00:0006:0012:0018:00now
watering +48
−2.4 idx/h
next ~9h
zone tint day / night water threshold hysteresis deadband watering commit anomaly sunrise / sunset prediction

Calibration range ladder

12 · Instrument

The calibration instrument: the raw-ADC axis with its seven bands, the wet/dry reference anchors, the live reading, a sample distribution, and — the point of the tool — current boundaries against proposed ones with the hysteresis deadband shaded between.

1200
1300
1600
1900
2200
2500
2800
3000
RAW COUNTS · inverted
Saturated≤1300
Wet1300–1600
Moist1600–1900
Ideal1900–2200
Drying2200–2500
Dry2500–2800
Parched≥2800
distribution · 7d
◆ WET CAL · 1245
◆ DRY CAL · 2910
current trigger · 2500
proposed · 2400 · −100
▸ reading 1830 · Moist
reference anchor (wet / dry endpoint) current boundary proposed boundary hysteresis deadband sample distribution

Distribution & integrity

13 · Instrument

Two health reads: where a channel spends its time across the bands, and whether the signal can be trusted moment to moment.

Time in band
CH01 · last 7 days · % of readings
2
9
31
38
14
5
1
Sat Wet Moist Ideal Dry- Dry Parch
Sits in Ideal/Moist 69% of the time — a well-tuned channel.
Signal integrity
CH01 · quality flag · 24h
00:0006:0012:0018:00now
OK 92% SUSPECT 5% SAT 1% NO_SIGNAL 2%
NOISE σ
±8
low
SPREAD
42
stable
UPTIME
98%
1 dropout

Tokens for engineering

14 · Handoff

For the self-contained HTML/Chart.js dashboard: lift these as CSS custom properties and Chart.js color refs. Names match this document. Toggle data-theme="dark" on the root for soil mode.

/* Sprout · core tokens (light) */
:root {
  /* brand + neutrals */
  --leaf: #34A853;   --sprout: #8BD24F;   --ink: #1E2A18;
  --muted: #6F7E62;  --border: #E3E9D8;  --surface: #FFFFFF;
  --surface-2: #F7FAF2; --bg: #EEF4E6;
  /* status (state = color) */
  --st-watering: #17B6C4;  --st-dry: #F5A623;   --st-due: #E8703A;
  --st-fault: #E0483D;     --st-predicted: #7C5CFF;
  /* 7 bands (wet -> dry) */
  --band-saturated: #0E7A86; --band-wet: #17B6C4;  --band-moist: #34A853;
  --band-ideal: #8BD24F;     --band-drying: #F5A623; --band-dry: #E8703A;
  --band-parched: #E0483D;
  /* quality flags */
  --q-ok: #34A853; --q-suspect: #F5A623; --q-saturated: #17B6C4; --q-nosignal: #9A8480;
  /* type */
  --font-display: "Baloo 2"; --font-ui: "Hanken Grotesk"; --font-data: "JetBrains Mono";
  /* shape + space (4px base) */
  --r-control: 8px; --r-tile: 14px; --r-card: 20px; --r-pill: 999px;
  --e1: 0 1px 2px rgba(30,42,24,.06);  --e2: 0 6px 18px rgba(30,42,24,.08);
}
/* soil mode */
[data-theme="dark"] {
  --ink: #E9F1EB;   --muted: #8B9B90;   --border: #29372F;
  --surface: #18231F; --surface-2: #111A16; --bg: #0C1311;
  --leaf: #93DD6A; --st-watering: #3FD0DE; --st-fault: #FF6B5E;
  /* glow accents: add 0 0 8px currentColor on live dots */
}
Chart.js notes
  • Per-channel line color is fixed: CH1 --leaf, CH2 --st-watering, CH3 --st-dry.
  • Prediction = same color, borderDash:[3,5].
  • Zone tints & deadband → annotation box plugin at 8–16% alpha.
  • Tension 0.35, border 2.6, no point markers except events.
Rules of thumb
  • Every number uses --font-data, right-aligned, tabular.
  • Band color names the meaning — never recolor a band.
  • Gauges show raw + band; any 0–100 is labelled “index”.
  • Mood derives from band, not from the index.
SPROUT · DESIGN SYSTEM v1 · built for React + TypeScript + Tailwind
tend well.