← Back to the bars

How this site was made

Criollo & Co. is a fictional bean-to-bar maker working a single criollo estate in Venezuela’s Ocumare valley, built as a design study. The audience is people who read tasting notes; the page’s one job is to sell a four-shipment “harvest year.” The motion language is melt: everything on the page arrives, transitions, and responds the way warm chocolate does — slowly, heavily, and in one direction.

Palette

Three concentrations of cacao carry the structure — the page literally darkens as the bean becomes bar. Cream is the inside of the chocolate box; husk gold is the working accent. The three fruit accents belong to the tasting wheel and are only released into the page when a note is selected.

Cacao 100#170C07
Cacao 85#2C160C
Cacao 70#4A2917
Cream#F3E7D3
Husk gold#C9994F
Red cherry#C8453C
Apricot#D97F3E
Fig#8F5877

Type

Fraunces is the confectioner’s serif — a variable face with an optical-size axis plus two eccentric ones, SOFT and WONK. Headlines run at opsz 144, SOFT 55, WONK 1 with discretionary ligatures on, which gives them the hand-lettered warmth of an old chocolate wrapper; body text runs the same family at opsz 11, where it behaves. Familjen Grotesk handles everything that must read as fact — provenance data, temperatures, batch numbers — with tabular figures so the conche clock doesn’t jitter.

Techniques

Melt dividers. Every section boundary is an SVG of hanging drips, generated at load with a seeded random walk so each divider drips differently but identically on every visit. The path scales vertically with scroll position — the previous section’s color melts down over the next:

const p = clamp01((vh * .96 - rect.top) / (vh * .55));
path.style.transform = `scaleY(${0.12 + 0.88 * p})`;
/* easing lives in CSS: cubic-bezier(.5, 0, .15, 1.1) — heavy, with a drip’s overshoot */

The tasting wheel. An eight-segment SVG donut built from arc paths. Three fruit segments are focusable buttons; choosing one sets data-note on <body>, and a single custom property re-flavors every accent on the page — buttons, quotes, the conche hand, the temper handle:

body[data-note="cherry"] { --note: var(--cherry); }
/* everything accent-colored uses var(--note) and transitions .5s */

The temper curve. Real chocolate physics as an interactive chart: temperature is a piecewise function of time (45° melt → 27.5° seed → 31.5° working temper), sampled into an SVG path. A draggable slider (pointer + arrow keys, role="slider") walks the curve; crystal rhombi appear as the mass seeds, and the unstable Forms III–IV visibly die on the reheat climb — only Form V survives to the pour.

The conche clock. Batch 41’s elapsed conching time is computed from a fixed offset against Date.now(), so it ticks in real time across visits. The dial hand steps once a second with a springy transition — a patient clock, not a stopwatch.

Video hero. The molten-ribbon loop was generated with Higgsfield Seedance 2.0 (silent, ~6 s, 1080p) and graded into the palette with a layered CSS overlay — a brown mix-blend-mode: color wash plus a vignette — so the cool marble in the footage sits inside the cacao world. A poster frame extracted with ffmpeg serves as the reduced-motion and loading fallback. The two photographs (split pods, snapped bar) were generated with gpt-image-2 from prompts written like photography briefs: lens, light, film stock.

The three passes

  1. Correctness & composition. Fixed the first melt divider dripping the wrong color, rebalanced the wheel’s label sizes and hub contrast, tightened the provenance strip’s grid at tablet widths, and cleared every console error.
  2. Elevation. Gave the temper chart its phase zones and dying seed crystals, added the sequential mould-pour on scroll, put the foil sheen on the bar cards, and re-cut the hero grade so the ribbon reads warm instead of grey.
  3. Taste. Chanel rule: removed a second scroll hint and a redundant hover lift, calmed the drip depths, checked 390 px seriously (wheel, chart and clock all re-set), and verified the reduced-motion page is a complete, still experience.

Do this yourself

  1. Pick a subject with a real process, then steal its physics for your motion language — chocolate melts, so everything here melts. Never animate generically.
  2. Ask Claude for a palette that encodes structure, not just mood. Here, background darkness = cacao percentage; the page ferments as you scroll.
  3. Choose one variable font with an eccentric axis (Fraunces’ SOFT/WONK) and use its extremes for display only; pair it with one sober sans for data.
  4. Build one interactive element that teaches something true — our temper curve is a real tempering profile, not decoration. Truth is what makes it memorable.
  5. Generate photography with prompts written like a photographer’s brief: lens, light source, time of day, film stock. Reject anything that looks like stock.
  6. Grade video into your palette with CSS blend modes instead of asking the generator for perfect color — you control the wash, it controls the motion.
  7. Screenshot at 1440 and 390, critique what you actually see, and iterate three times. The third pass should mostly delete things.
  8. Before shipping: keyboard-walk every control, load it with reduced motion on, and read every line of copy aloud once.

← Back to the bars

Video: Higgsfield Seedance 2.0 · Stills: gpt-image-2 · Type: Fraunces & Familjen Grotesk (Google Fonts) · Built by hand, no frameworks.