Design Direction

Guest experience platform for hotels.

The check-and-fix layer: every rule in this package stated as a check, a fix, and where a script can enforce it.

Inspect components Read the spec

21 Rules

How to verify a result against this system

The VERIFICATION surface: every major rule, HOW to check it (the visual signal + the script that enforces it), and the pass criterion. A human or an llm reviewer can audit a surface against it.

Two layers, and what each one reads
SCRIPT: python3 -m unittest discover tests (240 tests, green) gates the design-md ENGINE - the framework template under engine/artifact-types/design-md/framework/ and the engine's own workspace copy at engine/lib/designmd/workspace/projects/guesteria/output/. It does NOT read the pages of this document: 19 of its file paths point at that workspace output and ZERO at organizations/guesteria/, and the two have already diverged - the workspace creatives page carries 16 headings the shipped page does not, and the shipped page carries 14 the workspace copy does not. GEOMETRY of the CURVE FILES is the one part that does reach this document: the 13 svgs in assets/curves/ carry the exact geometry of the set tests/test_curves.py + tests/curve_geom.py parse - every d path string, viewBox, stroke-width, linecap and miterlimit is character-identical - so the named-edge slice and the cap clip, both pure geometry, are enforced on the exact shapes shipped here. The FILES are no longer byte-identical: the stroke ink was recoloured to the declared Royal Glow 800 #2D2F44, and that ink is the only byte in any of the 13 that differs. A claim about their geometry holds; a claim about their bytes does not. Everything page-level in the Script column - twin pairs, mark discipline, accent hierarchy, contrast, MD↔HTML parity - is asserted against the workspace copy and is a PROXY for this page, never a gate on it. VISUAL: the same rules with the eye-signal of a pass / fail - and below the curve files, the only layer that reads this document at all. Pointing the suite at the org output is an engine change affecting every organization; it is open, not done.
For an llm reviewer
Open the creative and apply the CHECK. If it fails, apply the FIX in the same row. The rules are the contract (framework/artifacts.md); the FIX column is the only sanctioned remedy.
Scope
Run the check on EVERY creative, not a sample. A rule passes for the document only when it passes for all of its creatives.

The rules — check & fix

