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.

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.

PairDayNightglph, as textVerdict
ink on paper14.8413.76passesPasses.
ink on paper-deep13.3114.61passesPasses.
ink-soft on paper5.977.78passesPasses.
ink-soft on paper-deep5.368.26passesPasses.
ink-soft on paper-edge4.476.54flagsFails by day (4.47). paper-edge is a border, never a ground.
ink-faint on paper2.633.74flagsFails as text. Rules, disabled and decoration only.
ink-faint on paper-deep2.363.97flagsFails as text.
pencil on paper8.0611.50passesPasses as text and as a control edge.
flag on paper4.213.57flagsIcons and 24px text only. The card's 19px fails.
flag on paper-deep3.783.79flagsIcons and 24px text only.
field on paper5.202.90flagsFails at night, below 3:1 even for the tick.
field-text on paper5.205.59passesPasses. The proposed fix for field at night.
cream on leather12.4415.28passesPasses.
cream-dim on leather5.837.16passesPasses.
card-ink on card-bg14.57samepassesPasses. Card tones never change with the theme.
card-dim on card-bg5.05samepassesPasses.
card-faint on card-bg1.57sameflagsFails as text. Strokes only; the diagnostic line uses the dim ink.
flag on card-bg3.75sameflags24px 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 invented

Spacing 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.

space-44px
space-66px
space-1010px
space-1212px
space-1414px
gutter16px
space-1818px
app-page-x20px
space-2222px
card-pad-x24px
space-2828px
gutter-wide32px
sec-y56px
sec-y-wide88px

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.

Hole 7

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.

middle.green

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.