# Design System and Experience Quality

The Oshun V1 design system is the shared visual, behavioral, and copy foundation
that every customer and admin surface is built on. It is not a style guide that
lives in a deck — it ships as real, tested TypeScript: design tokens
(`libs/oshun/design-tokens`), a reusable component library (`libs/oshun/ui`),
the localization catalog (`libs/oshun/i18n`), and a suite of _auditable_
design-language modules (`libs/oshun/design-language`) that encode the rules an
engineer or reviewer can query and a test can enforce. This page sits in the
platform-quality area alongside
[Analytics, Observability, Testing, and Security](./analytics-and-testing.md);
together they describe how Oshun makes the product feel calm, consistent,
accessible, and honest about AI. The companion architecture page is
[Architecture, Platform Foundations, and Security](./platform-foundations-and-security.md).

## What the design system is, and where it lives

V1 deliberately splits the design system into four cooperating packages so that
"the rules" are independently testable from "the components" and from "the
words":

| Concern                                         | Package                      | What it ships                                                         |
| ----------------------------------------------- | ---------------------------- | --------------------------------------------------------------------- |
| Tokens (color, type, spacing, motion, behavior) | `libs/oshun/design-tokens`   | `oshunTokenSchema`, themes, and behavior tokens                       |
| Reusable components                             | `libs/oshun/ui`              | 21 React components plus `motion/` and `theme/` subpackages           |
| Localized strings and formatting                | `libs/oshun/i18n`            | `CUSTOMER_MESSAGES` catalog, `translate()`, locale formatting         |
| Design-language rules and audits                | `libs/oshun/design-language` | scorecards, ergonomics, voice/tone, disclosure copy, visual-QA claims |

The web app (`apps/oshun/web`) consumes all four: tokens drive its theme,
`@oshun/ui` provides the components, `next-intl` wires the localized messages
(`apps/oshun/web/src/i18n/request.ts` and `apps/oshun/web/src/i18n/config.ts`),
and the design-language audits gate the design-review checklist.

## Product language and information architecture

V1 design begins with a single product thesis encoded in
`libs/oshun/design-language/src/index.ts` as `TARA_CENTERED_PRODUCT_LANGUAGE`:
"Oshun starts from Tara practice: calm attention first, then evidence, sky
context, habits, texts, and learning." The voice is `plain`, `source-aware`,
`non-shaming`, `specific`, and `quietly confident`; the _prohibited_ registers
are explicitly `growth pressure`, `fear-led prompts`, `unattributed certainty`,
and `operator jargon`. This is not decorative prose —
`assertSurfaceUsesTaraLanguage()` enforces that the home surface orders `tara`
first and that headlines avoid growth-pressure language, so a surface that
violates the thesis fails a test rather than merely a review.

The unified information architecture lives in `OSHUN_UNIFIED_IA`:

- **Customer shell:** `Home`, `Explore`, `Activity`, `Library`, `Assistant`,
  `Profile`.
- **Admin shell:** `Queues`, `Review`, `Policy`, `Incidents`, `Privacy`,
  `Models`, `Personas`, `Support`.
- **Journey models:** `morning Tara continuation`,
  `midday research-to-practice`, `evening sky-to-text`, `story-to-source`, and
  `assistant-led memory review`.

The customer/admin shell distinction is also a _visual_ distinction. The two
visual theses in `OSHUN_VISUAL_THESES` describe the customer surface as "a quiet
reading-and-practice workspace with Tara as the center, restrained chrome, clear
evidence affordances, and mobile-first continuity," and the admin surface as "a
dense operational console with scan-first hierarchy, hard audit edges, compact
queue states, and restrained color." These two theses explain almost every
density, color, and motion decision downstream — the customer shell trades
density for calm; the admin shell trades calm for scan speed.