RuleHow to verify (the signal)If it fails (the fix)Script
Named-edge sliceEvery curve pins its filename edges via preserveAspectRatio="<ALIGN> slice"; no cut end, no xMid / meet on a corner curve.Pin the named edges, remap after rotate / mirror.CurveAlignValid
Cap clip + interior breakNo round-cap blob on a named edge; a two-arc curve's centre break stays interior.Extend a real ending past its edge; leave interior termini put.CurveCapClip, Curve4InteriorBreak
TwinsONE continuous line across TWO EQUAL panels, connecting across the seam at one scale, contained with margin, one palette.Inline one path in both equal panels; each viewBox windows its half.TwinPairs
One accent shape, ONE registerA creative carries ONE accent shape from the brand's SINGLE chosen register (strong / soft / simple / custom - Guesteria = CUSTOM, the bell-swirl curve, see 05 Visual language); the SAME register reads across every creative, slide, the bento and the GENERATOR, and every accent is pulled from the CLOSED ten-curve canon - never a mix of registers, never a curve outside the canon. It clears its ground by ≥ ~3 ramp steps; no second device, never a bezier drawn by hand. The curve may also be a BACKGROUND (overscaled, cropped by the frame, or ghosted over a photo - a tier-4 subtone backing, still ONE per view; see 05 > Shape as background). It PAIRS with the corner stance (06): an angular shape with sharp-ish corners, a round shape with round corners - Guesteria's rounded-terminal curve pairs with round corners, never contradictory.Pick ONE register and carry it everywhere (incl. the generator pool), drawing every accent from the ten-curve canon; drop the second device; recolour the curve to clear the ground (or tone a backing curve to a near-tone).(visual)
Roundness stanceONE corner language (sharp ↔ round - see 06 Shape & roundness) drives EVERY wrapper radius; a wrapper's radius never exceeds its own padding (a paragraph .tagwrap--block radius ≤ its horizontal padding) so a corner never clips the copy.Set the stance once; map it onto the radius scale; keep .tagwrap--block radius at/below its padding.(visual)
Colour by roleA SUBJECT curve (gallery / hero, no heading over it) is distinguishable; a BACKING curve behind a bare heading is a NEAR-TONE of the ground so the title leads.Tone the backing curve toward the ground (same light/dark zone), or keep it bold + put the heading on a pill.(visual)
Tagwrap focus pillCopy close in colour to its ground rides a rounded pill; the pill colour differs from BOTH the ground AND the text (a same-colour pill vanishes); text centred.Pick a contrasting pill variant; --block uses a radius ≤ its padding; nudge text 1px down.TagwrapPill, TagwrapMuted
Composition (logo leads)Content reads as ONE cluster in reading order LOGO -> headline -> subtitle -> body: the lockup LEADS above the headline (never below the title or exiled to a far corner), the accent curve is the counterweight, no dead middle; the layout VARIES across FOUR named formats - top-cluster / center / side-band / diagonal. The functional ICON PINS to a CORNER or AXIS OPPOSITE the content block (content left -> a right corner, content right -> a left corner, a CENTRED block -> the centre axis at top / bottom), NEVER beside or behind the block.Lead the cluster with the logo; cluster the copy; add subtitle/body; vary the format across the four patterns (top-cluster / center / side-band / diagonal); pin the icon to the OPPOSITE corner / axis (.cre-icon-pin.at-*).(visual)
Edge padding (golden rule)Logo, icon and cluster sit the SAME distance from the frame edge (--cre-pad); a corner icon is NEVER tighter than the logo; the global alignment (left / centre / right) propagates to every child.Pin corner icons with .cre-icon-pin.at-* (not an inline --space-4); let the cluster class place + align the logo.CompositionEdgePad
Content island + liquid glassA multi-paragraph block lifts off a busy ground in a rounded .island whose radius TRACKS the type; .glass frosts an over-a-ground wrapper (the island OR a .tagwrap). CONTRAST: the light frost (.glass) takes DARK text, the dark frost (.glass--ink) takes LIGHT text - a light frost with light text vanishes. An inline <code> / chip inside glass keeps its OWN contrast (a light chip -> dark text), so it never inherits light-on-light.Wrap the copy in .island; add .glass over a LIGHT ground, .glass.glass--ink over a DARK ground / photo; keep the radius on var(--radius-island); size the frame to the copy.ContentIslandTests, LiquidGlassTests
Focus-wrap disciplineA .tagwrap phrase NEVER breaks mid-word (white-space: nowrap) and runs at most ONCE per paragraph; padding is FLAT (low, a hair more on the bottom) and em-based; a sentence-ending wrap pulls the full stop INSIDE the pill. A QUIET, no-fill variant exists (.tagwrap--quiet liquid edge / --quiet-tint rhythm border); the HTML renders a GALLERY of the registers.Keep one tagwrap per paragraph; pull the full stop inside a sentence-ending wrap; use --quiet when a filled pill is too loud; never force a mid-word break.TagwrapPill
Mark is a glyphThe brand mark is the supplied icon / lockup svg as shipped - never described or rebuilt as a letter.Inline the original svg; remove any letter framing.(visual)
One mark per creativeA single creative shows the full lockup OR the icon / brand-disc, NEVER both (a SYSTEM bento showcase is exempt - each tile is its own context); a FUNCTIONAL icon-disc's fill differs from the logo colour.Drop the redundant brand-disc when the lockup is present; recolour a functional disc so it differs from the logo.MarkDiscipline
Accent hierarchyThe one accent is spent on the MOST important element first: CTA > focus-wrap > icon > title > curve. BODY / paragraph copy stays NEUTRAL ink, never an accent or context tone (a sampled palette card's subtitle is neutral).Neutralise body subtitles to --text-secondary (light) / a translucent light (dark); keep the accent on the title / curve / CTA.HierarchyBodyNeutral
Contextual contrastEvery contextual element (a glass panel, a focus-wrap, an inline code chip, a media block) clears its GROUND by a luminance delta - a light frost over a DARK photo, or a light chip inheriting light text, both FAIL.Use .glass--ink over a dark ground; give the chip its own colour; pick the frost by the ground value.ContrastGuards
Bento first-screenmaster / uxui / creatives OPEN on a bento (id="identity") that REPLACES the text hero - the headline lives in a large tile; the assets / rules facets keep the plain hero. Every tile is contrast-correct.Lead the facet with 00b-bento; keep the nav #identity anchor on the opener; use .glass--ink on dark tiles.ComponentSurfaceTests

Run python3 -m unittest discover tests for the script layer - it gates the framework template and the engine's workspace copy, plus the geometry of the 13 curve svgs this document ships unchanged (only the stroke ink was recoloured); it does not read these pages (see Two layers, and what each one reads). For every other rule above, this page is the only layer.