# Governance · Spec · v1.0

**Status:** universal quality gates that apply to ALL archetypes (Harbor, Sentinel, Current, Lattice, Meridian).

**Use:** paste this block FIRST into any prompt that produces components, tokens, or a spec page (Prompts 1, 03, 04, 05, 08, 09). Then paste your archetype spec second. Two pastes per prompt — non-negotiable.

**Origin:** universal a11y/quality requirements + lessons from [reference/design-system-spec-v1.html](../../reference/design-system-spec-v1.html) §6.

---

```
═══════════════════════════════════════════════════════════════
GOVERNANCE · UNIVERSAL · v1.0
Applies to ALL archetypes — paste before archetype spec
═══════════════════════════════════════════════════════════════

───────────────────────────────────────────────────────────────
ACCESSIBILITY GATES (WCAG 2.1)
───────────────────────────────────────────────────────────────
• Contrast ratios:
    - Body text:        ≥ 4.5:1 (AA), aim for AAA on primary body
    - Large text (18pt+ or 14pt bold): ≥ 3:1 (AA)
    - Non-text UI (icons, focus rings, chart elements): ≥ 3:1
    - Decorative-only elements: exempt
• Every spec page MUST include an Accessibility Verification
  table computed from the actual token values (FG / BG / Ratio /
  Status pill: AAA / AA / FAIL). Do not omit. Do not estimate.
• Failing combinations must be flagged with "FAIL — do not use"
  and an alternative pairing suggested.

───────────────────────────────────────────────────────────────
KEYBOARD NAVIGATION
───────────────────────────────────────────────────────────────
• Every interactive element reachable via Tab in DOM order
• Focus indicator visible: 2px outline, offset 2px,
  --color-focus-ring (defined per archetype)
• Standard key bindings honored:
    Enter / Space  → activate buttons, toggles, links
    Esc            → close dialogs, drawers, popovers, menus
    Arrow keys     → navigate within tabs, radio groups, menus,
                     and listboxes
    Home / End     → jump to first / last item in lists
    Tab / Shift+Tab → forward / back through focusable elements
• Focus trapping: required for modal dialogs, drawers, command
  palettes. Esc returns focus to trigger.
• Skip-to-content link required at top of every page.

───────────────────────────────────────────────────────────────
SCREEN-READER REQUIREMENTS
───────────────────────────────────────────────────────────────
• All icon-only buttons must have aria-label
• All form fields must have programmatic labels (label[for] or
  aria-labelledby — never placeholder-as-label)
• Live regions for toasts, async results, validation errors
  (aria-live="polite" default; "assertive" only for errors
  blocking task completion)
• Test matrix: VoiceOver (Safari/macOS), NVDA (Firefox/Win),
  TalkBack (Chrome/Android) for any component shipped to mobile
• Decorative SVGs: aria-hidden="true". Meaningful SVGs:
  role="img" + <title>.

───────────────────────────────────────────────────────────────
MOTION & ANIMATION
───────────────────────────────────────────────────────────────
• prefers-reduced-motion: reduce → fallback to fade-only or
  no animation. Never just shorten duration; remove transform
  animation entirely.
• No autoplay video or animated backgrounds without user
  consent.
• Vestibular safety: avoid parallax > 20% offset, scroll-jacking,
  spinning loaders > 2s without text label.

───────────────────────────────────────────────────────────────
TOKEN HYGIENE
───────────────────────────────────────────────────────────────
• Zero raw hex in component CSS. Every color, every size, every
  shadow goes through var(--token-name).
• Components reference SEMANTIC tokens, never primitives.
  Bad:  color: var(--color-blue-500);
  Good: color: var(--color-link);
• Both light and dark mode tokens defined for every semantic
  token, even if a mode is unshipped.
• Tokens declared in a single :root + [data-theme="dark"]
  override block. No tokens defined inside component scope.

───────────────────────────────────────────────────────────────
COMPONENT STATE COVERAGE
───────────────────────────────────────────────────────────────
Every interactive component must implement these states
(visually distinct, not just functionally present):
    default
    hover           (pointer devices only — :hover)
    focus-visible   (keyboard users — :focus-visible, NOT :focus)
    active          (pressed — :active)
    disabled        ([disabled] or aria-disabled="true")
    loading         (where applicable — async actions)
    error           (where applicable — validation/failure)
    success         (where applicable — confirmation states)

Form fields additionally implement:
    empty / filled / required / read-only

───────────────────────────────────────────────────────────────
ERROR-MESSAGE FORMULA (UNIVERSAL)
───────────────────────────────────────────────────────────────
Every error message follows What → Why → How:
    What: [what happened, plain language]
    Why:  [the cause]
    How:  [recovery action — concrete, doable]

  Bad:  "Invalid input."
        "Something went wrong. Try again."
  Good: "Email format isn't recognized. Try name@example.com."
        "Upload failed. The file is over 10MB.
         Try compressing it."

Banned: stack traces in user-facing copy, error codes without
explanation, generic "Oops!" / "Whoops!" messaging.

───────────────────────────────────────────────────────────────
COPY HYGIENE (UNIVERSAL)
───────────────────────────────────────────────────────────────
• Sentence case for headings, buttons, labels (not Title Case,
  not ALL CAPS — except for an "overline" eyebrow style)
• No emoji in UI copy. SVG icons only. (Emoji acceptable in
  user-generated content rendering.)
• Contractions allowed (we'll, don't, can't) — softer voice
• Verb-first CTAs ("Save changes", not "Changes can be saved")
• Banned filler: "Please", "Kindly", "Just", "Simply"
• Banned marketing fluff in product UI: "Let's embark on…",
  "Unlock the power of…", "Revolutionize your workflow"

───────────────────────────────────────────────────────────────
ICONOGRAPHY (UNIVERSAL FLOOR)
───────────────────────────────────────────────────────────────
• SVG only. Inline preferred for color inheritance.
• fill="currentColor" or stroke="currentColor" — never hex
• aria-hidden="true" for decorative; <title> for meaningful
• Consistent grid (24px standard; archetype may override)
• Consistent stroke width within a family
• Never mix icon families on the same surface
• Banned: emoji as icon, raster (.png) icons, animated GIF icons

───────────────────────────────────────────────────────────────
VERSIONING
───────────────────────────────────────────────────────────────
SemVer (MAJOR.MINOR.PATCH):
    MAJOR — breaking token rename, removed component, breaking
            API change
    MINOR — new component, new variant, new token, deprecation
            notice
    PATCH — bug fix, doc update, non-visual refactor

Deprecation policy: deprecated tokens/components ship for
2 MINOR versions before removal. Deprecation warnings logged
in console at build time.

───────────────────────────────────────────────────────────────
CHANGELOG TEMPLATE
───────────────────────────────────────────────────────────────
## [VERSION] — YYYY-MM-DD

### Added
- [new components, tokens, variants]

### Changed
- [modifications to existing surfaces]

### Deprecated
- [old → new migration path, removal version]

### Removed
- [breaking removals — MAJOR only]

### Fixed
- [bug fixes]

### A11y
- [accessibility improvements — call out separately]

───────────────────────────────────────────────────────────────
QUALITY-GATE CHECKLIST (PR / RELEASE BLOCKING)
───────────────────────────────────────────────────────────────
☐ Contrast ratios verified (AA minimum, AAA for primary body)
☐ Keyboard navigable (Tab / Space / Enter / Esc / Arrows)
☐ Screen-reader tested (VoiceOver + NVDA minimum)
☐ prefers-reduced-motion honored
☐ Both light + dark mode tokens defined
☐ Storybook (or equivalent) story per variant + state
☐ No raw hex in components
☐ No emoji in UI
☐ Component implements default / hover / focus-visible /
  active / disabled
☐ Error messages follow What/Why/How
☐ Visual-regression snapshot committed
☐ Changelog entry under correct semver bump

───────────────────────────────────────────────────────────────
PERFORMANCE BUDGETS (universal floor)
───────────────────────────────────────────────────────────────
Performance is a design system concern. Slow systems erode every
other quality choice. Universal targets per page (every archetype):

First Contentful Paint (FCP):     < 1.5s on 4G mobile
Largest Contentful Paint (LCP):   < 2.5s on 4G mobile
Cumulative Layout Shift (CLS):    < 0.1
Time to Interactive (TTI):        < 3.5s on 4G mobile
Bundle (JS, gzipped):             < 100KB initial route
Bundle (CSS, gzipped):            < 30KB
Web font payload:                 < 100KB total (subset + woff2)
Largest image:                    < 200KB (WebP/AVIF preferred)

Per-archetype tightening (overrides):
  Current   — initial JS < 70KB (mobile networks)
  Lattice   — initial JS < 50KB; data-grid virtualization mandatory
  Meridian  — web font < 60KB (subset to article glyph set);
              first paint must show body text within 1s
  Harbor    — hero image < 150KB; font subset to display set
  Sentinel  — initial JS < 100KB (workhorse default)

Quality-gate addition: every release runs Lighthouse + WebPageTest
budget check. Regressions fail CI.

───────────────────────────────────────────────────────────────
INTERNATIONALIZATION (i18n)
───────────────────────────────────────────────────────────────
Every component MUST work in:

Direction:
  • LTR (default — English, most European)
  • RTL (Arabic, Hebrew, Persian, Urdu)
  Required: every component declares logical CSS properties
  (margin-inline-start instead of margin-left) so RTL flips
  correctly without per-language overrides.

Character ranges:
  • Latin (basic + extended)
  • CJK (Chinese, Japanese, Korean) — taller line-heights
    needed (1.6+ minimum); fonts may need to swap to
    region-appropriate (Noto Sans CJK)
  • Cyrillic, Greek, Devanagari per product reach

Locale-sensitive tokens:
  • Date / time formats — use Intl.DateTimeFormat, never
    hardcode "MM/DD/YYYY"
  • Number formats — Intl.NumberFormat handles
    locale separators, currency, units
  • Sort orders — Intl.Collator for string comparison
  • Pluralization — Intl.PluralRules + ICU MessageFormat

Banned i18n antipatterns:
  ✗ Hardcoded English strings in components (use i18n keys)
  ✗ Concatenated strings ("You have " + count + " items") —
    use ICU plurals
  ✗ Fixed-width buttons that truncate German (avg 30%+ longer)
  ✗ Direction-aware icons (chevrons, arrows) without RTL flip
  ✗ Assuming Latin characters in regex / validation
  ✗ ASCII-only password rules

───────────────────────────────────────────────────────────────
FORM VALIDATION STRATEGY (universal pattern)
───────────────────────────────────────────────────────────────
Validation behavior is a tonal choice — get it wrong and the
form feels nagging or surprises the user at submit time.

WHEN to validate:

  ✓ On blur (after user leaves the field)        — DEFAULT
  ✓ On submit (final check, always runs)         — REQUIRED
  ✓ On change (real-time), but ONLY for:
    - Password strength meters (visible feedback as user types)
    - Username/handle availability (debounced API check)
    - Match-confirmation fields (password confirm matches)

  ✗ On every keystroke for general fields (nagging, breaks
    flow — user is mid-thought)

WHAT to validate:
  • Required field empty
  • Format mismatch (email, URL, phone, date)
  • Range / length violations
  • Server-side rules (uniqueness, conflict, capacity)

HOW to display:
  • Error message replaces helper text below input
  • Field gets --color-error border + 3px focus ring on focus
  • Error message follows What/Why/How formula
  • Error icon to the left of message (color + icon redundant
    encoding — colorblind a11y)
  • aria-invalid="true" + aria-describedby pointing to error msg
  • Submit button stays enabled (per WCAG SC 3.3.4); never
    disable submit because that hides the form's validation
    state from the user

Per-archetype overrides:
  Sentinel  — inline validation on blur, parenthetical
              "(required)" not asterisk-only
  Current   — keyboard type matches input semantic
              (inputMode="numeric" / "email" / "tel")
  Meridian  — forms are rare; when present, generous spacing
              (--space-4 between fields), clear labels
  Lattice   — number-field formatting (mono + tabular figures);
              tab key advances within table-grid forms
  Harbor    — labels above (NEVER floating); error tone
              consistent with editorial voice (no exclamation)

───────────────────────────────────────────────────────────────
LOADING-STATE STRATEGY (universal decision tree)
───────────────────────────────────────────────────────────────
Choose the right loading affordance — wrong choice feels broken.

Operation duration → preferred loading state:

  < 100ms     → no loading state (instant)
                User won't notice; showing a spinner adds latency
                perception, not removes it.

  100–300ms   → optimistic UI (immediate state change, server
                confirms in background; rollback on error)
                Right for: like buttons, toggle switches, inline
                edits.

  300ms–1s    → button → loading state on the action
                Button shows spinner inline + disables; rest of
                page stays interactive.

  1s–5s       → skeleton placeholders (NOT spinner)
                Show shape of incoming content; reduces perceived
                wait. Skeleton MUST match content shape (don't
                use generic rectangles).

  5s–30s      → progress indicator with text label
                "Analyzing screenshot — 68% (about 4 seconds left)"
                Shows progress + ETA + ability to cancel.

  > 30s       → background processing + notification on completion
                Don't make the user wait. Submit, navigate away,
                notify (toast / email / push) when done.

Per-archetype rules (tightening):
  Lattice   — prefer NO loading state for sub-100ms ops; never
              hide chrome behind a loader (keep keyboard
              shortcuts + nav functional)
  Current   — pull-to-refresh haptic on threshold; skeleton
              required for any list waiting > 500ms
  Meridian  — skeletons banned (motion ban); use opacity-static
              placeholders OR no loader at all (most docs render
              statically anyway)
  Harbor    — skeletons subtle (--color-surface-2 base, opacity
              pulse), never shimmer (too feature-y)
  Sentinel  — text label required next to spinner if wait > 1s

Banned loading antipatterns (universal):
  ✗ Spinner with no text after 1s (ambiguous — stuck or working?)
  ✗ Full-screen blocker for partial-page loads
  ✗ Skeleton shimmer in Meridian / editorial contexts
  ✗ Hide nav / sidebar / chrome behind a loading state
  ✗ Disabling Submit button "to prevent double-click" — use
    debounce + button loading state instead

───────────────────────────────────────────────────────────────
HYBRID PRODUCTS (when one archetype isn't enough)
───────────────────────────────────────────────────────────────
Most real products are hybrids. Common patterns:

  Marketing site + Product app
    → Harbor for the marketing surface (homepage, pricing,
      case studies); Sentinel for the in-app product
    → Examples: Linear, Notion, Stripe, Vercel
    → Strategy: separate codebases or distinct route trees;
      Harbor + Sentinel each ship their own tokens.css with
      shared brand primitives (same primary hex) but
      independent semantic layers, type scales, density.

  Web app + Mobile app
    → Sentinel for desktop web; Current for native mobile
    → Examples: Slack, Figma, Notion, Asana
    → Strategy: shared brand color anchor; otherwise distinct
      systems. Don't try to "responsive" Sentinel down to mobile
      — touch ergonomics demand Current's rules (44px targets,
      bottom-anchored nav, sheets-not-modals).

  Product app + Data terminal view
    → Sentinel for the workflow shell; Lattice for the
      data-explorer / monitoring screens
    → Examples: Linear's command bar, Datadog inside their
      broader app, Snowflake's worksheet inside admin chrome
    → Strategy: keep Lattice scoped to specific routes;
      transition is explicit (visual rule: navigating into the
      Lattice route changes chrome density + introduces the
      data-system color palette)

  Marketing site + Documentation
    → Harbor for marketing; Meridian for docs subdomain
    → Examples: Stripe, Tailwind, Vercel — marketing on root,
      docs on /docs or docs.* subdomain
    → Strategy: shared header brand, distinct layouts. Docs
      reading experience must NOT inherit Harbor's atmospheric
      hero patterns.

  Product app + In-app docs / help center
    → Sentinel shell + Meridian content panes for docs
    → Strategy: docs render as a Meridian-styled panel inside
      Sentinel's chrome (right drawer, modal, dedicated route)

KEEP TOKEN FILES SEPARATE (the universal hybrid rule):
  Don't force one tokens.css to cover both archetypes. Each
  archetype owns its own:
    - Semantic layer (Layer 2 token names per archetype)
    - Typography scale (Harbor clamp vs Sentinel fixed px etc.)
    - Density scale
    - Component priority order
    - Banned patterns

  Share ONLY:
    - Brand primary hex (the anchor color)
    - Brand voice principles (broad guidelines, not specific
      voice rules — those vary per archetype)
    - Universal governance gates (this file)

The most expensive mistake in hybrid design: forcing one
archetype's choices onto another archetype's use case. A 14px
base font is correct for Lattice and catastrophic for Meridian.
Pick the right archetype per surface, then build within it.

───────────────────────────────────────────────────────────────
ARCHETYPE OVERRIDES — AGGREGATED SUMMARY
───────────────────────────────────────────────────────────────
Each archetype inherits this governance spec in full and adds
its own overrides. Below is the canonical aggregated summary
(updated whenever any archetype's overrides change).

Harbor — 9 overrides
  Theme: dark-first; semantic-only tokens; fluid clamp typography;
  warm oklch shadows; single accent enforced; serif italic
  display reserved for editorial emphasis; floating label class
  banned; indigo/purple banned; avatar initials default; one
  primary CTA per section; hero variants limited to template 01.
  See: [harbor.spec.md](harbor.spec.md)

Sentinel — 10 overrides
  Two-layer token architecture; accent-CTA rule (no white-on-
  orange in chrome); tabular numerals on numeric columns; fixed
  px modular typography; sans-serif only; cold rgba shadows;
  dark-mode tokens defined; WCAG verification table required
  in spec page; color-only encoding banned; "(required)"
  parenthetical (not asterisk-only). See: [sentinel.spec.md](sentinel.spec.md)

Current — 11 overrides
  44px minimum touch targets enforced; body font ≥ 16px on
  inputs; native font stack default; safe-area insets honored;
  hover-only interactions banned; hamburger nav banned as
  primary; tab bar capped at 5 items; haptics paired with
  visible state; modal-only patterns flagged for review;
  inputMode matches input semantic; both light + dark modes
  required. See: [current.spec.md](current.spec.md)

Lattice — 10 overrides
  Two-color-system architecture (chrome + data separate);
  monospace + tabular numerals on all numeric columns; every
  interactive element has documented keyboard shortcut;
  animation on data updates banned; shadows on default surfaces
  banned; confirmation dialogs banned for reversible actions;
  pagination banned for data tables (must virtualize); color-
  only encoding banned; body type ≥ 11px in chrome; pane
  resizability required. See: [lattice.spec.md](lattice.spec.md)

Meridian — 11 overrides
  Reading-width hard-capped at 72ch on body; body type ≥ 17px;
  body line-height ≥ 1.7; animation on body content banned;
  sepia + dark mode tokens defined; print stylesheet required;
  all headings (h2+) auto-id'd; external links flagged with
  icon; code blocks have copy button; ⌘/Ctrl+K search wired;
  marketing hype words blocked in body. See: [meridian.spec.md](meridian.spec.md)

───────────────────────────────────────────────────────────────
SPEC-PAGE OUTPUT REQUIREMENTS (Prompt 08)
───────────────────────────────────────────────────────────────
Every generated spec page MUST contain these sections, even if
the archetype spec doesn't enumerate them explicitly. Prompt 08
derives missing details from archetype rules.

Required sections (in this order):
  §1.1  Color system + Accessibility verification table
  §1.2  Typography (scale, weights, line-heights)
  §1.3  Spacing scale
  §1.4  Elevation + shadows (with use case per token)
  §1.5  Shape & borders (radii with use guidance)
  §1.6  Motion (durations + easings + reduced-motion fallback)
  §1.7  Iconography (family, grid, stroke, sample grid)
  §2    Voice & content (Do/Don't pairs)
  §3    Component library (foundation → composite → domain)
  §4    Patterns (form layout, empty state, + archetype-specific)
  §5    Accessibility (WCAG conformance, keyboard map, SR notes)
  §6    Versioning + Governance (this checklist + changelog
        template)
  Footer: version · generation date · mode · WCAG target ·
          archetype name

═══════════════════════════════════════════════════════════════
END GOVERNANCE · v1.0
═══════════════════════════════════════════════════════════════
```