For the customer-facing IA itself (Tara, Arete, Veritas, Nyx, Nisaba, Metis and
the cross-domain journeys), see the per-domain pages such as
[Tara — Rituals and Contemplative Practice](./domain-tara.md) and
[Nisaba — Scholarly Study](./domain-nisaba.md); the shell-level surfaces are
detailed in [Product Surfaces](./product-surfaces.md).

## Design tokens — the canonical foundation

`libs/oshun/design-tokens/src/tokens.ts` is the single source of truth for the
visual language. The canonical bundle is identified as
`OSHUN_V1_FOUNDATION_TOKEN_BUNDLE_ID = 'oshun-v1-foundation'` at version
`OSHUN_V1_FOUNDATION_TOKEN_BUNDLE_VERSION = '1.0.0'`, exported as the
`oshunV1Foundation` object.

### Color

The canonical V1 surface is a **cool, dark ink/teal-and-gold** system, not a
warm paper palette. `oshunTokenSchema.color` is built from six full 50–950
scales:

| Role    | Scale     | Anchor values                                      |
| ------- | --------- | -------------------------------------------------- |
| Neutral | `ink`     | `ink[500] = '#6E87A6'`, `ink[950] = '#040B16'`     |
| Neutral | `fog`     | `fog[500] = '#7386A2'`, `fog[950] = '#0D1628'`     |
| Brand   | `aqua`    | `aqua[500] = '#20C9D8'`, `aqua[600] = '#11A9B8'`   |
| Brand   | `amber`   | `amber[500] = '#F4A524'`, `amber[600] = '#DD8618'` |
| Status  | `success` | `success[500] = '#2AB673'`                         |
| Status  | `danger`  | `danger[500] = '#E24D4D'`                          |

The default theme is **dark**: `defaultOshunTheme = oshunThemes.dark`, and
`oshunThemes` provides all four named themes from `OshunThemeName` — `light`,
`dark`, `highContrastLight`, and `highContrastDark`. Theme resolution helpers
(`getSemanticTokens()`, `createCssVariables()`) default to the dark theme, and a
high-contrast resolver maps a "prefers high contrast" hint onto the
`highContrastLight`/`highContrastDark` variants.

> **Correction to older docs.** Earlier framing (e.g. `V1/ARCHITECTURE.md`
> around the Design System section) described the canonical surface as
> "cream-paper + terracotta." That is inverted. In the real tokens, cream-paper
> and terracotta are the **manuscript palette** used only for the _domain
> accents_, which the code itself describes as being "mapped into the Lilith
> register." The canonical neutrals/brand are the dark `ink`/`fog` and
> `aqua`/`amber` system above.

### Domain accents (the "Lilith register" / manuscript palette)

The domain accent hues live under `oshunTokenSchema.color.domain` (also exported
as `oshunDomainAccents`), and the source comment explains the intent directly:
each domain gets "a distinct hue from the manuscript palette … so the sidebar
reads as the same cream-paper-and-ink language as the rest of the surface."

| Domain    | Accent hex | Manuscript name         |
| --------- | ---------- | ----------------------- |
| `tara`    | `#5A7A3F`  | Lilith green            |
| `veritas` | `#9A3E1C`  | terracotta / burnt rust |
| `nyx`     | `#3B3325`  | ink-2                   |
| `arete`   | `#3F5E2B`  | deep green              |
| `nisaba`  | `#C89657`  | honey / tan             |
| `metis`   | `#6B5A44`  | tan-brown               |

How these accents may be _used_ is governed separately by
`oshunDomainAccentBehavior`, so the accent is a constrained signal (sidebar,
selection, domain header) rather than a free paint color. The translated
contemplative variants are applied at the persona-policy boundary — see
[Lilith Persona Policy](./lilith-persona-policy.md) and
[Persona, Avatar, and Voice Packs](./persona-avatar-voice-packs.md).

### Typography, spacing, motion, elevation

The non-color foundation tokens are exported as first-class constants:

- `oshunSpacingScale` — the numeric step scale that the semantic spacing tokens
  (`xxs … 3xl`) index into.
