# Lattice · Archetype Spec Sheet · v1.0

**Status:** authored from v1 Ch11 (Lattice section) + Finding 12 mock + data-terminal conventions (Bloomberg, Datadog, Linear, observability tools). Source of truth for the data-dense terminal archetype.

**Use:** two-paste workflow per prompt.
1. Paste [governance.spec.md](governance.spec.md) first (universal gates — non-negotiable).
2. Paste the fenced block below second (Lattice-specific rules).

Consumed by Prompt 1 (token generation), Prompt 03 (foundation components), Prompt 04 (composite components), Prompt 05 (UI patterns), Prompt 08 (spec page), Prompt 09 (workspace assembly).

**Origin:** [reference/book-v1.html](../../reference/book-v1.html) Ch11 lines 3052–3190. Mock pattern: [finalbookplan.md](../../finalbookplan.md) Finding 12.

---

```
═══════════════════════════════════════════════════════════════
LATTICE · ARCHETYPE SPEC · v1.0
Data-dense terminals / Trading desks / Observability
═══════════════════════════════════════════════════════════════

TAGLINE: a design system for data-dense terminals. Tabular,
monospace-heavy, maximum information per pixel. Built for
hours of focused use.

PREREQUISITE: governance.spec.md MUST be loaded before this
spec. Lattice inherits all universal gates and adds the
overrides at the end of this block.

───────────────────────────────────────────────────────────────
THEME
───────────────────────────────────────────────────────────────
Mode: DARK-FIRST — terminals are dark by convention (reduces
      eye strain over 8+ hour sessions in dim rooms)
Light mode: parallel theme (must be defined per governance —
            even if "office daylight" users use it rarely)
Palette character: maximally restrained chrome (grays + hairlines)
                   + saturated semantic colors RESERVED for data
                   only (status, severity, deltas)
Pure #000 acceptable in dark mode (not just OLED — high contrast
on data is the goal)
Reason: terminals run for shifts. Restraint in chrome maximizes
attention budget for the actual data. Color in chrome competes
with color in data — and color in data carries meaning.

───────────────────────────────────────────────────────────────
DENSITY DOCTRINE — the Lattice keystone
───────────────────────────────────────────────────────────────
Information density IS a feature. Every design decision asks:
"Does this take a pixel from the data zone?"

If yes → reject by default. Only justify density-cost when the
chrome carries critical context (active filter chip, alert
badge in nav).

Targets:
  - 50+ rows visible per screen (vs Sentinel's 20–30)
  - Sub-13px base type acceptable
  - 24px row height in compact mode
  - Multi-pane layouts (3–5 panes) standard

───────────────────────────────────────────────────────────────
TOKEN NAMING
───────────────────────────────────────────────────────────────
Strategy: numeric primitives + semantic aliases + heavy data-viz
          extensions (heaviest of all archetypes)
Layer 1: --color-neutral-50…900, --color-data-* (categorical /
         sequential / diverging palettes — data has its own
         color system separate from chrome)
Layer 2: --chrome-bg, --chrome-border, --chrome-text-*,
         --status-* (semantic for data)

Reason: in Lattice, chrome and data are DIFFERENT color systems.
Chrome is restrained grays. Data uses purpose-fit palettes
(sequential for magnitude, diverging for delta, categorical
for unrelated series). Mixing them — using accent color for a
chrome border AND for a data series — destroys data legibility.

───────────────────────────────────────────────────────────────
COLOR TOKENS (canonical defaults — substitute equivalents)
───────────────────────────────────────────────────────────────

▼ CHROME (dark mode primary)
Surfaces:
  --chrome-bg              #0A0A0A   page bg (near-black)
  --chrome-bg-elevated     #141414   pane bg
  --chrome-bg-input        #1C1C1C   input field bg
  --chrome-bg-row-hover    #1F1F1F   row hover (subtle)
  --chrome-bg-row-selected #2A2A2A   row selection
Borders:
  --chrome-border-subtle   rgba(255,255,255,0.06)
  --chrome-border-default  rgba(255,255,255,0.10)
  --chrome-border-strong   rgba(255,255,255,0.18)
Text:
  --chrome-text            #E5E5E5   body
  --chrome-text-muted      #999999   secondary
  --chrome-text-faint      #666666   metadata
  --chrome-text-disabled   #4A4A4A
Accent (chrome — used SPARINGLY, only for active states):
  --chrome-accent          #4DA3FF   selected pane border, focus
  --chrome-accent-subtle   rgba(77,163,255,0.12)

▼ CHROME (light mode parallel)
  --chrome-bg              #FAFAFA
  --chrome-bg-elevated     #FFFFFF
  --chrome-text            #1A1A1A
  ... (mirror dark mode roles)

▼ DATA — STATUS (semantic, used in DATA only)
  --status-success-bg      rgba(44,160,44,0.12)
  --status-success-text    #2CA02C
  --status-success-strong  #1F7A1F
  --status-warning-bg      rgba(232,178,77,0.12)
  --status-warning-text    #E8B24D
  --status-error-bg        rgba(214,39,40,0.12)
  --status-error-text      #D62728
  --status-error-strong    #B22020
  --status-info-bg         rgba(31,119,180,0.12)
  --status-info-text       #1F77B4

▼ DATA — DIVERGING (negative ↔ neutral ↔ positive)
Use for: P&L, deltas, change-from-baseline, heat with center
  --data-neg-strong  #D62728   strongly negative
  --data-neg         #F7B6B6   mildly negative (or light bg use)
  --data-neutral     #444444   neutral midpoint
  --data-pos         #A8DFA8   mildly positive
  --data-pos-strong  #2CA02C   strongly positive

▼ DATA — SEQUENTIAL (single-hue gradient for magnitude)
Use for: heatmaps, density plots, magnitude scales
  --data-seq-1   #0D1A2E
  --data-seq-3   #1F4080
  --data-seq-5   #6BAED6
  --data-seq-7   #B0D2F0
  --data-seq-9   #F7FBFF

▼ DATA — CATEGORICAL (distinct hues for unrelated series)
Use for: line charts with N series, legends, categorical buckets
  --data-cat-1   #1F77B4   blue
  --data-cat-2   #FF7F0E   orange
  --data-cat-3   #2CA02C   green
  --data-cat-4   #D62728   red
  --data-cat-5   #9467BD   purple
  --data-cat-6   #8C564B   brown
  --data-cat-7   #E377C2   pink
  --data-cat-8   #7F7F7F   gray
  Reason: D3-tableau10 palette (proven categorical
  distinguishability across colorblind audits)

▼ FOCUS RING
  --color-focus-ring  rgba(77,163,255,0.5)

───────────────────────────────────────────────────────────────
TYPOGRAPHY
───────────────────────────────────────────────────────────────
Approach: FIXED px scale, dense, monospace-first for numerics
Base: 12px (yes, really — terminal convention)
Family:
  --font-sans    "Inter", "SF Pro Text", system-ui, sans-serif
  --font-mono    "JetBrains Mono", "SF Mono", "IBM Plex Mono",
                 Menlo, monospace
  --font-number  var(--font-mono)   numbers ALWAYS monospace

Numbers in tables, prices, counts, IDs → mono with tabular
figures (font-feature-settings: "tnum" 1, "lnum" 1).

Scale (8 steps — heavily weighted toward small):
  --text-micro    10px   row counts, axis labels, legends
  --text-xs       11px   table cell text, dense UI
  --text-sm       12px   DEFAULT — base reading size
  --text-base     13px   emphasis in tables
  --text-lg       14px   pane headers
  --text-xl       16px   section titles (rare)
  --text-2xl      18px   workspace title
  --text-display  22px   max — only for primary nav title

Font weights:
  --weight-regular   400   body, table cells
  --weight-medium    500   column headers, labels
  --weight-semibold  600   emphasized values, totals
  --weight-bold      700   reserved for primary alerts only

Line heights:
  --leading-table    1.30   table rows (tight for density)
  --leading-tight    1.20   headers
  --leading-normal   1.45   prose / dialog body
  --leading-data     1.0    data cells (no extra leading)

Letter spacing:
  --tracking-tight   -0.01em   small headers
  --tracking-normal  0
  --tracking-wide    0.04em    overlines, status pills

Reason: dashboards trade readability for density. 12px is the
minimum that scans well in monospace at 80+ rows visible.
Monospace numerics are non-negotiable — column alignment
collapses without them. Headers stay small (14–16px max) so
they don't steal the data zone.

───────────────────────────────────────────────────────────────
DENSITY
───────────────────────────────────────────────────────────────
Character: MAXIMUM — every pixel earns its place
Spacing scale (2px base — half of other archetypes):
  --space-25    2px   inline gap, badge inner padding
  --space-50    4px   tight pair (icon+number)
  --space-75    6px   row internal padding
  --space-100   8px   DEFAULT cell padding
  --space-150  12px   between cells / form fields (rare)
  --space-200  16px   pane internal padding
  --space-300  24px   between sections (rare)
  --space-400  32px   page-level breaks (very rare)

Row height tokens (user-toggleable):
  --row-height-compact   24px   power user / dense view
  --row-height-standard  32px   DEFAULT
  --row-height-comfy     40px   accessibility / new user

Pane padding: --space-200 (16px) outer, --space-100 (8px) inner

Content widths:
  --content-fit       fill viewport (full-bleed default)
  --content-readable  640px   for any prose explanations
                              (settings, docs, errors)

Reason: 4px base would still waste pixels at terminal density.
2px increments allow finer tuning of dense rows. User-toggleable
row heights respect that operators have preferences (compact for
power users, comfy for accessibility).

───────────────────────────────────────────────────────────────
ACCENT STRATEGY
───────────────────────────────────────────────────────────────
Strategy: TWO PALETTES — chrome accent (single, restrained) +
          data palettes (purpose-fit by data shape)

Chrome accent: ONE color (default --chrome-accent #4DA3FF)
  Used for: focus ring, active pane border, current selection,
            keyboard cursor highlight
  NEVER used for: data series, status indicators, badges

Data palettes (pick one INTENTIONALLY per visualization):
  - Diverging: bi-directional data (P&L, delta, deviation)
  - Sequential: magnitude (heatmaps, density)
  - Categorical: unrelated series (line chart with N series)
  - Status: bg/text pair for badges, alerts, severity rows

THE RULE: never use chrome accent for data; never use data
colors for chrome. The two systems have one job each.

Banned: rainbow palettes for unrelated data (use categorical),
        random color picks ("the green one"), single accent
        hue strategy (Harbor/Current pattern), gradients on
        chrome surfaces

Reason: in a terminal, color is signal. A red row means
something specific. If chrome ever uses red, the signal weakens.
Restraint in chrome makes data colors louder.

───────────────────────────────────────────────────────────────
ELEVATION
───────────────────────────────────────────────────────────────
Default: ZERO — flat surfaces, hairline borders only.
         Lattice is the FLATTEST archetype — no shadows on
         default surfaces.
Shadows: reserved for transient overlays (popovers, tooltips,
         command palette result list)

  --shadow-overlay  0 4px 12px rgba(0,0,0,0.4)
  --shadow-modal    0 12px 40px rgba(0,0,0,0.6)

Banned: shadows on panes (would suggest float — panes are
        anchored)
Banned: shadows on rows / cells (visual noise; density killer)
Banned: warm oklch shadows (Harbor pattern)
Banned: gradient backgrounds on any chrome surface

Reason: shadows are visual weight. Visual weight reduces the
information zone. The density doctrine bans shadows everywhere
except where they signal "this is temporarily floating".

───────────────────────────────────────────────────────────────
RADII
───────────────────────────────────────────────────────────────
Scale (6 steps — tighter than Harbor, smaller than Sentinel):
  --radius-none  0      table cells, panes, dividers
  --radius-xs    2px    badges, chips (rare — Lattice prefers
                        sharp data feel)
  --radius-sm    4px    DEFAULT — buttons, inputs, popovers
  --radius-md    6px    dialogs (rare — modal use)
  --radius-lg    8px    only floating CTAs (rare in Lattice)
  --radius-circle 50%   keyboard hint pills, status dots

Banned: --radius-pill / fully rounded UI — too playful
Banned: --radius-xl+ — visual weight wasted
Banned: rounded table cells (breaks column alignment perception)

Reason: sharp corners reinforce the tabular grid. Lattice is
not trying to feel friendly — it's trying to feel precise.

───────────────────────────────────────────────────────────────
MOTION
───────────────────────────────────────────────────────────────
  --duration-instant   0ms     state changes (default!)
  --duration-fast      80ms    hover color shift
  --duration-base      120ms   popover entry, focus shift
  --duration-slow      200ms   pane resize commit
  --easing-linear      linear  default (no flourish)
  --easing-standard    cubic-bezier(0.4, 0, 0.2, 1)

Use motion functionally and SPARINGLY:
  - Pane resize: continuous (drag), then snap on release
  - Popover open: 120ms fade
  - Loading spinners: rotate (functional indicator)
  - Drag preview: opacity 0.5 + cursor

Reduced-motion fallback: instant transitions (Lattice's default
is already minimal).

Banned: animation on data updates (cell flash → distraction
        over 8 hours; use color tint instead)
Banned: animation on state change (selected row, sort, filter
        — all instant)
Banned: bouncing easing, scroll-jacking, skeleton shimmer,
        loading dots, transitions on every hover

Reason: motion fatigue is real. Power users in terminals for
8 hours will viscerally hate any animation that triggers on
common actions. Instant > smooth.

───────────────────────────────────────────────────────────────
ICONOGRAPHY
───────────────────────────────────────────────────────────────
Family default: TABLER ICONS
                Reason: pixel-precise, grid-aligned at 24px, 1.5px
                default stroke, optical alignment correct at 16px
                (where Lucide breaks down). Tabler reads as a tool
                — it's what Coda, Codeium, monitoring dashboards
                converge on. Substitute Codicon (VS Code's set) if
                you want even more developer-terminal feel.
                NEVER use Lucide for Lattice (Lucide's broader strokes
                visually compete with dense data; that's fine for
                Sentinel but wrong for Lattice).
Grid:           16px standard (smaller than other archetypes
                by default); 14px in dense rows; 20px in nav
Stroke:         1.5px at all sizes (Tabler default — matches density)
Color:          inherit via currentColor

Style:
  - Line icons by default
  - FILLED only for binary state indicators (active/muted),
    severity badges, status dots (filled circle)

Banned:
✗ Emoji as icon
✗ Multi-color icons in chrome
✗ Animated icons except spinner
✗ Any icon larger than 24px in chrome (display icons OK in
  empty states / errors)
✗ Phosphor / Iconoir / playful families (Phosphor reads editorial,
  wrong tone for terminal density)

Sparkline icons: a Lattice innovation — replace icon-button
combos with inline sparklines (mini bar / line / win-loss
chart) inside table cells. 80–120px wide, single-color.

───────────────────────────────────────────────────────────────
WORKSPACE LAYOUTS — page composition vocabulary
───────────────────────────────────────────────────────────────

W1 MULTI-PANE WORKSPACE (the Lattice default)
   Structure: top header (slim, 36px) + N resizable panes in
              configurable splits (vertical / horizontal /
              nested)
   Common configs: 2-pane horizontal (table + detail),
                   3-pane (nav + table + detail), 4-pane
                   quad (monitoring grid)
   Required: drag-to-resize splitters, keyboard resize
             (Shift+ArrowKey), min-width per pane,
             persistence per user
   Banned: fixed pane widths (operator preferences vary)

W2 FULL-TABLE WORKSPACE
   Structure: filter bar + virtualized table (full viewport) +
              optional detail drawer (right)
   Use for: exploration screens (logs, events, transactions)
   Required: virtualization (10,000+ rows smooth scroll),
             sticky header + filter bar

W3 CHART GRID
   Structure: header + N×M chart cards (resizable, draggable)
   Use for: monitoring dashboards (multi-metric)
   Required: each chart self-contained, independent zoom +
             time range, shared crosshair on hover

W4 SPLIT EDITOR (text + preview)
   Structure: 50/50 vertical split, syntax-highlighted text
              left, rendered preview right
   Use for: query editors, configuration editors, log filter
            builders
   Required: synced scroll option, keyboard shortcut to swap

W5 STREAMING LOG VIEW
   Structure: header (filters + pause/resume) + tail-following
              log (auto-scroll bottom unless user scrolls up)
   Required: pause-on-scroll-up, resume-on-scroll-bottom,
             keyboard shortcut to jump-to-tail

W6 MODAL / SETTINGS
   Structure: centered dialog (--content-readable wide) for
              sparse forms; full-screen overlay for power-user
              configuration
   Use for: only when input doesn't fit within a pane
   Required: Esc to close, Cmd/Ctrl+Enter to submit

Composition rule: every Lattice screen is one of these six.
Operators learn the chrome once and never re-learn it.

───────────────────────────────────────────────────────────────
COMPONENT LIBRARY — generate in this priority order
───────────────────────────────────────────────────────────────

▼ FOUNDATION (Layer 1 — Prompt 03)
1.  Button
    Variants: primary (subtle bg + chrome-accent border +
              accent text) / secondary (transparent + border) /
              tertiary (text-only + hover bg) / destructive
              (status-error border + text)
    Sizes:    xs (h:24px) / sm (h:28px) / md (h:32px)
    Lattice rule: NO LG button — terminals don't have generous
                  buttons; everything fits in headers
    Lattice rule: filled accent buttons are RARE — used only
                  for the singular primary commit action
                  (e.g., "Run query")

2.  Icon button
    Sizes: xs (24px hit) / sm (28px hit) / md (32px hit)
    Required: aria-label, tooltip with KEYBOARD SHORTCUT
              ("Refresh — R")
    Lattice rule: every icon button has a keyboard shortcut
                  documented in its tooltip

3.  Field (text / number / search / select)
    Variants: default / search (with icon) / number (mono) /
              select / multi-select (with chip list inside)
    States:   empty / filled / focus / error / disabled
    Required: inline validation on blur, error message
              positioned to NOT shift layout
    Lattice rule: number inputs use --font-number (mono +
                  tabular)
    Lattice rule: focus is a 1px chrome-accent border ring,
                  NOT a 3px glow (the glow steals pixels)

4.  Selection controls
    Checkbox  — square 14px (smaller than other archetypes),
                --radius-xs, indeterminate state required
    Radio     — circle 14px
    Switch    — 28×16px (smaller), no animation overshoot
    States:   unchecked / checked / indeterminate / disabled

5.  Tag / Badge
    Shape: --radius-xs (rectangular — fits density doctrine)
    Variants: neutral (gray) / status (success/warning/error/
              info, all use semantic data colors) / accent
              (chrome-accent — RARE)
    Sizes: micro (h:14px) / sm (h:18px)
    Lattice rule: count badges in monospace ("99+", "1.4k")

6.  Status dot
    Lattice innovation: 8px filled circle indicating state
                        (active / queued / failed)
    Used inline before label, as smallest possible state
    indicator. Always paired with text label (color-only
    encoding banned per governance).

7.  Keyboard hint pill
    Lattice innovation: monospace pill showing shortcut
    Style: --radius-circle for single keys ("J"), --radius-xs
           for combos ("⌘K"), --chrome-bg-input bg, 11px mono
    Use: ALWAYS visible next to actions where shortcut exists
         (in toolbars, in tooltips, in command palette results)

▼ COMPOSITE (Layer 2 — Prompt 04)

8.  Pane (the structural primitive of Lattice layouts)
    Structure: pane header (24–32px, title + actions) +
               resizable splitter (between siblings) + content
    Required: collapsible, resizable, keyboard-focusable
              (focus the pane → keyboard scoping)
    Active pane: 1px chrome-accent left-border on focused pane
                 (operator knows where keyboard input goes)

9.  Splitter (resize handle)
    Width: 4px hit-zone, 1px visual line (--chrome-border-default)
    Hover: visual line widens to 2px chrome-accent
    Drag: shows ghost preview line at potential drop location
    Required: keyboard resize (Shift+ArrowKey), double-click
              to reset to default, persistence

10. Toolbar
    Structure: horizontal row of icon-buttons + vertical
               dividers between groups + keyboard hints inline
    Height: 32px standard
    Lattice rule: every toolbar action has a keyboard shortcut
                  visible in its hover/focus tooltip

11. Filter bar
    Structure: search field (left) + active-filter chips
               (removable) + sort dropdown + density toggle +
               saved-view dropdown (right)
    Required: applied filters always visible as chips (never
              hidden behind a count); Cmd/Ctrl+F focuses search
    Lattice rule: filter chips use --font-mono for values
                  (e.g., "status=failed", "owner=team-x")

12. Popover
    Trigger: click on a button or table cell
    Style: --shadow-overlay, --chrome-bg-elevated, --radius-sm,
           1px border
    Width: --content-readable max
    Required: Esc to close, click-outside dismisses, focus
              moves into popover

13. Tooltip
    Trigger: hover (delay 200ms) + focus
    Style: --chrome-bg dark, --chrome-text, 11px, max-width
           240px
    Required: ALWAYS shows keyboard shortcut for the action
              if one exists

14. Loading states
    14a. Spinner — circle 16px, --chrome-accent stroke,
                   1s rotation
    14b. Skeleton — solid block (NO opacity pulse — too
                    distracting in terminal); --chrome-bg-input
                    bg, --radius-xs
    14c. Progress bar — 2px height (thinner than other
                        archetypes)
    Lattice rule: prefer NO loading state for sub-100ms ops
                  (visible loader is slower-feeling than no
                  loader)

15. Modal / Dialog
    USE SPARINGLY — modals interrupt density flow.
    Structure: title + body + footer (buttons right-aligned)
    Backdrop: rgba(0,0,0,0.6) — opaque, sits over chrome
    Required: focus trap, Esc to close, Cmd/Ctrl+Enter to
              submit
    Lattice rule: prefer popover or pane over modal whenever
                  possible

▼ PATTERNS (Layer 3 — Prompt 05)

16. Data grid (THE iconic Lattice component)
    Structure: virtualized rows (1000s scrollable smoothly) +
               sticky header + sticky pagination/count footer
    Required: column resize, column reorder (drag), column
              show/hide, column pin (left/right), sort
              (click header), filter (per column), row
              selection (checkbox + Shift-click range +
              Cmd/Ctrl-click multi), bulk action bar on
              selection
    Cell density: --space-100 (8px) horizontal, --space-50
                  (4px) vertical
    Number columns: --font-number, right-aligned
    Status columns: status pill or status dot + label
    Required: keyboard navigation (Arrow keys + Enter to open
              + Space to select)
    Lattice rule: ALL tables zebra-stripe (subtle —
                  alternating --chrome-bg / --chrome-bg-elevated)
                  (this DIFFERS from Sentinel which bans
                  zebra — Lattice density needs scan-aids)

17. Sparkline (inline mini-chart)
    Variants: line / bar / win-loss / area
    Size: 80×16px to 120×20px
    Color: single-hue (chrome-accent or status semantic)
    Use: inside table cells (last 30 days trend), in header
         summaries (latency over time)
    Required: tooltip on hover showing exact values
    Lattice rule: sparklines are first-class — they replace
                  "open chart" chrome with an inline glance

18. Heatmap cell
    Pattern: table cell with bg color from --data-seq-* ramp
             based on cell value
    Required: color + numeric value (governance — never color
              alone)
    Use: density tables, correlation matrices, calendar heatmaps

19. Diff row
    Structure: before-value | delta-arrow | after-value | %-change
    Color: delta uses --data-pos-strong / --data-neg-strong
    Format: monospace, right-aligned, signed numbers ("+1.4M",
            "-3.2%")
    Required: copy-on-click (any cell), tooltip with full
              precision

20. Streaming log row
    Structure: timestamp (mono, --chrome-text-faint) + level
               badge (status pill) + message (truncate with
               expand-on-click) + source/correlation ID
    Required: monospace throughout, virtualized, color-coded
              by level, search highlight inline

21. Saved view
    Structure: named filter+sort+column+pane-layout state
    Storage: per-user, per-workspace, shareable by URL
    UI: dropdown showing saved views + "Save current view"
        action

22. Command palette (Cmd/Ctrl+K)
    Structure: search field + grouped results (pages, actions,
               records, saved views) + keyboard hints in footer
    Required: fuzzy search, ArrowUp/Down to navigate, Enter
              to execute, Esc to close, focus on open
    Lattice rule: command palette is the PRIMARY input method
                  — every action in the UI must be reachable
                  from Cmd+K

23. Empty state (in-pane, in-table — NOT full-screen)
    Structure: small (NOT full-screen) — single line with
               muted text and optional action link
    Tone: terse — "No matching rows. Adjust filters."
    Banned: illustrations (waste pixels), apologetic copy

24. Detail drawer (right edge)
    Trigger: row click in main table
    Width: 480px default (resizable per-user)
    Structure: header (entity ID + close) + scrollable detail +
               sticky action footer
    Required: Esc closes, j/k cycles to next/prev row in table
              while drawer open

25. Error state
    Structure: terse message + record/job ID + "Retry" link +
               full error in expandable details
    Tone: forensic — "Job #4821 failed: timeout after 30s."
    Required: actionable next step (retry, escalate, view logs)

▼ PRINT BEHAVIOR (Layer 3 — system pattern)

Operators print Lattice views: incident reports, audit exports,
shift handoff docs, regulatory compliance snapshots. Print is a
first-class concern.

Print stylesheet (canonical pattern):
  @media print {
    /* Hide all chrome — only data prints */
    .sidebar, .toolbar, .filter-bar, .splitter,
    .keyboard-hint, .command-palette { display: none; }

    /* Force light mode for paper (operator's monitors are
       dark-first, but printers expect light) */
    :root {
      --chrome-bg:           #FFFFFF;
      --chrome-bg-elevated:  #FFFFFF;
      --chrome-text:         #1A1A1A;
      --chrome-text-muted:   #555555;
      --chrome-border-default: #CCCCCC;
    }

    /* Expand panes to full printable width */
    .pane, .data-grid, .workspace { width: 100% !important; }

    /* Data grid — preserve EVERY visible row + sticky header */
    .data-grid thead { display: table-header-group; }
    .data-grid tr { page-break-inside: avoid; }

    /* Replace status COLOR encoding with text + symbol
       (printer might be B&W) */
    .status-pill::before { content: attr(data-status) " — "; }

    /* Show timestamps in absolute UTC + relative */
    .timestamp-relative::after {
      content: " (" attr(data-utc) ")";
      color: var(--chrome-text-muted);
    }

    /* Show full job/record IDs (don't truncate for paper) */
    .id-truncated { white-space: nowrap; overflow: visible; }

    /* Pagination footer becomes a print footer */
    .pagination-footer {
      position: running(footer);
      font-size: 9pt;
    }

    /* Page header for context */
    @page {
      margin: 1cm;
      @top-left  { content: "Lattice export"; font-size: 9pt; }
      @top-right { content: "Page " counter(page) " of "
                            counter(pages); font-size: 9pt; }
    }

    /* Sparklines render as inline SVG — preserve them */
    /* Heatmap cells preserve background color via
       -webkit-print-color-adjust */
    * { -webkit-print-color-adjust: exact;
        print-color-adjust: exact; }
  }

Lattice rule: print stylesheet ships with the tokens.css output
              of Prompt 1; operators expect ⌘P to "just work"
              for any view.
Lattice rule: data-grid views MUST print sticky-header on every
              page (multi-page exports without column labels are
              useless for forensic review).
Lattice rule: status / severity colors MUST also encode as
              text-prefix in print (e.g., "CRITICAL — ") since
              B&W printers strip color encoding.

▼ DOMAIN LAYER (Layer 4 — product-specific composites)
Domain components compose Layers 1–3 with Lattice rules: mono
numbers, dense spacing, keyboard shortcuts visible in tooltips,
color reserved for data meaning, color+icon+text triple encoding
on every status. Below are 5 named examples for terminal /
trading / observability products. Extend per product domain.

26. Trade ticket row (trading desk)
    Composes: Diff row (19) + Status pill / Status dot (5/6) +
              Sparkline (17)
    Structure: timestamp (mono, --chrome-text-faint) + symbol
               (mono semibold) + side badge (BUY/SELL — diverging
               colors) + qty + price (mono right-aligned) +
               P&L sparkline + status dot + kebab actions
    Lattice rule: P&L delta uses --data-pos-strong / --data-neg-
                  strong; signed numbers always ("+1.4M", "-3.2%")
    Lattice rule: row click opens detail drawer (24); J/K cycles

27. Cluster node card (observability)
    Composes: Card (small variant) + Sparkline (17) + Status dot
              (6) + Heatmap cell (18) + Diff row (19)
    Structure: hostname (mono) + status dot + uptime + CPU
               sparkline (last 5min) + memory bar + last-deploy
               timestamp + kebab actions
    Lattice rule: card grid in W3 Chart Grid layout (resizable,
                  draggable); tap to open detail drawer
    Lattice rule: status dot + uptime label + sparkline = three
                  redundant signals (governance triple-encoding)

28. Streaming log row (log analytics)
    Composes: Streaming log row (20) + Severity badge / Status
              dot (per severity) + Code-block expansion + Tag/
              Badge for source/correlation ID
    Structure: timestamp (mono, microsecond precision) + level
               badge (filled severity icon + text) + message
               (truncated, expand-on-click) + source-host (mono
               muted) + correlation-id (mono, copy-on-click)
    Lattice rule: virtualized list (10k+ rows smooth); auto-tail
                  with pause-on-scroll-up; resume on scroll-bottom
    Lattice rule: search-match highlights inline using
                  --accent-highlight at low opacity

29. Query plan node (database/dataframe explorers)
    Composes: Pane primitive (8) nested + Diff annotations (19)
              + Heatmap cell (18 — for cost coloring)
    Structure: collapsible tree of operator nodes; each node
               shows: operator name (mono) + estimated rows +
               actual rows + cost-bar (heatmap-colored
               sequential ramp by cost percentile) + expand
               chevron
    Lattice rule: actual-vs-estimated diff colored
                  diverging (under-estimate red / over-estimate
                  green); large diffs flag for re-plan suggestion

30. Alert escalation row (incident response)
    Composes: Streaming log row (20) + Severity badge + Drawer
              (open detail) + Status pill (state machine)
    Structure: severity badge (critical/high/medium/low/info)
              + alert title + asset/host + acked-by avatar +
              age (mono) + state pill (firing/acked/resolved)
              + actions (acknowledge / silence / escalate /
              page-on-call)
    Lattice rule: keyboard shortcuts on every action (A=ack,
                  S=silence, E=escalate, P=page); shortcut hints
                  visible inline
    Lattice rule: silenced rows fade to --chrome-text-faint
                  but stay visible (don't hide — operators
                  need to see the silence)

───────────────────────────────────────────────────────────────
KEYBOARD-FIRST INTERACTION
───────────────────────────────────────────────────────────────
Lattice is keyboard-primary. Mouse is supported but not
optimized for. Every action must have a shortcut.

Standard shortcuts (reserve these — products inherit):
  Cmd/Ctrl+K     command palette
  Cmd/Ctrl+/     keyboard shortcut help overlay
  Cmd/Ctrl+F     focus search
  Cmd/Ctrl+Enter submit / commit
  Esc            close popover, clear focus, dismiss drawer
  J / K          next / previous row (vim-style)
  G then key     go-to (G then I = inbox, G then D = dashboard)
  N              new (context-sensitive)
  E              edit selected
  D              delete selected (with confirmation)
  R              refresh
  /              focus search (also Cmd+F)
  ? (Shift+/)    show keyboard shortcut help

Required: keyboard shortcut help overlay accessible from "?"
or Cmd/Ctrl+/. Lists every shortcut grouped by context.

Required: focus rings on all keyboard-reachable elements.
Required: tab order matches visual order.

Banned: any action that REQUIRES mouse (no drag-only
operations without keyboard alternative).

───────────────────────────────────────────────────────────────
VOICE RULES — apply to ALL generated copy
───────────────────────────────────────────────────────────────
(Inherits governance Voice rules. Lattice adds:)

• Labels abbreviate when scannable — "Qty", "Avg", "Min", "Max",
  "P50", "P95", "P99" are CLEARER in context than full words
• Numbers ALWAYS get units — "1.4M rows", "3.2s", "$40.1K",
  "P95 4.2ms"; naked numbers are ambiguous
• Timestamps in BOTH relative + absolute — "2m ago · 14:32:08
  UTC"; one for scanning, one for forensics
• Error states NAME the record/job/ID — "Job #4821 failed:
  timeout after 30s", never "Something went wrong"
• Column headers are nouns — "Status", "Owner", "Last run";
  never sentences
• No marketing language — "0 results" beats "Nothing here yet,
  let's get started!"
• Use technical vocabulary; do NOT explain it (operators know
  what P95 means; explaining it insults them)
• Tooltip text is short + includes keyboard shortcut

VOICE — Do / Don't pairs:

  Do  → "0 results"
  Don't → "Nothing here yet — let's get started!"
        Why: terse beats friendly in terminals.

  Do  → "Job #4821 failed: timeout after 30s"
  Don't → "Oops! Something went wrong. Please try again."
        Why: name the record + cause + duration.

  Do  → "P95 latency 4.2ms"
  Don't → "Your average latency is around 4 milliseconds"
        Why: precision; technical vocabulary; mono rendering.

  Do  → "Refresh — R"  (in tooltip)
  Don't → "Click to refresh the data"
        Why: action + shortcut; no instruction prefix.

  Do  → "1.4M rows · 3 filtered"
  Don't → "1,400,000 total records, 3 of which match your filters"
        Why: abbreviated unit; mono digit; scannable.

───────────────────────────────────────────────────────────────
BANNED PATTERNS — the Lattice anti-pattern catalog
───────────────────────────────────────────────────────────────

▼ Density / chrome antipatterns
✗ Card-based rhythm for data
    Why: wastes vertical space (5 rows visible instead of 50)
    Use: tabular rhythm, column alignment
✗ Oversized headings (anything > 22px in chrome)
    Why: eats the information zone
    Use: 14–16px section headers max
✗ Generous whitespace / padding > 16px in panes
    Why: density-cost without value
    Use: tight 8–16px pane padding
✗ Single-column layouts
    Why: defeats data comparison; no use of horizontal real
         estate
    Use: multi-pane (W1) or full-table (W2)
✗ Decorative imagery in chrome
    Why: pixels stolen from data zone; tonal mismatch
    Use: NONE — data IS the visual
✗ Shadows on default surfaces
    Why: visual weight; reduces information feel
    Use: flat with hairline borders
✗ Rounded corners > 4px on data containers
    Why: breaks tabular grid perception
    Use: 0–4px on panes, cells, tables

▼ Color antipatterns
✗ Random color for data series
    Why: unscientific; trends become invisible
    Use: pick a palette intentionally — diverging / sequential
         / categorical
✗ Single accent hue used for chrome AND data
    Why: weakens data signal; chrome competes with data
    Use: separate chrome accent from data palettes
✗ Rainbow palette for unrelated categories
    Why: implies ordinal relationship that doesn't exist
    Use: --data-cat-1…8 (D3 tableau10 categorical)
✗ Color-only encoding (red row, no icon, no text)
    Why: governance fail; colorblind a11y broken
    Use: color + status icon + text label
✗ Gradient fills on chrome surfaces
    Why: visual weight; pixel waste
    Use: solid surface tokens

▼ Typography antipatterns
✗ Variable-width font for numbers
    Why: column alignment collapses
    Use: --font-number (monospace + tabular figures)
✗ Body text > 14px in tables
    Why: reduces row count visible
    Use: 11–13px in dense rows
✗ Italic, bold-italic, or > 2 weights on the same surface
    Why: visual noise
    Use: regular + medium + semibold (3 weights max)

▼ Interaction antipatterns
✗ Animation on every state change (cell flash, row hover
  pulse)
    Why: motion fatigue over 8-hour session
    Use: instant state changes; motion only for drag/resize
✗ Hover-only tooltips on data
    Why: hidden detail; keyboard users blocked
    Use: persistent detail drawer or focus-visible tooltips
✗ Pagination for long lists
    Why: breaks scroll context; filter resets
    Use: virtualized scroll with sticky header + count
✗ Icon-only action buttons WITHOUT text or shortcut
    Why: ambiguous in dense UI
    Use: icon + tooltip with text + keyboard shortcut visible
✗ Confirmation dialogs for reversible actions
    Why: workflow friction; operators hate "are you sure"
    Use: undo snackbar after action commits
✗ Auto-refreshing data without pause control
    Why: rug-pulls active operator selections
    Use: pause-on-interaction, manual resume

▼ Copy antipatterns
✗ Marketing voice
    Why: tonal mismatch with operator audience
    Use: terse, technical, abbreviation-friendly
✗ Friendly empty-state copy
    Why: friction in operator workflow
    Use: terse — "0 results. Adjust filters."
✗ Naked numbers without units
    Why: ambiguous (3.2 — seconds? millions? percent?)
    Use: always unit-suffixed ("3.2s", "3.2M", "3.2%")
✗ "Click here" / "Submit" / "OK"
    Why: zero specificity
    Use: action-named ("Run query", "Commit changes")
✗ Tooltip without keyboard shortcut
    Why: misses opportunity to teach the keyboard-first model
    Use: always include shortcut if one exists

▼ Layout antipatterns
✗ Fixed pane widths (non-resizable)
    Why: ignores operator preferences (workflow varies)
    Use: drag-to-resize splitters with persistence
✗ Modal-as-default for any input
    Why: interrupts density flow
    Use: popover or pane edit; modal only for confirmation
✗ Sidebar that auto-collapses on narrow viewport
    Why: operators run on wide monitors; collapse logic bug-
         ridden
    Use: persistent sidebar (operator manually toggles)
✗ Hero-large numbers in dashboards (> 32px)
    Why: starves data density
    Use: 22px max for primary KPIs (sparkline > big number)

───────────────────────────────────────────────────────────────
BYOC — REQUIRED COLOR ROLES (Bring Your Own Colors)
───────────────────────────────────────────────────────────────
If you're using Prompt 1b (BYOC variant) instead of Lattice's
canonical chrome + data palettes, your supplied palette MUST
cover BOTH systems separately. Lattice's defining rule —
"chrome accent and data palettes are different systems" — is
enforced at the BYOC validation layer.

Required CHROME palette (~14 colors — restrained grays + ONE
accent):
  Surfaces (5):
    1  chrome-bg                page (near-black dark / off-white light)
    2  chrome-bg-elevated       pane bg
    3  chrome-bg-input          input field bg
    4  chrome-bg-row-hover      row hover (subtle)
    5  chrome-bg-row-selected   row selection
  Borders (3):
    6  chrome-border-subtle     hairline (~6% opacity)
    7  chrome-border-default    standard outline
    8  chrome-border-strong     emphatic separator
  Text (4):
    9  chrome-text              body
    10 chrome-text-muted        secondary
    11 chrome-text-faint        metadata
    12 chrome-text-disabled
  Chrome accent (2 — used SPARINGLY for active/selected states):
    13 chrome-accent            single hue, blue or teal default
    14 chrome-accent-subtle     accent at 12% opacity (focus tints)

Required DATA palette (~22 colors — semantic + diverging +
sequential + categorical):
  Status pairs (8 — bg + text for each):
    success-bg + success-text + success-strong
    warning-bg + warning-text
    error-bg + error-text + error-strong
    info-bg + info-text
  Diverging (5 — bi-directional, neg → neutral → pos):
    data-neg-strong / data-neg / data-neutral / data-pos /
    data-pos-strong
  Sequential (5–9 minimum — single-hue magnitude ramp):
    data-seq-1 → data-seq-9 (light to dark)
  Categorical (8 — distinct hues for unrelated series):
    data-cat-1 through data-cat-8 (D3 tableau10 default)

Optional (per product domain):
  + Severity (5: critical/high/medium/low/info — for
    monitoring/alerting/critique products)
  + Annotation pins (numbered colors — for review/critique tools)

VALIDATION RULES (Prompt 1b enforces):
  ✓ Two-system separation: chrome and data tokens cannot share
    the same hex value (lint flag)
  ✓ Both light AND dark mode tokens present (Lattice is
    dark-first but light mode required)
  ✓ Categorical palette passes colorblind audit (deuteranomaly
    + protanomaly minimum)
  ✓ Status colors combine with icon + text label (no color-only
    encoding — governance rule)

REJECTED palettes (Prompt 1b will fail):
  ✗ Single-hue accent strategy for data (rainbow ramps for
    unrelated categories — implies ordinal where there is none)
  ✗ Chrome and data sharing the same accent (defeats the
    two-system separation)
  ✗ Pastel data colors (insufficient differentiation for
    severity/status)
  ✗ Dark mode only — Lattice IS dark-first but governance
    requires light mode parity

───────────────────────────────────────────────────────────────
WHEN TO PICK LATTICE
───────────────────────────────────────────────────────────────
Pick Lattice IF:
• User stares at the screen for HOURS, not minutes
• Information density beats whitespace in every decision
• Monospace alignment of numeric data matters
• Primary UX is scanning tables, not navigating pages
• Keyboard is the primary input device
• Operators have technical expertise (use abbreviations,
  technical vocabulary)
• Multi-pane resizable workspaces are the norm
• Domains: trading, observability, monitoring, log analysis,
  query consoles, cluster managers, BI exploration tools

Sample adjectives that route to Lattice (archetype-selection
aid — Finding 5 demoted-adjective routing, NOT a generation
input):
  terse · technical · dense · scannable · instant · operator-grade
  · monospace · keyboard-first · multi-pane · low-chrome · forensic
  · streaming · power-user · abbreviated · grid-aligned
If three or more of your brand adjectives are in this list,
Lattice is likely your archetype.

Real-world examples (calibrate against these — public products
that exemplify Lattice's principles):
  • Bloomberg Terminal — the canonical reference; multi-pane,
    monospace numerics, keyboard-primary, dark-first
  • Datadog — observability dashboards, streaming logs, status
    pills with color+icon+text
  • Grafana — multi-pane workspace, sparklines, time-range scrub
  • Linear's command bar (Cmd+K), Raycast — Lattice-grade
    keyboard-first interaction inside otherwise Sentinel apps
  • Elastic Kibana — log explorer, dense tables, virtualized rows
  • New Relic / Sentry — error monitoring with severity rows
  • Snowflake / BigQuery query consoles — split editor (W4)
  • Cursor / Codeium — split editor + completions; partial Lattice

DO NOT pick Lattice if:
• Mobile is a primary target → [Current](current.spec.md)
• Single-screen task focus (CRM, ticketing) → [Sentinel](sentinel.spec.md)
• Reading-heavy (docs, articles) → [Meridian](meridian.spec.md)
• Marketing site or onboarding → [Harbor](harbor.spec.md)
• User base is non-technical → [Sentinel](sentinel.spec.md) (gentler density)
• 5–20 rows is the typical view → [Sentinel](sentinel.spec.md)

───────────────────────────────────────────────────────────────
FAILURE MODES — what breaks first when Lattice is misapplied
───────────────────────────────────────────────────────────────
When teams force Lattice onto the wrong use case, predictable
failures appear in this order.

1. New-user paralysis (Lattice for a non-technical audience)
   Symptom: First-time users open the product, see dense rows
   of monospace data, abbreviated labels ("Qty", "P95"), no
   onboarding. Bounce rate near 100%. Support tickets ask
   "how do I use this?"
   Root cause: Lattice's terse vocabulary + density assume
   technical expertise. Non-experts need scaffolding.
   → Switch to [Sentinel](sentinel.spec.md) (gentler density,
     less abbreviated, more discoverable).

2. Mobile collapse (Lattice on phone)
   Symptom: Multi-pane workspace can't fit; data grid horizontal-
   scrolls forever; 12px text at arms-length unreadable;
   keyboard shortcuts irrelevant on touch.
   Root cause: Lattice is desktop-first by definition — large
   monitors, keyboard, 8-hour sessions. None of that translates
   to mobile.
   → Switch to [Current](current.spec.md) for mobile companion;
     limit Lattice features to desktop.

3. Marketing-page absurdity (Lattice for marketing site)
   Symptom: Marketing page reads as a Bloomberg terminal; visitors
   leave instantly. Brand reads as cold, hostile, inaccessible.
   Root cause: Lattice's restraint is purposeful for operators;
   reads as alienating to prospects.
   → Switch to [Harbor](harbor.spec.md) for marketing surface;
     keep Lattice for the in-product terminal view.

4. Reading exhaustion (Lattice for prose / docs)
   Symptom: 12px text at 1.3 leading in a single column is
   unreadable for sustained prose. Eye strain in minutes.
   Root cause: Lattice optimizes for scan, not read.
   → Switch to [Meridian](meridian.spec.md) (17–19px body,
     1.75 leading, 68ch reading-width).

5. The "feels broken" failure (Lattice without keyboard discipline)
   Symptom: New developers ship Lattice features without
   keyboard shortcuts; operators who learned the rest of the
   product can't extend their muscle memory; they file bugs
   against the new feature.
   Root cause: Lattice's contract IS keyboard-first. Half-
   measures fail more visibly than they would in other
   archetypes.
   → Tighten governance: every interactive action must have
     a documented shortcut at lint time. (Not an archetype
     switch — a discipline fix within Lattice.)

───────────────────────────────────────────────────────────────
GOVERNANCE OVERRIDES (Lattice adds to universal gates)
───────────────────────────────────────────────────────────────
Inherits governance.spec.md in full. Lattice additionally
enforces:

☐ Two-color-system architecture — chrome and data palettes
  cannot share tokens (lint flags any shared color)
☐ Monospace + tabular figures required on any numeric column
  (font-feature-settings: "tnum" 1; lint flags variable-width
  numbers in tables)
☐ Every interactive element has a keyboard shortcut documented
  (lint flags icon-buttons without shortcut metadata)
☐ Animation on data updates banned (cell flash, row pulse —
  fails motion-fatigue review)
☐ Shadows on default surfaces banned (panes, cells, rows —
  lint flags any non-overlay shadow)
☐ Confirmation dialogs banned for reversible actions (use
  undo snackbar pattern — workflow review flag)
☐ Pagination banned for data tables (must virtualize — lint
  flags any paginated data grid)
☐ Color-only encoding banned (every status indicator combines
  color + icon + text — governance baseline, Lattice strict
  enforcement)
☐ Body type ≥ 11px in chrome (10px allowed only for axis
  labels, micro-metadata)
☐ Pane resizability required (any non-resizable splitter
  fails workspace lint)

───────────────────────────────────────────────────────────────
PHILOSOPHY (paste into prompt context as guiding principle)
───────────────────────────────────────────────────────────────
"Information density is a feature. Users who spend eight hours
a day in a terminal don't want whitespace; they want more rows
visible, faster sorts, keyboard shortcuts over mouse travel.
Lattice bans card rhythm, oversized headings, and animation-
by-default because each one steals pixels from the information
zone."

═══════════════════════════════════════════════════════════════
END LATTICE SPEC · v1.0
═══════════════════════════════════════════════════════════════
```

