Example standard
middle.green, governed by glph
This is not glph’s standard. It is middle.green’s: a brand standard authored as a glph catalog and checked by the same deterministic engine that governs what agents render at runtime.
Below the line, the page is set in middle.green’s own type and color. The catalog file decides what may be rendered, and a test proves it on every run. See the verdicts, or visit middle.green.
The middle.green Design Standard · 2026-10-24
A caddie for the rest of us.
middle.green is a voice golf caddie. The phone stays in a pocket, and a tap brings Eve’s answer: the number to the middle of the green, the club, and where to aim. The design is the caddie’s book: paper by day, leather after dark, and a pencil.
Principles and voice
Silent until asked. One breath.
Less is more.
Each screen has one primary element.
Laid back.
Nothing hurries, nothing celebrates.
Silent until asked.
She speaks after a tap or a question.
One breath.
Every line she says, and every line on a screen, is one sentence.
The engine owns every number.
The engine computes it; the voice only says it.
Tournament mode is a switch.
It strips the club, the line, plays-like and wind. Distances stay.
Her voice
The hole first, then the number, then the club, then where to aim.
Hole seven. 150, plays about 160 into the wind. It’s your 6-iron, favor the right half.
In tournament mode
Numbers only today. 140 front, 150 middle, 163 back.
Say where to aim, never the hazard as the target.
No praise, no pep talk. After a bad shot, nothing happened.
Sentence case, verbs first: Start round. No exclamation marks.
Digits for every number. Write middle.green lowercase, with the dot.
Color
Paper by day, leather after dark.
One red for danger, one green for confirmed, each always beside its small sign. No link blue, no gradients, no other color. Contrast figures are computed by glph from the catalog’s hex values as this page builds.
Paper (day)
paper
#f4efe6
The page.
paper-deep
#eae3d5
A sheet laid on the page.
paper-edge
#d9d0bf
A sheet's 1px edge. Never a ground for text.
ink
#1e1c19 · 14.84:1
Primary text and the number.
ink-soft
#5f5a52 · 5.97:1
Secondary text. The faintest text may go.
ink-faint
#9a9488 · 2.63:1
Rules, disabled outlines, decoration. Never text.
pencil
#4b4740 · 8.06:1
Eve's hand and every pencil stroke.
flag
#d6331e · 4.21:1
Danger only, beside its sign. Text at 24px and up.
field
#4f6b48 · 5.20:1
Confirmed only, beside its tick.
field-text
#4f6b48 · 5.20:1
Field for text and ticks in every theme (proposed).
leather
#2b241f
The dark sheet: soul.md and the sign-up.
cream
#efe7d9 · 12.44:1
Text on leather.
cream-dim
#a79f91 · 5.83:1
Secondary text on leather.
Leather (night)
paper
#1f1a17
The page.
paper-deep
#181412
A sheet laid on the page.
paper-edge
#2f2824
A sheet's 1px edge. Never a ground for text.
ink
#ece5d8 · 13.76:1
Primary text and the number.
ink-soft
#b7ad9e · 7.78:1
Secondary text. The faintest text may go.
ink-faint
#7c7468 · 3.74:1
Rules, disabled outlines, decoration. Never text.
pencil
#dbd2c2 · 11.50:1
Eve's hand and every pencil stroke.
flag
#d6331e · 3.57:1
Danger only, beside its sign. Text at 24px and up.
field
#4f6b48 · 2.90:1
Confirmed only, beside its tick.
field-text
#769d6d · 5.59:1
Field for text and ticks in every theme (proposed).
leather
#15110f
The dark sheet: soul.md and the sign-up.
cream
#efe7d9 · 15.28:1
Text on leather.
cream-dim
#a79f91 · 7.16:1
Secondary text on leather.
The round card follows the light, not the theme.
150
Night · dim 5.05:1
150
Dawn · dim 4.82:1
150
Noon · dim 5.16:1
150
Dusk · dim 5.36:1
Contrast, stated honestly.
Text needs 4.5:1, or 3:1 at 24px and up. Icons and control edges need 3:1. The tokens stay exact; where the source paints a failing pair, the components use ink-soft or the card’s dim ink instead.
| Pair | Day | Night | glph, as text | Verdict |
|---|---|---|---|---|
| ink on paper | 14.84 | 13.76 | passes | Passes. |
| ink on paper-deep | 13.31 | 14.61 | passes | Passes. |
| ink-soft on paper | 5.97 | 7.78 | passes | Passes. |
| ink-soft on paper-deep | 5.36 | 8.26 | passes | Passes. |
| ink-soft on paper-edge | 4.47 | 6.54 | flags | Fails by day (4.47). paper-edge is a border, never a ground. |
| ink-faint on paper | 2.63 | 3.74 | flags | Fails as text. Rules, disabled and decoration only. |
| ink-faint on paper-deep | 2.36 | 3.97 | flags | Fails as text. |
| pencil on paper | 8.06 | 11.50 | passes | Passes as text and as a control edge. |
| flag on paper | 4.21 | 3.57 | flags | Icons and 24px text only. The card's 19px fails. |
| flag on paper-deep | 3.78 | 3.79 | flags | Icons and 24px text only. |
| field on paper | 5.20 | 2.90 | flags | Fails at night, below 3:1 even for the tick. |
| field-text on paper | 5.20 | 5.59 | passes | Passes. The proposed fix for field at night. |
| cream on leather | 12.44 | 15.28 | passes | Passes. |
| cream-dim on leather | 5.83 | 7.16 | passes | Passes. |
| card-ink on card-bg | 14.57 | same | passes | Passes. Card tones never change with the theme. |
| card-dim on card-bg | 5.05 | same | passes | Passes. |
| card-faint on card-bg | 1.57 | same | flags | Fails as text. Strokes only; the diagnostic line uses the dim ink. |
| flag on card-bg | 3.75 | same | flags | 24px only. |
Type
Thin Plex, tabular numbers, no bold.
IBM Plex Sans at 100, 200 and 300 only. Emphasis is size, never weight. Every number is tabular, so nothing jitters as the ball moves.
number · 184px · 100
The number on a sheet or the full card.
150
number-card · 132px · 100
The round card. The app steps it to 200; flagged for review.
150
number-phone · 104px · 200
Below about 140px the Thin stroke vanishes in sun, so it steps to 200.
150
figure · 30px · 200
A carry in Clubs, the stepper's value.
157
display · 68px · 200
A caddie for the rest of us.
title · 42px · 200
Three things to ask her.
page-title · 30px · 200
Clubs
heading · 22px · 300
What we collect
question · 20px · 300
“What do I hit?”
lede · 18px · 300
Ask her anything on the course.
body · 17px · 300
Every line is one breath, in the same order.
small · 15px · 300
Try it first
caption · 13px · 300
Nothing plays on its own.
eyebrow · 13px · 300
The ask
Caveat is Eve’s words and nothing else.
Never a label, a button, a heading, or a number standing alone. Caveat 500 is the heaviest the system allows, for a long line read outdoors.
eve-says · 29.6px · 400
It’s your 6-iron, favor the right half.
eve-card · 26px · 400
Your 6-iron, favor the right half.
eve-note · 24px · 400
Driver, favor the left side.
eve-last · 18px · 400
“Hole seven. 150, plays about 160.”
eve-emphasis · 26px · 500
Not quite, love.
Plex Mono is the soul file.
And the one diagnostic hairline on the card. Two inks only, never syntax-colored.
eve/soul.md
voice soft, Scottish, unhurried
says the hole first, then the number,
then the club, then where to aim
never names the hazard as the target
after a bad shot: nothing happened
# locked for every caddie, yours included
kind true
truthful true
numbers from the engine, never inventedSpacing and radius
Exact values. 22px stays 22px.
Spacing is the source’s exact values, not a grid: rounding 22 to 24 would change the book. Paragraphs stop at 36rem; the page stops at 1080px. Targets are at least 44px, and 56px for gloves.
radius-sheet · 18px
Sheets from the book.
radius-card · 30px
The round card.
radius-pill · 999px
The site's pill buttons.
radius-focus · 3px
The focus outline's corner.
pencil frame · none
Drawn, so it has no radius.
The pencil
Drawn by hand, the same way every time.
The pencil is for frames, outlines, rules, rings and ticks, the way a caddie marks up a yardage book. It is drawn in pencil at 1.5px or heavier, so it survives glare, with round caps and joins.
Every element draws from its own seed, its label, so the same button has the same wobble on every screen and every load. Strokes never jitter, shimmer or animate. Two or three pencil elements on a screen at most.
Never in pencil
The number, the hazard line, and body text.
Those are facts and stay in type. A pencil frame round Caveat reads as a greeting card, so a pencil label is always Plex.
box · seed “Start round”
the same seed, drawn again
ring · the chosen one
rule · between groups
tick · you marked this
Components
One number, two buttons, End on the mark.
PencilButton · primary 160px and quiet 88px
PencilSegmented · Casual and Tournament
Number, club, where to aim.
Numbers only. No club, line or wind. Locked till you end it.
End, on the mark
End is never a single tap. Hold the mark at the top right for about 600 ms, and a pencil track slides out to its left; drag the dot along it to end the round. Let go early and nothing happens.
The round card
Number and Ask are two wide pencil rectangles, stacked, 64px tall. Number is the primary, with the faint second pass. The number and the hazard line stay in type.
Par 4, 412
2:10 · 88° · wind 6, into
150
to the middle
138 front 163 back
Plays about 160
Your 6-iron, favor the right half.
Water right at 230
“Hole seven. 150, plays about 160.”
±3 m · 212 fixes · log
RoundCard
agent-renderable
The round screen: a page from the caddie's book with one number on it, in a tone that follows the light, and End on the mark at the top right.
NumberDisplay
agent-renderable
The number to the middle of the green, set huge in thin, tabular Plex, with front and back beneath it. The engine computes it; nothing else this big shares the screen.
Transcript
agent-renderable
Eve's words in her hand, lit word by word as she says them, with what the golfer asked above in type.
HazardLine
agent-renderable
The one red line on the page, with its water or sand sign. Said once on the tee, written on the card, never in pencil. Its color is fixed to flag and its size to 24px, the only size at which flag passes as text.
PencilButton
agent-renderable
A button boxed in pencil the way a caddie boxes a word in the book: the 160px square Start round, the quiet 88px square, and the full-width Number and Ask on the round card.
PencilSegmented
agent-renderable
A choice between Casual and Tournament, with the chosen word ringed in pencil and one line beneath that says what the mode does.
PencilRing
agent-renderable
The ring a caddie draws round the one chosen thing in a group: a course, a mode, the current page. Never round the number or the hazard.
PencilRule
agent-renderable
A divider drawn in pencil, never quite level, between groups that mean different things. Rows keep the straight rule.
PencilCheck
agent-renderable
A setting's box with a pencil tick: the golfer's own mark that they chose this.
PencilToggle
agent-renderable
An on and off setting on a pencil track, its knob sliding 20px in 180 ms.
ListRow
agent-renderable
One line, an optional detail and a value at the end, divided by the straight rule: courses, clubs, rounds, settings.
SectionLabel
agent-renderable
The eyebrow: a small, spaced, uppercase label in ink-soft that names a section.
InlineNotice
agent-renderable
A quiet line under a pencil rule that says something is off, in ink, with no color and no icon.
EmptyState
agent-renderable
When there is nothing to show, one line says so plainly, with at most one thing to do about it.
Stepper
agent-renderable
A value between two 56px pencil steps, for a carry in Clubs.
TextLink
agent-renderable
A link in words, underlined, verb first: Ask for your course.
Mark
product only
The only logo: a green as a caddie draws it, and its middle. Placed by the product, never by an agent.
SoulFile
product only
Eve's soul.md in Plex Mono on leather. Authored, never generated.
MarkCandidates
product only
The nine archived mark explorations. None was chosen; not for use without a new decision.
The mark
A green as a caddie draws it, and its middle.
Stroke only, single ink, it takes the text color around it. Its dot breathes while she speaks and is the only thing that moves on its own.
On paper, on leather, beside the name on the card, and at 16, 22 and 32px.
Decision, 2026-10-24: keep the current mark.
Nine candidates were explored. They are archived, not chosen, and are not for use without a new decision.
Governed by glph
The standard is a file. The engine reads it.
Everything above was authored into one glph catalog. An agent rendering for middle.green gets the same verdict as these examples, from the same code, with no model in the path.
01
The catalog
lib/catalog/fixtures/middle-green.json
- 45 color tokens: day values as the primary set, 10 night values as night-* keys
- 16 spacing steps, exact
- 22 type sizes, from the standard’s styles
- 5 radii
- 16 agent-renderable components, 3 product only
02
The brand rules
{
"spacingMustBeOnGrid": false,
"colorsMustBeTokens": true,
"typeSizesMustBeInScale": true,
"minContrast": {
"normalText": 4.5,
"largeText": 3
},
"colorSnapMaxDeltaE": 8
}The grid rule is off because the standard is not on a grid; off-scale spacing is still caught against the exact scale.
03
The test
lib/catalog/middle-green.test.mts
Validates the catalog, pins the standard’s published contrast figures, and runs the trees in lib/catalog/fixtures/middle-green-render.json through validate and glph check. The verdicts below were computed by the same code when this page was built.
roundCard
The round card: number, her line, Number and Ask.
0 violations. Ships as authored.
faintAsk
The golfer's question set in ink-faint on paper.
1 violation.
contrast-too-low: found #9A9488 on #F4EFE6, expected >= 4.5:1, auto-fix color.card-noon-dim
offScaleNumber
The number at 120px.
1 violation.
type-not-in-scale: found 120px, expected one of scale: 11, 12, 13, 14, 15, 17, 18, 19, 20, 21, 22, 24, 26, 28, 29.6, 30, 42, 60, 68, 104, 132, 184, auto-fix 132px
smallHazard
The hazard line at the source's 19px.
1 violation.
variant-not-allowed: found 19px, expected one of: 24px
Where the engine is honest about itself. For the faint question, the auto-fix is the passing token nearest in color, which is a round-card tone, card-noon-dim. middle.green’s own fix is ink-soft. An auto-fix is a proposal; the violation is the guarantee.
Where a rule lives in the component. glph grades every text pair at 4.5:1 and does not yet know a pair’s size, so the standard’s 3:1 allowance for flag at 24px is held by HazardLine itself: its color is fixed inside the component and its size is pinned to 24px. The translucent hairlines (rule, scrim) are decoration and stay out of the color map, which holds the hex values contrast can be computed on.
Compare glph’s own standard, or open the catalog studio.