- `oshunFontWeights` (`regular`, `medium`, `semibold`, `bold`, `extrabold`) and
  `oshunTypographyRamp`, with the type families `Space Grotesk`/`Manrope`
  (display), `Manrope`/`Avenir Next` (body), and `IBM Plex Mono` (mono). The
  ramp runs `displayXl` (48/56) down through `labelSm` and `monoSm`.
- `oshunMotionDurationScale` and `oshunMotionTokens` (duration, easing,
  distance, scale) — motion is a token, so reduced-motion parity can be
  expressed by swapping tokens rather than rewriting components.
- `oshunElevationTokens` — a named shadow ramp (`none`, `xs`, `sm`, `md`, `lg`,
  `xl`, `inner`).
- Component radius ceilings: `radius.sm = 8` … `radius.pill = 999`. The
  experience-quality rules pin an "8px component radius ceiling" so the system
  stays calm rather than bubbly.

### Behavior tokens — the part most design systems leave to convention

The distinctive part of `design-tokens` is that _interaction behavior_ is itself
tokenized, not just appearance. These exported behavior objects encode the rules
for the trust-and-honesty surfaces V1 cares about most:

- `oshunGroundedEvidenceUiBehavior` — how evidence cards, source counts, and
  confidence bands present (pairs with
  [Sophia Grounding](./sophia-grounding.md)).
- `oshunDisclosureUiBehavior` — where and how AI disclosure appears.
- `oshunAssistantPersonaSwitchingUiBehavior` — how a persona switch is signaled.
- `oshunAvatarVoiceIdentityUiBehavior` — avatar/voice identity affordances.
- `oshunTrustSignalUiBehavior` — trust/confidence/provenance badges.
- `oshunReviewApprovalUiBehavior` and `oshunAdminStateUiBehavior` — review
  decisions, approval states, queue/severity/SLA states for the admin console.

## The component library (`@oshun/ui`)

`libs/oshun/ui/src/index.ts` re-exports three subpackages: `components/`,
`motion/`, and `theme/`. The component layer ships **21** real React components,
not a placeholder barrel:

| Group        | Components                                                      |
| ------------ | --------------------------------------------------------------- |
| Primitives   | `Box`, `Stack`, `Text`, `Button`, `IconButton`, `Chip`, `Badge` |
| Data display | `Card`, `ListRow`, `StatTile`                                   |
| Navigation   | `TopBar`, `BottomNav`, `DomainSwitcher`, `CommandPalette`       |
| Feedback     | `Banner`, `Toast`, `EmptyState`, `ErrorState`                   |
| Overlays     | `Modal`, `BottomSheet`, `ActionSheet`                           |

Each group has a paired `.stories.tsx` and `.test.tsx` (`primitives`,
`data-display`, `navigation`, `feedback`, `overlays`), and the whole surface is
exercised by `accessibility-snapshots.test.tsx`, which asserts the rendered
accessibility tree — so a regression that strips an accessible name or focus
affordance fails CI rather than slipping into a release.

Richer, domain-specific composites (evidence sidebar, claim/source/passage
items, notebooks, collections, admin queues, policy diffs, avatar/voice cards)
are tracked as catalog requirements (next section) and implemented across
`@oshun/ui` and the web design-system package.

## Design-language audit modules (`@oshun/design-language`)

This package turns design rules into queryable, testable data — the mechanism
that lets V1 claim design-system completeness without manually re-reading every
component barrel. `libs/oshun/design-language/src/index.ts` re-exports ten audit
modules, each versioned and each with a sibling `.test.ts`:

