Greenville Triumph SC Design System v3
Greenville Triumph SC

Screens

The system for anything a member or a guest actually uses: the member portal, account pages, and public web. It extends v2 rather than replacing it, loading the same tokens and the same weave, then adding the components a screen needs. Every rule here came out of a page that shipped.

It does not replace v2.

Print, flyers, PDFs, and anything handed to a client stay on v2. Internal data dashboards stay on the dashboard system at the root of this domain. v3 is the third door, and it only opens for screens a member or a guest sees.

Print, promo, handout, anything on paperv2
Member or public screenv3, this one
Internal data dashboardDashboards

Seven rules.

Each one exists because breaking it produced a page that got rejected. They are ordered by how often that happened.

Rule 0

Two grounds. Never a third.

Navy and fog. That is the whole palette of section backgrounds. A panel on fog is white, a panel on navy is navy. --mist is a chip colour and an avatar colour; the moment it fills a band the width of the content column it reads as a third ground and the page looks broken.

Sections alternate in content blocks, not one by one. Group the sections that tell one story onto one ground, and flip at the story break.

Rule 1

One continuous field.

The weave runs the length of the page as a single field. It is not a texture restarted per section. components.css handles it with --field-y and field.js writes the value.

Paint the weave yourself and you get a hard reset at every boundary: the tiles do not meet, and the seam reads as an accidental header bar halfway down the page. The ink flips at a seam. The grid never does.

Rule 2

No box in a box in a box.

A filled or bordered panel may hold text and controls. It may not hold another filled panel that holds another filled panel.

A long list is one surface with dividing rules, not one card per row. A grid of cells shares one hairline: gap: 1px over a hairline ground, with the cells carrying no borders of their own, because two rules in the same place is a smudge. If a row needs a status, give it a bar or a mark, not a tinted inner box.

Rule 3

Colour lives in marks, not in type.

Triumph Green and Lime never set type on a light surface. Green lands near 2.8:1 on fog and Lime near 1.7:1, so both fail at any size and Lime is close to invisible.

The status word stays navy. The colour goes in the mark under it and the swatch in the legend above the list. That is what .status-word, .status-marks, and .legend are for. On navy, Lime is correct for eyebrows, accents, and the avatar chip.

Rule 4

Less on the page, more in the sheet.

A surface shows a heading and the one value somebody came for, then Details. Every other fact, the paragraph, and the links live in the shared detail sheet.

There is one sheet per page, and tiles, ledger rows, and cards all open it. That is what makes the rule affordable instead of hostile.

Rule 5

Collections collapse. They never enumerate.

Anything that renders per item has to degrade before it runs off the edge. Names in prose list up to three, then switch to a count: Seat 10 and 11, Seat 10, 11, and 12, 10 seats. Repeated marks run one per item up to six, then one per distinct outcome. Any wrapper that renders N children gets flex-wrap and a width cap.

Write the test. Assert 1, 2, 3, 6, and 10. The worked example in the member portal caught a missing serial comma inside its own fix.

Rule 6

Copy.

Oxford comma, always. Zero em-dashes; use commas, periods, semicolons, and parentheses. Literal labels: No scan, not "Didn't make it".

Say which of two things happened. A seat leaves a pass when a transfer is sent, not when it is claimed, so the row says which one it was.

Floors

Accessibility floors that are also design floors.

Tap targets are 44px, which a button tile gets for free and a bare link does not. A sticky bar that hides on scroll down comes back on scroll up. Scroll-lock a modal with position: fixed on body, never overflow: hidden, because iOS ignores the latter, and restore the offset on close. Anything that opens the sheet from an in-page anchor releases the lock first, or the jump lands behind a frozen body.

Registry

Eight components.

Small on purpose. A screen system that ships forty components is a system nobody holds in their head.

.field .field-navy .field-fog
Section ground plus the continuous weave. The only two grounds there are.
.on-solid
A fill under running text on a navy field, so long copy never sits directly on pattern.
.appbar
Sticky bar: mark, the section you are actually in, initials, and a lime rule. On a phone that is the whole bar.
.grid-divided .on-navy
Cells sharing one hairline. Works identically on both grounds.
.tile
Heading, one value, Details. The whole surface is the button.
.ledger
A long dated list on one surface, with month headings as divider rows inside it.
.status-word .status-marks .legend
Rule 3 in practice: navy word, coloured marks, swatches above the list.
.sheet-scrim .sheet .facts
The one detail sheet, with facts as label and value rather than a paragraph in a box.

Previews.

Each page shows the component, the rule it enforces, and the version of it that gets rejected.

Install

Four files, in this order.

Link them from this domain, or copy the folder into a project that has to self host. Self hosting is the rule for anything rendered behind office TLS inspection or exported to PDF.

<link rel="stylesheet" href="https://design.greenvilletriumph.club/screens/tokens.css">
<link rel="stylesheet" href="https://design.greenvilletriumph.club/screens/pattern.css">
<link rel="stylesheet" href="https://design.greenvilletriumph.club/screens/components.css">
<script src="https://design.greenvilletriumph.club/screens/field.js"></script>
tokens.cssThe v2 palette, type, and spacing, unchanged, plus the woven pattern as an inline data URI and the three self-hosted faces.
pattern.cssThe v2 weave classes, unchanged.
components.cssThe screen layer. Eight components and nothing else.
field.jsWrites --field-y per section so the weave is one field. No dependencies. Re-runs on load, resize, font swap, and reflow.
agents.mdThe build contract, written for an AI to follow. Same seven rules, no prose.

Fonts load through @font-face inside tokens.css, so nothing needs a Google Fonts link. The live example is the season ticket member portal, which is where all of this came from.