Blue accent
A card with the blue bar and icon.
Every number on this page is read out of styles.css when the page loads. Nothing here is transcribed by hand, so this cannot drift out of date the way a written style guide does: if the stylesheet changes, this page changes with it.
Which also means it cannot flatter. Several counts below are marked ad hoc because they are: this stylesheet still carries values chosen one page at a time, and a guide that rounded those down would be the kind nobody trusts twice. The numbers are the point: they are how we know whether the last tidy-up worked.
This documents lunarwebstudio.com. A build on the Voyager plan gets one of these for its own brand (the same structure, its colors, its components, its numbers) not a copy of ours.
Everything below this section is measured from the stylesheet. This part is not: it is the set of rules the numbers cannot state, written down because each one was learned the expensive way.
How many distinct values each dimension uses. A dimension with a handful of values is a scale you can hold in your head; one with thirty is a set of decisions made a page at a time. The thresholds are arbitrary but fixed: 8 or fewer reads as a scale, 9-14 as loose, 15 or more as ad hoc. The palette is counted but not graded: how many colors a brand needs is a question with no right answer. The number worth watching is the one beside it: colors written straight into a rule instead of referenced from :root.
Custom properties declared on :root that resolve to a color. These are the palette.
Every foreground token measured against every background token, worst first, with the ratio the browser actually paints. 4.5:1 is the WCAG AA floor for body text, 3:1 for large text, 7:1 is AAA. Not every pair here is one the site uses (the ones it does use are the ones to care about) but a pair that fails is a pair nobody should reach for without knowing.
The rest of :root: timings and geometry the launch animation reads.
The --text-* steps, each rendered at its own size. Whole pixels through the body range, because the stylesheet used to carry nineteen sizes between 12 and 15px and nobody can see the difference between .82rem and .83rem.
Sizes still written directly into a rule. Most of what is left belongs there: an em resolves against its parent rather than the root, so it is not interchangeable with a step, and the fluid clamp() sizes are responsive decisions rather than steps: they are shown live below, so they respond as you resize this window.
The --space-* steps, drawn to scale. These are the vocabulary: a padding, margin or gap should reach for one of these rather than name a length.
Lengths still written directly into a padding, margin or gap instead of referencing a step. This is the working list, most-used first, though not all of it should become a step. Some of these are not spacing decisions at all: the 36px is clearance for the select chevron, the 17rem clears the hero art, and the values under 4px are optical nudges. Those belong as literals.
The --radius-* steps.
Radii still written into a rule. What is left here is shapes rather than steps: 0, inherit, and the multi-corner forms that round one side or make a teardrop. Those are not scale values and should stay where they are.
The shadows that are shared rather than bespoke, on an identical tile.
Everything else. Unlike spacing or type this is not a tail to work through: these are distinct effects doing distinct jobs: the moon's crater shading, the rocket's exhaust, focus rings, button rest and hover. Two of them looking similar in a list does not make them duplicates; the two moons differ because one is 84px and the other is up to 210px, and their inset shading is scaled to match.
Every distinct @media condition. The one matching your window right now is marked.
Live specimens using the real classes, not screenshots and not copies. What renders here is what renders on the site.
A .lead paragraph: the size that opens a section.
A .page-intro paragraph, which sits under a page title.
A .section-note, the smaller print that closes a section.
A card with the blue bar and icon.
A card with the amber bar and icon.
A card with the purple bar and icon.
What the plan includes, in one line
| First $99/mo | Second $199/mo | |
|---|---|---|
| A figure row | $594 | $1,194 |
| An included row | Included | Included |
| An excluded row | Not included | Included |
Not in any page's markup: back-to-top.js builds it and appends it to <body> on the twenty pages that carry the site chrome. Fixed to the bottom-right corner, and hidden until the page has scrolled one full viewport, so a page shorter than the screen never shows one. If you have read this far, the live one is in the corner to your right; the copy below is the same button parked in place, which is the only way a fixed element can sit in a row of specimens.
Clicking it scrolls with window.scrollTo(0, 0) and then hands focus to the header, so the keyboard arrives where the eye did. The two-argument call is deliberate: it defers to the CSS scroll-behavior, which the reduce-motion block turns back to auto. Under 640px it stands down entirely while the consent banner is up, rather than stack on top of it.