# Premium Design System Spec (LLM-ready) **What this is**: a measured design specification you can paste into Claude, ChatGPT, Gemini, or any coding agent to make an ordinary website read as expensive. Every value was read out of production CSS on 17 professionally art-directed sites and the commercial design system most of them run on, measured 21 August 2026. **How to use it**: paste this entire file into your AI, then add one line describing your site. For example: *"Apply this spec to my Eleventy site at ./src. It is a dental practice, currently blue and white, headings are bold Montserrat."* The agent has everything it needs below. **License**: use it, adapt it, ship it. Attribution appreciated but not required. Originally published at https://jwatte.com/blog/design-craft-beyond-github-style-repos/ --- ## INSTRUCTIONS FOR THE ASSISTANT You are applying a measured design system to an existing website. Follow these rules in order. 1. **Read before you write.** Find how the site currently handles color and theming. If it already defines CSS custom properties, redefine those same property names rather than writing new component rules. That single decision is the difference between a one-file change and a rewrite. 2. **Presentation only.** Do not change markup, templates, structured data, meta tags, canonicals, hreflang, or any machine-readable output. If a fix seems to require a markup change, say so and ask first. 3. **Additive and reversible.** Prefer a new stylesheet loaded after the existing one over edits scattered through existing files. The user should be able to revert by deleting one ``. 4. **Measure, do not eyeball.** Every color pair you introduce must be checked with the contrast procedure in Section 7. Do not report a design as finished until that check returns zero failures. 5. **State your adaptations.** Where you deviate from a value below, say which value, what you used instead, and why. **Do not**: add a CSS framework, add a dependency, add a build step, or introduce a component library. None of this needs one. **If the user asks you to measure someone else's site to extend this spec**: read that site's `robots.txt` ([RFC 9309](https://www.rfc-editor.org/rfc/rfc9309.html)) and its Terms of Service first, and do not automate access where either prohibits it. Prefer a page the user saved from their browser. Never fetch anything behind a login or paywall, never collect personal data, and treat a block or challenge page as an answer rather than an obstacle. Copy values, never identity. See `parse-a-site-starter-kit.md` for the full boundaries. --- ## 1. THE THESIS The code layer of web design is commoditized and free. What separates a cheap-looking site from an expensive-looking one is a short list of *value* decisions plus one *budget* decision (photography). This spec is the value decisions. Seventeen sites that read as expensive turned out to run on one commercial template plus one site-builder instance. Zero bespoke engineering. **The code is not the differentiator, because the code is shared.** --- ## 2. TYPE (the change that moves the most) Measured heading scale from the production system: | Element | Size | Weight | Line-height | |---|---|---|---| | h1 | `clamp(4rem, 4.453125vw, 14.25rem)` | 400 | 1.03 | | h2 | `clamp(3.25rem, 3.125vw, 10rem)` | 400 | 1.15 | | h3 | `clamp(2.625rem, 2.343vw, 7.5rem)` | 400 | 1.14 | | h4 | `clamp(2rem, 1.093vw, 3.5rem)` | 300 | 1.12 | | h5 | `clamp(1.5rem, 0.78125vw, 2.5rem)` | 300 | 1.17 | | h6 | `clamp(1.25rem, 0.664vw, 2.125rem)` | 300 | 1.3 | | body | `clamp(1rem, 0.625vw, 2rem)` | 300 | 1.38 | **RULE 1: emphasis comes from size, not weight.** Nothing in that scale is bold. Headings are 400 and 300. Reaching for `font-weight: 700` on headings is the single most reliable tell of a self-built site. Go bigger and go lighter. **RULE 2: open the gap between heading and body leading.** Headings 1.03 to 1.17, body 1.38. The common default pairing of 1.2 and 1.6 is a narrower gap in both directions and produces loose headlines over crowded body copy. **RULE 3: track out small uppercase labels only.** Measured letter-spacing (1.5px, 1px, 0.5px, 2px, 3px, 0.2em) appears almost exclusively on small uppercase eyebrows. The system sets `letter-spacing: normal` on every heading token. Leave display type alone. **ADAPTATION NOTE**: those upper clamp bounds suit image-led pages carrying six words. For a content-dense site, keep the weights and line-heights **exactly** and pull the upper bounds down. The weights and leading are the part that reads as expensive; the absolute sizes are taste. For long-form prose, body leading of 1.6 to 1.65 is better than 1.38: what matters is that the gap stays wide. **Face pairing**: one display serif for headings, one neutral sans for everything else. Never three families. Display serifs observed: Cormorant Garamond, Tenor Sans, Italiana, Arapey, Butler, Saol Display, Playfair Display. Sans observed: Montserrat (8 of 16), Inter, Lato, Open Sans, Karla, Syncopate. *Montserrat's dominance is a warning as much as a recommendation. It is the most recognizable "we bought a template" face in this category. Keep the structure, pick a less saturated pairing.* **CHECK FIRST**: if the site self-hosts its display face, inspect the font files. Variable fonts commonly cover 400 to 900 while the stylesheet only declares 700+. Adding `font-weight: 400 500` declarations pointing at the same files gives you the light weight for **zero additional bytes**. --- ## 3. COLOR Default token set read from the production system: ``` --color-primary-1: #fff; --color-primary-2: #1a1a1a; --color-primary-3: #161515; --color-primary-4: #eeede9; --color-primary-5: #000; --color-accent: #b18463; --color-accent-dark: #916648; --color-accent-light: #db9d72; --color-gray-100: #313131; --color-gray-500: #999; --color-gray-200: #272727; --color-gray-600: silver; --color-gray-300: #404040; --color-gray-700: #e2e2e2; --color-gray-400: #5e5e5e; --color-gray-800: #f8f8f8; ``` Corroborating frequency counts across all 17 pages: `#848484` (180), `#1a1a1a` (93), `#403e3f` (54), `#f1f0eb` (54), `#5f5d61` (37), `#e2e0d9` (36), `#fbfbf9` (35), `#141414` (32), `#3e1214` (30), `#e4dfd8` (29), `#c28563` (28), `#c09b57` (21). **RULE 4: ground is bone, not white.** `#f1f0eb`, `#eeede9`, `#fbfbf9`, `#e4dfd8`. Warm, a few points off pure. Two hex digits, outsized effect. **RULE 5: ink is charcoal, not black.** `#1a1a1a`, `#141414`, `#403e3f`. Pure `#000` on pure `#fff` is a harsher contrast than print ever produced and reads as unconsidered. **RULE 6: exactly one accent, in three shades.** That is the entire chromatic budget. Muted earth tones (`#c09b57` old gold, `#c28563` clay, `#b18463` tan, `#3e1214` oxblood) do the job a saturated brand color would with less noise. **Why framework defaults fight you**: general-purpose frameworks ship a primary, success, danger, warning and info, all fully saturated because they are designed for dashboards where color carries meaning. On a marketing page that spends five times this budget before you have made a single decision. **The permitted exception**: one site in the corpus overrides the accent to a bright yellow with a navy secondary, and it works, because the restraint holds everywhere else. One loud accent inside a strict system reads as confident. A loud accent plus five other colors reads as a template. If you want a loud brand color, buy it by being stricter elsewhere. **CRITICAL: see Section 7.1. One color token cannot be both ink and fill.** Define `--accent` (dark enough to read as text on the light ground) and `--accent-fill` (light enough that dark text reads on it) as separate values from the start. --- ## 4. SPACE ``` --gap-xsmall: .5rem; --gap-large: 3.875rem; --gap-small: 1rem; --gap-xlarge: 15rem; /* 240px */ --gap-medium: 1.5rem; --spacing-large: clamp(8.5rem, 9.4531vw, 30.25rem); /* 136-484px */ --spacing-xlarge: clamp(11.5rem, 6.8554vw, 21.9375rem); --container-small: 67.875rem; /* 1086px */ --container-medium: 82rem; /* 1312px */ --container-large: 90rem; /* 1440px */ ``` Also observed: flat `176px` section padding, and `7.8vw`. **RULE 7: whitespace is a named token, not a feeling.** Nobody reaches 240px of empty space by instinct; it looks like a mistake while you are building it. You only get there by deciding the value in advance and trusting it over your in-the-moment judgment. This is the cheapest change in the entire spec. **MOBILE**: do not ship 240px gaps to a 390px viewport. The `clamp()` forms above already collapse. If you use flat values, halve them below your primary breakpoint. --- ## 5. MOTION ``` --ease-standard: cubic-bezier(0.645, 0.045, 0.355, 1); /* 24 uses */ --ease-out-soft: cubic-bezier(0.23, 1, 0.32, 1); /* 18 uses */ --ease-dramatic: cubic-bezier(0.835, 0, 0.19, 1); /* 16 uses */ --duration-fast: .2s; /* 146 uses */ --duration-base: .3s; /* 163 uses */ ``` Values of 2s to 6s in the corpus belong to slow image pans and marquees, **never** to interface transitions. **RULE 8: the restraint is the design.** The system offers ~38 named keyframe animations. The pages use a handful, almost all fade and slide. Nothing in the corpus bounces. Installing a forty-effect animation library actively works against this by making every effect equally available at zero cost. **RULE 9: always ship the off switch.** The reference sites are not uniformly good about this. Be better: ```css @media (prefers-reduced-motion: reduce) { *, *:before, *:after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; } } ``` --- ## 6. BREAKPOINTS Measured frequency: `max-width: 768px` (551), `560px` (316), `767px` (201), `992px` (143), `1024px` (134), `900px` (55), and `(hover: hover) and (pointer: fine)` (47). **RULE 10: three stops are enough.** Roughly 768, 560, and one of 992/1024. The proliferation above is many hands editing one system over years, not a requirement. **RULE 11: gate every hover effect on `(hover: hover) and (pointer: fine)`.** An ungated hover state sticks after a tap on a touch device. It appears 47 times in the corpus for exactly this reason. --- ## 7. VERIFICATION (do not skip) ### 7.1 One token cannot be both ink and fill An accent dark enough to read as **text** on a light ground is too dark to be a **background** behind dark text. If one token does both, fixing one role silently breaks the other everywhere it is used. In a real retrofit, darkening an accent to reach 4.5:1 as text took every button using it as a fill down to 2.88:1 in a single edit. ```css --accent: /* readable as TEXT on the light ground, >= 4.5:1 */ --accent-fill: /* light enough that dark text reads ON it, >= 4.5:1 */ --on-accent-fill: /* the ink that sits on --accent-fill */ ``` **Prefer ink for buttons.** If the accent already carries eyebrows, numerals, rules and links, putting it on buttons too overspends the one-accent budget. Ink means "do this", accent means "notice this". ### 7.2 Contrast procedure For every text element: 1. Get its computed color and background. 2. **Composite alpha.** Walk up the ancestor chain, compositing each translucent background onto the next until you reach an opaque one. A checker that treats `rgba(...,0.14)` as opaque will invent failures that do not exist and miss real ones. 3. Compute the WCAG relative-luminance ratio. 4. Threshold: **4.5:1** normal text; **3:1** for large text (>= 24px, or >= 18.66px at weight >= 700); **3:1** for non-text UI components including **input borders** (WCAG 1.4.11: the most commonly missed one). 5. Where a color fails, walk it darker (or lighter) along its own hue until it clears on **every** ground it appears on, not just the page background. A muted gray that passes on the page will often fail on a card, because the card is a step darker. ### 7.3 Test each theme independently A clean light-theme sweep says nothing about dark. Audit them separately. See the companion retrofit kit for the cascade trap that makes this essential. --- ## 8. THE PART NO SPEC CAN GIVE YOU **16 of the 17 sites lead with video in the hero.** That is a shoot, a crew, and an edit, and it is the largest single cost in a premium website. Be honest with yourself: apply everything above perfectly, fill it with weak stock photography, and you will have a well-built site that still does not read as expensive, and you will wrongly conclude the tokens did not work. **The design system makes good photography look expensive. It does not make bad photography look good.** More whitespace and larger type magnify a weak image rather than hiding it. Cheapest-first ladder: cull hard (six strong images beat thirty mediocre ones) → shoot the one hero → crop to the ratio the layout wants rather than fitting layout to crop → prefer real and imperfect over stock and polished → video last. --- ## 9. PASTE-READY TOKENS ```css :root { /* Color: bone ground, charcoal ink, one accent */ --ground: #f4f2ed; --ground-raised: #fbfaf7; --ground-sunken: #e8e5dd; --ink: #1c1b19; --ink-soft: #403e3f; --ink-muted: #696660; /* verify on your darkest card ground */ --rule: #e0dcd2; --rule-input: #8e8576; /* WCAG 1.4.11, 3:1 */ --accent: #6f5719; /* TEXT on the light ground */ --accent-fill: #9f7e3a; /* BACKGROUND behind dark text */ --on-accent-fill: #14130f; --accent-wash: rgba(179, 146, 78, .12); /* Inverted surface for a closing CTA band + footer */ --inv-surface: #17150f; --inv-ink: #efeae0; --inv-ink-2: #c0b9ab; --inv-ink-3: #948c7e; /* floor for legal text */ --inv-accent: #c9a94e; /* Type */ --font-display: 'YourDisplaySerif', Georgia, 'Times New Roman', serif; --font-body: 'YourNeutralSans', system-ui, -apple-system, 'Segoe UI', sans-serif; --size-display: clamp(2.75rem, 6vw, 5rem); --size-h1: clamp(2.25rem, 4.6vw, 3.75rem); --size-h2: clamp(1.875rem, 3.4vw, 2.75rem); --size-h3: clamp(1.375rem, 2.2vw, 1.875rem); --size-h4: clamp(1.125rem, 1.4vw, 1.375rem); --size-eyebrow: .75rem; --size-body: clamp(1rem, .55vw, 1.0625rem); --weight-display: 400; --weight-body: 400; --leading-display: 1.06; --leading-heading: 1.18; --leading-body: 1.65; --track-eyebrow: .18em; --track-display: 0; /* Space */ --gap-xs: .5rem; --gap-sm: 1rem; --gap-md: 1.5rem; --gap-lg: 3.875rem; --gap-xl: clamp(3rem, 6vw, 7.5rem); --section-y: clamp(3.5rem, 7vw, 7rem); --section-y-lg: clamp(4.5rem, 9vw, 9.5rem); --container: 1200px; --container-wide: 1440px; --gutter: clamp(1.25rem, 4vw, 2.5rem); --radius: 2px; /* Motion */ --ease-standard: cubic-bezier(0.645, 0.045, 0.355, 1); --ease-out-soft: cubic-bezier(0.23, 1, 0.32, 1); --ease-dramatic: cubic-bezier(0.835, 0, 0.19, 1); --duration-fast: .2s; --duration-base: .3s; } @media (hover: hover) and (pointer: fine) { /* every hover treatment goes in here, never outside it */ } @media (prefers-reduced-motion: reduce) { *, *:before, *:after { animation-duration: .01ms !important; animation-iteration-count: 1 !important; transition-duration: .01ms !important; scroll-behavior: auto !important; } } ``` The clamp bounds above are deliberately pulled in from the measured originals, which were tuned for near-textless pages. Raise them toward Section 2 if your pages are that sparse. --- ## 10. THE TEN-LINE VERSION 1. Headings at weight 300 to 400, never 700. Emphasis from size. 2. Heading line-height 1.03 to 1.17; body 1.38 to 1.65. Keep the gap wide. 3. Ground off-white (`#f1f0eb`), not `#ffffff`. 4. Ink charcoal (`#1a1a1a`), not `#000000`. 5. Exactly one accent, in three shades, muted. 6. Separate `--accent` (ink) from `--accent-fill` (background). Never one token. 7. A named large spacing token, 8rem to 15rem, halved on mobile. 8. Three easing curves, 0.3s base. Start with `cubic-bezier(0.645, 0.045, 0.355, 1)` and stop adding. 9. Three breakpoints; gate hover on `(hover: hover) and (pointer: fine)`; ship `prefers-reduced-motion`. 10. Fewer, larger, better images. This is the one that costs money. --- ## PROVENANCE AND LIMITS Measured 21 August 2026 from 17 production homepages and one 1.49 MB production design-system stylesheet. Token names, values, counts and byte sizes were read from those files, not estimated. - The 16-site sample came from a portfolio page published by a vendor that sells real estate websites, about its own client work. It is a vendor portfolio, not an independent ranking. The individual businesses are deliberately not named. - Color and easing frequency counts count occurrences in markup. They weight heavily-repeated inline declarations and are evidence of what is in the system, not a measure of visual area. - Vendors change design systems without notice. Re-measure before relying on any specific value. - A passing contrast sweep is a floor, not proof of accessibility. It does not test keyboard operability, screen-reader semantics, or focus order. Companion file: **design-retrofit-audit-kit.md**, for applying this to a site that already exists and already earns.