| Module                  | Key export                                                                                                                           | What it encodes                                                                                                                      |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| `component-catalog.ts`  | `OSHUN_COMPONENT_CATALOG` (`component-catalog-v1`)                                                                                   | Maps each required component to its canonical export, implementation path, test path, customer/admin scope, and required a11y checks |
| `scorecards.ts`         | `OSHUN_SURFACE_SCORECARDS`, `OSHUN_IMMERSIVE_VS_INSTRUMENTAL`                                                                        | Surface-by-surface quality scorecards; immersive-vs-instrumental guidance                                                            |
| `ergonomics.ts`         | `OSHUN_THUMB_ZONE_MODEL`, `OSHUN_DENSITY_TIERS`, `OSHUN_ERGONOMIC_BUDGETS`, `OSHUN_ONE_HANDED_SURFACE_CONTRACTS`                     | One-handed mobile thumb zones, layout-density tiers, ergonomic budgets                                                               |
| `responsive-system.ts`  | `OSHUN_BREAKPOINTS`, `OSHUN_CONTENT_MEASURE`, `OSHUN_READING_RHYTHM`                                                                 | Grid/gutter/max-width, reading measure and rhythm                                                                                    |
| `surface-language.ts`   | `OSHUN_IMAGERY_RULES`, `OSHUN_ILLUSTRATION_RULES`, `OSHUN_TEXTURE_RULES`, `OSHUN_AMBIENT_MEDIA_RULES`, `OSHUN_CARD_AVOIDANCE_RULES`  | Imagery/illustration/texture/ambient-media and the card-avoidance rules                                                              |
| `voice-and-tone.ts`     | `OSHUN_VOICE_TRAITS`, `OSHUN_PROHIBITED_COPY`, `OSHUN_VOICE_DO_DONT_PAIRS`, `OSHUN_ACCESSIBILITY_TONE_POLICIES`                      | The voice traits and prohibited-copy patterns, with do/don't pairs                                                                   |
| `ai-disclosure-copy.ts` | `OSHUN_DISCLOSURE_COPY`, `OSHUN_DISCLOSURE_SURFACE_RULES`, `OSHUN_AI_DISCLOSURE_PREFERRED_TERMS`, `OSHUN_AI_DISCLOSURE_BANNED_TERMS` | Canonical AI-disclosure copy and the terms you may/may not use                                                                       |
| `failure-copy.ts`       | `OSHUN_FAILURE_TEMPLATES`, `OSHUN_INCIDENT_TITLES`, title/body token budgets                                                         | Error/outage/fallback copy with word/sentence budgets                                                                                |
| `visual-qa.ts`          | `OSHUN_QA_VIEWPORTS`, `OSHUN_VISUAL_QA_CLAIMS` (`playwright-visual-qa-v1`)                                                           | The Playwright visual-QA checklist and viewport matrix                                                                               |
| `completion-audit.ts`   | `OSHUN_29X_COMPLETION_REQUIREMENTS`                                                                                                  | The 29.X design-system requirement audit                                                                                             |

### Why a catalog instead of "just look at the code"

`component-catalog.ts` exists, per its own header, so "completion can be
verified without manually reading barrels."
`OSHUN_REQUIRED_COMPONENT_REQUIREMENTS` enumerates the 22 required reusable
components from the feature list — `domain-switcher`, `continuity-card`,
`evidence-card`, `evidence-sidebar`, `claim-item`, `source-item`,
`passage-item`, `notebook`, `collection`, `assistant-disclosure`,
`memory-state`, `provenance-badge`, `admin-queue`, `admin-filter`,
`incident-severity`, `sla-timer`, `review-decision`, `policy-diff`, `avatar`,
`voice-pack`, `rights-summary`, `license-summary` — grouped into `navigation`,
`continuity`, `evidence`, `library`, `assistant`, `admin`, `policy`,
`embodiment`, and `rights`. Each `OshunComponentCatalogEntry` records its
`canonicalExport`, `implementationPath`, `testPath`, whether it appears in the
`customerShell` and/or `adminShell`, and the `requiredA11yChecks` (from
`accessible-name`, `keyboard`, `focus-visible`, `semantic-state`,
`screen-reader-copy`). A coverage function can then assert that every
requirement is met — turning "we have a component library" into a
machine-checked claim.

