From e6d1dcc2ec6af64aa2aa0db193d7270999bca614 Mon Sep 17 00:00:00 2001 From: Nahiyan Khan Date: Thu, 9 Jul 2026 00:58:58 -0400 Subject: [PATCH 1/6] =?UTF-8?q?materials:=20tokens=20audit=20=E2=80=94=20r?= =?UTF-8?q?adius=20roles,=20hoist=20grammar-enumerated=20values?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.ghost/materials/primitives.css | 50 +++++++++---------- .../ref/composition.conversation.html | 2 +- .../materials/ref/composition.form.html | 2 +- .../vessel-light/.ghost/materials/tokens.css | 16 +++++- 4 files changed, 41 insertions(+), 29 deletions(-) diff --git a/packages/vessel-light/.ghost/materials/primitives.css b/packages/vessel-light/.ghost/materials/primitives.css index 36217835..a8304d3d 100644 --- a/packages/vessel-light/.ghost/materials/primitives.css +++ b/packages/vessel-light/.ghost/materials/primitives.css @@ -60,11 +60,11 @@ body { .surface--radius-lg { border-radius: var(--radius-lg); } -.surface--radius-card { - border-radius: var(--radius-card); +.surface--radius-surface { + border-radius: var(--radius-surface); } -.surface--radius-pill { - border-radius: var(--radius-pill); +.surface--radius-control { + border-radius: var(--radius-control); } .surface--border { border: 1px solid var(--border); @@ -86,7 +86,7 @@ body { .stack { display: flex; flex-direction: column; - gap: 16px; + gap: var(--gap-md); align-items: stretch; justify-content: flex-start; flex-wrap: nowrap; @@ -98,19 +98,19 @@ body { gap: 0; } .stack--gap-xs { - gap: 4px; + gap: var(--gap-xs); } .stack--gap-sm { - gap: 8px; + gap: var(--gap-sm); } .stack--gap-md { - gap: 16px; + gap: var(--gap-md); } .stack--gap-lg { - gap: 24px; + gap: var(--gap-lg); } .stack--gap-xl { - gap: 32px; + gap: var(--gap-xl); } .stack--align-start { align-items: flex-start; @@ -142,7 +142,7 @@ body { margin: 0; color: var(--foreground); font-family: var(--font-sans); - font-size: 14px; + font-size: var(--text-body-size); line-height: 1.625; } .text--display { @@ -152,13 +152,13 @@ body { letter-spacing: var(--heading-display-letter-spacing); } .text--headline { - font-size: 24px; + font-size: var(--text-headline-size); font-weight: 400; line-height: 1.25; letter-spacing: -0.025em; } .text--title { - font-size: 18px; + font-size: var(--text-title-size); font-weight: 600; line-height: 1; letter-spacing: -0.025em; @@ -171,7 +171,7 @@ body { } .text--mono { font-family: var(--font-mono); - font-size: 14px; + font-size: var(--text-body-size); line-height: 1.5; } .text--muted { @@ -198,17 +198,17 @@ body { display: inline-flex; align-items: center; justify-content: center; - gap: 8px; + gap: var(--gap-sm); min-width: 0; - height: 36px; + height: var(--control-height); padding: 8px 24px; border: 1px solid transparent; - border-radius: var(--radius-pill); + border-radius: var(--radius-control); background: var(--primary); color: var(--primary-foreground); box-shadow: none; font: inherit; - font-size: 14px; + font-size: var(--text-body-size); line-height: 1; text-decoration: none; white-space: nowrap; @@ -261,7 +261,7 @@ body { .button--size-xs { height: 24px; padding: 4px 8px; - gap: 4px; + gap: var(--gap-xs); font-size: 12px; } .button--size-sm { @@ -280,8 +280,8 @@ body { padding: 0; } .button--icon { - width: 36px; - height: 36px; + width: var(--control-height); + height: var(--control-height); } .button--icon-xs { width: 24px; @@ -300,13 +300,13 @@ body { .field { display: flex; flex-direction: column; - gap: 8px; + gap: var(--gap-sm); } .label { display: flex; - gap: 8px; + gap: var(--gap-sm); color: var(--foreground); - font-size: 14px; + font-size: var(--text-body-size); line-height: 1; user-select: none; } @@ -314,7 +314,7 @@ body { display: flex; width: 100%; min-width: 0; - height: 36px; + height: var(--control-height); padding: 4px 12px; border: 1px solid var(--input); border-radius: var(--radius-input); diff --git a/packages/vessel-light/.ghost/materials/ref/composition.conversation.html b/packages/vessel-light/.ghost/materials/ref/composition.conversation.html index ad9b02ef..0bf293d4 100644 --- a/packages/vessel-light/.ghost/materials/ref/composition.conversation.html +++ b/packages/vessel-light/.ghost/materials/ref/composition.conversation.html @@ -44,7 +44,7 @@ -
+
diff --git a/packages/vessel-light/.ghost/materials/ref/composition.form.html b/packages/vessel-light/.ghost/materials/ref/composition.form.html index 4ca49304..9049fcc0 100644 --- a/packages/vessel-light/.ghost/materials/ref/composition.form.html +++ b/packages/vessel-light/.ghost/materials/ref/composition.form.html @@ -12,7 +12,7 @@ -
+

Workspace settings

diff --git a/packages/vessel-light/.ghost/materials/tokens.css b/packages/vessel-light/.ghost/materials/tokens.css index 2cd75191..3f389f08 100644 --- a/packages/vessel-light/.ghost/materials/tokens.css +++ b/packages/vessel-light/.ghost/materials/tokens.css @@ -87,10 +87,22 @@ --radius-sm: calc(var(--radius) - 4px); --radius-md: calc(var(--radius) - 2px); --radius-lg: var(--radius); - --radius-card: 20px; - --radius-pill: 999px; + --radius-surface: 20px; + --radius-control: 999px; --radius-input: 999px; + --gap-xs: 4px; + --gap-sm: 8px; + --gap-md: 16px; + --gap-lg: 24px; + --gap-xl: 32px; + + --text-body-size: 14px; + --text-title-size: 18px; + --text-headline-size: 24px; + + --control-height: 36px; + --background: var(--color-white); --foreground: var(--color-gray-900); --card: var(--background); From 1bb4da448189f12a9c970e6e5580f67305d7aeca Mon Sep 17 00:00:00 2001 From: Nahiyan Khan Date: Thu, 9 Jul 2026 01:06:53 -0400 Subject: [PATCH 2/6] =?UTF-8?q?corpus:=20fork-axis=20re-author=20=E2=80=94?= =?UTF-8?q?=20grammar/signature/register/anti-goal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.ghost/anti-goal.decoration.md | 21 ---- .../vessel-light/.ghost/anti-goal.median.md | 101 +++++++++++++----- .../vessel-light/.ghost/anti-goal.tells.md | 37 +++++++ .../.ghost/checks/conversation-grammar.md | 4 +- .../vessel-light/.ghost/checks/density.md | 12 ++- .../.ghost/checks/median-tells.md | 4 +- .../.ghost/checks/motion-restraint.md | 2 +- .../.ghost/foundation.expression.md | 34 ------ .../vessel-light/.ghost/foundation.motion.md | 21 ---- .../vessel-light/.ghost/foundation.tokens.md | 23 ---- .../vessel-light/.ghost/foundation.type.md | 22 ---- .../vessel-light/.ghost/foundation.voice.md | 25 ----- packages/vessel-light/.ghost/glossary.md | 41 +++++-- .../.ghost/grammar.color-roles.md | 30 ++++++ .../.ghost/grammar.conversation.md | 30 ++++++ .../vessel-light/.ghost/grammar.hierarchy.md | 48 +++++++++ .../vessel-light/.ghost/grammar.motion.md | 27 +++++ .../vessel-light/.ghost/grammar.rhythm.md | 27 +++++ .../vessel-light/.ghost/grammar.surfaces.md | 35 ++++++ packages/vessel-light/.ghost/index.md | 32 ++++-- .../.ghost/pattern.conversation.md | 20 ---- .../.ghost/pattern.data-density.md | 28 ----- .../vessel-light/.ghost/pattern.editorial.md | 26 ----- packages/vessel-light/.ghost/pattern.email.md | 27 ----- .../vessel-light/.ghost/primitive.control.md | 22 ---- .../vessel-light/.ghost/primitive.stack.md | 19 ---- .../vessel-light/.ghost/primitive.surface.md | 20 ---- .../vessel-light/.ghost/primitive.text.md | 17 --- .../.ghost/register.data-density.md | 39 +++++++ .../vessel-light/.ghost/register.editorial.md | 41 +++++++ .../vessel-light/.ghost/register.email.md | 43 ++++++++ .../vessel-light/.ghost/signature.palette.md | 45 ++++++++ .../vessel-light/.ghost/signature.shape.md | 27 +++++ .../.ghost/signature.temperature.md | 37 +++++++ .../vessel-light/.ghost/signature.type.md | 37 +++++++ 35 files changed, 643 insertions(+), 381 deletions(-) delete mode 100644 packages/vessel-light/.ghost/anti-goal.decoration.md create mode 100644 packages/vessel-light/.ghost/anti-goal.tells.md delete mode 100644 packages/vessel-light/.ghost/foundation.expression.md delete mode 100644 packages/vessel-light/.ghost/foundation.motion.md delete mode 100644 packages/vessel-light/.ghost/foundation.tokens.md delete mode 100644 packages/vessel-light/.ghost/foundation.type.md delete mode 100644 packages/vessel-light/.ghost/foundation.voice.md create mode 100644 packages/vessel-light/.ghost/grammar.color-roles.md create mode 100644 packages/vessel-light/.ghost/grammar.conversation.md create mode 100644 packages/vessel-light/.ghost/grammar.hierarchy.md create mode 100644 packages/vessel-light/.ghost/grammar.motion.md create mode 100644 packages/vessel-light/.ghost/grammar.rhythm.md create mode 100644 packages/vessel-light/.ghost/grammar.surfaces.md delete mode 100644 packages/vessel-light/.ghost/pattern.conversation.md delete mode 100644 packages/vessel-light/.ghost/pattern.data-density.md delete mode 100644 packages/vessel-light/.ghost/pattern.editorial.md delete mode 100644 packages/vessel-light/.ghost/pattern.email.md delete mode 100644 packages/vessel-light/.ghost/primitive.control.md delete mode 100644 packages/vessel-light/.ghost/primitive.stack.md delete mode 100644 packages/vessel-light/.ghost/primitive.surface.md delete mode 100644 packages/vessel-light/.ghost/primitive.text.md create mode 100644 packages/vessel-light/.ghost/register.data-density.md create mode 100644 packages/vessel-light/.ghost/register.editorial.md create mode 100644 packages/vessel-light/.ghost/register.email.md create mode 100644 packages/vessel-light/.ghost/signature.palette.md create mode 100644 packages/vessel-light/.ghost/signature.shape.md create mode 100644 packages/vessel-light/.ghost/signature.temperature.md create mode 100644 packages/vessel-light/.ghost/signature.type.md diff --git a/packages/vessel-light/.ghost/anti-goal.decoration.md b/packages/vessel-light/.ghost/anti-goal.decoration.md deleted file mode 100644 index 0ba31560..00000000 --- a/packages/vessel-light/.ghost/anti-goal.decoration.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -description: What Vessel rejects — gather before styling anything, and whenever the instinct is to add gradients, borders, extra color, shadows, or celebration to make a view feel finished. ---- - -Reject gradients and glassmorphism. Use flat semantic surfaces with the correct role, border, radius, and elevation. - -Reject color beyond the register's expression budget. Product views: monochrome plus one functional accent, expression hues only inside data visualization; data consoles: one status hue family; email: one expressive moment in one hue; editorial: at most two expression hues per page. - -Reject expressive color on interactive controls in every register. Buttons, inputs, and links are monochrome pills everywhere; that constant is what keeps the volumes one brand. - -Reject colors outside the expression palette and status set. An invented hue is not a bolder Vessel; it is a different brand. - -Reject borders as decoration, especially around assistant text. Use space, tone, and type hierarchy instead. - -Reject invented shadows. Use the three elevation tiers — card, popover, modal — and let interaction importance choose the tier. - -Reject celebration UI, exclamation-point success, and confetti language. Confirm quietly with clear text and, only when meaningful, a success tone. - -Reject icon confetti. Icons may clarify an action or status, but text labels carry meaning. A row of clever glyphs is not Vessel. - -Reject visual compensation for weak structure. If a surface feels unfinished, fix the stack, copy, or hierarchy before adding effects. diff --git a/packages/vessel-light/.ghost/anti-goal.median.md b/packages/vessel-light/.ghost/anti-goal.median.md index 95bda60f..68e2bfd0 100644 --- a/packages/vessel-light/.ghost/anti-goal.median.md +++ b/packages/vessel-light/.ghost/anti-goal.median.md @@ -1,40 +1,83 @@ --- -description: "The measured defaults of unsteered generation — gather before any build to know what the model will reach for on its own, and veer." +description: "The model's median defaults this fingerprint refuses — gather for any greenfield visual surface or first-draft copy. Each rule is reject→replace; delete lines your brand legitimately violates." --- -These are not aesthetic opinions. They are the measured convergence of 300 -unsteered generations across three frontier models (the antimedian -experiment): the defaults a model reaches for when nobody hands it a brand. -An output showing several of these tells reads as generated, whatever else -it does right. +This is the model's median, not your brand. Each rule is reject→replace. +Delete every line your brand legitimately violates — `ghost validate` will +surface any check the deletion orphans. -Reject hover-lift as the default interaction: cards, buttons, or anything -else rising on `translateY` with a growing shadow. The single most -convergent motion tell (341 combined occurrences). Vessel confirms hover -with color and background shifts at `--duration-fast`, not levitation. +These are not aesthetic opinions. Where a count is given, it is the measured +convergence of 300 unsteered generations across three frontier models (the +antimedian experiment): the defaults a model reaches for when nobody hands it +a brand. An output showing several of these tells reads as generated, +whatever else it does right. -Reject the indigo/blue default accent (`#4f46e5`, `#2563eb` and neighbors) — -the most convergent accent choice. Vessel's palette is monochrome plus the -five expression hues; an indigo CTA is the model speaking, not the brand. + +Reject hover-lift (`translateY` + growing shadow) as the default interaction +→ confirm with color and background change at the fingerprint's fast +duration. (measured: 341) -Reject unprompted dark theme. Dark was the second most common unsteered -choice (271). In Vessel, dark is one sanctioned editorial moment — the -full-bleed dark band — never a whole-page default nobody asked for. + +Reject the indigo/blue/purple default accent (`#4f46e5`, `#2563eb`, +`#8b5cf6` family; purple/violet hue 260–310) → the fingerprint's declared +palette; absent one, monochrome plus a single functional accent. -Reject gradient page backgrounds — radial washes, diagonal blue-purple, and -gradient-filled CTAs. Model-signature moves, not brand moves. Surfaces are -flat semantic roles. + +Reject unprompted dark theme → the fingerprint's declared surface. +Dark-to-look-cool and light-to-be-safe are the same retreat from a decision. +(measured: 271) -Reject chat bubbles with initials-circle avatars for assistant turns. The -measured chat median is alternating balloons; Vessel's conversation grammar -is plain assistant text on the page surface. + +Reject gradient page and section backgrounds and gradient-filled CTAs → flat +surfaces in semantic roles. -Reject emoji as icons and emoji as imagery. Text labels carry meaning. + +Reject side-stripe borders (a thick colored border on one side of a rounded +card) — the single most recognizable tell of AI-generated UI → a full +hairline border, a 4–8% surface tint, or a leading glyph. -Reject stock template copy: "Simple, transparent pricing" appeared verbatim -across all three models. If a heading could be swapped into a competitor's -page unchanged, write a different heading. + +Reject the cream/sand/beige default surface (warm off-white; token names +like `--cream`, `--sand`, `--parchment` are the tell) → a true off-white, +the brand's own hue, or a committed color; warmth via accent and type, not +the ground. -Two median patterns Vessel deliberately shares, so their presence is -fidelity here, not drift: pill-shaped controls and fluid clamp display -headings. Convergence is not the crime; surrendering the choice is. + +Reject glassmorphism (decorative backdrop blur) → flat surfaces with real +borders and the fingerprint's elevation tiers. + + +Reject chat bubbles with initials-circle avatars for assistant turns → +assistant text plain on the page surface; user turns marked compactly. + + +Reject stock template copy ("Simple, transparent pricing") → headings that +state what this product specifically does. + + +Reject celebration copy and UI (exclamation success, confetti language) → +quiet factual confirmation. + + +Reject nested cards and everything-in-cards → one surface level per region; +interior hierarchy from spacing and type; spacing and alignment group +without card overhead. + + +Reject the hero-metric template (big number + small label + supporting stats +as default proof) → evidence specific to the product, or nothing. A +prominent metric showing real user data is fine. + + +Reject every button a primary button → one primary per view; the rest step +down the fingerprint's emphasis ladder. + + +Reject an eyebrow kicker on every section → at most one, where the register +sanctions it; one named kicker is voice, every-section is AI grammar. + + +Reject decorative looping animation (pulse/float/shimmer) and uniform +fade-and-rise on every scrolled section → motion as evidence of state +change; loops only for genuine loading; decoration never compensates for +weak structure — fix spacing, copy, and hierarchy first. diff --git a/packages/vessel-light/.ghost/anti-goal.tells.md b/packages/vessel-light/.ghost/anti-goal.tells.md new file mode 100644 index 00000000..73ed11c8 --- /dev/null +++ b/packages/vessel-light/.ghost/anti-goal.tells.md @@ -0,0 +1,37 @@ +--- +description: "Failure modes specific to this brand's own signature — gather alongside any signature node you pull." +--- + +These are the near-misses of Vessel's own signature: outputs that got close +enough to cite the brand and still missed it. Each reject names its +replacement. + +Reject rectangular buttons. A rectangular button is not a variant; it is a +different design system → controls take `--radius-control`, the pill. + +Reject swapped radius roles: the surface radius on a control, the pill on a +surface, or 20px cells in a data table → `--radius-control` on what you +click, `--radius-surface` on what contains, small radius on data cells. + +Reject expression hues on interactive controls, an invented sixth hue, or a +tinted gray posing as monochrome → the five named expression hues at their +register's volume, and a true gray spine. An invented hue is not a bolder +Vessel; it is a different brand. + +Reject custom shadows that sit near a tier → the exact tier — card, popover, +or modal — chosen by interaction importance. + +Reject borrowing `--shadow-btn` or `--shadow-kbd` for layout → component +shadows belong to the primitives that own them; layout elevation comes from +the three tiers. + +Reject editorial display type in product UI, and product type timidity in +editorial → each register keeps its own vocabulary; a modal title is not a +poster, and a hero at product scale reads as timid. + +Reject borders around assistant text → the assistant speaks as plain text on +the page surface; use space, tone, and type hierarchy instead. + +Fidelity note: pills and fluid clamp display headings are medians Vessel +deliberately shares — their presence is fidelity, not drift. Convergence is +not the crime; surrendering the choice is. diff --git a/packages/vessel-light/.ghost/checks/conversation-grammar.md b/packages/vessel-light/.ghost/checks/conversation-grammar.md index a51cc3c8..938e77ff 100644 --- a/packages/vessel-light/.ghost/checks/conversation-grammar.md +++ b/packages/vessel-light/.ghost/checks/conversation-grammar.md @@ -3,8 +3,8 @@ name: Conversation grammar description: Flags conversation UI that breaks plain assistant text, prompt-input structure, primary-action discipline, or collapsed tool output. severity: high references: - - pattern.conversation - - primitive.surface + - grammar.conversation + - grammar.surfaces --- Apply this check to diffs that touch AI threads, agent consoles, prompt composers, chat messages, or tool-call rendering. diff --git a/packages/vessel-light/.ghost/checks/density.md b/packages/vessel-light/.ghost/checks/density.md index d5bb8ff1..b3510655 100644 --- a/packages/vessel-light/.ghost/checks/density.md +++ b/packages/vessel-light/.ghost/checks/density.md @@ -3,11 +3,13 @@ name: Density and token discipline description: Flags decorative color, raw values, and invented shadows that break Vessel's monochrome-first token contract and register expression budgets. severity: high references: - - anti-goal.decoration - - foundation.tokens - - foundation.expression - - primitive.stack - - primitive.control + - anti-goal.median + - grammar.color-roles + - grammar.surfaces + - grammar.rhythm + - grammar.hierarchy + - signature.palette + - signature.shape --- Review changed HTML and CSS by view, not just by file. diff --git a/packages/vessel-light/.ghost/checks/median-tells.md b/packages/vessel-light/.ghost/checks/median-tells.md index 19104465..e678598f 100644 --- a/packages/vessel-light/.ghost/checks/median-tells.md +++ b/packages/vessel-light/.ghost/checks/median-tells.md @@ -4,8 +4,8 @@ description: Flags the measured defaults of unsteered generation — hover-lift, severity: high references: - anti-goal.median - - foundation.motion - - pattern.conversation + - grammar.motion + - grammar.conversation --- These flags target the measured convergence patterns of unsteered model diff --git a/packages/vessel-light/.ghost/checks/motion-restraint.md b/packages/vessel-light/.ghost/checks/motion-restraint.md index aeedd3ff..0de32a48 100644 --- a/packages/vessel-light/.ghost/checks/motion-restraint.md +++ b/packages/vessel-light/.ghost/checks/motion-restraint.md @@ -3,7 +3,7 @@ name: Motion restraint description: Flags non-token motion, looping decoration, and keyframes that do not explain state change. severity: medium references: - - foundation.motion + - grammar.motion --- Review changed transitions and animations for vocabulary first. diff --git a/packages/vessel-light/.ghost/foundation.expression.md b/packages/vessel-light/.ghost/foundation.expression.md deleted file mode 100644 index 94c7e0de..00000000 --- a/packages/vessel-light/.ghost/foundation.expression.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -description: "The expression palette and its volume ladder — gather whenever color beyond monochrome is in question, in any register: product, data, email, or editorial." -materials: - - materials/tokens.css ---- - -Vessel is one brand at different volumes. Monochrome is the spine in every -medium. The expression palette is volume, and volume is set by register. - -The palette is five named hues and only these: amber (`--expression-1`), -periwinkle (`--expression-2`), clay (`--expression-3`), orchid -(`--expression-4`), sage (`--expression-5`). Expressive color outside this set -is not expression; it is another brand. - -The volume is set by register, not by taste: - -Product UI: expression lives only in data visualization. A chart may use the -hues; the interface around it stays monochrome. - -Data-dense consoles: one hue family may mark status. Nothing atmospheric. Charts inside a console keep the product carve-out — hues stay inside the plot area and never leak into rows, badges, or headers. - -Email: exactly one expressive moment per message — a header band or the -figure that matters. One hue, quiet everywhere else. - -Editorial: expression is sanctioned atmosphere — a tinted dark section, a -colored pull-quote accent, a duotone moment. Never more than two hues per -page. Loudness comes from commitment to few colors at scale, not variety. - -The constant that makes it one brand: expression never touches what you -click. Buttons, inputs, and links stay monochrome pills in every register. -A colored control is a different design system. - -The status colors (red, green, yellow, blue) are not expression. They keep -their meanings in every register and never moonlight as atmosphere. diff --git a/packages/vessel-light/.ghost/foundation.motion.md b/packages/vessel-light/.ghost/foundation.motion.md deleted file mode 100644 index b5d74be0..00000000 --- a/packages/vessel-light/.ghost/foundation.motion.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -description: Use only the three duration tokens and the spring ease; motion explains state change and never decorates. -materials: - - materials/tokens.css - - "**/*.css" - - "**/*.html" ---- - -Motion in Vessel is evidence of a state change. It confirms hover, press, reveal, collapse, entrance, exit, and spatial movement. It does not entertain. - -The entire vocabulary is three durations and one spring ease. Fast is for hover and press. Normal is for reveals, fades, and small state changes. Slow is reserved for spatial transitions where the user needs to understand movement. - -Use `--ease-spring` when the transition should feel resolved without feeling elastic. Do not introduce novelty easings because a surface feels static. - -Nothing loops except explicit loading states. A spinner may continue because work continues. Decorative pulsing, floating, glowing, and attention-seeking keyframes are off-language. - -Prefer opacity and small transform changes. - -If removing an animation does not reduce comprehension, the animation was decoration. - -Condition: editorial surfaces may stage entrances — scroll reveals and section transitions are part of editorial rhythm, still built from the three durations and the spring ease. In product UI the same staging is decoration. diff --git a/packages/vessel-light/.ghost/foundation.tokens.md b/packages/vessel-light/.ghost/foundation.tokens.md deleted file mode 100644 index 6ede6def..00000000 --- a/packages/vessel-light/.ghost/foundation.tokens.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -description: Use semantic monochrome tokens, status-only utility colors, three elevation tiers, pill controls, and the signature 20px card radius. -materials: - - materials/tokens.css - - "**/*.css" - - "**/*.html" ---- - -The token file is the source of truth. An agent may combine tokens, but it may not author around them. - -The base palette is monochrome gray. That is the default atmosphere of Vessel: calm, legible, and resistant to novelty. - -Author with semantic roles: `background`, `foreground`, `card`, `popover`, `primary`, `secondary`, `muted`, `border`, `input`, `ring`, and the status roles. Raw hex values are implementation detail, never product language. - -Red, green, yellow, and blue exist only when meaning demands them. Red means destructive or error. Green means success. Yellow means warning. Blue means information. None of them are brand accents. - -One view should not perform a color palette. If a status color is present, let the rest of the view stay gray. Richness beyond this is register-gated: the expression palette exists, but its volume ladder lives in the expression node — in product UI it appears only inside charts. - -Elevation on surfaces is three tiers: card (sits in flow), popover (floats above the flow), modal (interrupts the task). Pick the tier that matches the interaction; never write a custom `box-shadow` because the composition feels flat. Component shadows (`--shadow-btn`, `--shadow-mini`, `--shadow-kbd`) belong to the primitives that own them; never borrow them for layout. - -Controls are pills. Buttons and text inputs use `--radius-pill` (999px); cards use the 20px signature radius. Never give a button the card radius — a rectangular button is the fastest tell that the output is not Vessel. - -`--radius: 20px` is a signature. Vessel is rounder than default shadcn, but not bubbly. Use the radius system as restraint, not as decoration. diff --git a/packages/vessel-light/.ghost/foundation.type.md b/packages/vessel-light/.ghost/foundation.type.md deleted file mode 100644 index 1d10d226..00000000 --- a/packages/vessel-light/.ghost/foundation.type.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -description: HK Grotesk type scale — gather for any text, and for heroes, landing pages, and editorial moments where the display and section tiers apply. -materials: - - materials/tokens.css - - materials/fonts/*.woff2 ---- - -HK Grotesk is the voice of the interface. Use it everywhere unless a mono variant is required for code, tool detail, or machine output. vessel-light ships HK Grotesk as its embedded voice; the React package currently falls back to system-ui. This fingerprint is the intended future — here, `tokens.css` is canonical. - -The heading scale is editorial: display, section, sub, and card each carry their own rhythm. Display sizes use tight tracking and sub-1 line heights because the words behave like composition, not paragraph text. - -The heading tokens (`--heading-section-*`, `--heading-sub-*`, `--heading-card-*`) exist for editorial pages composed outside the text primitive. Product UI uses only the six text variants: display, headline, title, body, label, mono. Do not mix the two vocabularies in one view. - -Do not fake hierarchy with arbitrary font sizes. Choose the tier that matches the job, then use tone, weight, and spacing for the rest. - -Labels are small, semibold, and tracked wide. They mark structure: category tags, field labels, bylines, metadata, and compact status. They should feel precise, never loud. - -Body text is for reading and interface explanation. Keep it in the established reading sizes with relaxed line height; do not shrink important prose until it becomes legal copy. - -Condition: display and section scale are for editorial or hero moments. Product UI lives in headline, title, body, label, and mono. A modal title is not a poster. - -When in doubt, make type quieter and layout clearer. diff --git a/packages/vessel-light/.ghost/foundation.voice.md b/packages/vessel-light/.ghost/foundation.voice.md deleted file mode 100644 index 8f68229e..00000000 --- a/packages/vessel-light/.ghost/foundation.voice.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -description: "Interface copy voice — factual, quiet, lowercase-calm in product; declarative and confident in editorial; never celebratory." ---- - -Product UI is the default register: factual, quiet, sentence case, and free of applause. - -Copy states what happened, what is possible, or what the user must decide. It does not perform personality. - -Do not use exclamation marks. Celebration is not reassurance. - -Errors name the problem and the fix in the place where the user can act. A vague failure banner is evasion. - -Confirmations are quiet: “Changes saved”, never “Awesome!” The system should sound reliable, not excited by basic competence. - -Buttons name the act. Use “Delete account”, “Save changes”, and “Invite member”, not “Do it” or “Let’s go”. - -Destructive copy is direct because the risk is direct. Softening the verb makes the interface less honest. - -Condition: editorial surfaces switch register. Short declarative confident fragments are correct in heroes and section headings. - -That same editorial confidence is wrong in a settings form. Product copy serves the task before it serves the voice. - -Email copy uses the product voice: factual, not campaign-like. Email's color budget is its own — see the expression ladder. - -Vessel never celebrates at the user. Trust comes from precision, restraint, and naming the truth plainly. diff --git a/packages/vessel-light/.ghost/glossary.md b/packages/vessel-light/.ghost/glossary.md index 901fcedf..04718897 100644 --- a/packages/vessel-light/.ghost/glossary.md +++ b/packages/vessel-light/.ghost/glossary.md @@ -1,24 +1,45 @@ --- kinds: - - name: foundation - - name: primitive - - name: pattern + - name: grammar + - name: signature + - name: register - name: anti-goal posture: guard --- -# foundation +# grammar -The token contract: raw values, semantic roles, type rhythm, shape, shadow, and motion vocabulary. Gather foundation nodes before inventing values. +The brand's decision logic: closed sets, role vocabularies, and assembly +rules, stated in token roles and never in literal values. Grammar survives a +rebrand unchanged — fork the package, swap every value, and these nodes still +hold. Gather grammar before inventing structure. -# primitive +# signature -A steering element of the compositional alphabet. Each primitive is a closed variant vocabulary with opinionated defaults, not a suggestion list. +The dials: the choices that make this brand this brand, each stated as a +current answer that stands until you replace it. Signature nodes name real +values because they are the values — on fork, edit the token roles in +`materials/tokens.css` and restate the node. Gather signature before setting +any value a dial governs. -# pattern +# register -Assembly grammar that spans primitives. Patterns name the arrangement that makes raw HTML/CSS feel like Vessel instead of a pile of styled tags. +A condition-scoped contract: a situation — data-dense consoles, editorial +pages, transactional email — where parts of the default rules invert. Each +register names its condition first. Truths from the wrong register are +poison, not context; gather a register only when its condition matches the +task. # anti-goal -What Vessel never looks like. These are review-critical rejects with replacements, especially when an agent tries to decorate its way out of weak structure. +What this package refuses, each reject paired with its replacement. +`anti-goal.median` is the model's floor, not the brand's taste; +`anti-goal.tells` is the near-miss map of this brand's own signature. Gather +anti-goals before styling anything greenfield. + +--- + +To adapt this package to another brand, follow the transplant procedure — +it ships with the ghost skill bundle. In short: new manifest id, prune the +median rules your brand legitimately violates, answer each signature node, +edit `materials/tokens.css`, regenerate the refs, rewrite the tells. diff --git a/packages/vessel-light/.ghost/grammar.color-roles.md b/packages/vessel-light/.ghost/grammar.color-roles.md new file mode 100644 index 00000000..99e28261 --- /dev/null +++ b/packages/vessel-light/.ghost/grammar.color-roles.md @@ -0,0 +1,30 @@ +--- +description: "Semantic color roles and the rules that govern them — gather before choosing any color; roles not raw values, status is meaning, expression is register-gated and never on controls." +materials: + - materials/tokens.css + - "**/*.css" + - "**/*.html" +--- + +The token file is the source of truth. An agent may combine tokens, but it +may not author around them. Raw color values are implementation detail, never +product language. + +Author with semantic roles: `background`, `foreground`, `card`, `popover`, +`primary`, `secondary`, `muted`, `accent`, `border`, `input`, `ring`, and the +status roles. If a container needs a color, it first needs a role. + +The status roles — destructive, success, warning, info — exist only when +meaning demands them. Destructive means destructive or error. Success means +success. Warning means warning. Info means information. None of them are +brand accents, and they never moonlight as atmosphere, in any register. + +One view should not perform a color palette. If a status color is present, +let the rest of the view stay on the base roles. Richness beyond this is +register-gated: the expression roles (`--expression-1` through +`--expression-5`) exist, but their volume ladder is a brand answer — see the +palette signature — and each register caps how loud they may be. + +The constant that holds across every register: expression never touches what +you click. Buttons, inputs, and links stay on the base roles everywhere. A +colored control is a different design system. diff --git a/packages/vessel-light/.ghost/grammar.conversation.md b/packages/vessel-light/.ghost/grammar.conversation.md new file mode 100644 index 00000000..980a8ac3 --- /dev/null +++ b/packages/vessel-light/.ghost/grammar.conversation.md @@ -0,0 +1,30 @@ +--- +description: "Conversation grammar — plain assistant text, compact user surfaces, collapsed tool calls, one structured prompt input; gather for any AI thread, agent console, review assistant, or prompt composer." +materials: + - materials/ref/composition.conversation.html + - "**/*.html" +--- + +Conversation UI is not chat cosplay. The assistant speaks on the page surface +as plain text: no bubble, no border, no fill. + +User turns are compact muted surfaces aligned right. They mark authorship +without turning the thread into alternating balloons. + +Assistant hierarchy comes from prose, spacing, and type. Wrapping assistant +messages in cards makes the system look defensive and wastes density. + +Tool calls are operational evidence. Collapse them to a labeled one-line +summary with status. Expand only when the user asks for detail, then show +mono content inside the disclosed area. + +The prompt input is one bordered surface. The textarea region stays empty of +controls so writing remains the focus. Attachments, model choices, secondary +tools, and send live in a single row below it. + +There is one primary send action. Stop and send are mutually exclusive states +of the same action area, not two competing primary buttons. + +Use the conversation reference when building any AI thread, agent console, +review assistant, or prompt composer. It carries the grammar that agents most +often get wrong. diff --git a/packages/vessel-light/.ghost/grammar.hierarchy.md b/packages/vessel-light/.ghost/grammar.hierarchy.md new file mode 100644 index 00000000..db66170f --- /dev/null +++ b/packages/vessel-light/.ghost/grammar.hierarchy.md @@ -0,0 +1,48 @@ +--- +description: "The closed hierarchy vocabulary — six text variants, seven tones, a five-rung control emphasis ladder, one primary per view — gather for any view that contains text or actions." +materials: + - materials/primitives.css + - materials/ref/composition.form.html + - "**/*.html" + - "**/*.css" +--- + +Hierarchy is a closed vocabulary, not a size slider. Every piece of text and +every control picks from a named set; anything outside the set is a broken +primitive, not a variant. + +The text variants are exactly six: display, headline, title, body, label, +mono. Variant names are jobs, not decoration. Display leads a rare editorial +moment. Headline names a section. Title anchors a card, dialog, or compact +region. Body carries reading. Label names structure — category tags, field +labels, bylines, metadata, compact status. Mono carries code and machine +detail. Do not fake hierarchy with arbitrary font sizes; choose the tier that +matches the job, then use tone, weight, and spacing for the rest. + +The tones are exactly seven: default, muted, inverse, success, warning, info, +destructive. Tone is part of the message. Default is the main reading plane. +Muted carries secondary information. Inverse is for dark or primary surfaces. +The four status tones appear only when the words have that state meaning. +Hierarchy starts with tone and weight before size — a secondary note usually +wants muted body or label, not a smaller custom font. If the prose needs +emphasis, improve the sentence before adding a style. + +The control emphasis ladder is exactly five rungs: primary, secondary, +outline, ghost, link. One primary action per view is the rule; everything +else steps down the ladder. Primary is for the action the screen exists to +complete — if two buttons both look primary, the hierarchy failed. +Destructive is a meaning, not a rung: it is rare, it names the destructive +act directly, and it is never borrowed for urgency, emphasis, or brand heat. + +Fields are quiet until they are active: hairline border, muted placeholder, +clear label, and a focused ring when the user engages. The focus ring is +guidance, not decoration. Errors state facts next to the field that caused +them — do not hide field errors in modals, toasts, or generic banners when +the user needs to fix one input. + +Balanced text is for headings and compact statements. Do not balance long +body copy into jagged reading. + +The form reference shows the intended decision order: stacked labels and +fields, compact helper text, one submit, secondary escape. Copy the decision +order before adjusting surface detail. diff --git a/packages/vessel-light/.ghost/grammar.motion.md b/packages/vessel-light/.ghost/grammar.motion.md new file mode 100644 index 00000000..406ea1c4 --- /dev/null +++ b/packages/vessel-light/.ghost/grammar.motion.md @@ -0,0 +1,27 @@ +--- +description: "Motion doctrine — motion is evidence of state change, never decoration; a closed vocabulary of three duration roles and one ease; gather for any transition, animation, or hover treatment." +materials: + - materials/tokens.css + - "**/*.css" + - "**/*.html" +--- + +Motion is evidence of a state change. It confirms hover, press, reveal, +collapse, entrance, exit, and spatial movement. It does not entertain. + +The entire vocabulary is three duration roles and one ease. Fast is for hover +and press. Normal is for reveals, fades, and small state changes. Slow is +reserved for spatial transitions where the user needs to understand movement. +Do not introduce novelty easings because a surface feels static; the ease's +character is a brand answer — see the temperature signature. + +Nothing loops except explicit loading states. A spinner may continue because +work continues. Decorative pulsing, floating, glowing, and attention-seeking +keyframes are off-language. + +Prefer opacity and small transform changes. If removing an animation does not +reduce comprehension, the animation was decoration. + +Condition: editorial surfaces may stage entrances — scroll reveals and +section transitions are part of editorial rhythm, still built from the three +durations and the one ease. In product UI the same staging is decoration. diff --git a/packages/vessel-light/.ghost/grammar.rhythm.md b/packages/vessel-light/.ghost/grammar.rhythm.md new file mode 100644 index 00000000..afdc9f1b --- /dev/null +++ b/packages/vessel-light/.ghost/grammar.rhythm.md @@ -0,0 +1,27 @@ +--- +description: "Layout rhythm — all layout is stacks with a closed gap step set; gather before laying anything out; never ad-hoc sibling margins." +materials: + - materials/primitives.css + - "**/*.html" + - "**/*.css" +--- + +All layout is stacks. Rhythm comes from relationships between siblings, not +from isolated margins pasted onto whichever element was last touched. + +The gap steps are exactly five: `--gap-xs`, `--gap-sm`, `--gap-md`, +`--gap-lg`, `--gap-xl`. Choose the gap that states the relationship. Do not +tune by single pixels to make a screenshot pass. + +The default is column, medium gap, stretch alignment, start justification. +That is the ordinary reading rhythm. + +Columns are for almost everything: forms, cards, message lists, modal bodies, +settings, empty states, and page sections. A column lets the user scan. + +Rows are conditional. Use them for controls, metadata lines, compact status, +and paired label/value moments. If a row starts wrapping awkwardly, it +probably wanted to be a column. + +Ad-hoc margins between siblings are forbidden because they hide the rhythm. +When spacing feels wrong, change the stack gap or split the stack. diff --git a/packages/vessel-light/.ghost/grammar.surfaces.md b/packages/vessel-light/.ghost/grammar.surfaces.md new file mode 100644 index 00000000..b9a5e9b3 --- /dev/null +++ b/packages/vessel-light/.ghost/grammar.surfaces.md @@ -0,0 +1,35 @@ +--- +description: "Surface roles and the closed elevation set — gather for any card, popover, modal, dialog, scrim, or bordered container; flat is the default, borders are structural, exactly three elevation tiers." +materials: + - materials/primitives.css + - materials/ref/composition.overlay.html + - "**/*.html" + - "**/*.css" +--- + +Surface is the only way an element gets a background, border, radius, or +shadow. If a container needs visual treatment, it first needs a surface role. + +The vocabulary is closed: role, padding, radius, border, and elevation. These +axes create enough range for page flow, cards, popovers, muted blocks, +accents, and dark moments without inventing one-off boxes. + +The default surface is flat: no border, no shadow. We do not outline +everything to prove layout exists. + +The elevation tiers are exactly three: card, popover, modal. Elevation +implies hierarchy — a card sits in the document flow, a popover floats above +the flow, a modal interrupts the task. Pick the tier that matches the +interaction; never write a custom shadow because the composition feels flat, +and never pair a low tier with an interrupting role or give a routine card +modal gravity. Component shadows belong to the primitives that own them; +never borrow them for layout. + +Borders are structural, especially for inputs and overlays. They are not +decorative frames around ordinary text — reject borders as decoration, +especially around assistant text, and use space, tone, and type hierarchy +instead. + +The overlay reference shows the interrupting end of the system: background +scrim, modal radius, modal shadow, compact header, clear footer. Copy its +hierarchy when a user must stop and decide. diff --git a/packages/vessel-light/.ghost/index.md b/packages/vessel-light/.ghost/index.md index 25e06caa..37753ab5 100644 --- a/packages/vessel-light/.ghost/index.md +++ b/packages/vessel-light/.ghost/index.md @@ -4,16 +4,34 @@ materials: - materials/tokens.css --- -vessel-light is Vessel without the React package: the design language as a repo-local steering packet for agents writing raw HTML and CSS. +vessel-light is Vessel without the React package: the design language as a +repo-local steering packet for agents writing raw HTML and CSS. -The contract is narrow. Style only with the tokens. Lay out only with the primitives. Imitate the compositions when the task matches them. +The contract is narrow. Style only with the tokens. Compose only with the +closed sets the grammar enumerates. Imitate the refs when the task matches +them — they are worked examples to copy from, not a framework to import. -The package spans registers. Product surfaces are the default; editorial, email, and data-density patterns each name their condition and invert parts of the default contract. Gather against the actual task and pull only the nodes whose conditions apply, because truths from the wrong register are poison, not context. +The corpus carries three trust tiers. Grammar and the median floor are law: +safe to consume verbatim, unchanged by any rebrand. Signature nodes are +dials awaiting your values: each states Vessel's current answer and stands +until you replace it. Registers are conditions: editorial, email, and +data-density each name the situation where parts of the default contract +invert. Gather against the actual task and pull only the nodes whose +conditions apply, because truths from the wrong register are poison, not +context. -The refs are worked examples to copy from, not a framework to import. They show the grammar in plain HTML so an agent can reproduce the decisions without carrying component code. +The reset raises the floor; only the fingerprint escapes the median. -Monochrome comes first. Status color is functional language for danger, success, warning, and information — never atmosphere. Atmosphere exists, but it is catered: a five-hue expression palette whose volume rises with the register, from charts-only in product to two hues in editorial, and never on controls. +Monochrome comes first. Status color is functional language for danger, +success, warning, and information — never atmosphere. Atmosphere exists, but +it is catered: a five-hue expression palette whose volume rises with the +register, from charts-only in product to two hues in editorial, and never on +controls. -The fingerprint protects the taste that disappears when an agent freehands: quiet surfaces, deliberate spacing, one obvious action, and restrained motion. +The fingerprint protects the taste that disappears when an agent freehands: +quiet surfaces, deliberate spacing, one obvious action, and restrained +motion. -When a requested UI is not covered by a ref, compose from primitives. Do not invent a new styling system. If the result needs a new pattern, the new pattern should come from observed drift, not anticipation. +When a requested UI is not covered by a ref, compose from the grammar. Do +not invent a new styling system. If the result needs a new pattern, the new +pattern should come from observed drift, not anticipation. diff --git a/packages/vessel-light/.ghost/pattern.conversation.md b/packages/vessel-light/.ghost/pattern.conversation.md deleted file mode 100644 index 86d619b4..00000000 --- a/packages/vessel-light/.ghost/pattern.conversation.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -description: Build AI conversations with plain assistant text, compact user surfaces, collapsed tool calls, and one structured prompt input. -materials: - - materials/ref/composition.conversation.html - - "**/*.html" ---- - -Conversation UI is not chat cosplay. The assistant speaks on the page surface as plain text: no bubble, no border, no fill. - -User turns are compact muted surfaces aligned right. They mark authorship without turning the thread into alternating balloons. - -Assistant hierarchy comes from prose, spacing, and type. Wrapping assistant messages in cards makes the system look defensive and wastes density. - -Tool calls are operational evidence. Collapse them to a labeled one-line summary with status. Expand only when the user asks for detail, then show mono content inside the disclosed area. - -The prompt input is one bordered surface. The textarea region stays empty of controls so writing remains the focus. Attachments, model choices, secondary tools, and send live in a single row below it. - -There is one primary send action. Stop and send are mutually exclusive states of the same action area, not two competing primary buttons. - -Use the conversation reference when building any AI thread, agent console, review assistant, or prompt composer. It carries the grammar that agents most often get wrong. diff --git a/packages/vessel-light/.ghost/pattern.data-density.md b/packages/vessel-light/.ghost/pattern.data-density.md deleted file mode 100644 index dbce3abf..00000000 --- a/packages/vessel-light/.ghost/pattern.data-density.md +++ /dev/null @@ -1,28 +0,0 @@ ---- -description: "Data-dense consoles — gather for tables, dashboards, logs, and monitoring; compresses product rhythm to 4/8px, mono numerals, muted-first." -materials: - - materials/ref/composition.table.html - - materials/primitives.css ---- - -Condition: this node applies to data-dense surfaces — tables, dashboards, transaction logs, and admin consoles. - -Data density inverts the settings-page rhythm. Operators need scan speed before they need breathing room. - -Use 4px and 8px gaps where forms use 16px. Tight adjacency is meaning when rows compare against rows. - -Numerals are mono so columns align. A ragged amount column is a broken instrument. - -Hierarchy is muted-first. Data is the default plane, labels are muted, and emphasis is rare enough to stay useful. - -Data surfaces take the small radius. A 20px-radius table cell is costume. - -Status is a text label with at most one functional color family per view. - -Charts inside a console follow the product carve-out: expression hues live inside the plot area only. Outside the plot, the one-status-hue cap holds — chart color never leaks into rows, badges, or headers. More status color turns monitoring into confetti. - -No zebra striping. Hairline borders carry rows with less noise and more trust. - -Hover confirmation uses `--duration-fast`. It should acknowledge targeting, not animate the table. - -Generous whitespace is drift here. Wasted density makes operators scroll. diff --git a/packages/vessel-light/.ghost/pattern.editorial.md b/packages/vessel-light/.ghost/pattern.editorial.md deleted file mode 100644 index dcd214f2..00000000 --- a/packages/vessel-light/.ghost/pattern.editorial.md +++ /dev/null @@ -1,26 +0,0 @@ ---- -description: "Editorial and landing surfaces — gather for heroes, marketing pages, pull quotes, and full-bleed dark moments; inverts product type restraint." -materials: - - materials/ref/composition.editorial.html - - materials/tokens.css ---- - -Condition: this node applies to marketing, landing, and editorial surfaces — never to product UI. - -Editorial surfaces invert the product type rules. Display scale is not an indulgence here; it is the job. - -Use `--heading-display-font-size: clamp(64px, 8vw, 96px)`, `--heading-display-line-height: 0.88`, and `--heading-display-font-weight: 900` when the words are the composition. - -Section rhythm is `--section-padding-vertical: 100px`, not a 16px product stack stretched until it looks important. - -The sanctioned dramatic moment is the full-bleed dark section. Use the `--surface-dark-*` family and let contrast carry the scene. - -Pull quotes are visual punctuation for longform. They interrupt reading with judgment, not decoration. - -The tracked uppercase label is the kicker grammar. It gives the page a hard editorial edge before the headline lands. - -Monochrome remains the spine, but editorial is the loud end of the expression ladder: up to two expression hues per page as atmosphere — a tinted dark section, a colored pull-quote accent, a duotone image moment. Commit to few colors at scale; variety is where expression collapses into decoration. - -There is one primary action per page, and it remains a pill. Editorial confidence does not excuse competing calls to action. - -A hero built at product scale reads as timid. Timidity is drift here, exactly as spectacle is drift in product UI. diff --git a/packages/vessel-light/.ghost/pattern.email.md b/packages/vessel-light/.ghost/pattern.email.md deleted file mode 100644 index f3e09a75..00000000 --- a/packages/vessel-light/.ghost/pattern.email.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -description: "Transactional email — gather ONLY for email; inverts the token contract: inline styles, hardcoded hex, table layout, system fonts." -materials: - - materials/ref/email.html ---- - -Condition: this node applies only to email. In any other medium, everything below is a violation. - -Email clients do not honor the web contract. Custom properties, external stylesheets, flex layout, and webfonts are unreliable materials here. - -Email inverts the material contract deliberately. Transcribe token values by hand instead of referencing tokens. - -Use `#1a1a1a` for foreground, `#999999` for muted text, and `#e8e8e8` for borders when the email needs the Vessel palette. - -Keep the 20px card radius and the pill button shape. The values survive even when the token names cannot travel. - -Build with table layout, a 600px wrapper, predictable cells, and bulletproof buttons. Email fidelity is made from boring structure. - -HK Grotesk falls back to the system stack. The voice must survive without the font file. - -The soul survives the body swap: monochrome spine, quiet factual copy, one primary action, no celebration. - -Email gets exactly one expressive moment: a header band or the figure that matters, in one expression hue (transcribed by hand, like every value here — amber is `#f6b44a`). One moment, one hue. A receipt is allowed one degree of warmth; it is not allowed a palette. - -Do not add further color to compensate for email constraints. Constraint is not permission to perform. - -Hardcoding hex here is fidelity, not drift. The check exemption is the condition itself. diff --git a/packages/vessel-light/.ghost/primitive.control.md b/packages/vessel-light/.ghost/primitive.control.md deleted file mode 100644 index ece934e7..00000000 --- a/packages/vessel-light/.ghost/primitive.control.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -description: Use quiet fields, focused rings, factual errors, and one primary action per view. -materials: - - materials/primitives.css - - materials/ref/composition.form.html - - "**/*.html" - - "**/*.css" ---- - -Controls make decisions obvious without making the whole view loud. One primary action per view is the rule; everything else steps down to secondary, outline, ghost, or link. - -Buttons and inputs are pills. The pill radius is Vessel's most visible control signature; a rectangular button is not a variant, it is a different design system. - -Primary is for the action the screen exists to complete. If two buttons both look primary, the hierarchy failed. - -Destructive is red and rare. It must name the destructive act directly. Do not use red as urgency, emphasis, or brand heat. - -Fields are quiet until they are active: hairline border, muted placeholder, clear label, and a focused ring when the user engages. The focus ring is guidance, not decoration. - -Errors state facts next to the field that caused them. Do not hide field errors in modals, toasts, or generic banners when the user needs to fix one input. - -The form reference shows the intended density: stacked labels and fields, compact helper text, one submit, secondary escape. Copy the decision order before adjusting surface detail. diff --git a/packages/vessel-light/.ghost/primitive.stack.md b/packages/vessel-light/.ghost/primitive.stack.md deleted file mode 100644 index 678a1405..00000000 --- a/packages/vessel-light/.ghost/primitive.stack.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -description: Compose layout with stack direction, gap, alignment, justification, and wrap; never ad-hoc sibling margins. -materials: - - materials/primitives.css - - "**/*.html" - - "**/*.css" ---- - -All layout is stacks. Vessel rhythm comes from relationships between siblings, not from isolated margins pasted onto whichever element was last touched. - -The gap scale is the spacing language: 4, 8, 16, 24, and 32. Choose the gap that states the relationship. Do not tune by single pixels to make a screenshot pass. - -The default is column, medium gap, stretch alignment, start justification. That is Vessel's ordinary reading rhythm. - -Columns are for almost everything: forms, cards, message lists, modal bodies, settings, empty states, and page sections. A column lets the user scan. - -Rows are conditional. Use them for controls, metadata lines, compact status, and paired label/value moments. If a row starts wrapping awkwardly, it probably wanted to be a column. - -Ad-hoc margins between siblings are forbidden because they hide the rhythm. When spacing feels wrong, change the stack gap or split the stack. diff --git a/packages/vessel-light/.ghost/primitive.surface.md b/packages/vessel-light/.ghost/primitive.surface.md deleted file mode 100644 index 3c9630e4..00000000 --- a/packages/vessel-light/.ghost/primitive.surface.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -description: Backgrounds, borders, radius, shadow, and overlays — gather for any card, popover, modal, dialog, or scrim; the only route to elevation. -materials: - - materials/primitives.css - - materials/ref/composition.overlay.html - - "**/*.html" - - "**/*.css" ---- - -Surface is the only way an element gets a background, border, radius, or shadow. If a container needs visual treatment, it first needs a surface role. - -The vocabulary is closed: role, padding, radius, border, and elevation. These axes create enough range for page flow, cards, popovers, muted blocks, accents, and dark moments without inventing one-off boxes. - -The default surface is flat: no border, no shadow. Vessel does not outline everything to prove layout exists. - -Elevation implies hierarchy. A card sits in the document flow. A popover floats above the flow. A modal interrupts the task. Do not pair a low-shadow treatment with an interrupting role or give a routine card modal gravity. - -Borders are structural, especially for inputs and overlays. They are not decorative frames around ordinary text. - -The overlay reference shows the interrupting end of the system: background scrim, modal radius, modal shadow, compact header, clear footer. Copy its hierarchy when a user must stop and decide. diff --git a/packages/vessel-light/.ghost/primitive.text.md b/packages/vessel-light/.ghost/primitive.text.md deleted file mode 100644 index e1e7288a..00000000 --- a/packages/vessel-light/.ghost/primitive.text.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -description: Pick text from the closed variant and tone set; build hierarchy through tone and weight before size. -materials: - - materials/primitives.css ---- - -Every piece of text chooses a variant: display, headline, title, body, label, or mono. Text outside the scale is a broken primitive. - -Variant names are jobs, not decoration. Display leads a rare editorial moment. Headline names a section. Title anchors a card, dialog, or compact region. Body carries reading. Label names structure. Mono carries code and machine detail. - -Tone is part of the message. Default is the main reading plane. Muted carries secondary information. Inverse is for dark or primary surfaces. Success, warning, info, and destructive appear only when the words have that state meaning. - -Hierarchy starts with tone and weight before size. A secondary note usually wants muted body or label, not a smaller custom font. - -Balanced text is for headings and compact marketing-like statements. Do not balance long body copy into jagged reading. - -If the prose needs emphasis, improve the sentence before adding a style. diff --git a/packages/vessel-light/.ghost/register.data-density.md b/packages/vessel-light/.ghost/register.data-density.md new file mode 100644 index 00000000..85adfcaf --- /dev/null +++ b/packages/vessel-light/.ghost/register.data-density.md @@ -0,0 +1,39 @@ +--- +description: "Data-dense consoles — gather for tables, dashboards, logs, and monitoring; compresses product rhythm to the two smallest gap steps, mono numerals, muted-first." +materials: + - materials/ref/composition.table.html + - materials/primitives.css +--- + +Condition: this node applies to data-dense surfaces — tables, dashboards, +transaction logs, and admin consoles. + +Data density inverts the settings-page rhythm. Operators need scan speed +before they need breathing room. + +Use the two smallest gap steps (`--gap-xs`, `--gap-sm`) where forms use the +medium step. Tight adjacency is meaning when rows compare against rows. + +Numerals are mono so columns align. A ragged amount column is a broken +instrument. + +Hierarchy is muted-first. Data is the default plane, labels are muted, and +emphasis is rare enough to stay useful. + +Data surfaces take the small radius. A surface-radius table cell is costume — +the signature radius (see signature.shape) belongs on cards, not cells. + +Status is a text label with at most one functional color family per view. + +Charts inside a console follow the product carve-out from the palette +signature: expression hues live inside the plot area only. Outside the plot, +the one-status-hue cap holds — chart color never leaks into rows, badges, or +headers. More status color turns monitoring into confetti. + +No zebra striping. Hairline borders carry rows with less noise and more +trust. + +Hover confirmation uses the fast duration. It should acknowledge targeting, +not animate the table. + +Generous whitespace is drift here. Wasted density makes operators scroll. diff --git a/packages/vessel-light/.ghost/register.editorial.md b/packages/vessel-light/.ghost/register.editorial.md new file mode 100644 index 00000000..27fd2602 --- /dev/null +++ b/packages/vessel-light/.ghost/register.editorial.md @@ -0,0 +1,41 @@ +--- +description: "Editorial and landing surfaces — gather for heroes, marketing pages, pull quotes, and full-bleed dark moments; inverts product type restraint." +materials: + - materials/ref/composition.editorial.html + - materials/tokens.css +--- + +Condition: this node applies to marketing, landing, and editorial surfaces — +never to product UI. + +Editorial surfaces invert the product type rules. Display scale is not an +indulgence here; it is the job. + +Use the `--heading-display-*` tokens — size, line height, and weight — when +the words are the composition. The display tier belongs to this register (see +signature.type for the scale's character). + +Section rhythm uses `--section-padding-vertical`, not a product stack +stretched until it looks important. + +The sanctioned dramatic moment is the full-bleed dark section. Use the +`--surface-dark-*` family and let contrast carry the scene. + +Pull quotes are visual punctuation for longform. They interrupt reading with +judgment, not decoration. + +The tracked uppercase label is the kicker grammar. It gives the page a hard +editorial edge before the headline lands. + +Monochrome remains the spine, but editorial is the loud end of the expression +ladder (see signature.palette): up to two expression hues per page as +atmosphere — a tinted dark section, a colored pull-quote accent, a duotone +image moment. Commit to few colors at scale; variety is where expression +collapses into decoration. + +There is one primary action per page, and it keeps the control radius from +signature.shape. Editorial confidence does not excuse competing calls to +action. + +A hero built at product scale reads as timid. Timidity is drift here, exactly +as spectacle is drift in product UI. diff --git a/packages/vessel-light/.ghost/register.email.md b/packages/vessel-light/.ghost/register.email.md new file mode 100644 index 00000000..3517f07e --- /dev/null +++ b/packages/vessel-light/.ghost/register.email.md @@ -0,0 +1,43 @@ +--- +description: "Transactional email — gather ONLY for email; inverts the token contract: inline styles, hardcoded hex transcribed from tokens.css, table layout, system fonts." +materials: + - materials/ref/email.html +--- + +Condition: this node applies only to email. In any other medium, everything +below is a violation. + +Email clients do not honor the web contract. Custom properties, external +stylesheets, flex layout, and webfonts are unreliable materials here. + +Email inverts the material contract deliberately. Transcribe token values by +hand instead of referencing tokens — every hex below is a transcription of +`materials/tokens.css`, which stays the single source; if a token changes, +re-transcribe. + +Use `#1a1a1a` (`--color-gray-900`, foreground) for text, `#999999` +(`--color-gray-500`, muted) for muted text, and `#e8e8e8` (`--color-gray-200`, +border) for borders when the email needs the Vessel palette. + +Keep the surface radius on cards and the control radius on buttons (see +signature.shape). The values survive even when the token names cannot travel. + +Build with table layout, a 600px wrapper, predictable cells, and bulletproof +buttons. Email fidelity is made from boring structure. + +HK Grotesk falls back to the system stack. The voice must survive without the +font file. + +The soul survives the body swap: monochrome spine, quiet factual copy, one +primary action, no celebration. + +Email gets exactly one expressive moment: a header band or the figure that +matters, in one expression hue, transcribed by hand like every value here — +amber is `#f6b44a` (`--expression-1`). One moment, one hue. A receipt is +allowed one degree of warmth; it is not allowed a palette. + +Do not add further color to compensate for email constraints. Constraint is +not permission to perform. + +Hardcoding hex here is fidelity, not drift. The check exemption is the +condition itself. diff --git a/packages/vessel-light/.ghost/signature.palette.md b/packages/vessel-light/.ghost/signature.palette.md new file mode 100644 index 00000000..1669e57e --- /dev/null +++ b/packages/vessel-light/.ghost/signature.palette.md @@ -0,0 +1,45 @@ +--- +description: "Gather whenever color beyond the base roles is in question, in any register. The palette dial: a monochrome spine plus a closed expression set whose volume rises with the register — this brand's current answer is gray plus five named hues." +materials: + - materials/tokens.css +--- + +This is Vessel's answer to palette — it stands until you replace it. + +The relationship is fixed: one brand at different volumes. A monochrome spine +is the default atmosphere in every medium — calm, legible, and resistant to +novelty — and a closed expression set supplies the atmosphere, with volume +set by register, never by taste. + +Vessel's current answer: the base palette is monochrome gray, and the +expression palette is five named hues and only these — amber +(`--expression-1`), periwinkle (`--expression-2`), clay (`--expression-3`), +orchid (`--expression-4`), sage (`--expression-5`). Expressive color outside +this set is not expression; it is another brand. An invented hue is not a +bolder Vessel; it is a different brand. + +The volume ladder, by register: + +Product UI: expression lives only in data visualization. A chart may use the +hues; the interface around it stays monochrome. + +Data-dense consoles: one hue family may mark status. Nothing atmospheric. +Charts inside a console keep the product carve-out — hues stay inside the +plot area and never leak into rows, badges, or headers. + +Email: exactly one expressive moment per message — a header band or the +figure that matters. One hue, quiet everywhere else. + +Editorial: expression is sanctioned atmosphere — a tinted dark section, a +colored pull-quote accent, a duotone moment. Never more than two hues per +page. Loudness comes from commitment to few colors at scale, not variety. + +Two constants that outrank the ladder: expression never touches what you +click — buttons, inputs, and links stay monochrome in every register — and +the status roles are not expression; they keep their meanings everywhere and +never moonlight as atmosphere. + +To adapt: edit the `--expression-*` values (and the gray ramp, if the spine +changes) in `materials/tokens.css` and restate this node's current answer. +The ladder — a quiet spine, a closed hue set, register-gated volume — is the +part worth keeping. diff --git a/packages/vessel-light/.ghost/signature.shape.md b/packages/vessel-light/.ghost/signature.shape.md new file mode 100644 index 00000000..1ccd7f0f --- /dev/null +++ b/packages/vessel-light/.ghost/signature.shape.md @@ -0,0 +1,27 @@ +--- +description: "Gather before setting any radius or corner treatment. The shape dial: controls take --radius-control, surfaces take --radius-surface — this brand's current answer is pills on controls and a 20px signature radius on surfaces." +materials: + - materials/tokens.css + - materials/primitives.css +--- + +This is Vessel's answer to shape — it stands until you replace it. + +The relationship is fixed: controls and surfaces carry different radius +roles, and the two never swap. Buttons and text inputs use +`--radius-control`; cards and other surfaces use `--radius-surface`. + +Vessel's current answer: controls are pills (`--radius-control: 999px`) and +surfaces take the 20px signature radius (`--radius-surface: 20px`). The pill +is Vessel's most visible control signature; a rectangular button is not a +variant, it is a different design system. Never give a button the surface +radius — a rectangular button is the fastest tell that the output is not +Vessel. + +20px is a considered position: rounder than default shadcn, but not bubbly. +Use the radius system as restraint, not as decoration. + +To adapt: edit the `--radius-control` and `--radius-surface` values in +`materials/tokens.css` and restate this node's current answer. The +role split — one radius for what you click, one for what contains — is the +part worth keeping. diff --git a/packages/vessel-light/.ghost/signature.temperature.md b/packages/vessel-light/.ghost/signature.temperature.md new file mode 100644 index 00000000..88e7c498 --- /dev/null +++ b/packages/vessel-light/.ghost/signature.temperature.md @@ -0,0 +1,37 @@ +--- +description: "Gather for any copy and for motion character. The temperature dial: how the brand sounds and how it moves — this brand's current answer is factual, quiet, never celebratory, with resolved spring motion." +materials: + - materials/tokens.css +--- + +This is Vessel's answer to temperature — it stands until you replace it. + +The relationship is fixed: voice and motion carry the same temperature. Copy +states what happened, what is possible, or what the user must decide — it +does not perform personality — and motion confirms rather than entertains. + +Vessel's current answer in words: product UI is the default register — +factual, quiet, sentence case, and free of applause. No exclamation marks; +celebration is not reassurance. Confirmations are quiet: "Changes saved", +never "Awesome!" The system should sound reliable, not excited by basic +competence. Errors name the problem and the fix in the place where the user +can act; a vague failure banner is evasion. Buttons name the act — "Delete +account", "Save changes", "Invite member", not "Do it" or "Let's go". +Destructive copy is direct because the risk is direct; softening the verb +makes the interface less honest. Vessel never celebrates at the user. Trust +comes from precision, restraint, and naming the truth plainly. + +Vessel's current answer in motion: three durations — `--duration-fast`, +`--duration-normal`, `--duration-slow` — and one ease, `--ease-spring`, which +should feel resolved without feeling elastic. Hover confirms with color and +background shifts at the fast duration, not levitation. + +Condition: editorial surfaces switch register. Short declarative confident +fragments are correct in heroes and section headings. That same editorial +confidence is wrong in a settings form — product copy serves the task before +it serves the voice. Email copy uses the product voice: factual, not +campaign-like. + +To adapt: rewrite this node's current answers in your brand's voice and edit +the duration and ease values in `materials/tokens.css`. The coupling — words +and motion sharing one temperature — is the part worth keeping. diff --git a/packages/vessel-light/.ghost/signature.type.md b/packages/vessel-light/.ghost/signature.type.md new file mode 100644 index 00000000..c0c7b5b2 --- /dev/null +++ b/packages/vessel-light/.ghost/signature.type.md @@ -0,0 +1,37 @@ +--- +description: "Gather for any text, and for heroes, landing pages, and editorial moments. The type dial: one voice typeface plus a mono for machine detail, with an editorial heading scale kept separate from product text — this brand's current answer is HK Grotesk." +materials: + - materials/tokens.css + - materials/fonts/*.woff2 +--- + +This is Vessel's answer to type — it stands until you replace it. + +The relationship is fixed: one typeface is the voice of the interface, +everywhere, with a mono variant only for code, tool detail, and machine +output. The heading scale is editorial — its tokens exist for pages composed +outside the text variants — and product UI never mixes the two vocabularies +in one view. + +Vessel's current answer: HK Grotesk. vessel-light ships it as its embedded +voice; the React package currently falls back to system-ui. This fingerprint +is the intended future — here, `tokens.css` is canonical. + +The heading scale is editorial: display, section, sub, and card each carry +their own rhythm (`--heading-display-*`, `--heading-section-*`, +`--heading-sub-*`, `--heading-card-*`). Display sizes use tight tracking and +sub-1 line heights because the words behave like composition, not paragraph +text. + +Labels are small, semibold, and tracked wide. They should feel precise, never +loud. Body text keeps the established reading sizes with relaxed line height; +do not shrink important prose until it becomes legal copy. + +Condition: display and section scale are for editorial or hero moments. +Product UI lives in headline, title, body, label, and mono. A modal title is +not a poster. When in doubt, make type quieter and layout clearer. + +To adapt: swap the font files, edit `--font-sans`, `--font-mono`, and the +heading tokens in `materials/tokens.css`, and restate this node's current +answer. The one-voice rule and the editorial/product vocabulary split are the +parts worth keeping. From ee58af1995e4cc46cd61d8551d16a0384e186564 Mon Sep 17 00:00:00 2001 From: Nahiyan Khan Date: Thu, 9 Jul 2026 01:16:42 -0400 Subject: [PATCH 3/6] =?UTF-8?q?checks:=20relationship/value=20split=20?= =?UTF-8?q?=E2=80=94=20density.md=20retired,=20median-tells=20gains=20demo?= =?UTF-8?q?ted=20rules,=20frequency=20thresholds,=20model-named=20tells?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vessel-light/.ghost/checks/density.md | 35 ----------- .../.ghost/checks/median-tells.md | 62 ++++++++++++++++--- .../.ghost/checks/relationships.md | 32 ++++++++++ packages/vessel-light/.ghost/checks/values.md | 50 +++++++++++++++ 4 files changed, 135 insertions(+), 44 deletions(-) delete mode 100644 packages/vessel-light/.ghost/checks/density.md create mode 100644 packages/vessel-light/.ghost/checks/relationships.md create mode 100644 packages/vessel-light/.ghost/checks/values.md diff --git a/packages/vessel-light/.ghost/checks/density.md b/packages/vessel-light/.ghost/checks/density.md deleted file mode 100644 index b3510655..00000000 --- a/packages/vessel-light/.ghost/checks/density.md +++ /dev/null @@ -1,35 +0,0 @@ ---- -name: Density and token discipline -description: Flags decorative color, raw values, and invented shadows that break Vessel's monochrome-first token contract and register expression budgets. -severity: high -references: - - anti-goal.median - - grammar.color-roles - - grammar.surfaces - - grammar.rhythm - - grammar.hierarchy - - signature.palette - - signature.shape ---- - -Review changed HTML and CSS by view, not just by file. - -Classify the register of each changed view first: table layout, `bgcolor`, or a 600px wrapper means email; display-scale headings, `--section-padding-vertical`, or `--surface-dark-*` means editorial; compressed 4/8px gaps with mono numerals means data-density; otherwise product. - -Count distinct non-gray colors visible in each view, then judge against that register's expression budget: product views get one functional accent, with expression hues permitted only inside chart or visualization markup; data consoles get one status hue family, with the same chart carve-out inside the plot area; email gets one expressive moment in one hue; editorial pages get at most two expression hues. Flag anything over budget, and flag expression hues used atmospherically outside their register. Status colors count toward the total unless the view compares two or more distinct statuses side by side (for example a status column). - -Flag any color that is neither a gray, a status token, nor one of the five expression hues (`--expression-1` through `--expression-5`, or their hex values in email). Invented hues are drift in every register. - -Flag expression hues on buttons, inputs, or links in every register. Controls stay monochrome; no budget covers them. - -Flag raw hex, rgb, hsl, or named color values in changed CSS or inline styles when a Vessel token could express the same role. The authoring vocabulary is semantic tokens, not literal color. Exception: email files — hardcoded values transcribed from tokens are the contract there; flag only values that correspond to no token and no expression hue. - -Flag `box-shadow` values that do not use the elevation tier variables (`--shadow-card`, `--shadow-popover`, `--shadow-modal`) or the component shadows owned by a primitive (`--shadow-btn`, `--shadow-mini`, `--shadow-kbd`). Do not accept a custom shadow because it is visually close. - -Flag buttons or text inputs that are not pill-radius. A rectangular control is a token violation, not a style choice. - -Flag more than one primary-variant button per view. Secondary actions step down to secondary, outline, ghost, or link. - -Flag `margin` set on siblings inside a stack in changed CSS or inline styles. Rhythm comes from the gap scale; recommend changing the stack gap or splitting the stack. - -Flag borders, fills, gradients, glass effects, or colored accents used to make ordinary structure feel designed. Recommend semantic surfaces, stack spacing, text tone, or the existing elevation tier instead. diff --git a/packages/vessel-light/.ghost/checks/median-tells.md b/packages/vessel-light/.ghost/checks/median-tells.md index e678598f..1570e0ed 100644 --- a/packages/vessel-light/.ghost/checks/median-tells.md +++ b/packages/vessel-light/.ghost/checks/median-tells.md @@ -1,6 +1,6 @@ --- name: Median tells -description: Flags the measured defaults of unsteered generation — hover-lift, default accents, unprompted dark theme, chat bubbles, emoji icons, stock copy. +description: Flags the measured defaults of unsteered generation and current model-signature tells — hover-lift, default accents, unprompted dark theme, gradient text, frequency tells, and per-model signatures. severity: high references: - anti-goal.median @@ -9,30 +9,74 @@ references: --- These flags target the measured convergence patterns of unsteered model -generation. Each is mechanically detectable in a diff. +generation, plus tells specific to individual models. Each is mechanically +detectable in a diff. Pruning a rule from `anti-goal.median` orphans its +paired flag here — delete both together. Flag `transform` with `translateY` inside a `:hover` rule on cards, buttons, or list items, especially paired with a shadow increase. Hover confirmation in Vessel is color and background change, not lift. +(`anti-goal.median > rule:median-hover-lift`) -Flag accent values in the indigo/blue default family (`#4f46e5`, `#6366f1`, -`#2563eb`, `#3b82f6`, and close neighbors) unless the diff shows the user -asked for them. They are model defaults, not palette members. +Flag accent values in the indigo/blue/purple default family (`#4f46e5`, +`#6366f1`, `#2563eb`, `#3b82f6`, `#8b5cf6`, and close neighbors) unless the +diff shows the user asked for them. They are model defaults, not palette +members. (`rule:median-indigo-accent`) Flag whole-page dark backgrounds when the ask did not request dark mode. Dark surfaces in Vessel are the editorial dark band or an explicit `.dark` -theme, never an unprompted default. +theme, never an unprompted default. (`rule:median-dark-theme`) Flag `linear-gradient` or `radial-gradient` as page or section backgrounds, -and gradient-filled buttons. Also flag `backdrop-filter: blur` used for -glassmorphism cards. +and gradient-filled buttons. (`rule:median-gradients`) + +Flag `backdrop-filter: blur` used for glassmorphism cards. +(`rule:median-glassmorphism`) + +Flag `background-clip: text` (with or without the `-webkit-` prefix) paired +with a gradient. Emphasis comes from weight or size in a single solid color. + +Flag a thick colored border on one side of an element (`border-left` or a +`border-l-*` utility at 2px or more in a non-neutral color) while the other +sides stay thin. (`rule:median-side-stripe`) + +Flag warm off-white page backgrounds in the cream/sand/beige band, and token +names like `--cream`, `--sand`, `--parchment`, `--linen` introduced by the +diff. (`rule:median-cream-surface`) Flag assistant messages rendered as bubbles with initials-circle avatars. -Flag emoji used as icons or imagery in interface chrome. +(`rule:median-chat-bubbles`) + +Flag emoji used as icons or imagery in interface chrome. Text labels carry +meaning. Flag stock template copy in headings: "Simple, transparent pricing", "Welcome back", and interchangeable-with-a-competitor phrasing. Recommend copy that states what this product specifically does. +(`rule:median-stock-copy`) + +Frequency tells — the crime is repetition, not the move (advisory): + +Flag three or more uppercase, tracked eyebrow kickers above section headings +in one page. One named kicker is voice; a kicker on every section is model +grammar. (`rule:median-eyebrow-kicker`) + +Flag five or more em-dashes in body copy in one view. + +Flag three or more instances of the aphoristic rebuttal cadence ("Not X. Y." +/ "Sentence. No qualifiers.") in one page's copy. + +Model-signature tells — skip any block whose model did not produce the diff +(advisory): + +Codex: flag a 1px border paired with a box-shadow of 16px blur or more on +the same element — pick a solid border or a tight shadow, not both. Flag +border-radius of 32px or more on cards, sections, or inputs. Flag 1px +linear-gradient grid or repeating-stripe backgrounds used as decoration. + +Gemini: flag `transform` (scale, rotate, translate) on `img` inside a +`:hover` rule, including group-hover utilities targeting a child image. +Animate the card's background, border, or shadow instead. Do not flag pill-shaped controls or fluid clamp display headings — those median patterns are deliberately shared by Vessel and their presence is diff --git a/packages/vessel-light/.ghost/checks/relationships.md b/packages/vessel-light/.ghost/checks/relationships.md new file mode 100644 index 00000000..29ecb88b --- /dev/null +++ b/packages/vessel-light/.ghost/checks/relationships.md @@ -0,0 +1,32 @@ +--- +name: Relationship discipline +description: Flags structural violations of the grammar — emphasis-ladder breaks, sibling margins, decorative borders, nested cards. These rules survive any rebrand. +severity: high +references: + - grammar.hierarchy + - grammar.rhythm + - grammar.surfaces +--- + +These assertions test relationships between token roles, not the values behind +them. They hold for any brand built on this grammar; a fork keeps this check +unchanged. + +Flag more than one primary-variant button per view. Secondary actions step +down the emphasis ladder: secondary, outline, ghost, or link. + +Flag `margin` set on siblings inside a stack in changed CSS or inline styles. +Rhythm comes from the gap scale; recommend changing the stack gap or splitting +the stack. + +Flag borders, fills, gradients, glass effects, or colored accents used to make +ordinary structure feel designed. Recommend semantic surfaces, stack spacing, +text tone, or the existing elevation tier instead. + +Flag card-like surfaces nested inside card-like surfaces. One surface level +per region; interior hierarchy comes from spacing and type, not another +container. + +Flag `box-shadow` values that belong to no declared elevation tier and no +component-owned shadow. Do not accept a custom shadow because it is visually +close to a tier — elevation is a closed set, whatever the values are. diff --git a/packages/vessel-light/.ghost/checks/values.md b/packages/vessel-light/.ghost/checks/values.md new file mode 100644 index 00000000..031e2d40 --- /dev/null +++ b/packages/vessel-light/.ghost/checks/values.md @@ -0,0 +1,50 @@ +--- +name: Value discipline +description: Flags off-signature values — non-pill controls, off-palette hues, raw color literals, expression over budget. A fork rewrites this check alongside the signature nodes. +severity: high +references: + - signature.shape + - signature.palette + - register.data-density + - register.editorial + - register.email +--- + +These assertions test Vessel's current answers to the signature dials. A +rebrand that changes the dials rewrites this check with them; the paired +relationship check stays. + +Review changed HTML and CSS by view, not just by file. Classify the register +of each changed view first: table layout, `bgcolor`, or a 600px wrapper means +email; display-scale headings, `--section-padding-vertical`, or +`--surface-dark-*` means editorial; compressed smallest-gap-step layouts with +mono numerals means data-density; otherwise product. + +Flag buttons or text inputs that are not pill-radius (`--radius-control`). +A rectangular control is a token violation, not a style choice. + +Flag surfaces that carry a radius other than `--radius-surface`, and radius +roles swapped across the boundary: control radius on a surface, surface +radius on a control. + +Count distinct non-gray colors visible in each view, then judge against that +register's expression budget: product views get one functional accent, with +expression hues permitted only inside chart or visualization markup; data +consoles get one status hue family with the same chart carve-out; email gets +one expressive moment in one hue; editorial pages get at most two expression +hues. Flag anything over budget, and flag expression hues used +atmospherically outside their register. Status colors count toward the total +unless the view compares two or more distinct statuses side by side. + +Flag any color that is neither a gray, a status token, nor one of the five +expression hues (`--expression-1` through `--expression-5`, or their hex +values in email). Invented hues are drift in every register. + +Flag expression hues on buttons, inputs, or links in every register. Controls +stay monochrome; no budget covers them. + +Flag raw hex, rgb, hsl, or named color values in changed CSS or inline styles +when a Vessel token could express the same role. The authoring vocabulary is +semantic tokens, not literal color. Exception: email files — hardcoded values +transcribed from tokens are the contract there; flag only values that +correspond to no token and no expression hue. From 62db05cbd95f2ea798fa980f0345f50495323651 Mon Sep 17 00:00:00 2001 From: Nahiyan Khan Date: Thu, 9 Jul 2026 01:28:18 -0400 Subject: [PATCH 4/6] =?UTF-8?q?materials:=20regenerate=20refs=20=E2=80=94?= =?UTF-8?q?=20annotated,=20closed-set=20complete?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../.ghost/materials/primitives.css | 13 +++ .../ref/composition.conversation.html | 16 ++- .../materials/ref/composition.editorial.html | 17 ++- .../materials/ref/composition.form.html | 106 ++++++++++++------ .../materials/ref/composition.overlay.html | 33 +++++- .../materials/ref/composition.table.html | 6 +- .../.ghost/materials/ref/email.html | 25 ++++- packages/vessel-light/demo/README.md | 2 +- packages/vessel-light/demo/asks.md | 12 +- 9 files changed, 164 insertions(+), 66 deletions(-) diff --git a/packages/vessel-light/.ghost/materials/primitives.css b/packages/vessel-light/.ghost/materials/primitives.css index a8304d3d..999159b4 100644 --- a/packages/vessel-light/.ghost/materials/primitives.css +++ b/packages/vessel-light/.ghost/materials/primitives.css @@ -258,6 +258,19 @@ body { color: var(--foreground); border-color: var(--input); } +.button--link { + padding-inline: 4px; + background: transparent; + color: var(--foreground); + text-decoration: underline; + text-underline-offset: 3px; + transition: color var(--duration-fast) var(--ease-spring); +} +.button--link:hover { + background: transparent; + color: var(--muted-foreground); + box-shadow: none; +} .button--size-xs { height: 24px; padding: 4px 8px; diff --git a/packages/vessel-light/.ghost/materials/ref/composition.conversation.html b/packages/vessel-light/.ghost/materials/ref/composition.conversation.html index 0bf293d4..7d7e9a5b 100644 --- a/packages/vessel-light/.ghost/materials/ref/composition.conversation.html +++ b/packages/vessel-light/.ghost/materials/ref/composition.conversation.html @@ -1,3 +1,7 @@ + @@ -18,7 +22,7 @@
-
+

Can you make the billing page feel calmer without losing the upgrade prompt?

@@ -27,19 +31,19 @@

The page should feel like account infrastructure first, promotion second.

-
-
+
+ Inspecting tokens Completed -
+
read packages/vessel/src/components/billing-card.tsx
-
+

Use one card surface for the current plan, muted rows for secondary facts, and a primary action only where the user can commit. Keep helper copy short and concrete.

-
+

Show me the smallest set of changes.

diff --git a/packages/vessel-light/.ghost/materials/ref/composition.editorial.html b/packages/vessel-light/.ghost/materials/ref/composition.editorial.html index c614775f..ba68d064 100644 --- a/packages/vessel-light/.ghost/materials/ref/composition.editorial.html +++ b/packages/vessel-light/.ghost/materials/ref/composition.editorial.html @@ -1,3 +1,7 @@ + @@ -21,7 +25,8 @@ .dark-muted { color: var(--surface-dark-muted); } .feature-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(calc(var(--page-container-side-gutter) * 12), 1fr)); gap: var(--section-heading-margin-bottom); } .feature { border-top: 1px solid var(--surface-dark-border); padding-top: var(--page-container-side-gutter); } - .pullquote { max-width: calc(var(--page-container-side-gutter) * 48); margin: 0; font-size: var(--pullquote-size); font-weight: var(--pullquote-weight); line-height: var(--pullquote-line-height); letter-spacing: var(--pullquote-letter-spacing); border-left: 3px solid var(--expression-1); padding-left: var(--page-container-side-gutter); } + .pullquote { max-width: calc(var(--page-container-side-gutter) * 48); margin: 0; font-size: var(--pullquote-size); font-weight: var(--pullquote-weight); line-height: var(--pullquote-line-height); letter-spacing: var(--pullquote-letter-spacing); padding-left: var(--page-container-side-gutter); position: relative; } + .pullquote::before { content: "\201C"; position: absolute; left: 0; top: 0; color: var(--expression-1); font-size: var(--pullquote-size); line-height: 1; } @@ -35,20 +40,20 @@

Make every generated screen ans
-

A small set of primitives carries the whole system.

+

A small set of primitives carries the whole system.

-

Density

+

Density

Compact by default

Controls stay close to their labels. Surfaces reserve padding for decisions, not decoration.

-

Restraint

+

Restraint

Monochrome first

Contrast, rhythm, and type scale do the work before color is asked to explain status.

-

Trust

+

Trust

Every action is explicit

Buttons name the commitment. Secondary copy clarifies consequence without trying to persuade.

@@ -57,7 +62,7 @@

Every action is explicit

-
“The interface should feel authored even when an agent produced the first pass.”
+
The interface should feel authored even when an agent produced the first pass.

diff --git a/packages/vessel-light/.ghost/materials/ref/composition.form.html b/packages/vessel-light/.ghost/materials/ref/composition.form.html index 9049fcc0..87996e81 100644 --- a/packages/vessel-light/.ghost/materials/ref/composition.form.html +++ b/packages/vessel-light/.ghost/materials/ref/composition.form.html @@ -1,3 +1,7 @@ + @@ -12,44 +16,74 @@ -
- -
-

Workspace settings

+
+
+
+

Workspace settings

Tune the defaults your team sees when Vessel drafts interface work.

-
- -
-
- - -
- -
- - -

Use a verified sender before inviting collaborators.

-
- -
- Default density -
- Comfortable - +
+ +
+ +
+ +
+

Profile

+

These values appear on receipts, invites, and review packets.

+
+ +
+
+ + +
+ +
+ + +

Use a verified sender before inviting collaborators.

+
+ +
+ Default density +
+ Comfortable + +
+
+ + +
+ +
+ API access +
+ vsl_live_4f8a…03c2 + +
+

Regenerating invalidates the key currently in use by integrations.

+
+ +
+
+ Delete this workspace + Removes every fingerprint and review record immediately. +
+ +
+ +
- - - - -
- - -
- + + + diff --git a/packages/vessel-light/.ghost/materials/ref/composition.overlay.html b/packages/vessel-light/.ghost/materials/ref/composition.overlay.html index 2a70ab92..f5ed74e7 100644 --- a/packages/vessel-light/.ghost/materials/ref/composition.overlay.html +++ b/packages/vessel-light/.ghost/materials/ref/composition.overlay.html @@ -1,3 +1,7 @@ + @@ -7,24 +11,45 @@ +
+
+

Fingerprint

+ +
+

Three nodes changed since the last publish. Review the diff, then publish from the actions menu.

+ + + +
+ +