A short maker's note: the concept, the palette that changes with the season, and the code behind the dial.
Domaine de Clairaux is a fictional Burgundy estate, eleven generations old, selling its frost-shortened 2024 allocation and cellar tastings. The design thesis: for a vigneron, the year is the interface — so the page's signature control is a season dial that re-grades the entire site (an SVG hillside, the page palette, and the copy itself) through bud-break, véraison, harvest and dormancy.
Everything else stays disciplined and label-like: engraved double rules, small-caps eyebrows set like wine-label type, cuvée cards framed as label plates, and a terroir cross-section whose depth marks are real information, not decoration.
Four estate constants, plus a chalk ground that is deliberately not fixed — it drifts warmer at harvest and colder in dormancy, so even the background obeys the year.
Each season is a full set of about twenty CSS custom properties — sky, sun, hills, row lines, leaf colour and opacity, grape opacity, mist, snow — switched by one attribute on the root element.
Clos de la Chapelle
Cormorant · display — a French fine-wine serif with sharp, engraved terminals; set light and large
The night of 22 April we lit candles in the Clos and lost only the low rows.
EB Garamond · body — a book face; reads like an estate ledger, not a website
Clairaux premier cru · monopole
Marcellus SC · labels — engraved small caps, tracked wide, exactly as on a foil-stamped wine label
The whole re-grade is one attribute swap. Every seasonal colour lives in CSS custom properties scoped to [data-season] on <html>; SVG shapes reference them with fill: var(--…) and carry a 1.4s transition, so the hillside cross-fades rather than snaps:
:root[data-season="harvest"] {
--chalk: #f0e8d4; /* the page itself warms */
--leaf: #c08a3e; /* canopy turns amber */
--grape-o: 1; /* fruit becomes visible */
--snow-o: 0;
--sun-shift: translate(40px, 26px); /* lower sun */
}
.scene .leaf {
fill: var(--leaf);
opacity: var(--leaf-o);
transition: fill 1.4s, opacity 1.4s;
}
JavaScript only does three small jobs: it sets data-season (defaulting to the real season on the visitor's calendar), rotates the dial needle by the shortest path, and cross-fades the season-specific copy marked with data-copy attributes:
function setSeason(key) {
document.documentElement.setAttribute("data-season", key);
var delta = ((SEASONS[key].angle - angle % 360) + 540) % 360 - 180;
angle += delta; /* never spins the long way round */
needle.style.transform = "rotate(" + angle + "deg)";
copyEls.forEach(function (el) { fadeSwap(el, SEASONS[key][el.dataset.copy]); });
}
The seven vine rows and their ~250 leaf and grape dots are generated at load with a seeded pseudo-random walk along the slope curve, so the hillside looks hand-planted but ships as a few kilobytes of code. The three photographs were generated with gpt-image-2 from detailed photographic prompts (lens, film stock, light), then compressed to JPEG.
data- attribute on the root.prefers-reduced-motion, and that the page still makes sense with JavaScript off.