Six Inks
The site runs on six flat colors and two typefaces. Here is where that came from, what it costs, and why the dark mode is a different hour rather than an inversion.
Every page here is printed from six colors. A cream, a deep forest slate, a burnt sienna, an ochre, a sage, and a dusky blue for whatever is meant to sit furthest away. Two typefaces, Oswald for anything that shouts and Bitter for anything you actually read. That is the whole supply. When something needs to look different from the thing beside it, it does that with shape or weight or position, because there is no seventh color to go and fetch.
What I wanted at the start was something softer and more natural than the default, which right now is a near-black page, a near-white page, and one saturated cool accent doing all the work. Given that this site is named after a squashed up snow leopard, a retro national park poster felt like the honest place to land.
Six colors, on purpose
The shortage is not something I imposed for the discipline of it. It came with the reference. Those posters were screenprinted, one flat plate per color, and every plate cost money and another pass through the press. Most of what people like about them now is the residue of somebody being told they could have four.
It turns out to be a good constraint to inherit. A small palette gives you cohesion for free, which is worth something when the alternative is what a lot of sites do now: a plain background, a couple of stock photographs dropped in, and no visual argument anywhere. Photographs are easy and they carry their own color with them, so a page full of them never quite settles.
The practical version is that “what color should this be” has six answers and five of them are wrong on sight. The decision takes a second instead of an afternoon. What I did not expect is that it keeps paying out on pages I have not built yet. There was never enough gamut for anything to drift far, so new things land near old things without my having to remember why.
Light and dark are times of day
Most dark modes are an inversion. You take the light palette, flip the ramp, and ship it. It works, and it always looks like the same poster with the lights switched off.
The version here is meant to be the same place at a different hour. The ground drops to near-black, the accents brighten the way color does once the light goes flat, and the sun in the poster art becomes a moon: smaller disc, thin halo ring around it. Rosettes that sit in the footer as a faint watermark during the day pick up a little ochre and start catching light instead. The ridges get a rim along their top edge that is simply switched off in daylight, because flat blocking reads fine under a midday sun and an edge highlight there would be a lie.
The part I got wrong first was the sky. I had drafted it as ochre, which is a lovely dusk color and completely useless here, because the moon is also ochre. An ochre disc on an ochre sky is nothing at all. Dropping the sky back to the cream and reserving ochre for the moon and the rim lights is the whole reason the light source reads.
None of this branches on the theme in the components. There are four knobs the
dusk palette turns, grain, rosette color, rosette opacity, and rim opacity, and
everything downstream just reads them. The poster paints into named slots and
never picks a color itself, so flipping the attribute on <html> repaints the
entire scene from CSS with no JavaScript involved.
Nothing that only announces itself
Sneppard is a squashed up snow leopard, so there is a snow leopard threaded through the site. Rosettes as a texture in the footer. A paw print doing the job of the bullet in lists. A tail curling out of the rule between sections.
The rule I set myself was that none of it should be the first thing you notice, and preferably not the second either. A mascot would have been easier and much worse. What I was after is the version where you read a few pages quite happily and then at some point clock that the bullets have toes.
Contrast is an input, not a check at the end
The ochre does not work as body text. It sits at 2.5:1 against the cream when small text wants 4.5:1, which I know because measuring it was one of the first things I did rather than one of the last.
I could have dulled it until it passed. That would have cost the posters their light, and a sun the color of wet cardboard is no sun at all. So ochre became a fill and never a typeface, with a darkened cut of it kept aside for the occasional label that has to live in that family. Sage got the same treatment for the same reason.
Doing this early is cheap, and it changes what you build rather than just vetoing it. The clearest case was at dusk, where the sienna I had picked measured 4.47 against the panel color. That is 0.03 short, which is invisible to look at and still a fail, so the sienna moved five percent brighter and the panels went darker instead of lighter. Both of those are now things I like about how the night version looks. Finding the same problem once forty components already exist would have meant living with it.
It should be inspectable
The whole thing is static files. No framework runtime, no hydration, one small script for the theme toggle and another for the view transitions, and that is the entire inventory of JavaScript on the site.
I would like to claim that as principle. Really it is that a portfolio is a claim about how somebody builds things, and this way you can go and check.