## Accessibility, copy, and ergonomics as first-class rules

The `OSHUN_EXPERIENCE_QUALITY_RULES` object fixes the non-negotiables:

- **Accessibility:** `visible focus`, `reduced motion parity`,
  `high-contrast tokens`, `screen-reader labels`. The high-contrast token
  requirement is satisfied by the `highContrastLight`/`highContrastDark` themes;
  reduced-motion parity is expressed through `oshunMotionTokens`.
- **Disclosure:** `body-copy disclosure`, `provenance link`, `confidence band`,
  `source count` — the AI-honesty quartet, backed by `oshunDisclosureUiBehavior`
  and the `OSHUN_DISCLOSURE_COPY`/`OSHUN_AI_DISCLOSURE_BANNED_TERMS` rules.
- **Layout:** `8px component radius ceiling`, `no nested cards`,
  `stable control dimensions`, `Tara-first home ordering` — the card-avoidance
  rule is enforced by `surface-language.ts`, the ordering by
  `assertSurfaceUsesTaraLanguage()`.
- **Mobile:** `one-handed primary actions`, `large tap targets`,
  `offline read fallback`, `handoff continuity` — the thumb-zone model and
  one-handed surface contracts in `ergonomics.ts` make this checkable per
  surface.

The copy rules deserve emphasis because they are the part most easily faked. AI
disclosure copy is canonical (`OSHUN_DISCLOSURE_COPY`) with explicit
`OSHUN_AI_DISCLOSURE_PREFERRED_TERMS` and `OSHUN_AI_DISCLOSURE_BANNED_TERMS`, so
a surface cannot, for example, call a generated answer "verified" when it is
"AI-assisted." Failure/outage copy is bounded by token budgets
(`OSHUN_FAILURE_TITLE_TOKEN_BUDGET = { minWords: 3, maxWords: 6 }`,
`OSHUN_FAILURE_BODY_TOKEN_BUDGET = { minSentences: 1, maxSentences: 2 }`) so
error states stay short, calm, and non-shaming under stress — the moment users
most need plain language.

## Localized strings and formatting (`@oshun/i18n`)

Localization is part of the design system, not an afterthought, because text
length and direction reshape layout. `libs/oshun/i18n/src/index.ts` is the
canonical catalog. (The web app layers `next-intl` on top —
`apps/oshun/web/src/i18n/config.ts` defines
`locales = OSHUN_LAUNCH_LANGUAGE_PREFERENCES` and derives `rtlLocales` from
`RTL_LOCALES` — but the shared catalog underneath is what guarantees coverage
and fallback.) For the full localization story see
[Taxonomy, Localization, and Versioning](./taxonomy-localization-versioning.md);
the design-system-relevant facts are:

- **Eight launch locales.**
  `OSHUN_LAUNCH_LOCALES = ['en-US','es-US','fr-FR', 'de-DE','ar','he','ja-JP','pt-BR']`,
  with `OSHUN_DEFAULT_LAUNCH_LOCALE = 'en-US'` and `RTL_LOCALES = {ar, he}`.
  `localeDirection()` returns `'rtl'` for Arabic and Hebrew so shells flip
  rather than break.
- **Text-expansion budgets drive layout QA.** `LOCALE_EXPANSION_BUDGET` records,
  per locale, how much longer than the `en-US` baseline a string may run while
  still fitting the same shell: `de-DE 1.4` (the widest), `fr-FR 1.3`,
  `pt-BR 1.3`, `es-US 1.25`, `ar 1.2`, `he 1.15`, and `ja-JP 0.7` (the only one
  that contracts). Layout QA verifies a `de-DE` label at 1.4x does not truncate
  or break a grid column.