---

## Maintenance notes (do not paste into prompts)

- **When governance evolves:** update this file once. All five archetype specs inherit automatically — no per-archetype updates needed unless an archetype overrides a gate.
- **Archetype overrides:** each archetype spec includes a `GOVERNANCE OVERRIDES` block at the end that adds (never removes) gates specific to that archetype. Examples: Harbor enforces warm oklch shadows; Current enforces 44px minimum touch targets; Sentinel enforces sentence-case-only.
- **What is NOT in this file:** archetype-flavored aesthetic rules (typography choices, density, accent strategy), component priority orders, banned patterns specific to a visual language. Those live in the archetype spec.
- **CSS hygiene — `overflow-x: clip` not `hidden` on html/body.** The rendered HTML uses `overflow-x: clip` (not `hidden`) on both `html` and `body`. The `hidden` variant creates a scrolling-ancestor context that breaks `position: sticky` on descendants — including the `.sidebar` chrome at line 104. `clip` achieves the same horizontal-scroll suppression without establishing a containing block for sticky. When re-running Prompt 08 to regenerate the spec page, ensure the regenerated CSS does NOT reintroduce `overflow-x: hidden` on html/body — substitute `clip`.
- **Publishing footer (post-render step, not part of the spec contract):** the rendered HTML at [build/preview/specs/governance.html](../../build/preview/specs/governance.html) appends an inline credit row as the LAST element inside the existing `<footer>`, immediately after the `.footer-bottom` row — book backlink (`../../index.html`, opens in new tab), author attribution (Ishdeep S Sahni), © 2026 Ishdeep S Sahni · All rights reserved, "Confidential & proprietary." Self-contained inline styles use `currentColor` + `opacity:0.55` so it adapts to whichever theme is active. Prompt 08 does NOT generate this row — it's appended post-render. When re-running Prompt 08 to regenerate the spec page, re-apply the canonical credit row (see existing governance.html for the exact markup, just before the closing `</footer>`) before committing the new HTML.
- **Cross-references:**
  - Universal predecessor for: [harbor.spec.md](harbor.spec.md), [sentinel.spec.md](sentinel.spec.md), [current.spec.md](current.spec.md), [lattice.spec.md](lattice.spec.md), [meridian.spec.md](meridian.spec.md)
  - Consumed by: Prompts 1, 03, 04, 05, 08, 09
