A design pass: the type ladder from the logo, and one name per thing

TYPOGRAPHY, taken from the lockup and walked down to something you can read a paragraph in. "The Vine" in
LeJour Script over COFFEEHOUSE + BAKERY in AdBhashitha is the whole brand voice, so: the script stays in
the wordmark and nowhere else (it is unreadable at length); AdBhashitha carries h1–h4 and the price, and
keeps the wordmark's 0.01em letter-spacing so a heading sits on the same rhythm as the logo above it;
`eyebrow` and `label` are the hinge — sans, but letterspaced like the tagline — and then plain Raleway.
Sizes are declared once in type.css instead of being re-chosen per template, and none of the type classes
set a colour, because the same heading appears in sage on cream and in cream on sage.

BUTTONS AND SURFACES have names now. `panel` is the white box that was "bg-white rounded-3xl shadow-xs"
written out in nine places (which is how two of them end up with different corners); `panel-lift` is one
that reacts. `pill` is one shape in four colourways, which exist because this site puts buttons on cream
AND on sage and they cannot be the same colour on both. `chip`/`chip-on` are the products filter.

RHYTHM: `section` (py-16 md:py-24) and `band` (py-14 md:py-20, tighter because a coloured strip is already
doing the separating) replace nine hand-picked paddings.

FOCUS: one visible ring for everything reachable by keyboard, as an outline rather than a shadow so it
works on cream, on white and on the sage bands, at zero specificity so a utility can still win.

Z-INDEX: written down in base.css, all two of it — 40 the sticky header, 30 the mobile panel, which is a
child of the header and so can only ever sit under the bar. Everything else stacks in document order. The
point of the comment is that a third layer doesn't get invented at 9999.

DROPDOWNS: the admin's category selects were drawing the platform's own arrow in the platform's grey; they
get the site's chevron and room for it.

53 tests green. Every class used across all nine pages — five public, four admin — resolves in the
compiled stylesheet, so nothing here is styled by a name that doesn't exist.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
This commit is contained in:
2026-07-26 18:10:47 -05:00
co-authored by Claude Opus 5
parent 8d54db7c30
commit 6b6ddcea42
14 changed files with 266 additions and 76 deletions
+23
View File
@@ -18,6 +18,29 @@ there is no JavaScript framework in this repo. The look has not changed through
| Photos | public MinIO bucket `itsthevine`**not** in the repo or the image |
| Deploy | Gitea CI → image → Watchtower → Caddy |
### The look, in one place
`src/main/styles` is the whole of it — no bundler, no framework, one stylesheet:
| file | what it holds |
|---|---|
| `theme.css` | the three typefaces and the sage-and-cream palette. Names, nothing drawn |
| `base.css` | bare elements: page background, body type, the fade-in, the focus ring, the z-index scale |
| `type.css` | the typographic ladder (below) |
| `components.css` | `panel`, `pill-*`, `chip`, `section`/`band` — the site's own classes |
| `admin.css` | the admin's controls, as `@utility` so `file:` variants work on the photo pickers |
**The type ladder comes out of the logo.** The lockup is "The Vine" in LeJour Script over COFFEEHOUSE +
BAKERY in AdBhashitha, letterspaced — and everything below is that idea made progressively more readable:
the script stays in the wordmark and nowhere else; AdBhashitha carries `h1``h4` and `price`, keeping the
wordmark's 0.01em letter-spacing so a heading sits on the same rhythm as the logo above it; `eyebrow` and
`label` are the hinge, sans but letterspaced like the tagline; then plain Raleway for anything you have to
read a paragraph of. None of the type classes set a colour — the same heading appears in sage on cream and
cream on sage.
Write those class names in templates rather than the utilities behind them: a button is `pill-sage`, and
the four colourways exist because the site puts buttons on cream *and* on sage.
### Why server-rendered
The pages are content: a menu, a story, opening hours, a price list. Rendering them in the browser meant