- **A complete working catalog, not just "externalized strings."**
  `CUSTOMER_MESSAGES` is a frozen map of customer-facing keys — covering shell
  navigation, AI disclosures, memory state, evidence/provenance, offline states,
  errors, status, auth, and privacy — fully translated across all eight locales.
  The catalog is keyed message-first then locale-second precisely so per-key
  audits ("which locales does this key cover?") are trivial.
- **Translation with a defined fallback chain.**
  `translate(key, locale, options)` resolves through `resolveFallbackChain()` —
  requested locale → language-only locale → `en-US` (so `es-US` tries `es-US`,
  then `es`, then `en-US`). It returns a `TranslationResult` of
  `{ value, resolvedLocale, fallbackApplied }`, and emits a
  `TranslationFallbackEvent` when a fallback fired, so gaps are observable in
  telemetry rather than silent.
- **Critical messages are flagged.** `isCriticalMessageKey()` marks any key
  under the prefixes `assistant.disclosure.`, `evidence.`,
  `auth.minimum_version_required`, or `privacy.` as critical — a fallback on a
  legally or safety-relevant string (an AI disclosure, a provenance label, a
  consent notice) is treated differently from a fallback on a nav label.
- **Gap detection for launch readiness.** `findFallbackGaps()` walks every key
  against every locale and returns any `<key, locale>` pair that resolves via
  fallback rather than a direct hit — a non-empty result is a translation gap to
  close before launch.
- **Locale-aware formatting.** `formatForLocale()` produces date, time,
  date-time, timezone, currency, number, region, and relative-time strings using
  the platform `Intl.DateTimeFormat`, `Intl.NumberFormat`,
  `Intl.RelativeTimeFormat`, and `Intl.DisplayNames` with explicit options. All
  eight launch locales currently use the Gregorian calendar (`LOCALE_CALENDAR`);
  the Japanese imperial calendar is reserved for specific opted-in cultural
  surfaces.

## Visual QA and design review

Visual QA is encoded, not improvised. `visual-qa.ts` defines the viewport matrix
`OSHUN_QA_VIEWPORTS` and a list of `OSHUN_VISUAL_QA_CLAIMS`
(`playwright-visual-qa-v1`) that the design-review and Playwright-backed
checklist runs against — covering shell, domain, admin, and the
mobile/desktop/laptop/tablet/narrow-mobile states called for in the feature
list. Those claims feed the broader accessibility and Lighthouse CI coverage
tracked in
[Analytics, Observability, Testing, and Security](./analytics-and-testing.md),
which is also where the web performance budgets
(`apps/oshun/web/lighthouse-budget.json`) and the per-journey automation matrix
live.

### Honesty note

The token, component, i18n, and design-language modules described above are
real, sizeable, tested code in `libs/oshun/*`. What this page does **not**
assert is that a full live Lighthouse, axe, or Playwright sweep currently passes
on every route — the budget files and CI-coverage manifests exist, but a green
run is a property of CI at a given commit, not of these source files. Where a
claim is a process gate rather than shipped code, the
[analytics-and-testing.md](./analytics-and-testing.md) page says so explicitly.

## Related

- [Analytics, Observability, Testing, and Security](./analytics-and-testing.md)
  — performance budgets, accessibility/Lighthouse CI, and the QA matrix.
- [Taxonomy, Localization, and Versioning](./taxonomy-localization-versioning.md)
  — the broader localization, taxonomy, and versioning story.
- [Lilith Persona Policy](./lilith-persona-policy.md) and
  [Persona, Avatar, and Voice Packs](./persona-avatar-voice-packs.md) — where
  the translated contemplative register is applied.
- [Sophia Grounding](./sophia-grounding.md) — the evidence and confidence model
  behind the grounded-evidence behavior tokens.
- [Product Surfaces](./product-surfaces.md) — the customer/admin shells the
  design system renders into.
- [Architecture, Platform Foundations, and Security](./platform-foundations-and-security.md)
  — the companion platform/architecture page.
- [../features.md](../features.md) — feature hub.