---

## Maintenance notes (do not paste into prompts)

- **When you extend Lattice** (new data palette, new pane type, new sparkline variant): edit the spec block above, bump the version, and re-paste into prompts.
- **Conflict with v1 Ch11 Lattice section:** the spec wins. v1 covered Lattice lightly; this spec elevates it to first-class status (per Finding 12 Decision 3).
- **Lattice is the densest spec — be ruthless about new components.** Every addition trades density for capability. Justify every extension.
- **Publishing footer (post-render step, not part of the spec contract):** the rendered HTML at [build/preview/specs/lattice.html](../../build/preview/specs/lattice.html) appends an inline credit row as the LAST element inside the existing `<div class="spec-footer">` (Lattice uses a div, not a `<footer>`) — 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` and `flex-basis:100%` to force a full-width row in Lattice's flex-wrap footer layout. 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 lattice.html for the exact markup, just before the closing `</div>` of the spec-footer) before committing the new HTML.
- **Cross-references:**
  - Universal predecessor: [governance.spec.md](governance.spec.md)
  - Companion specs: [harbor.spec.md](harbor.spec.md), [sentinel.spec.md](sentinel.spec.md), [current.spec.md](current.spec.md), [meridian.spec.md](meridian.spec.md)
  - Consumed by Prompts 1, 03, 04, 05, 08, 09 (per Finding 12 locked scope)
