| 1 | --- |
| 2 | name: Movement |
| 3 | description: A flyposted bill — acid stock, two inks, and the green that only exists where they overprint. |
| 4 | colors: |
| 5 | stock: "#f0e34a" |
| 6 | bone: "#f7f4e6" |
| 7 | ink: "#17140f" |
| 8 | blue: "#1b2a8f" |
| 9 | blue-strong: "#121d68" |
| 10 | cyan: "#14a0c8" |
| 11 | overprint: "#2f6b46" |
| 12 | dim-on-stock: "#6b5f14" |
| 13 | dim-on-bone: "#6a6455" |
| 14 | faint: "#8b8574" |
| 15 | rule: "rgba(23, 20, 15, 0.22)" |
| 16 | rule-on-stock: "rgba(23, 20, 15, 0.3)" |
| 17 | rule-strong: "rgba(23, 20, 15, 0.55)" |
| 18 | negative-fg: "#8e2417" |
| 19 | negative-bg: "rgba(158, 42, 26, 0.14)" |
| 20 | typography: |
| 21 | shout: |
| 22 | fontFamily: "Big Shoulders, Haettenschweiler, Arial Narrow, sans-serif" |
| 23 | fontSize: "clamp(4rem, 16vw, 10.5rem)" |
| 24 | fontWeight: 800 |
| 25 | lineHeight: 0.84 |
| 26 | letterSpacing: "-0.02em" |
| 27 | headline: |
| 28 | fontFamily: "Big Shoulders, Haettenschweiler, Arial Narrow, sans-serif" |
| 29 | fontSize: "clamp(1.9rem, 5vw, 3.25rem)" |
| 30 | fontWeight: 800 |
| 31 | lineHeight: 0.92 |
| 32 | letterSpacing: "normal" |
| 33 | title: |
| 34 | fontFamily: "Big Shoulders, Haettenschweiler, Arial Narrow, sans-serif" |
| 35 | fontSize: "clamp(1.35rem, 3vw, 1.9rem)" |
| 36 | fontWeight: 800 |
| 37 | lineHeight: 1 |
| 38 | letterSpacing: "normal" |
| 39 | body: |
| 40 | fontFamily: "Public Sans, ui-sans-serif, system-ui, -apple-system, sans-serif" |
| 41 | fontSize: "clamp(1rem, 1.15vw, 1.125rem)" |
| 42 | fontWeight: 400 |
| 43 | lineHeight: 1.55 |
| 44 | letterSpacing: "normal" |
| 45 | reply: |
| 46 | fontFamily: "Public Sans, ui-sans-serif, system-ui, -apple-system, sans-serif" |
| 47 | fontSize: "clamp(1.0625rem, 1.3vw, 1.1875rem)" |
| 48 | fontWeight: 400 |
| 49 | lineHeight: 1.62 |
| 50 | letterSpacing: "normal" |
| 51 | label: |
| 52 | fontFamily: "Public Sans, ui-sans-serif, system-ui, -apple-system, sans-serif" |
| 53 | fontSize: "0.8125rem" |
| 54 | fontWeight: 700 |
| 55 | lineHeight: 1.3 |
| 56 | letterSpacing: "0.06em" |
| 57 | stamp: |
| 58 | fontFamily: "Public Sans, ui-sans-serif, system-ui, -apple-system, sans-serif" |
| 59 | fontSize: "0.875rem" |
| 60 | fontWeight: 700 |
| 61 | lineHeight: 1.2 |
| 62 | letterSpacing: "0.14em" |
| 63 | rounded: |
| 64 | none: "0" |
| 65 | spacing: |
| 66 | hair: "0.35rem" |
| 67 | tight: "0.5rem" |
| 68 | field: "1.35rem" |
| 69 | block: "1.25rem" |
| 70 | gutter: "clamp(1.5rem, 4vw, 3.5rem)" |
| 71 | band: "clamp(1.75rem, 4vw, 3rem)" |
| 72 | page-x: "clamp(1.25rem, 4vw, 3.5rem)" |
| 73 | page-y: "clamp(1.25rem, 3vw, 2.5rem)" |
| 74 | components: |
| 75 | stamp: |
| 76 | backgroundColor: "{colors.blue}" |
| 77 | textColor: "{colors.stock}" |
| 78 | typography: "{typography.stamp}" |
| 79 | rounded: "{rounded.none}" |
| 80 | padding: "0.85rem 1.75rem" |
| 81 | stamp-hover: |
| 82 | backgroundColor: "{colors.blue-strong}" |
| 83 | textColor: "{colors.stock}" |
| 84 | stamp-disabled: |
| 85 | backgroundColor: "transparent" |
| 86 | textColor: "{colors.dim-on-bone}" |
| 87 | rounded: "{rounded.none}" |
| 88 | tab: |
| 89 | backgroundColor: "{colors.stock}" |
| 90 | textColor: "{colors.ink}" |
| 91 | typography: "{typography.headline}" |
| 92 | rounded: "{rounded.none}" |
| 93 | padding: "0.9rem 1.1rem 1rem" |
| 94 | height: "clamp(5rem, 7vw, 6.5rem)" |
| 95 | field-input: |
| 96 | backgroundColor: "transparent" |
| 97 | textColor: "{colors.ink}" |
| 98 | typography: "{typography.body}" |
| 99 | rounded: "{rounded.none}" |
| 100 | padding: "0.45rem 0" |
| 101 | field-textarea: |
| 102 | backgroundColor: "rgba(23, 20, 15, 0.05)" |
| 103 | textColor: "{colors.ink}" |
| 104 | typography: "{typography.body}" |
| 105 | rounded: "{rounded.none}" |
| 106 | padding: "0.55rem 0.7rem" |
| 107 | notice-negative: |
| 108 | backgroundColor: "{colors.negative-bg}" |
| 109 | textColor: "{colors.negative-fg}" |
| 110 | rounded: "{rounded.none}" |
| 111 | padding: "0.75rem 0.9rem" |
| 112 | --- |
| 113 | |
| 114 | # Design System: Movement |
| 115 | |
| 116 | ## Overview |
| 117 | |
| 118 | **Creative North Star: "The Flyposted Bill"** |
| 119 | |
| 120 | This is a sheet pasted on a wall, photographed as it is: cheap coloured stock, |
| 121 | two inks, a heavy impression, and the halftone dots of a job that was printed |
| 122 | rather than rendered. Nothing here is a card floating on a canvas. The stock is |
| 123 | the surface — full-bleed acid yellow on the bill itself — and the reading |
| 124 | surfaces drop to bone because acid yellow is a shout and a shout cannot also be |
| 125 | a paragraph. Depth is ink and perforation. The one exception is a tear-off tab |
| 126 | lifting off the wall, which is a thing paper actually does. |
| 127 | |
| 128 | The two inks are the whole colour theory. Ultramarine is the first ink; cyan is |
| 129 | the second; the green is not a chosen colour at all but the consequence of cyan |
| 130 | multiplied into yellow stock, offset a couple of pixels off true because a |
| 131 | two-colour job never registers perfectly. That misregistration is the tell that |
| 132 | the thing was printed, and it is load-bearing: remove the offset or swap the |
| 133 | blend and the world stops being a press and becomes a gradient. |
| 134 | |
| 135 | Typographically it is a condensed display face shouting in caps against a plain |
| 136 | grotesque doing the reading. The composition is hard: ruled columns, ruled |
| 137 | underlines for fields, square dashes, zero radius anywhere. It refuses the |
| 138 | centred single-field waitlist page — the page sorts you before it asks you for |
| 139 | anything, and the primary action on the first surface is tearing off a tab, not |
| 140 | pressing a button. |
| 141 | |
| 142 | **Key Characteristics:** |
| 143 | - Drenched stock, not accented white; two paper colours, never a screen white |
| 144 | - Two inks that build where they cross; green only as a product of overprint |
| 145 | - Zero radius everywhere — a printed sheet has corners |
| 146 | - Perforations, dashed rules and torn edges instead of borders and shadows |
| 147 | - Condensed uppercase display against a quiet body grotesque |
| 148 | - Self-hosted faces only; no third-party font origin exists in this world |
| 149 | |
| 150 | ## Colors |
| 151 | |
| 152 | Two paper stocks and two inks, plus the third colour the inks make between them. |
| 153 | |
| 154 | ### Primary |
| 155 | - **Ultramarine Ink** (`{colors.blue}`): the first ink. Every headline that |
| 156 | carries a claim, every outbound link's 3px underline, the stamp button's |
| 157 | ground, the caret, the selection ground, and the focus outline. It is the |
| 158 | voice of the press. |
| 159 | - **Press Cyan** (`{colors.cyan}`): the second ink, and never used as a flat |
| 160 | colour on its own. It exists only as an overprint band multiplied into |
| 161 | whatever is underneath: the stripe across the shout, the strike across the |
| 162 | stamp's face, the mark struck across a receipt's top rule. |
| 163 | |
| 164 | ### Secondary |
| 165 | - **Overprint Green** (`{colors.overprint}`): what cyan makes of yellow stock. |
| 166 | Recorded as a token because status tones are tinted from it, but it is a |
| 167 | *result*, not a paint. Where it appears on a surface it is produced by |
| 168 | multiply, not painted on. |
| 169 | |
| 170 | ### Neutral |
| 171 | - **Acid Stock** (`{colors.stock}`): the bill's paper. Full-bleed on the first |
| 172 | surface, and the ground of every tear-off tab and every torn stub carried |
| 173 | onto a later page. Also the text colour on ultramarine. |
| 174 | - **Bone** (`{colors.bone}`): the reading paper. Every stance sheet, receipt, |
| 175 | sign-in and ledger sits on it. Warm, never white. |
| 176 | - **Press Ink** (`{colors.ink}`): body text, perforations, table head rules, |
| 177 | field underlines. |
| 178 | - **Thinned Ink on Stock** (`{colors.dim-on-stock}`) and **Thinned Ink on Bone** |
| 179 | (`{colors.dim-on-bone}`): secondary text, one per stock. The bill page |
| 180 | swaps the muted token to the yellow-safe one on its own surface. |
| 181 | - **Rules** (`{colors.rule}`, `{colors.rule-on-stock}`, `{colors.rule-strong}`): |
| 182 | hairlines and column rules; the stock variant is heavier because yellow |
| 183 | swallows a light rule. |
| 184 | |
| 185 | ### Named Rules |
| 186 | **The Overprint Rule.** Green is never picked from a swatch. Wherever ink |
| 187 | crosses ink, the upper layer is `mix-blend-mode: multiply` so the inks *build* |
| 188 | and darken. `screen` is a defect in this world, not an option; it lightens and |
| 189 | turns a press into a light-box. |
| 190 | |
| 191 | **The Misregistration Rule.** Every overprint band sits 1–2px off true |
| 192 | (`transform: translateY(2px)` on the shout, `1px` on the stamp). The offset is |
| 193 | the evidence of a two-colour job. It is not a rendering bug and must not be |
| 194 | "corrected". |
| 195 | |
| 196 | **The Two-Stock Rule.** There are exactly two grounds: acid stock for the bill |
| 197 | and its tabs, bone for everything meant to be read. No third surface colour, and |
| 198 | no white anywhere — white is a screen colour and this is a printed thing. |
| 199 | |
| 200 | ## Typography |
| 201 | |
| 202 | **Display Font:** Big Shoulders 800 (with Haettenschweiler, Arial Narrow) |
| 203 | **Body Font:** Public Sans 400/700 (with ui-sans-serif, system-ui) |
| 204 | |
| 205 | **Character:** A tall condensed grotesque shouting in uppercase against a plain, |
| 206 | unfussy text face that never raises its voice. The display face is only ever |
| 207 | used at weight 800, uppercase, with negative tracking and sub-1 line height, so |
| 208 | it sets as a solid block of ink rather than a line of letters. |
| 209 | |
| 210 | ### The ramp |
| 211 | |
| 212 | Nine steps, declared once in `theme.css`. Four display and five text. Nothing |
| 213 | in the app sets a literal font size — a bill has a handful of sorts in the |
| 214 | case, not a continuum. |
| 215 | |
| 216 | | Token | Value | Used by | |
| 217 | |---|---|---| |
| 218 | | `--t-shout` | `clamp(4rem, 16vw, 10.5rem)` | the first-viewport headline, and nothing else | |
| 219 | | `--t-display-1` | `clamp(2rem, 5vw, 3.25rem)` | ledger title, receipt mark | |
| 220 | | `--t-display-2` | `clamp(1.5rem, 3.2vw, 2.75rem)` | tab word, torn stub's word | |
| 221 | | `--t-display-3` | `clamp(1.35rem, 3vw, 1.9rem)` | the slip's heading above a form | |
| 222 | | `--t-lede` | `clamp(1.0625rem, 1.3vw, 1.1875rem)` | stance reply, receipt body, tear instruction | |
| 223 | | `--t-body` | `clamp(1rem, 1.15vw, 1.125rem)` | the bill's two-column argument | |
| 224 | | `--t-base` | `0.9375rem` | ledger table | |
| 225 | | `--t-sm` | `0.875rem` | imprint line, stamp label | |
| 226 | | `--t-xs` | `0.8125rem` | field labels, tab addresses, status lines | |
| 227 | | `--t-xxs` | `0.75rem` | ledger column heads | |
| 228 | |
| 229 | Display steps carry weight 800, uppercase, negative tracking and sub-1 line |
| 230 | height (0.84 on the shout, 0.9–1 below it). Text steps run 1.5–1.62. |
| 231 | |
| 232 | Two relative multipliers are not steps and are allowed to stay relative: the |
| 233 | stance reply's first paragraph at `1.15em`, and the ledger's tally figure at |
| 234 | `1.5em`. Both size against their own context rather than against the ramp. |
| 235 | |
| 236 | ### Named Rules |
| 237 | **The Self-Hosted Faces Rule.** Both families are served from |
| 238 | `static/fonts/*.woff2` with `font-display: swap`. This is a constraint, not a |
| 239 | preference: the app ships `default-src 'self'`, so a third-party font link is |
| 240 | blocked at the browser. Never introduce a font CDN, and never add a face without |
| 241 | vendoring the woff2. |
| 242 | |
| 243 | **The Display-Is-Caps Rule.** The condensed face appears only uppercase, only at |
| 244 | 800, and only for shouts, marks, titles and tab words. It is never used for |
| 245 | running text, labels or numbers in prose — except the ledger's tally figures, |
| 246 | where it sets the count as a struck number beside body-face copy. |
| 247 | |
| 248 | **The Nine Sorts Rule.** Every size comes from the ramp above, as a `--t-*` |
| 249 | token. A literal `font-size` anywhere in the app is a defect, not a local |
| 250 | decision — the first version of this stylesheet had twenty-one of them across |
| 251 | twelve unrelated values, and the ramp documented here did not exist until the |
| 252 | design detector pointed out that the record described a system the code had |
| 253 | never had. The two `em` multipliers named above are the only exceptions. |
| 254 | |
| 255 | **The No-Costume-Mono Rule.** A monospace stack is declared but is not used on |
| 256 | any surface. Monospace here would be a costume for "technical" on pages that are |
| 257 | not about machines. Tabular figures in the ledger come from |
| 258 | `font-variant-numeric: tabular-nums`, not from a mono face. |
| 259 | |
| 260 | ## Layout |
| 261 | |
| 262 | One column of measured width per surface, never a centred narrow strip. The bill |
| 263 | and the stance sheet share a `78rem` max width with fluid page padding |
| 264 | (`{spacing.page-y} {spacing.page-x}`); the ledger sits at `66rem`, the receipt at |
| 265 | `46rem`. |
| 266 | |
| 267 | The bill fills the viewport (`min-height: 100svh`) only above `46rem` wide *and* |
| 268 | `40rem` tall, so the tear strip lands near the fold on real screens without |
| 269 | stranding it on short ones. Its argument sets in two hard columns divided by a |
| 270 | 1px column rule, collapsing to one column below `46rem`. |
| 271 | |
| 272 | The stance sheet is a two-up grid under a single 2px rule: reply |
| 273 | (`minmax(0, 1.55fr)`) beside slip (`minmax(19rem, 1fr)`), stacking below `60rem`. |
| 274 | The tear strip is three equal grid columns, stacking to one below `46rem` where |
| 275 | the tabs' vertical dashed dividers become horizontal ones. |
| 276 | |
| 277 | Rhythm is fluid rather than stepped: `clamp()` bands do the vertical spacing |
| 278 | (`{spacing.band}` between major blocks, `{spacing.gutter}` for gutters), with |
| 279 | fixed small steps only inside components (`{spacing.field}` between fields, |
| 280 | `{spacing.hair}` label-to-input). |
| 281 | |
| 282 | ## Elevation & Depth |
| 283 | |
| 284 | The system is flat. Depth is ink density, rules, perforation and torn edges — not |
| 285 | layering. Both stocks carry an authored inline-SVG halftone: a two-dot screen at |
| 286 | a 6px pitch, at 13% opacity on the acid stock and 7% on bone. It is a dot screen, |
| 287 | not a texture image, and it is what makes the stock read as paper. |
| 288 | |
| 289 | There is exactly one shadow, and it belongs to a tab lifting off the wall on |
| 290 | hover or focus. It carries an offset *and* a blur because that is what a real |
| 291 | shadow has. |
| 292 | |
| 293 | ### Shadow Vocabulary |
| 294 | - **Tab lift** (`box-shadow: 0 10px 30px rgba(23, 20, 15, 0.28→0.32)`, paired |
| 295 | with `translateY(-10px)` over `260ms cubic-bezier(0.16, 1, 0.3, 1)`): the only |
| 296 | shadow any app surface may use. Suppressed below `46rem` (where the tab tints |
| 297 | to bone instead) and under `prefers-reduced-motion: reduce`. |
| 298 | |
| 299 | ### Named Rules |
| 300 | **The One Shadow Rule.** A shadow exists in this world only to show paper |
| 301 | leaving the wall. Nothing else is elevated: no panels, no menus, no hovering |
| 302 | cards. A hard offset shadow with no blur belongs to a different world and is not |
| 303 | this one. |
| 304 | |
| 305 | **The Halftone Rule.** Paper texture is the 6px inline-SVG dot screen at low |
| 306 | opacity, multiplied into the stock. Never a raster texture, never a bevel, |
| 307 | emboss, gradient or inner shadow. |
| 308 | |
| 309 | ## Shapes |
| 310 | |
| 311 | Radius is zero, everywhere, on purpose: `--rst-radius`, `--rst-radius-sm` and |
| 312 | `--rst-radius-pill` are all `0`, and every app-authored control restates |
| 313 | `border-radius: 0`. A printed sheet has corners. |
| 314 | |
| 315 | Form language is drawn with rules, not boxes: |
| 316 | - **Perforation:** a 2px `repeating-linear-gradient` at 7px on / 7px off, so the |
| 317 | dashes stay square. Not a dashed border. |
| 318 | - **Dashed dividers:** 2px dashed ink between tear-off tabs. |
| 319 | - **Torn edge:** a 28-point `clip-path` polygon giving the carried-over stub a |
| 320 | ragged lower edge, because that is where the perforation gave. |
| 321 | - **Rules:** 2px solid ink for structural divisions (strip foot, sheet head, |
| 322 | receipt top and bottom, table head); 1px translucent ink for column rules and |
| 323 | table rows. |
| 324 | - **Fields:** ruled underlines, never outlined boxes. |
| 325 | |
| 326 | ## Components |
| 327 | |
| 328 | ### Stamp (the primary button) |
| 329 | A blue block with the second ink struck across its face. |
| 330 | - **Shape:** square (`0`) |
| 331 | - **Primary:** ultramarine ground, acid-stock lettering, uppercase 700 at |
| 332 | `0.875rem` with `0.14em` tracking, padding `0.85rem 1.75rem`; a 7px cyan bar |
| 333 | multiplied across at 56% height and offset 1px. |
| 334 | - **Hover:** ground deepens to `{colors.blue-strong}` over `160ms ease-out`. |
| 335 | - **Disabled:** ground drops out entirely to a 2px dashed ink outline with |
| 336 | thinned lettering, and the cyan strike is removed — an unstruck stamp. |
| 337 | |
| 338 | ### Tear-off Tab (signature component) |
| 339 | The primary action of the first surface: three equal tabs hanging off a |
| 340 | perforation, each printed on the stock and carrying its own address. |
| 341 | - **Shape:** square, no border except the 2px dashed divider between tabs and a |
| 342 | 2px solid rule closing the strip's foot. |
| 343 | - **Content:** the position word in display caps, and beneath it the URL that tab |
| 344 | leads to in `0.8125rem` blue label type. Nothing else. |
| 345 | - **State:** lifts `-10px` with the single system shadow on hover and |
| 346 | focus-visible; on narrow screens it tints to bone instead of lifting. |
| 347 | |
| 348 | **The Equal Tabs Rule.** Tabs are never numbered, ranked, ordered by emphasis, or |
| 349 | given a "recommended" treatment. Three positions numbered 1-2-3 imply a rank; |
| 350 | these three are equal by design, and the only differences between them are the |
| 351 | word and the address. |
| 352 | |
| 353 | **The Tab Carries Its Address Rule.** A tear-off tab exists to be the thing you |
| 354 | walk away holding, so it prints its own destination. A separate "take one" call |
| 355 | to action beside it says the same thing twice. |
| 356 | |
| 357 | ### Fields |
| 358 | Ruled lines on paper, one grammar for all of them. |
| 359 | - **Style:** transparent ground, no border except a 2px solid ink underline, |
| 360 | padding `0.45rem 0`, radius `0`. Label above in 700 `0.8125rem` with `0.06em` |
| 361 | tracking. |
| 362 | - **Textarea:** the one variation — a faint `rgba(23,20,15,0.05)` ink tint and |
| 363 | boxed padding, present to show the field's extent, not as a fill. It keeps the |
| 364 | same square corners and vertical-only resize. |
| 365 | - **Focus:** the global registration mark — a 3px ultramarine outline offset 2px, |
| 366 | square. |
| 367 | - **Error:** a notice ruled 2px along its *top* edge in the negative tone over a |
| 368 | tinted ground; never a left-border callout, never a rounded alert. |
| 369 | |
| 370 | ### Receipt |
| 371 | The terminal surface for every send, confirm, dead link and sign-in: a bone block |
| 372 | between two 2px ink rules, with a cyan mark struck across the top rule and the |
| 373 | outcome set as a display-caps mark in ultramarine. |
| 374 | |
| 375 | ### Ledger (admin) |
| 376 | The same hand, operating rather than persuading: display-caps title in |
| 377 | ultramarine, tallies where the figure is set in the display face at `1.5em` |
| 378 | beside body-face copy, and a `border-collapse` table with a 2px ink head rule, |
| 379 | 1px row rules, uppercase `0.75rem`/`0.12em` column heads and tabular numerals. |
| 380 | |
| 381 | ### Browser surfaces |
| 382 | Not decoration — the cheapest place to stay consistent. Selection is the inks |
| 383 | swapped (ultramarine ground, stock lettering), caret is ultramarine, the |
| 384 | scrollbar is thin ink on transparent, and focus is a square 3px ultramarine |
| 385 | registration mark. |
| 386 | |
| 387 | ## Do's and Don'ts |
| 388 | |
| 389 | ### Do: |
| 390 | - **Do** build every ink-over-ink crossing with `mix-blend-mode: multiply` and a |
| 391 | 1–2px offset, so the colour is produced by the press rather than picked. |
| 392 | - **Do** keep radius at `0` on every new surface and control, including |
| 393 | restating `border-radius: 0` on native controls. |
| 394 | - **Do** put new reading surfaces on bone and reserve the acid stock for the |
| 395 | bill, its tabs, and stubs torn from it. |
| 396 | - **Do** draw dividers as perforations, dashed 2px rules, or solid 2px ink rules, |
| 397 | and fields as ruled underlines. |
| 398 | - **Do** vendor any new face into `static/fonts/` as woff2; the CSP serves |
| 399 | `default-src 'self'` and an external font link is blocked at the browser. |
| 400 | - **Do** keep `tokens.css` byte-identical to the framework's copy and make all |
| 401 | visual changes in `theme.css` (palette, faces, shape, browser surfaces) or |
| 402 | `bill.css` (composition). `internal/movementtest/vendored_test.go` records that |
| 403 | divergence deliberately. |
| 404 | |
| 405 | ### Don't: |
| 406 | - **Don't** use `screen`, `overlay`, `lighten`, or a flat green fill to make the |
| 407 | overprint colour. Cyan on its own is never a surface colour. |
| 408 | - **Don't** "fix" the 2px band offset, the ragged `clip-path` edge, or the square |
| 409 | perforation dashes — each is authored, and each is the evidence that this was |
| 410 | printed. |
| 411 | - **Don't** add a second shadow, an elevated panel, or a card. Elevation exists |
| 412 | only as a tab leaving the wall. |
| 413 | - **Don't** number, rank or otherwise differentiate the three tabs. |
| 414 | - **Don't** introduce white (`#fff`) as a surface, or a third stock colour. |
| 415 | - **Don't** set running text, labels or UI copy in the monospace stack, and don't |
| 416 | set the display face in anything but uppercase 800. |
| 417 | - **Don't** replace the halftone with a raster texture, a gradient, or a bevel. |
| 418 | - **Don't** centre a single email field as a surface strategy; forms sit beside |
| 419 | the argument they belong to, in the sheet's two-up grid. |
| 420 | |