← Back to the screen

Design system portfolio

luxury-hospitality — Solviva — the record

The four direction lines behind this page, the generator command that produced its tokens, and the pairs it was measured against.

A twenty-four-cover coastal restaurant: the room, the menu, the booking.

The direction, settled before the first section existed

The second scrimmed block is the caption on the full-bleed pass photograph. It used to sit under the image on a band of night ground, which between a bleed photograph and the cream menu reads as a slab of near-black carrying one 13px line — a rule nobody drew, and widening the band only made the slab bigger. The caption now rides the image's own bottom edge on the gradient lux_tokens.py --scrim prints for edge-anchored text (0.58 at the caption's end, nothing by 45%), which costs less of the photograph than the 0.576 flat wash text free to land anywhere would need. Measured afterwards on the real crop, shooting twice so a cream glyph could not be read as a bright background pixel: the worst pixel behind the caption is #4d4947 at 1440, #47413e at 1280 and #444444 at 375, giving 8.40:1, 9.47:1 and 9.19:1 against a 4.5:1 floor.

The second state is the booking answer. A restaurant with two services a night and nine tables turns people away most evenings, so the hard state here is not an empty list: it is "no", said in a way that keeps the guest. The page ships with the form set to a Sunday, and the panel beside it says the room is dark, names the next two tables that fit the party, offers the counter to anyone booking for two or fewer, and offers the first table outright.

The book answers four ways and all four are reachable: a table, a full service, a dark day, and nothing left in the fortnight, which the last evening in the list produces for a party of six. Taking an alternative sets the form to it and asks again, so the guest confirms the table they can see rather than one named in a button; confirming writes it into the panel and leaves a way back out. Focus follows the panel whenever the control that moved it has just been replaced.

Generator

lux_tokens.py --both > tokens.css

The brief names lux_tokens.py. --both earns its place by emitting the day mood the menu section needs. Nobody hand-edits tokens.css; the generator owns every line of it.

Why this product suits this system

The system exists for the one thing this page has to do: make a room feel expensive on a phone in a dim bar, while somebody decides where to take somebody to dinner. Its hardest rule — solve the scrim, never guess it — is the rule a coastal restaurant breaks first, since the hero is a bright sea through tall windows and the caption goes straight on top of it. Its type scale reserves an eyebrow at 11px with 0.18em of tracking, which carries most of the genre's signature. Its palette holds three families and one metal, which is what keeps a menu from reading as a dashboard with a serif bolted on.

Deviations from CONTRACT.md

§2, "every <img> is a data: URI". The four photographs live as files under img/ and the page references them by path. The first build inlined them and the numbers decided it: the document came to 303 kB, 104 kB of that base64 hero on the LCP path, and every device downloaded both hero crops because no media attribute can choose between two data URIs — and a data URI cannot carry a srcset at all, so inlining would cost the page the width selection that is the whole point of the image work. As files the document is 42 kB, a phone fetches a 102 kB portrait crop, a 2× laptop a 202 kB wide one, and a browser without AVIF falls back to WebP. The page still reaches no other origin.

§5, "both themes … prefers-color-scheme … data-theme". This system publishes night and day as which room a page is in rather than as a user preference, and its skill rejects reading them as a dark-mode toggle. <html data-mood="night"> sets the page; the menu section declares data-mood="day", so both moods appear at once. tokens.css still carries the generator's @media (prefers-color-scheme: light) block, which governs any page that declares no mood at all.

APCA disagrees with WCAG on two small-text pairs. The 11px to 12px uppercase eyebrow, brass on night, measures 8.36:1 and Lc −57.3; the button label, ink on brass, measures 5.59:1 and Lc +42.3. Both clear WCAG 2.2 AA and both fail APCA at that size. Both sizes come from the system's own scale and component rules, which the contract lets win. The eyebrow carries font-weight: 500 rather than 400 to narrow the gap.

Image resolution. The two full-width crops stop at 2560px. A 1440 display at 2× asks for 2880 and a 1920 one for 3840, and serving either would put the hero past the 250 kB the system caps it at. The page buys 1.78× on those two and a true 2× on the two editorial frames. CREDITS.md has the measurement.

Lint findings this page keeps

copy-lint.ignore records three, each with its reason. directional covers "above the water", which says where the room sits rather than where the layout sits. title-case covers "Cala Rotja · Menorca", a place and an island, both spelled the way the map spells them. label-period covers the menu's <dd> lines, which are complete sentences — and in the allergen case a safety message that the system's voice reference insists stays plain and complete.