# SKILLS.md

<!-- thorbis-mobile-hig-reference -->
> **Mobile platform gate (D-025):** Every mobile-app task requires the [Native contract](https://design.thorbis.com/skills/native), HIG-001–HIG-022, and relevant live [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

How an agent builds Thorbis. 11 skills. Linear is the shared baseline, not a separate skill. Each skill is its own file under `.agents/skills/`. This file is the selective index and bundle.

Live: https://design.thorbis.com/resources#skills

Not on skills.sh. Do not run `npx skills add`.

Pick the smallest owning skill. Do not average them. The Linear baseline is inherited automatically; open the pattern matrix only when the owner is ambiguous.

| When | Chapter |
| --- | --- |
| Inventing a page, a tool, or a canvas | [Product](https://design.thorbis.com/skills/product) |
| Consequential workflow, integration, migration, or incident | [Resilience](https://design.thorbis.com/skills/resilience) |
| Large collections, discovery, deep records, relationships, or cross-device continuity | [Ecosystem](https://design.thorbis.com/skills/ecosystem) |
| Any screen | [UI](https://design.thorbis.com/skills/ui) |
| Phone, Android, desktop chrome | [Native](https://design.thorbis.com/skills/native) |
| Marketing, first-run, or a product video | [Cinematic](https://design.thorbis.com/skills/cinematic) |
| Animation | [Motion](https://design.thorbis.com/skills/motion) |
| Color, theme, or color theory | [Color](https://design.thorbis.com/skills/color) |
| Type or copy | [Type](https://design.thorbis.com/skills/type) |
| A component growing flags | [Composition](https://design.thorbis.com/skills/composition) |
| Filing or closing work | [Tracking](https://design.thorbis.com/skills/tracking) |

Pattern reference when needed: https://design.thorbis.com/research/linear-patterns


## Product

Design any new Thorbis surface so it belongs. Same shell, same feel, no costume. Use when inventing a page, a tool, a canvas, or anything that does not already exist.

> **Linear baseline:** This skill specializes one part of Thorbis; it does not introduce another product grammar. Preserve quiet chrome, one dominant work region, structured density, stable action neighborhoods, contextual surfaces, visible keyboard paths, durable state, and role-adaptive mobile. Use the [Thorbis × Linear pattern matrix](https://design.thorbis.com/research/linear-patterns) only when the owning pattern is ambiguous.

<!-- thorbis-mobile-hig-reference -->
> **Mobile platform gate (D-025):** Every mobile-app task requires the [Native contract](https://design.thorbis.com/skills/native), HIG-001–HIG-022, and relevant live [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

How Thorbis acts and feels. Open this when you invent something new.

This is its own skill. Drop it at `.agents/skills/product.md`. Pick this file. Do not average it with the others.

Live: https://design.thorbis.com/skills/product

[Rules](https://design.thorbis.com) is what we ship. [Research](https://design.thorbis.com/research) is the homework. [`DESIGN.md`](https://design.thorbis.com/design.md) is the constitution. [`AGENTS.md`](https://design.thorbis.com/agents.md) is the contract. UI is craft. Linear is the baseline for shell geometry. Native is the device. This chapter is the join: the new thing sits in the shell we already have, and a dispatcher cannot tell it was added last week.

**This skill holds:** **D-001** (fill a pattern or name the gap), **D-002** (the page does not own chrome), **D-006** **D-007** **D-012** (search, then stop if nothing fits), **D-013** **D-014** (surface must earn its role; no desktop drawer), **D-009** (states exist), **D-015** (preference where people differ).

**Homework:** Linear, Vercel, Cursor. Grammar, not costume. Ryo Lu — the designer ships; the workbench is the product. Aman Sanger — agents follow a file; they do not invent taste. Michael Truell — a conversation is fine for a sketch; the constitution is for the ship.

If the surface is marketing or first-run, stop. Use [Cinematic](https://design.thorbis.com/skills/cinematic). Name the mode: router, explore, film, or store. One idea per scene. **D-022**.

### What this skill owns

- The product feel. Quiet chrome. Precise work. Easy to look at. Easy to understand.
- How new work enters the 90% shell.
- When a new occupant is allowed, and when you must stop and name a gap.
- The test at the end of every invention.

It does not own pixel tokens ([Color](https://design.thorbis.com/skills/color), [Type](https://design.thorbis.com/skills/type)). It does not own inverted-L measures or surface roles; those come from the shared Linear baseline and `DESIGN.md`. It does not own iOS chrome ([Native](https://design.thorbis.com/skills/native)). Read those after the join is right.

### First

Answer these, in order, before you draw. Write the answers down. If you cannot, you are not ready.

1. Who is holding it, and what just interrupted them? Dispatcher at 7 a.m. Tech in a crawlspace. Owner closing the books.
2. Which profile? Workbench, Guided, Evidence, or Showcase. One. Do not mix.
3. What is the one action on this view? Dispatch. Arrive. Save invoice. Add a step. Everything else is quieter.
4. Is this a place, a transaction, or context? Route, modal, popover, inspector, peek, or inline. Not a desktop drawer. **D-013**. **D-014**.
5. Which room already exists? List, Board, Record, Schedule, Inbox, Search, Settings, Guided, Evidence, Canvas. Fill that room. The occupant table is below.
6. What already exists in the kit? Search the registry. **D-007**. Native control, then the kit, then last a new primitive. **D-006**.

Do not offer a menu of looks. Make the call. Then invent only the occupant, never the chrome.

### The feel

Thorbis is the cleanest thing they touch all day. That is not a slogan. It is a test.

A screen is easy to look at when:

- One grey family. Canvas, chrome, sheet, well. No extra grey you invented.
- One accent. Electric blue. It points. It does not paint.
- A fill is one mix. No gradient. No solid colored border on the leading or trailing edge of a row. **D-018**.
- Media holds its hole. A list that continues shows it. **D-019**.
- Outline at rest. Fill when this is the place. **D-020**.
- Overlay is a mix, not a blur. **D-021**.
- Type does the hierarchy. 32 / 16 / 14 / 13 / 12. No costume font. No kicker.
- Regions meet by tone. No 1px line around a room.
- Depth is a whisper. Rest, sink, lift, overlay. Nothing else.

A screen is easy to understand when:

- You know where you are from the location bar.
- You know what the work is from the sheet. Street first. `114 Oak`, then the leak.
- You know the one action without hunting. It is a commit. Ink.
- Status is a word. Open. En route. On site. Not a green blob.
- Empty names the one action. `No steps yet. Add a step.`
- Errors name the problem and the exit. Not “Oops.”
- Words are ours. Job, stop, tech, truck. Not ticket, agent, resource.

If a new thing needs a legend to be read, it is not Thorbis yet.

### Customize

Prefer a preference when the work varies person to person. **D-015**.

Theme. Density. This list (columns, sort, group). Saved views. Default place. Pinned places.

The default ships finished. If they must open Display before the board works, you built a kit.

Do not let them rewrite the inverted L, the tokens, or the words. Do not put a hex picker in Settings. Do not put five display options on Arrive. A shared invoice does not wear their Light theme as the document.

Display for this list lives on the view bar. Shop-wide facts live in Settings. Persist what is theirs. The URL holds what is shareable.

### The 90% shell

Most of Thorbis is one app. The chrome does not change. The occupant does.

```
canvas
  sidebar          places you can go
  main
    location bar   where you are
    view bar       how this work is sliced
    sheet          the work
      inspector    optional, one selected thing
```

This is the inverted L. The sheet is the product. The page does not own the sidebar, the location bar, or the view bar. **D-002**.

Allowed occupants of that shell:

`ListPage` `BoardPage` `RecordWorkspace` `ScheduleTimeline` `InboxPage` `SearchPage` `SettingsPage` `GuidedFlow` `EvidencePage` `CanvasWorkspace`

A new feature is almost always a new occupant of the sheet, or a new row inside an occupant you already have. It is almost never a new shell.

Fail if you invent:

- A second header
- A second sidebar
- A floating toolbar that hides the location bar
- A card grid that is the page
- A dashboard of equal buttons
- A desktop drawer doing a page’s job
- A new color language “because this tool is spatial”

The operator does not relearn the app because you shipped Workflow.

### How a new thing joins

Follow this. Do not skip.

#### 1. Name the room

If the work is a list of jobs, it is List. If it is a job, it is Record. If it is time against trucks, it is Schedule. If it is find-and-compare, it is Search. If it is one field action, it is Guided. If it is a number that must be right, it is Evidence. If the work is spatial — a graph, a map of steps, Brain, Workflow — it is Canvas.

If none of those is true, stop. Write the gap. Do not invent a page-local shell. **D-012**.

#### 2. Keep the chrome

Same sidebar. Same location bar. Same view bar. Same sheet. Same inspector slot.

The new thing fills the sheet. It may use the inspector. It may add a view-bar slice. It may add a command. It does not add a chrome row.

#### 3. Dress it in our surfaces

| Thing on the new surface | It is | Token |
| --- | --- | --- |
| The empty plane | Canvas. Not a working surface. | `bg` |
| A node, a card, a step, a truck | A sheet | `panel` |
| An input on that node | A well | `field` |
| The title of the node | Type | `fg` |
| The caption, the edge, the handle | Marker | `marker` |
| The selected node, the live edge, focus | Accent | `accent` |
| The one action | A commit. Ink. | `fg` fill, inverse type |

Same fill as the parent is illegal. A node is not a flat sticker on the sheet. It is a small sheet: 14px radius, tone, optional 1px rim if the thumb must find it. Selected is accent, the way a live row is accent. Not a new selection kit.

#### 4. Keep the words and the type

Inter on the work. Geist Mono on IDs and money. Sentence case. Prefer a mark. When a control has a word, it names the action: `Save invoice`, not `Continue`, not `+ Node`. **D-016**.

Street first even on a graph. The node is `114 Oak`, not `N-1842`. If the node is a step, the title is the verb: `Dispatch`, `Arrive`, `Invoice`. Not `Function_3`.

#### 5. Keep the keys

`⌘K` still goes or does. `/` may filter this view. `J` `K` move the selectable thing. `Enter` opens. `Space` peeks. `Esc` closes the top layer or deselects. `C` still quick-creates when create exists.

Hover is color, gated to a real mouse. Focus is an accent ring. Selected is a fill or a mark. They are not the same.

Shortcut-only is a defect. **D-008**.

#### 6. Keep the states

Empty, loading, error, disabled, permission, destructive. Designed. **D-009**.

A canvas with no nodes is empty, not a blank void. Name the action. A failed save sits under the field or as a page banner if the page is the problem. A missing permission does not leak the invoice.

#### 7. Keep the phone

The inverted L collapses. Sidebar becomes command. Inspector becomes a bottom sheet. The sheet stays the work. A spatial view may pan and zoom. It does not become a squeezed desktop. 44px for anything that stands alone. [Native](https://design.thorbis.com/skills/native).

### Spatial work

Workflow. Brain. A map of steps. A graph of nodes. This is Canvas. It is a room, not a second product.

The sheet is the plane. Nodes sit on it the way jobs sit on a list. The location bar names the graph. The view bar slices it. The inspector holds the selected node. Adding a node is a commit or a `C` modal, not a costume palette.

A third-party graph library is infrastructure. Its default theme is a costume. Strip it. Tokens only. No neon edges. No alien selection. No library watermark. No second typeface from the package.

### Color, type, motion

Do not invent a palette because the tool feels “creative.”

- Brand, focus, the live thing: `accent`. One blue.
- Status: success, danger, info, warning. Words first.
- Olive, forest, pumpkin, burnt: extras. Fun. Not a job. Not a node type system.
- Light is a retune, not an invert. The same grammar. [Color](https://design.thorbis.com/skills/color).

Type scale does not grow because the canvas is big. A node title is 14 / 500 or 16 / 500. It is not 32. 32 is the page. [Type](https://design.thorbis.com/skills/type).

Motion: frequency first. Panning a canvas is the work, not an animation. Selecting a node is color, not a bounce. Connecting an edge may take 120ms ease-out on `transform` and `opacity`. Keyboard is instant. [Motion](https://design.thorbis.com/skills/motion).

### Composition

Name the occupant after the job: `WorkflowCanvas`, `BrainGraph`, `JobMap`. Not `SmartBoard`. Not `InfiniteCanvas`.

Export pieces, not flags. The shell owns chrome. The occupant owns the work. A canvas component does not paint a sidebar. [Composition](https://design.thorbis.com/skills/composition).

Search the registry. If `CanvasWorkspace` exists, fill it. If it does not, name the gap, then add it as an occupant of `AppShell`, not as a new app.

### Never

- A new shell for a new idea
- A second visual language “for this tool”
- React Flow, Mapbox, or FullCalendar wearing their factory clothes
- Neon edges, glow handles, a rainbow of node types
- A floating HUD that covers the location bar
- Mini-map chrome that shouts louder than the graph
- `N-1842` as the title of a node
- A desktop drawer that holds the canvas
- Marketing copy on a workbench canvas
- Hex, `text-white`, or a raw shadow in product code
- Linear purple, Linear dress, or “Issue”
- Mixing Workbench density with Showcase theater on one view
- A hex picker, a theme store, or a Guided flow with display options
- A default that is broken until they open Settings
- A gradient, mesh, or fade, unless the brief named that wash
- A solid colored border on the leading or trailing edge of a row, a node, or a card

### Audit

- [ ] Person, profile, one action, and surface are named
- [ ] The room is named. The occupant fills the 90% shell
- [ ] No second header, no second sidebar, no extra chrome row
- [ ] Tokens only. One accent. Regions have no borders
- [ ] Nodes / cards / rows use panel, well, type, marker. Selected is accent
- [ ] Trade words. Street first. Status is a word
- [ ] `J` `K`, `⌘K`, Escape, Space. A visible path for the one action
- [ ] Empty, loading, error exist
- [ ] 390px: inspector is a bottom sheet. No squeezed desktop
- [ ] Light and dark. Theme still sticks
- [ ] A preference exists where people differ, or you named why not. **D-015**
- [ ] A dispatcher would believe this was always here

Two failures: do not ship.

### Done

Name the person, the profile, the room, the surface, and the one action. Name the occupant you filled. Name anything you refused, including a library theme you stripped. If you named a gap instead of inventing a shell, that is success.


### Rooms

The 90% shell is one app. These are the occupants of the sheet. Fill one. Do not invent a sixteenth chrome.

`AppShell` owns canvas, sidebar, location, view, sheet, inspector. Measures live in the shared Linear baseline. This skill is the join.

### Same chrome

| Slot | Job | A new feature may | A new feature may not |
| --- | --- | --- | --- |
| Sidebar | Places you can go | Add a place if it is durable | Put filters, a second logo, or the new tool’s tree here |
| Location bar | Where you are | Name this graph, this job, this list | Become a marketing header or a toolbar |
| View bar | How this work is sliced. Density. This list’s display. | Add a slice: Map / List, All / Leaks. A density control. | Become a second location, a floating HUD, or shop-wide Settings |
| Sheet | The work | Be a list, a board, a record, a canvas | Be a stack of cards that is the page |
| Inspector | Context beside the work | Show the selected row or node | Become a second app or a desktop drawer |

One main landmark. One inverted L. The operator does not relearn the app when the occupant changes.

### Occupants

| Room | Owner | The sheet holds | One action | Not |
| --- | --- | --- | --- | --- |
| List | `ListPage` | Rows. Street first. | Create a job. Dispatch the selection. | A dashboard above the list |
| Board | `BoardPage` | Columns of status words | Move a job. Open it. | A second color language per column |
| Record | `RecordWorkspace` | Identity, feed, the job | The primary verb on this job | A chat toy. A squeezed inspector |
| Schedule | `ScheduleTimeline` | Time on the spine. Trucks as rows | Place a stop | A month-grid costume |
| Inbox | `InboxPage` | The thread. The job beside it | Reply. Turn it into a job | A Messenger |
| Search | `SearchPage` | Results. Split preview | Open. Refine. | A bigger `⌘K` |
| Settings | `SettingsPage` | A column of settings | Save this section | One Save for five topics. A hex picker. Display that belongs on the view bar |
| Guided | `GuidedFlow` | One step | Arrive. Capture. Send. | A squeezed board |
| Evidence | `EvidencePage` | Question, number, table | Trust the number | Motion. A blue wash |
| Canvas | `CanvasWorkspace` | A plane of nodes, steps, or a map | Add a step. Run. Select. | A second product. A library theme |

Guided and Evidence may drop the inverted L. Name that. Everything else keeps it.

Showcase is not a room of this shell. [Cinematic](https://design.thorbis.com/skills/cinematic).

### Canvas

Workflow and Brain live here. So does any spatial work that is still the shop: a graph of steps, a map of stops, a tree of automations.

- The plane is the sheet, sitting on the canvas. Nodes are small sheets.
- Location names the graph: `After-hours leak` or `Brain`.
- View bar slices: `Map` / `List`, or `All` / `Leaks` / `HVAC`.
- Inspector is the selected node. Properties, not a second canvas.
- Create is a commit or a `C` modal. Not a costume stencil well that covers the location bar.
- List is still legal. A canvas that cannot become a list is a trap for a dispatcher on a phone.

If the spatial thing is a month calendar of the shop, stop. That is Schedule, or a named gap. Do not fake Schedule inside Canvas.

### Portal

The customer-facing Guided flow. Not a workbench. One action. The customer does not see the inverted L. They see a sheet and a commit. Do not pour Admin into the portal.

### When nothing fits

Stop. Write the gap. A named gap is work. A page-local shell is drift. **D-012**.

Do not add a room because a library came with a layout. The library sits inside a room we already named.

### New surface

How to invent something so it belongs. Constitution: `DESIGN.md`. Feel: [Product](https://design.thorbis.com/skills/product). Shell: shared Linear baseline. Craft: [UI](https://design.thorbis.com/skills/ui).

Do this in order. Write the answers. Then build.

### Protocol

1. **Person.** Dispatcher, tech, or owner. Device. What interrupted them.
2. **Profile.** Workbench, Guided, Evidence, or Showcase. One.
3. **One action.** The verb on this view.
4. **Surface.** Route, modal, popover, inspector, peek, or inline. **D-013**. Not a desktop drawer. **D-014**.
5. **Room.** List, Board, Record, Schedule, Inbox, Search, Settings, Guided, Evidence, Canvas.
6. **Search.** Token, primitive, occupant, component. **D-007**. If `CanvasWorkspace` exists, fill it.
7. **Gap.** If nothing fits, name it and stop. **D-012**. Do not invent a shell so the ticket can close.
8. **Join.** The new thing occupies the sheet. Chrome stays. Inspector stays available.
9. **Dress.** Panel, well, type, marker, one accent. Strip any library theme.
10. **Words.** Ours. Street first. Sentence case. The button is the verb.
11. **Keys.** `⌘K` `/` `J` `K` `Enter` `Space` `Esc` `C`. Visible path. **D-008**.
12. **States.** Empty, loading, error, disabled, permission, destructive. **D-009**.
13. **Narrow.** 390px. Inspector is a bottom sheet. 44px if it stands alone.
14. **Both themes.** Light is a retune. The choice persists.
15. **Audit.** The checklist on [Product](https://design.thorbis.com/skills/product). Two failures: do not ship.

Report: person, profile, room, surface, one action, reused, refused, how you checked.

### Worked: a canvas of nodes

The ask: “Build a canvas component with nodes.”

#### Answers, written down

| Question | Answer |
| --- | --- |
| Person | Dispatcher. Office. Keyboard. Building an after-hours leak path. |
| Profile | Workbench |
| One action | Add a step. Second: select a step and edit it. |
| Surface | Route. The graph is durable. Shareable. Revisit it. |
| Room | Canvas |
| Occupant | `CanvasWorkspace` on the sheet of `AppShell` |
| Create a step | Modal (`C`) or a commit on the sheet. One task. |
| Edit a step | Inspector. Stays beside the plane. |
| Change a type | Popover on the node or in the inspector |
| Peek a job the step points at | Space. Do not navigate away. |

Not a new app. Not a drawer. Not Showcase.

#### What the page is

```
AppShell
  sidebar            Jobs, Schedule, Inbox, Workflow, Brain, Books
  location bar       Workflow · After-hours leak
  view bar           Map | List
  sheet              CanvasWorkspace
    plane            bg. Pan and zoom are the work.
    node             panel. 14px radius. Title is the verb.
    selected node    accent rim or accent wash at 8%. Same as a live row.
    edge             marker. 1px. No neon. No arrows that shout.
    handle           field circle. 8–10px. Findable. Not a candy gem.
  inspector          The selected step. Name, when, who, the job it points at.
```

Location, view, sheet. No extra chrome row. No floating library toolbar over the location bar. Zoom, undo, snap: view-bar actions or a quiet cluster on the sheet, 28px chrome, 13 / 500, color-only hover.

#### How a node looks

- Fill `panel`. On the plane (`bg`) it lifts by tone, not a drop-shadow stack.
- Title 14 / 500 `fg`. `Dispatch to on-call`. Not `Node 4`. Not `N-1842`.
- Caption 12 / 500 `marker`. `After 5pm · Mike`.
- Status is a word on the node, same words as the rest of the app.
- Selected: accent. Focus: accent ring. Hover: slightly brighter panel. Three different things.
- Nested inputs on the node are wells. They do not appear until the inspector, unless the edit is inline and tiny.
- Radius 14 on the node. Inner controls: `inner = outer − padding`. [UI](https://design.thorbis.com/skills/ui).

Do not color nodes by type with olive / forest / pumpkin. Type is a word or a quiet Phosphor Regular 16 mark. Extras are not a type system.

#### How the library is used

A graph package is allowed as infrastructure. Its CSS is not.

Strip:

- The factory color palette
- The factory selection box
- The factory minimap chrome
- The factory attribution
- The factory typeface
- Glow, dash animations, emoji nodes

Keep:

- Pan, zoom, connect, snap
- Our tokens on every node, edge, handle, and control
- Our focus ring
- Our empty, loading, and error

If the package cannot be undressed, do not use it. Name the gap. Draw the plane with what we own.

#### Keys and mouse

| Input | Result |
| --- | --- |
| Click empty plane | Deselect |
| Click a node | Select. Inspector fills. |
| Drag a node | Move. 120ms is not required. The hand is the motion. |
| Drag a handle | Connect. Edge is marker until drop, then it stays marker. |
| `J` `K` | Move selection through nodes |
| `Enter` | Focus the inspector, or open the linked job |
| `Space` | Peek the linked job |
| `C` | Add a step. Modal. |
| `⌘K` | Go or do. “Add a step.” “Open 114 Oak.” |
| `Esc` | Deselect, or close the modal, or close peek |
| `/` | Filter nodes on this graph, or jump to List |

A trackpad pans. A mouse with no modifier may drag the plane when not on a node. Hover is gated.

#### Empty, loading, error

- Empty: the plane is still the sheet. Centered, not a hero. `No steps yet.` Commit: `Add a step`.
- Loading: the last graph shape, waiting. Not a spinner in a void.
- Error: `Could not save this step. Check the name.` Under the field if the field is the problem. A banner if the page is offline.
- Permission: `You cannot edit this workflow.` Do not show the hidden nodes.

#### Phone

- Sidebar is gone. Places live in command.
- Location and a short view bar stay.
- The plane is the sheet. Pan and zoom with fingers.
- Inspector is a bottom sheet when a node is selected.
- `Add a step` is a 44px commit, reachable by the thumb.
- List view is the default if the graph is unusable at 390px. Map is still offered. Do not ship a squeezed desktop editor.

#### What you refuse

- A second product called “the canvas app”
- A rainbow of node types
- Mini-map larger than a postage stamp, or styled like a game HUD
- `auto` layout that fights the dispatcher’s placement without a way to turn it off
- Animation on `⌘K`
- Light theme that inverts the graph into a different language

#### Done line

Workbench. Canvas. Route. One action: add a step. Occupant: `CanvasWorkspace`. Reused: `AppShell`, inspector, commit, well, accent for selected. Refused: the library theme, a new shell, type-as-color. Checked: desktop, 390px, keyboard, both themes.

### Other inventions, same join

| Ask | Room | Sheet holds | Inspector holds | Refuse |
| --- | --- | --- | --- | --- |
| A map of today’s stops | Canvas or Schedule | The map, or time as the spine | The selected stop | A consumer map skin |
| A photo of the leak | Record | The feed. The photo is evidence on the job | The photo’s meta | A lightbox as the page |
| A customer portal status | Guided | One sheet. One commit | — | The workbench L |
| An invoice PDF view | Evidence | The question and `$186.00` | — | Motion. Accent wash |
| Chat with the shop | Inbox | The thread | The job | A Messenger costume |
| A report builder | Evidence or Canvas | The question, then the table | The selected metric | A BI dashboard of equal cards |

If the ask is “make it pop,” you are being asked to break the feel. Do not. Quiet chrome. Precise work.

### Stop conditions

Stop and name the gap when:

- You need a second header to make the tool make sense
- You need a color the tokens do not have
- You need a desktop drawer because a route felt like too much work
- You cannot name the room
- You cannot name the one action
- The library cannot wear our surfaces

A named gap is the right output. A costume is not.

### Applied bookmark research

Reviewed 2026-09-06. These are Thorbis applications and review exercises, not replacements for DESIGN.md, COMPONENTS.md, or the owning skill. Linear remains the operational baseline. External advice that conflicts with the constitution stays out.

These worked examples are not a claim that the product behaviors have been implemented or verified.

#### Make the task easier, not the screen busier

Owning skill: [product](https://design.thorbis.com/skills/product).

A feature can look complete while the dispatcher still has to reconstruct context or wait for unrelated content.

Start from one person, interruption, and completed task. Keep the current job and its next action usable while optional evidence arrives. Treat the real constraint as part of the brief, not something polished away afterward.

**Thorbis example:** For assigning a tech, show the job, relevant availability, and the consequence of the assignment. Do not make the dispatcher traverse a marketing-style sequence or a new shell to finish a routine task.

**Verify:** Walk through the task with representative long and missing records. Check that the essential action remains understandable when optional content is slow or unavailable. Record the result rather than claiming a performance improvement without measurement.

**Do not import:** No additional shell, feature hero, framework migration, or new dependency. Keep the approved surface role.

Evidence: [Design Engineer Principles](https://vercel.com/design/engineer); [How we think about design](https://resend.com/handbook/design/how-we-think-about-design); [Component Architecture for React Server Components](https://aurorascharff.no/posts/component-architecture-for-react-server-components). [Source access limits](https://design.thorbis.com/research/bookmarks#application-product).

[All 26 sources and review limits](https://design.thorbis.com/research/bookmarks).

## Resilience

Review Thorbis features, architecture, migrations, incidents, and consequential workflows for multi-factor failure, degraded operation, recovery, observability, and human-in-the-loop safety. Use for payments, dispatch, tenant data, authorization, customer communication, AI actions, integrations, background work, offline sync, bulk actions, or any change with meaningful blast radius.

> **Linear baseline:** This skill specializes one part of Thorbis; it does not introduce another product grammar. Preserve quiet chrome, one dominant work region, structured density, stable action neighborhoods, contextual surfaces, visible keyboard paths, durable state, and role-adaptive mobile. Use the [Thorbis × Linear pattern matrix](https://design.thorbis.com/research/linear-patterns) only when the owning pattern is ambiguous.

<!-- thorbis-mobile-hig-reference -->
> **Mobile platform gate (D-025):** Every mobile-app task requires the [Native contract](https://design.thorbis.com/skills/native), HIG-001–HIG-022, and relevant live [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

Design for recovery, not imagined perfection. Complex systems contain changing faults, people keep them operating, and serious incidents usually require several conditions to align.

### Before the change

1. Name the intended business outcome and credible customer harm.
2. Map the services, stores, queues, vendors, people, and timing assumptions involved.
3. Trace at least three realistic failure paths:
   - one dependency or component failure;
   - one multi-factor path;
   - one human-plus-technical path.
4. Classify consequence, reversibility, coupling, uncertainty, and blast radius.
5. Define safe degraded behavior and the operator recovery path.

### Defenses

Use the smallest independent, observable, testable defenses that materially reduce harm.

- Enforce authorization and tenant isolation at every trusted boundary.
- Make retries idempotent or detect duplicates explicitly.
- Bound retries and timeouts. Prevent retry storms and infinite hidden work.
- Expose pending, stale, conflicted, partial, and failed states honestly.
- Preserve an audit trail for consequential state changes.
- Put irreversible or high-impact actions behind preview, confirmation, or policy.
- Make automation observable, interruptible, and recoverable by a person.
- Scope rollout with flags or migration stages when blast radius warrants it.
- Do not add more coupling than the defense removes.

### AI and agent identity

Agent identity and accountability are safety properties, not optional branding.

- Every agent has a persistent non-human identity and is visibly marked as an AI agent wherever it invokes, authors, suggests, acts, waits, or appears in evidence.
- Never give an agent a human identity treatment or present machine work as though it came from a person.
- Keep the accountable person or role visible when work is delegated. An agent may act; it is not the accountable human.
- Distinguish suggestion, pending approval, executing, completed, partial, failed, and committed product state.
- Consequential actions expose scope, external effects, reversibility, approval, audit, interrupt, and recovery paths.

Verify identity in compact, expanded, mobile, screen-reader, exported evidence, notification, and audit contexts. A hidden disclosure or a one-time onboarding message does not satisfy the contract.

### Review the operator

Ask what the dispatcher, technician, owner, support person, or agent knew at the time. Account for workload, production pressure, incentives, missing context, overrides, and common workarounds. Human adaptation is a defense to support, not noise to eliminate.

### Verify

Test the normal path plus the applicable degraded paths:

- unavailable and slow dependencies;
- stale data;
- duplicate, delayed, and out-of-order delivery;
- partial completion and retry;
- lost connectivity and reconnect;
- revoked or insufficient authorization;
- cross-tenant isolation;
- rollback, reconciliation, and manual recovery.

Require telemetry that reveals the business outcome, not only a successful API response.

### Incident output

Return:

- **Decision:** proceed, proceed with conditions, or redesign.
- **System boundary:** actors and components included.
- **Failure paths:** trigger, contributing conditions, defenses, impact, detection, containment, recovery.
- **Human factors:** available information, workload, incentives, overrides, and adaptations.
- **Required changes:** ordered by risk reduction.
- **Verification:** tests, telemetry, rollout, and rollback evidence.
- **Residual risk:** what remains accepted and why.

Name a proximate trigger when useful, but do not stop at a single root cause or “human error.” Recommend changes that reduce a class of harm without creating disproportionate complexity.

For low-consequence, easily reversible visual work, keep the review light. Ceremony scales with credible harm.

### Applied bookmark research

Reviewed 2026-09-06. These are Thorbis applications and review exercises, not replacements for DESIGN.md, COMPONENTS.md, or the owning skill. Linear remains the operational baseline. External advice that conflicts with the constitution stays out.

These worked examples are not a claim that the product behaviors have been implemented or verified.

#### Immediate acknowledgment is not confirmed success

Owning skill: [resilience](https://design.thorbis.com/skills/resilience).

A fast animation can falsely tell a person that money moved, a message arrived, or an assignment was saved.

Distinguish initiation, pending work, confirmed outcome, failure, and uncertain outcome. Show what is known. A repeated request needs a deliberate recovery path, not a second untracked business action.

**Thorbis example:** Collect payment keeps its label while the request is pending. A timeout says the result is not yet known and provides a way to check it; it does not invite an unconditional second charge. Confirmation names the actual result.

**Verify:** Review pending, explicit rejection, timeout after submission, reconnect, and repeat activation. Confirm that copy does not claim settlement from mere request acceptance and that a recoverable draft is preserved.

**Do not import:** No optimistic completion for consequential work, invented delivery guarantee, or success decoration that hides uncertainty.

Evidence: [7 Principles of Rich Web Applications](https://rauchg.com/2014/7-principles-of-rich-web-applications); [Philosophy](https://resend.com/philosophy); [Web Interface Guidelines](https://vercel.com/design/guidelines). [Source access limits](https://design.thorbis.com/research/bookmarks#application-resilience).

[All 26 sources and review limits](https://design.thorbis.com/research/bookmarks).

## Ecosystem

Make large Thorbis ecosystems feel simple. Use for discovery, collections, deep records, cross-device continuity, state-rich workflows, and contextual relationships.

> **Linear baseline:** This skill specializes one part of Thorbis; it does not introduce another product grammar. Preserve quiet chrome, one dominant work region, structured density, stable action neighborhoods, contextual surfaces, visible keyboard paths, durable state, and role-adaptive mobile. Use the [Thorbis × Linear pattern matrix](https://design.thorbis.com/research/linear-patterns) only when the owning pattern is ambiguous.

<!-- thorbis-mobile-hig-reference -->
> **Mobile platform gate (D-025):** Every mobile-app task requires the [Native contract](https://design.thorbis.com/skills/native), HIG-001–HIG-022, and relevant live [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

Use this skill when the problem is not a single control but the comprehensibility of a large connected system: many records, modules, relationships, states, devices, or ways into the same work.

This skill is derived from Thorbis research into Xbox.com’s discovery and ecosystem patterns, combined with Thorbis’s existing Apple, Linear, shadcn, accessibility, and product rules. It imports grammar, never gaming costume.

Reference: `content/design/XBOX_REFERENCE.md`.

### The premise

Do not make a large system look simple by pretending the system is small.

Make the next relevant part obvious.

Thorbis may contain CRM, properties, jobs, scheduling, communications, estimates, invoices, payments, inventory, finance, Sites, reporting, AI, fleet, media, and more. The interface must expose breadth progressively without turning the shell into a directory of everything.

### First read, second read, third read

Design complex surfaces in levels.

**First read — glance:**

- Where am I?
- What matters now?
- What needs action?
- What is the state?

**Second read — inspect:**

- metadata
- relationships
- timestamps
- supporting context
- secondary actions
- history

**Third read — intentional depth:**

- full record
- audit trail
- advanced configuration
- automation
- raw/technical detail

Do not make second- or third-read information compete with the first read.

### Curate before the explorer

A database is not a home screen.

Before `All`, offer operationally useful subsets when they genuinely reduce hunting.

Jobs may expose: Needs attention, Today, Unassigned, Running late, Awaiting approval, Ready to invoice.

Customers may expose: Recently active, Needs follow-up, Outstanding balance, New leads.

Inventory may expose: Low stock, Needed today, Recently used, Awaiting delivery.

Then provide the complete searchable, sortable, filterable explorer.

A curated collection and a full explorer are different patterns. Do not render the same table twice at different heights.

### Collection grammar

Prefer this information architecture when the domain is large:

`overview / curated subset → complete explorer → record → related records`

The user should be able to enter from a useful subset, widen to the complete dataset, inspect one object, and move into its relationships without returning to global navigation.

### Recognition before reading

Every major entity needs a stable silhouette.

- Customer: identity, name, state, contextual metadata.
- Property: photo/map, address, property markers.
- Job: trade/state, customer, location, schedule.
- Invoice: amount, payment state, customer, due date.
- Equipment: image, model, age, operational state.
- Technician: identity, availability, current assignment.

Keep ordering stable. Do not reshuffle metadata per page because there is room.

### Objects navigate to themselves

If an object is clearly a destination, the object is the link.

A job row opens the job. A property identity opens the property. A timeline event opens its source record. Do not add a redundant `View` button merely to make navigation possible.

Use real links for destinations. Preserve deep links, Back/Forward, Cmd/Ctrl+Click, middle-click, and open-in-new-tab.

### Preserve the shell; adapt the workspace

The Thorbis shell stays recognizable. The workspace optimizes for the job.

- Dashboard summarizes.
- Dispatch operates.
- Customer explains context.
- Finance transacts.
- Reports analyze.
- Settings configures.
- Canvas manipulates spatial systems.

Do not force all of them into one generic table/card/dashboard composition.

### State must survive without color

Consequential state uses plain language plus structure, iconography, shape, or position. Color reinforces it.

A person with color-vision deficiency, a monochrome printout, or a low-quality field display must still distinguish Draft, Scheduled, Dispatched, En route, On site, Needs approval, Approved, Declined, Due, Paid, Overdue, and Canceled.

Do not create a second state language for a new module.

### Brand color is scarce

Electric blue points. It does not paint.

Prefer it for:

- focus
- active navigation
- selection
- primary interaction
- links
- Thorbis identity
- meaningful live emphasis

Do not use blue as generic decoration. Scarcity makes the accent feel more premium and more informative.

### Relationships appear where they matter

A job can expose customer, property, technician, estimate, invoice, equipment, media, and communications contextually.

Do not add every relationship to the global sidebar.

The global shell answers “where can I work?” Context answers “what is connected to this thing?”

### Deep records keep orientation

Every deep object keeps four things understandable as the user moves through it:

1. identity
2. state
3. primary action
4. local navigation

For records with many sections, show the most relevant local tabs and move the rest into predictable overflow/command access. Do not force 10–15 equal tabs into one horizontal strip.

### Cross-device continuity

Change the interface for the device; preserve the state of the work.

A dispatcher can create a job on desktop, a tech can update it on mobile, a customer can approve through Portal, and the owner can review the result later. Those are different interfaces over the same work state.

Do not treat mobile as a separate product or a squeezed desktop. Do not lose context merely because the surface changed.

### Direct manipulation for spatial work

For property scans, LiDAR, infrastructure graphs, site plans, AR, equipment maps, and vehicle inspection, prefer user-controlled manipulation:

- pan
- zoom
- rotate
- select
- isolate
- filter layers
- jump to asset
- inspect history

Animation can teach a transition. It must not replace inspection.

### Content frames survive bad input

User content is hostile to visual perfection by accident.

Every media/content frame defines:

- aspect ratio
- crop / object position
- overflow
- fallback
- loading state
- missing state
- contrast protection
- long text behavior
- filename behavior
- error behavior

A poor property photo, huge logo, long customer name, malformed filename, or missing image must not break the surrounding product.

### Actions use concrete verbs

Prefer `Create estimate`, `Schedule job`, `Send invoice`, `Record payment`, `Add location`, `Assign technician`, `Call customer`.

Avoid vague enterprise verbs when the concrete action is known. The label should predict the result.

### Accessibility is component architecture

A component is not done until its relevant modes work:

- keyboard
- pointer
- touch
- visible focus
- screen reader semantics
- zoom/reflow
- contrast
- text scaling
- reduced motion
- non-color state

Use WCAG and WAI-ARIA as normative standards. Xbox Accessibility Guidelines are supporting research and examples.

### Premium test

Premium is control, not ornament.

A premium Thorbis surface has:

- fewer simultaneous focal points
- stable object grammar
- predictable state
- restrained accent
- strong content framing
- immediate first read
- optional depth
- no visual panic when the dataset grows
- no behavioral discontinuity across devices

### Refuse

- Gaming aesthetics imported literally
- Promotional density inside operational work
- Fake achievements, points, badges, or streaks
- Carousels as the default operational collection
- All-caps operational UI
- Decorative neon/glow/angled motifs
- Animation that delays work
- Color-only state
- A global nav item for every relationship
- Blank database views when a useful curated entry point is obvious
- A separate `View` button on every navigable object
- Desktop layouts merely shrunk onto phones

### Audit

- [ ] First read answers location, priority, action, and state
- [ ] Second-read detail is available without competing with the first read
- [ ] Large collections have useful entry points and a complete explorer
- [ ] Entity silhouettes are stable and recognizable
- [ ] Navigable objects use real links
- [ ] State is understandable without color
- [ ] Electric blue is used as signal, not paint
- [ ] Relationships are contextual rather than dumped into global navigation
- [ ] Deep records retain identity, state, action, and local orientation
- [ ] Device-specific UI preserves the same underlying work state
- [ ] Spatial information is directly manipulable when inspection matters
- [ ] Bad/missing user content cannot break the layout
- [ ] Actions use concrete verbs
- [ ] Accessibility modes are part of component acceptance

Two failures: revise before shipping.

### Applied bookmark research

Reviewed 2026-09-06. These are Thorbis applications and review exercises, not replacements for DESIGN.md, COMPONENTS.md, or the owning skill. Linear remains the operational baseline. External advice that conflicts with the constitution stays out.

These worked examples are not a claim that the product behaviors have been implemented or verified.

#### Preserve the place as the collection grows

Owning skill: [ecosystem](https://design.thorbis.com/skills/ecosystem).

Large customer, property, and inspiration collections become expensive to navigate when every inspection loses the current place.

Treat filters, selected records, scroll, and Back behavior as part of the task. Loading a child or optional panel should not reset the whole collection. A saved reference includes enough context to be useful when revisited.

**Thorbis example:** Open a property from a filtered customer list and return to the same filter and position. On the inspiration wall, reserve the media footprint and retain source credit even when the preview is unavailable.

**Verify:** Try refresh, Back and Forward, a direct record link, an empty result, a failed preview, and a long collection. Check that late data does not overwrite a draft or move the action under the pointer.

**Do not import:** No unbounded eager media, private information in shareable URLs, or a local-only storage promise borrowed from Copper.

Evidence: [7 Principles of Rich Web Applications](https://rauchg.com/2014/7-principles-of-rich-web-applications); [Component Architecture for React Server Components](https://aurorascharff.no/posts/component-architecture-for-react-server-components); [Philosophy](https://resend.com/philosophy); [Copper](https://shadcn.com/copper). [Source access limits](https://design.thorbis.com/research/bookmarks#application-ecosystem).

[All 26 sources and review limits](https://design.thorbis.com/research/bookmarks).

## UI

Build any Thorbis screen. Quiet chrome, one accent, work on the sheet. Use when designing or implementing UI.

> **Linear baseline:** This skill specializes one part of Thorbis; it does not introduce another product grammar. Preserve quiet chrome, one dominant work region, structured density, stable action neighborhoods, contextual surfaces, visible keyboard paths, durable state, and role-adaptive mobile. Use the [Thorbis × Linear pattern matrix](https://design.thorbis.com/research/linear-patterns) only when the owning pattern is ambiguous.

<!-- thorbis-mobile-hig-reference -->
> **Mobile platform gate (D-025):** Every mobile-app task requires the [Native contract](https://design.thorbis.com/skills/native), HIG-001–HIG-022, and relevant live [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

Craft for the operating system for the trades. Linear’s grammar. Our words. Tokens only.

This is its own skill. Drop it at `.agents/skills/ui.md`. Pick this file. Do not average it with the others.

Live: https://design.thorbis.com/skills/ui

[Rules](https://design.thorbis.com) is what we ship. [Research](https://design.thorbis.com/research) is the homework. [`DESIGN.md`](https://design.thorbis.com/design.md) is the constitution. [`AGENTS.md`](https://design.thorbis.com/agents.md) is the contract.

**This skill holds:** **D-003** (no raw visual values), **D-004** (interactive controls use the kit), **D-016** (prefer a mark), **D-017** (a radius is a curve you can see), **D-018** (a fill is one mix; no solid colored side rail), **D-019** (reserve the space), **D-020** (outline at rest, fill when this is the place), **D-021** (overlay is a mix), **D-023** (role owns prominence; the group owns geometry), **D-024** (attention orders media). The picture: figure and ground, proximity, the inverted L as composition.

**Homework:** Byron Wade — no borders on the page; a 1px rim on the field; one pour. Steve Schoger — start with too much space; remove until one more useful row fits. Rauno Freiberg — a sheet grows from the row that opened it. shadcn is the kit; we dress it. Grammar, not costume.

For inventing a new surface so it belongs, use [Product](https://design.thorbis.com/skills/product). For shell geometry use [Linear baseline](https://design.thorbis.com/research/linear-patterns). For iOS, Android, or desktop use [Native](https://design.thorbis.com/skills/native). For marketing and video use [Cinematic](https://design.thorbis.com/skills/cinematic). For motion, color, or type, open those skills after this one.

**References:** open one only when the task needs it.

- [Cloudflare forms](https://design.thorbis.com/skills/ui/references/cloudflare-forms): form kind, labels, field width, errors beside the field, and commit names.
- [Shopify Polaris](https://design.thorbis.com/skills/ui/references/shopify-polaris): collections, filters, saved views, bulk actions, multi-edit, record structure, and save state.
- [Vercel + Geist](https://design.thorbis.com/skills/ui/references/vercel-geist): choosing a primitive by role, semantic tokens, empty and loading states.

### First

Answer these, in order, before you draw.

1. Who is holding the device, and what just interrupted them? Dispatcher at 7 a.m. Tech in a crawlspace. Owner closing the books.
2. Which profile? Workbench, Guided, Evidence, or Showcase. One. Do not mix.
3. What already exists? Native control, then the kit, then last a new primitive. **D-004**. **D-007**.
4. What is the one action on this view? Dispatch. Arrive. Save invoice. Everything else is quieter.

Do not offer a menu of looks. Make the call. Write the interface.

### Profiles

| Profile | Where | Density | Motion |
| --- | --- | --- | --- |
| Workbench | Board, books, Admin | High. Keyboard. | Press only. |
| Guided | Arrive, estimate, portal | One action. | Rare; follow Motion. |
| Evidence | Invoice, report, audit | Paper. | None. |
| Showcase | Marketing, first-run | Product is the picture. | Delight only here. |

A dispatch board is not a landing page. If the surface is Showcase, stop and open [Cinematic](https://design.thorbis.com/skills/cinematic).

### Stack

`tokens → primitives → components → patterns → pages`

Pages fill patterns. They do not invent buttons.

1. Tokens own color, type, space, radius, shadow, motion. No hex in JSX. No `text-white`. **D-003**.
2. Primitives are the kit. Copy shadcn in, dress with tokens. Base UI when a primitive is missing. We own the styles.
3. Components are stable combinations: SearchField, DataTable, EmptyState, CommandMenu.
4. Patterns are List, Record, Settings, Evidence, Guided, Board, Inbox, Search, Canvas.
5. Pages put trade data in a pattern. A durable job is a route. A collect-payment is a modal. [Linear baseline](https://design.thorbis.com/research/linear-patterns) owns that call.

Search the registry before you create. A new primitive is design-system work, not a feature shortcut. **D-006**. **D-007**.

### Surfaces

Dark is the default product. Light is a retune, not an invert.

| Token | Dark | Light | Job |
| --- | --- | --- | --- |
| `bg` | near-black void | cream | Canvas. Never a working surface. |
| `panel` | `#171717` | paper white | The sheet. The job lives here. |
| `field` | one step darker | warm well | Inputs, wells, icon circles. |
| `fg` | cream `#f7f4ee` | warm ink | Titles, active, commits. |
| `body` | cool grey | warm grey | Sentences. |
| `marker` | quieter grey | quieter grey | Chrome, captions. |
| `accent` | electric blue | same blue | Brand, focus, the live row. |

- The sheet is brighter than chrome. They meet by tone. Regions have no borders as separators.
- A rounded figure that must be found has a 1px rim that follows the radius. Overflow clips content, not the stroke. Never an inset box-shadow as the outer edge of an overflowing box. Canvas-on-canvas without that rim is a defect. **D-017**.
- A field is a well: one step darker than its parent, inset, 1px rim.
- A commit is ink: type-color fill, inverse type, 10px radius, 1px rim.
- Same fill as the parent is illegal. If you cannot see the control, change the fill, not the stroke.
- Chips are pills. Icon-only is a circle. Sheets are 14px.
- Photos get a 1px rim that follows the radius, plus the same short lift.
- Nested radii stay concentric: `inner = outer − padding`.
- Depth is a whisper: 1px drop. The rim is a border. Not a card stack.
- Menu and place marks may carry a quiet extra (olive, forest, pumpkin, burnt, mixed accent). The word stays type-color. [Color](https://design.thorbis.com/skills/color).
- A fill is one mix. Never a gradient, mesh, or fade unless the brief names that wash. Never a solid colored border on the leading or trailing edge. Live is a word, a mark, or accent on the thing. **D-018**.

Numbers live in [Color](https://design.thorbis.com/skills/color).

### Controls

| Kind | Shape | Type | Visual height |
| --- | --- | --- | --- |
| Icon-only | circle | 16px mark | 28px |
| Chrome word | none | 13 / 500 | ~28px |
| Chip / pill | pill | 13 / 500 | ~28px |
| Field | well, 10px | 14 / 400 | Shared control density |
| Commit | ink, 10px | 14 / 500 | Shared control density |
| Isolated mobile | well or ink | 16+ | 44px |
| Sheet | 14px | — | — |

Use the compact or comfortable density defined in [`DESIGN.md`](https://design.thorbis.com/design.md#controls). The field and its actions share height and type size; weight and surface still express their roles. On mobile or a coarse pointer, use the touch size and at least 16px input type.

Desktop hit 40. Touch 44. Isolated mobile 44. Hit areas never overlap. If it looks tappable, the whole chip has to take the tap.

Prefer a mark. Add a word only when the action would be guessed wrong without it. **D-016**.

For action-neighborhood geometry and prominence, follow [`DESIGN.md`](../../DESIGN.md) **D-023**.

- Chrome is icon-only: search, theme, command, close, back, overflow. Accessible name. Title on a mouse. Regular at rest. Fill when this is the place. Directional marks flip in RTL. **D-020**.
- A commit keeps a word when it is destructive, when two commits sit together, when the mark is not a household verb, or when it is the one Guided action. `Save invoice`. `Cancel job`. `Arrive`.
- A value chip stays a word. `Leak` is not an icon.
- Labels persist. Placeholders are emptiness (`Mike Reyes`), not the label (`Enter name`).
- Help sits under the field. An error takes its place. Not a toast.
- Loading morphs the mark and turns. If a word is there, the word stays. Do not swap Save for a spinner. Dispatching twice creates two trucks.
- Hover is color only. No wash behind a nav word. Gate it: `(hover: hover) and (pointer: fine)`.
- Focus is visible and is not selection. Accent ring. Keyboard works everywhere.
- `⌘K` is instant. Do not animate it.
- If it lifts, you can press it.
- Two rimmed controls keep 12px. Field to commit is 12px. A name field kissing Dispatch reads as one mashed control in the van.
- Overlay is a mix, not a blur. A popover grows from its trigger. A menu fades. **D-021**.
- A full-width commit sits in the sheet’s pad, not flush to the viewport.
- Media has an `aspect-ratio`. A horizontal list shows 16–32px of the next item. Fade a list that continues. **D-019**.
- For media delivery order, follow [`DESIGN.md`](../../DESIGN.md) **D-024**.
- Destructive money is a modal. Voiding an invoice is money. Do not confirm “Mark arrived.”

### Type and words

Inter Variable for UI. Geist Mono for code, the shop's printed number, and money. Details in [Type](https://design.thorbis.com/skills/type). Chrome is 13. Content is 14.

| Ours | Not |
| --- | --- |
| Job | Ticket, case, request |
| Stop | Appointment slot |
| Tech | Agent, resource, user |
| Truck | Vehicle asset |
| Board | Kanban, pipeline |
| Sheet | Modal, drawer, card |
| Dispatch | Assign, allocate |
| Arrive | Check in, clock |

Street first. `114 Oak`, then the leak. Not `JOB-1842` as the title. Status is a word: Open. En route. On site. Not a green blob.

Sentence case. When a control has a word, it names the action: `Save invoice`, not `Continue`. Prefer a mark. Empty names the one action. Errors name the problem and the exit.

### Picture

One focus. The sheet is figure. Chrome is ground.

Every view has one thing they came to do, and one place the eye should land.

- Workbench: the selected row, the record title, the field they are in.
- Guided: the step. Then the commit.
- Evidence: the number.
- Showcase: the object. [Cinematic](https://design.thorbis.com/skills/cinematic).

If two things shout, neither is read. Size, position, and weight do the shouting. Color last. Accent is the live thing, not the layout.

| Law | Means | In Thorbis |
| --- | --- | --- |
| Figure and ground | Work on a quieter field | Sheet on canvas. Canvas is never the work. |
| Negative space | Empty is structure | Tight inside a group. Generous between groups. Measure 65–75ch. |
| Hierarchy | Size, then position, then weight | 32 title. 16 section. 14 body. 13 chrome. No kicker. |
| Proximity | Close means related | Label, field, help. Not a card per field. |
| Similarity | Same look, same kind | One commit shape. One well. One chip. |
| Continuity | The eye follows a line | Inverted L. Sidebar, location, sheet. Do not break it with a second header. |
| Alignment | Edges agree | Type, fields, commits share a start. Do not mix center and start on one sheet. |
| Contrast | Difference is the signal | Well vs sheet. Ink vs quiet. Live row vs the rest. |
| Balance | Weight, not decoration | A long list is the weight. Chrome stays quiet so it can carry it. |

Golden ratio is not a layout tool here. Thirds are for Showcase and video. A dispatch list is a column, not a poster.

Read top-left to the sheet. F-pattern on a list. Z-pattern only on Guided and Ask, where there is one title and one commit.

- Street first in the row. Time is a column. Status is a word on the end.
- The primary action sits with the work, not in a dashboard of equal buttons.
- More space above a heading than below it. The heading belongs to what follows.

Do not place a commit on a thirds intersection to “feel cinematic.” That is Showcase. On a board it is costume.

Rest, sink, lift, overlay. Four, not five. The sheet is planar. A field sinks. A commit lifts. A menu overlays. Hover is none of these. If it lifts, you can press it. A drop shadow on a heading is a lie.

Media has an `aspect-ratio` before it loads. A skeleton matches the hole. A horizontal list shows 16–32px of the next item so it does not read as the end. Where a list continues, fade the edge. **D-019**. A van photo that pops in after the row has already been read shoves the next job. Delivery order follows [`DESIGN.md`](../../DESIGN.md) **D-024**.

A mix, not a blur. The board behind Collect payment stays sharp and one step dimmer. A popover grows from its trigger. **D-021**.

### Floor

- Body contrast APCA |Lc| ≥ 75. Fix with lightness, not hue. [Color](https://design.thorbis.com/skills/color).
- Chrome is 13. Content is 14. Measure 65–75ch. Headings `balance`. Body `pretty`.
- Hover gated. `100dvh`. `viewport-fit=cover`. Tap highlight off.
- Inputs on a phone are 16px or larger. Never `user-scalable=no`.
- States exist: hover, disabled, loading, error, empty, permission, destructive. **D-009**.
- Real trade data. Not Acme. Not Lorem.
- Desktop 40. Touch 44. Destructive money is a modal.
- Light and dark are both first-class. Theme still sticks.

### Never

- A second visual language on one product
- A line around a region as a separator
- A radius whose corners disappear
- An inset box-shadow as the outer edge of a clipped radius
- Canvas-on-canvas without a rim
- A wash behind a nav word
- Card-of-cards as the page
- A second header invented by the page
- Animation on a shortcut
- Marketing copy on a board
- A desktop drawer used as a page
- A nested overlay
- Hex, `text-white`, or a raw shadow in product code
- A word on a button a mark would have made obvious
- Icon-only chrome with no accessible name
- A gradient, mesh, or fade across a surface, unless the brief named that wash
- A solid colored border on the leading or trailing edge of a row, a card, a quote, a callout, or a sheet
- A blurred overlay
- A scroller that hides the next item
- Layout shift from a photo without an aspect-ratio
- A thirds grid on a workbench
- Filling negative space because it looked empty
- A second focal point “for balance”

### Done

Name the profile, the one action, and the token or primitive you used. Name anything you refused.

### Applied bookmark research

Reviewed 2026-09-06. These are Thorbis applications and review exercises, not replacements for DESIGN.md, COMPONENTS.md, or the owning skill. Linear remains the operational baseline. External advice that conflicts with the constitution stays out.

These worked examples are not a claim that the product behaviors have been implemented or verified.

#### A control keeps its meaning through every state

Owning skill: [ui](https://design.thorbis.com/skills/ui).

A button that changes width, a field that loses input, or a dialog that loses focus breaks the task even when the resting design looks precise.

Review the approved primitive as a sequence: resting, focused, activated, pending, resolved, and recovered. Keep the action label and footprint stable, associate errors with their fields, and preserve a visible keyboard path.

**Thorbis example:** Save estimate remains Save estimate while its state mark changes. A validation error keeps the entered values, explains the repair beside the field, and moves focus only when the interaction calls for it.

**Verify:** Test Tab, Shift-Tab, Enter, Escape where applicable, paste, invalid input, rapid activation, and a slow response. Repeat at 390px, in both themes, with zoom and reduced motion.

**Do not import:** No hand-built duplicate primitive, hidden label, disabled browser zoom, or borrowed shadow-only outer edge that violates D-017.

Evidence: [Web Interface Guidelines](https://vercel.com/design/guidelines); [Invisible Details](https://invisibledetails.com/); [components.build](https://www.components.build/); [Details that make interfaces feel better](https://interfaces.dev/magazine/issues/details-that-make-interfaces-feel-better). [Source access limits](https://design.thorbis.com/research/bookmarks#application-ui).

[All 26 sources and review limits](https://design.thorbis.com/research/bookmarks).

## Motion

Decide if something should move, then implement 120ms ease-out transform and opacity. Use when adding motion, press, or a transition.

> **Linear baseline:** This skill specializes one part of Thorbis; it does not introduce another product grammar. Preserve quiet chrome, one dominant work region, structured density, stable action neighborhoods, contextual surfaces, visible keyboard paths, durable state, and role-adaptive mobile. Use the [Thorbis × Linear pattern matrix](https://design.thorbis.com/research/linear-patterns) only when the owning pattern is ambiguous.

<!-- thorbis-mobile-hig-reference -->
> **Mobile platform gate (D-025):** Every mobile-app task requires the [Native contract](https://design.thorbis.com/skills/native), HIG-001–HIG-022, and relevant live [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

Two failures. The first is worse.

1. Animating something that should not move.
2. Moving the right thing the wrong way.

This is its own skill. Drop it at `.agents/skills/motion.md`. Pick this file. Do not average it with the others.

Live: https://design.thorbis.com/skills/motion

[Rules](https://design.thorbis.com) is what we ship. [Research](https://design.thorbis.com/research) is the homework. [`DESIGN.md`](https://design.thorbis.com/design.md) is the constitution. [`AGENTS.md`](https://design.thorbis.com/agents.md) is the contract.

**This skill holds:** frequency-first motion, `--motion-fast` and `--ease-out`, **D-021** (overlay is a mix, a popover grows from its trigger, a menu fades), and the motion half of **D-022** (a Film sequence may follow scroll; the browser still owns the wheel).

**Homework:** Emil Kowalski. Most UI does not need to move. 100dvh. Hover only if they can hover. Rauno Freiberg: a sheet grows from the row that opened it. High-frequency menus stay still. Grammar, not a spring showcase.

Do not offer a menu of motions. Make the call.

### First

1. How often does this happen? A hundred times a day does not animate.
2. Who is holding it? Keyboard is instant. A thumb may drive a sheet. A visitor on Film may own a sequence.
3. What is the purpose? Feedback, space, state, or continuity. If you cannot name it, do not build it.
4. Which token? `--motion-fast`, `--motion-overlay`, `--ease-out`. No private curve.

A dispatcher with vestibular issues still has to run the morning board. Instant is the respectful default.

### Gate

| Frequency | Decision | Examples |
| --- | --- | --- |
| 100+ / day | No animation. | `⌘K`, shortcuts, row focus, `J` `K` |
| Tens / day | Near nothing. Color only. | Hover, selected row |
| Occasional | 120–200ms. | Dialog, sheet, toast |
| Rare / Showcase | The only delight budget. | First-run, marketing cut |

On a Film page, scroll may drive a sequence. The visitor owns speed and reverse. The browser still owns the wheel. Do not pin the page. Motion must explain a join. Headings that drift: refuse. **D-022**. [Cinematic](https://design.thorbis.com/skills/cinematic).

Keyboard is instant. Destructive commits on release, not on press. Swipe-to-cancel a job commits when the thumb lifts, so they can abort mid-swipe with muddy gloves.

If the animation does not help them see what changed on a job, cut it.

| Purpose | Allowed |
| --- | --- |
| Feedback | Press dim, success tick |
| Space | Sheet from an edge |
| State | Dialog in, toast in |
| Continuity | Shared element on Showcase |

### Tool

| Need | Tool |
| --- | --- |
| Hover, press, color | CSS transition |
| Mount, no JS | `@starting-style` |
| Known sequence | CSS animation |
| Programmatic | WAAPI |
| Spring or gesture | Motion |

Do not install a library for a fade. Don’t ship a spring library so a toast can fade. CSS is enough for almost every shop-floor motion.

### Ingredients

- `transform` and `opacity` only. `clip-path` allowed. `height` only for accordions. Jank on the board loses the 7 a.m. window.
- Never `scale(0)`. Start at `0.95` plus fade, or do not scale. A bounce looks like a game, not a job.
- `--ease-out: cubic-bezier(0.23, 1, 0.32, 1)`. Never `ease-in` on UI. A sheet that eases in late feels broken. First frame already moving.
- Press 80–120ms. Hover 100–120ms. Dialog and sheet 160–200ms. Ordinary web UI transitions take at most 200ms. Popovers and menus use the event recipes below. A slow drawer on a job they open 80 times a day is stolen time.
- Exit the way it entered. Exit quieter than enter. Interrupt with transitions, not keyframes. They will tap another job before the first inspector finishes. The next one has to win.
- Overlay is a mix, not a blur. A popover grows from the control that opened it. A menu fades; it does not fly off the screen. **D-021**.
- Reduced motion: keep opacity, drop movement.
- Hover motion gated to `(hover: hover) and (pointer: fine)`.
- `will-change` only on `transform` or `opacity`, and only if the first frame stutters. Take it off when the motion ends. Never `will-change: all`.

```css
--ease-out: cubic-bezier(0.23, 1, 0.32, 1);
--motion-fast: 120ms;
--motion-overlay: 180ms;
```

Copy the token. Do not invent a curve.

### Recipes

| Event | Recipe |
| --- | --- |
| Press | opacity or brightness, 80–120ms, ease-out |
| Hover color | color, 120ms, gated to a real mouse |
| Dialog | opacity + translate 8px, 160–200ms; `--motion-overlay` is 180ms |
| Sheet | translate from its edge, 200ms, reduced-motion = opacity |
| Popover | scale from the trigger, 120–160ms. Origin is the control. |
| Menu close | opacity, 80–120ms. Do not fly off screen. |
| Toast | opacity, 120ms |
| Sidebar | transform + negative margin. Never `width`. |
| `⌘K` | Instant. No scale. No fade. |
| Showcase enter | Stagger ~100ms on first load only. Title, then copy, then the shot. Never on a board. |

If two things move, they are one event, not two shows. A first-run empty state can arrive in pieces. The morning board cannot.

A status icon that pops in next to On site can fade. The whole toolbar cannot.

Closing a job sheet should get out of the way. The row they picked may flash as the inspector closes, so they know which job they just edited. The next job is the show.

The finger drives the sheet. A canned animation that ignores the swipe fights them.

A popover from a job row grows from that row. From the center it feels like a different product.

### Showcase

Delight lives here only. Do not export this motion into Admin.

On Film, a sequence may be tied to scroll: it moves when they move, pauses when they stop, reverses when they go back. Do not pin the page and fake a reel. Do not hijack or artificially slow the scroll.

Motion must explain a join, a before/after, a config, a dimension, a workflow. Headings that drift, cards that float, objects that spin for atmosphere: refuse.

Preserve one subject. Change one or two properties. Many objects moving at once is a template, not a film.

Reduced-motion stills of the same crop. A usable page before cinematic assets load. [Cinematic](https://design.thorbis.com/skills/cinematic).

### Never

- `transition: all`
- Animation on `⌘K`
- Ungated `:hover`
- Everything at once
- A bounce on a workbench control
- Animating `width` on the sidebar. Use transform plus negative margin.
- `backdrop-filter` as an overlay
- `will-change: all`
- A private cubic-bezier
- A spring library for a fade
- Cinematic stagger on a board
- Motion that only resembles Apple

### Audit

- [ ] Frequency named. 100+/day is instant
- [ ] Purpose named, or motion refused
- [ ] Token curve and duration. No private easing
- [ ] `transform` and `opacity` only (or a named accordion)
- [ ] Overlay is a mix. Popover grows from its trigger. Menu fades. **D-021**
- [ ] Reduced motion: opacity only
- [ ] Hover gated to a real mouse
- [ ] Keyboard path is instant
- [ ] If Showcase: the motion explains a join. **D-022**

Two failures: do not ship.

### Done

State the gate, the tool, the curve, the duration. If you refused motion, say so. That is success.

### Applied bookmark research

Reviewed 2026-09-06. These are Thorbis applications and review exercises, not replacements for DESIGN.md, COMPONENTS.md, or the owning skill. Linear remains the operational baseline. External advice that conflicts with the constitution stays out.

These worked examples are not a claim that the product behaviors have been implemented or verified.

#### Frequent work stays immediate; allowed motion can be interrupted

Owning skill: [motion](https://design.thorbis.com/skills/motion).

A small delay repeated through a working day becomes friction, and a transition that restarts from the wrong position disconnects feedback from input.

Apply the existing profile first: Workbench is press-only, Evidence has no motion, and other profiles remain constrained by their owner. Where a transition is already permitted, preserve continuity and the state footprint when input interrupts it.

**Thorbis example:** Command-menu selection follows the key immediately. A permitted popover opens from its trigger and survives open-close-open without snapping, losing focus, or changing the action label.

**Verify:** Repeat the interaction rapidly, switch between input methods, and test reduced motion. Compare with the nonanimated version at ordinary task speed. Use existing tokens rather than copying durations or curves from an article.

**Do not import:** No row stagger in routine work, delayed keyboard highlights, ornamental blur, minimum success delay, or automatic spring-library adoption.

Evidence: [You Don't Need Animations](https://emilkowal.ski/ui/you-dont-need-animations); [7 Practical Animation Tips](https://emilkowal.ski/ui/7-practical-animation-tips); [Train Your Judgement](https://emilkowal.ski/ui/train-your-judgement); [Details that make interfaces feel better](https://interfaces.dev/magazine/issues/details-that-make-interfaces-feel-better). [Source access limits](https://design.thorbis.com/research/bookmarks#application-motion).

[All 26 sources and review limits](https://design.thorbis.com/research/bookmarks).

## Composition

Build compound components. No boolean-prop soup. Use when a component is growing flags.

> **Linear baseline:** This skill specializes one part of Thorbis; it does not introduce another product grammar. Preserve quiet chrome, one dominant work region, structured density, stable action neighborhoods, contextual surfaces, visible keyboard paths, durable state, and role-adaptive mobile. Use the [Thorbis × Linear pattern matrix](https://design.thorbis.com/research/linear-patterns) only when the owning pattern is ambiguous.

<!-- thorbis-mobile-hig-reference -->
> **Mobile platform gate (D-025):** Every mobile-app task requires the [Native contract](https://design.thorbis.com/skills/native), HIG-001–HIG-022, and relevant live [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

Flags double the state space. Compose the pieces the surface needs.

This is its own skill. Drop it at `.agents/skills/composition.md`. Pick this file. Do not average it with the others.

This chapter is **code composition**. How a *picture* is built lives in UI. How a *video* is framed lives in Cinematic. How a *new surface* joins the shell lives in Product. Do not mix them.

Live: https://design.thorbis.com/skills/composition

[Rules](https://design.thorbis.com) is what we ship. [Research](https://design.thorbis.com/research) is the homework. [`DESIGN.md`](https://design.thorbis.com/design.md) is the constitution. [`AGENTS.md`](https://design.thorbis.com/agents.md) is the contract.

**This skill holds:** **D-002** (the compound does not own chrome), **D-004** (use the kit; do not hand-build a dialog), **D-005** (a new variant needs a semantic reason and a canonical owner), **D-006** (a new primitive is design-system work), **D-007** (search the registry), **AG-001**, **AG-003** (use generators and primitives that already exist; fill behavior; do not invent structure).

**Homework:** John Ousterhout — deep modules; a file that grows past the job gets split. React composition. shadcn is a start; we own the CSS. Base UI when the kit is missing. Grammar, not a second component kit.

### First

If a boolean exists to hide a slot the caller could have omitted, delete the boolean.

If two call sites share 90% of the markup, that is success. The 10% is why they are not one component with a `variant`.

Search the registry before you add a piece. A duplicate is a defect. **D-007**. **AG-001**.

Interactive controls use the kit. Do not hand-build a dialog. **D-004**.

A new variant needs a semantic reason and a canonical owner. `destructive` is a reason. `isInvoice` is not. **D-005**.

A new primitive is design-system work, not a feature shortcut. **D-006**.

### Test

**Don’t**

```tsx
<Composer isThread isEditing showNotify tone="job" />
```

**Do**

```tsx
<DispatchThreadComposer>
  <Composer.Input />
  <Composer.Notify />
  <Composer.Footer>
    <Composer.Submit>Dispatch</Composer.Submit>
  </Composer.Footer>
</DispatchThreadComposer>
```

Name the thing after the job: `JobNoteComposer`, `InvoiceLineTable`, `ArriveSheet`, `WorkflowCanvas`. Not `SmartPanel`. Not `SmartBoard`. Not `InfiniteCanvas`.

### Rules

1. Export pieces, not configurations. The caller omits what it does not need.
2. A variant is a name (`JobNoteComposer`), not a flag (`variant="job"`).
3. Context holds state, actions, meta. Do not leak setters. Expose `save`, not `setDirty`.
4. Lift state so a toolbar Save and a dirty-dot can see it. Do not sync two `useState`s.
5. React 19: refs are props. No `forwardRef`.
6. Feature logic stays out of a shared primitive. A primitive does not know what a job is. Do not put feature copy in it.
7. Search the registry before you add a piece. **D-007**. **AG-001**.
8. A compound does not paint `AppShell`. Chrome is the page’s. The compound is the work on the sheet. **D-002**.
9. Use generators and primitives that already exist. Fill behavior. Do not invent structure. **AG-003**.
10. One button. One field. One dialog. Variants are semantic (`destructive`, `ghost`), not `isInvoice`.
11. Do not import a second component kit. Do not hand-roll a menu or a tabs list.

### Compound pattern

```
Provider     state, actions, meta
  Frame
    Input
    Footer
      Submit
      Cancel
```

Callers omit what they do not need. No `showX` props.

Context exposes verbs (`save`, `reset`, `busy`) and facts (`dirty`, `error`). It does not expose `setState`.

If a flag starts to branch markup, split. Do not wait until you “feel tidy.”

Keep one component when every caller needs the same slots in the same order.

A new occupant of the sheet (`WorkflowCanvas`, `InvoiceLineTable`) is a named compound. It is not a page-local shell. **D-012**. Inventing the occupant: [Product](https://design.thorbis.com/skills/product).

### Worked: a note on a job

The ask: a composer that can be a thread, a job note, or an invoice comment, with optional notify, optional attachments, optional “also dispatch.”

That is three compounds, not one with flags.

- `JobNoteComposer` — note on a job. Footer is Save. Notify is omitted.
- `DispatchThreadComposer` — thread. Notify is a piece. Submit is Dispatch.
- `InvoiceCommentComposer` — comment on an evidence page. No notify. No dispatch.

Shared pieces live in `Composer.Input`, `Composer.Footer`, `Composer.Submit`. Shared does not mean one mega-component.

The primitive under them is the kit’s field and commit. The composer does not know what a job is beyond the name on the submit.

### Worked: a table growing flags

`DataTable` with `isInvoice`, `showTotals`, `stickyHeader`, `compact`, `hideFilter` is soup.

- Density is a view on the view bar, not a flag. **D-015**. Preserve the shared Linear baseline.
- Totals are `InvoiceLineTable`, a named compound, because the math is the job.
- Sticky header is the pattern’s, not a boolean the page passes in.
- Filter lives in the view bar, not inside the table.

If `DataTable` already exists, fill it. If invoice math does not fit, name `InvoiceLineTable` and say why. Do not add `isInvoice`.

### Split

Split when a flag starts to branch markup.

Keep together when the slots are the same and the difference is data.

A primitive that grows a `tone="job"` is a primitive that now knows the domain. Move the domain up. Leave the primitive stupid.

Feature code consumes primitives. It does not fork a color, a radius, or a dialog “for this invoice.” **D-003**. **D-004**.

### Never

- `variant: "job" | "thread"` that branches in every child
- Feature logic in a shared primitive
- A second kit imported beside the one we own
- `showX` / `hideY` / `isZ` growing past two
- A compound that paints its own page chrome
- A boolean to hide a slot the caller could have omitted
- Hand-building a dialog that the kit already has. **D-004**
- A new primitive on a feature ticket. **D-006**
- `forwardRef`
- Two `useState`s kept in sync “for now”

### Audit

- [ ] Registry searched. **D-007**. **AG-001**
- [ ] Kit dialog, menu, tabs reused. **D-004**. **AG-003**
- [ ] No `showX` for a slot the caller can omit
- [ ] Named after the job, not `Smart*`
- [ ] Context exposes verbs and facts, not setters
- [ ] Does not paint `AppShell`. **D-002**
- [ ] New variant has a semantic reason and an owner. **D-005**
- [ ] Primitive still does not know what a job is

Two failures: do not ship.

### Done

Name the compound, the pieces you exported, and the boolean you deleted. Name the primitive you reused. If you named a gap instead of inventing a shell, that is success.

### Applied bookmark research

Reviewed 2026-09-06. These are Thorbis applications and review exercises, not replacements for DESIGN.md, COMPONENTS.md, or the owning skill. Linear remains the operational baseline. External advice that conflicts with the constitution stays out.

These worked examples are not a claim that the product behaviors have been implemented or verified.

#### Make invalid combinations difficult to express

Owning skill: [composition](https://design.thorbis.com/skills/composition).

Independent loading, success, and error flags can contradict each other; presentation and business logic become tangled as a component grows.

Choose an explicit state model and a semantic composition API. Reuse the approved primitives, keep domain operations outside them, and locate loading boundaries according to the work they protect. Documentation names which variants actually ship.

**Thorbis example:** A payment dialog composes an approved trigger, content, fields, and actions around a domain-owned operation. The button receives one coherent request state, not several competing booleans and a private set of colors.

**Verify:** Exercise each valid state and transition, keyboard and focus behavior, controlled and uncontrolled contracts where supported, server-rendered output, and slow or missing data. Check provenance and license before source adoption.

**Do not import:** No arbitrary color escape hatch, duplicate component kit, unregistered dependency, or migration from Astro merely because a source uses RSC.

Evidence: [React handbook](https://devouringdetails.com/resources/react-handbook); [components.build](https://www.components.build/); [Component Architecture for React Server Components](https://aurorascharff.no/posts/component-architecture-for-react-server-components); [shadcncraft](https://shadcncraft.com/). [Source access limits](https://design.thorbis.com/research/bookmarks#application-composition).

[All 26 sources and review limits](https://design.thorbis.com/research/bookmarks).

## Tracking

Keep Linear as the only board. Search before create, every issue on a milestone, close the loop. Use when planning, starting, or finishing work.

> **Linear baseline:** This skill specializes one part of Thorbis; it does not introduce another product grammar. Preserve quiet chrome, one dominant work region, structured density, stable action neighborhoods, contextual surfaces, visible keyboard paths, durable state, and role-adaptive mobile. Use the [Thorbis × Linear pattern matrix](https://design.thorbis.com/research/linear-patterns) only when the owning pattern is ambiguous.

<!-- thorbis-mobile-hig-reference -->
> **Mobile platform gate (D-025):** Every mobile-app task requires the [Native contract](https://design.thorbis.com/skills/native), HIG-001–HIG-022, and relevant live [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

Linear is the source of truth. Not a side tool. Not a second board in another app.

This is its own skill. Drop it at `.agents/skills/tracking.md`. Pick this file. Do not average it with the others.

[`AGENTS.md`](https://design.thorbis.com/agents.md) is the contract. This file is how work is filed and closed. A visual change still follows UI. A new surface still follows Product. This skill does not replace those. It is the loop around them.

Live: https://design.thorbis.com/skills/tracking

[Rules](https://design.thorbis.com) is what we ship. [Research](https://design.thorbis.com/research) is the homework. [`DESIGN.md`](https://design.thorbis.com/design.md) is the constitution.

**This skill holds:** **AG-001** (search before you create), **AG-006** (a structural decision is written down first), **AG-007** (say what changed and how you checked it), **AG-008** (report failures; do not hide a skipped step), **AG-009** (an agent does not approve its own exception), **AG-010** (do not merge your own work), **AG-011** (if the change is large, split it), **D-007** (search the registry the same way), **D-011** (gold screens have screenshot baselines).

**Homework:** Tuomas Artman — papercuts in seven days; the team is trained to see them. Karri Saarinen — quality is the north star; reduce scope. Linear is the board we keep. Grammar, not a second tracker.

### First

Search. Reuse the issue that exists. Do not open a twin.

Search by outcome, by file, by the last title you almost typed. If it is already In Progress, comment and join. Do not file a shadow. Search the registry the same way: a duplicate component is a defect. **AG-001**. **D-007**.

If the change is large, split it before you call it done. **AG-011**.

A structural decision gets written down first. Then you build it. **AG-006**.

Choose the decision's owning skill using the [skill selection policy](https://design.thorbis.com/agents.md#skills). Record that owner and any required specialist or mandatory Native context. Do not average competing rules.

### File

1. Every issue has a milestone. If it is not on one, it is not planned.
2. Titles are outcomes (`Focus ring matches accent`), not chores (`Fix CSS`).
3. One outcome per issue. Description is the brief. Acceptance is a list the next person can check against Rules and the skill you followed.
4. Papercuts are real. File them. Do not batch “we’ll polish later.”
5. A due date without a milestone is decoration. Prefer the milestone. Use a date only when the outside world constrains us (launch, payroll, install).
6. Name the person the work is for. Dispatcher, tech, or owner. Name the profile. Workbench, Guided, Evidence, or Showcase.
7. Record the owning skill and required context selected under that policy.

### Lifecycle

Search → reuse or file → milestone → start → evidence → done.

| State | Meaning | You may |
| --- | --- | --- |
| Backlog | Not this milestone | Leave it. Do not start it. |
| Todo | Ready | Start it. |
| In Progress | Someone is on it | Work it. Leave a note if you stop overnight. |
| In Review | Built, not checked | Attach evidence. Ask for the check. |
| Done | Checked. Evidence in the thread. | Nothing. It is closed. |

Done means verified. A successful build alone is not completion. Report what each check actually proves and supply the applicable interaction and accessibility evidence.

Leave In Progress overnight only with a note: what landed, what is open, where to pick up.

In Review is not Done. Attach the check. Then close.

Nothing ready sits in Backlog. Nothing unfinished sits in Done.

### Evidence

In the thread, say:

- What you opened (desktop, 390px, both themes)
- What you pressed (keyboard path, `⌘K`, the commit)
- What you refused (a second shell, a gradient, a solid colored side rail, a word on a mark)
- Which skill owned the decision and what additional context was required
- A screenshot or a clip when the change is visual

This is **AG-007** and **AG-008**. Report failures. Do not hide a skipped step.

Gold screens have screenshot baselines. **D-011**. If the screen and `DESIGN.md` disagree, the constitution wins and the screen is a bug.

Two AG failures: do not ship.

### Close

The issue matches reality. Evidence is attached. Blockers are named as their own issues, on a milestone.

An agent does not approve its own exception. A human does. **AG-009**. A comment in the PR that says “had to” is not an exception.

Do not merge your own work. **AG-010**.

### Worked: a papercut

The miss: hover wash behind a nav word on Jobs.

1. Search Linear for “nav hover” and “Jobs wash.” Search the registry for the nav primitive.
2. Reuse the issue if it exists. If not, file: `Nav word hover is color only`. Milestone: this week’s papercuts. Person: dispatcher. Profile: Workbench. Skill: UI.
3. Acceptance: no wash behind the word; hover gated to a real mouse; both themes; 390px unchanged.
4. Build against [UI](https://design.thorbis.com/skills/ui). Do not open Color to invent a grey.
5. Evidence: desktop hover, a phone (no hover), light and dark, a screenshot of Jobs.
6. In Review. A human checks. Then Done.

Do not batch this with “also the focus ring, also the empty state.” Those are other issues.

### Worked: a large change

The ask: a canvas of workflow nodes.

1. Write the decision first. Room: Canvas. Occupant: `CanvasWorkspace`. Surface: route. Skill: Product. **AG-006**. [Product](https://design.thorbis.com/skills/product).
2. Split before you call it done. **AG-011**. Issues, not a saga:
   - `Workflow is a Canvas occupant of AppShell`
   - `A step is a small sheet with trade words`
   - `Inspector holds the selected step`
   - `Library theme is stripped`
3. Each issue names Product, or UI, or Composition. Not all three.
4. Evidence on each. Screenshot baselines on the gold screen. **D-011**.
5. Do not merge your own work. **AG-010**.

### Report

When you finish, say:

- The profile
- The pattern
- The skill you followed
- What you reused
- What you refused
- How you checked it (desktop, 390px, keyboard, both themes, console)

If you skipped a step, say so. A hidden skip is a defect. **AG-008**.

### Never

- A second board in another tool
- “I’ll file it later”
- Issues with no project or milestone
- Marking Done because the build passed
- Twin issues for the same outcome
- Averaging three skills into one ticket
- An exception written as “had to” in a PR
- Batching papercuts into a polish epic that never ships
- Starting work that sits in Backlog
- Closing In Review without evidence

### Audit

- [ ] Linear searched. Issue reused or filed. **AG-001**
- [ ] Milestone present
- [ ] Title is an outcome
- [ ] One skill named
- [ ] Person and profile named
- [ ] Evidence in the thread. **AG-007**
- [ ] Failures reported. **AG-008**
- [ ] No self-exception. **AG-009**
- [ ] Someone else merges. **AG-010**
- [ ] Large work is split. **AG-011**
- [ ] Gold screen has a baseline if the change is visual. **D-011**

Two failures: do not ship.

### Done

The issue matches the screen. Evidence is in the thread. The next person could check it against Rules and the skill you named.

### Applied bookmark research

Reviewed 2026-09-06. These are Thorbis applications and review exercises, not replacements for DESIGN.md, COMPONENTS.md, or the owning skill. Linear remains the operational baseline. External advice that conflicts with the constitution stays out.

These worked examples are not a claim that the product behaviors have been implemented or verified.

#### Close the loop with evidence, not the word polished

Owning skill: [tracking](https://design.thorbis.com/skills/tracking).

Vague design requests produce repeated subjective revisions and hide which parts of the result were actually checked.

A review records the person and task, the observed defect, the owning rule, the smallest correction, and its verification. Preserve source access limits. Turn repeated feedback into a better existing default rather than another detached instruction file.

**Thorbis example:** Instead of make the button premium, record that its pending state moves the label, identify the UI owner, compare the corrected state under the same content, and attach the relevant checks and remaining uncertainty.

**Verify:** Separate a source that was read from a demo that was exercised. Separate a passing content test from a browser check, and a committed branch from a deployed release. Report failed and skipped checks explicitly.

**Do not import:** No fabricated research, inferred paid lesson content, unmeasured uplift claim, or declaring work live because a commit exists.

Evidence: [Agents with Taste](https://emilkowal.ski/ui/agents-with-taste); [Train Your Judgement](https://emilkowal.ski/ui/train-your-judgement); [Developing Taste](https://emilkowal.ski/ui/developing-taste); [How we think about design](https://resend.com/handbook/design/how-we-think-about-design); [Design Engineer Principles](https://vercel.com/design/engineer). [Source access limits](https://design.thorbis.com/research/bookmarks#application-tracking).

[All 26 sources and review limits](https://design.thorbis.com/research/bookmarks).

## Color

Apply the Thorbis palette, theme, and contrast. Use when setting color, building a theme control, or fixing a pair that fails.

> **Linear baseline:** This skill specializes one part of Thorbis; it does not introduce another product grammar. Preserve quiet chrome, one dominant work region, structured density, stable action neighborhoods, contextual surfaces, visible keyboard paths, durable state, and role-adaptive mobile. Use the [Thorbis × Linear pattern matrix](https://design.thorbis.com/research/linear-patterns) only when the owning pattern is ambiguous.

<!-- thorbis-mobile-hig-reference -->
> **Mobile platform gate (D-025):** Every mobile-app task requires the [Native contract](https://design.thorbis.com/skills/native), HIG-001–HIG-022, and relevant live [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

Dark greys and cream type. Electric blue is the brand. Status is ours. Extras are guests.

This is its own skill. Drop it at `.agents/skills/color.md`. Pick this file. Do not average it with the others.

Live: https://design.thorbis.com/skills/color

[Rules](https://design.thorbis.com) is what we ship. [Research](https://design.thorbis.com/research) is the homework. [`DESIGN.md`](https://design.thorbis.com/design.md) is the constitution. [`AGENTS.md`](https://design.thorbis.com/agents.md) is the contract.

**This skill holds:** **D-003** (no hex in product code), **D-015** (theme is a preference, not a hue picker), **D-018** (a fill is one mix; no solid colored side rail), **D-020** (outline at rest, fill when this is the place), APCA verification, OKLCH, light as a retune.

**Homework:** Andrew Somers / APCA — perceptual contrast; WCAG 2 is an independent floor. Kaelig Deloumeau-Prigent — a token is a decision, not a hex. Paco Coursey — the theme is a class on the root; one hatch; no flash. Grammar, not a second palette.

Surfaces in use: [UI](https://design.thorbis.com/skills/ui). Showcase color in a frame: [Cinematic](https://design.thorbis.com/skills/cinematic).

### First

1. Name the token. If you cannot, you are sneaking a value.
2. Name the job: surface, type, pointer, status, or guest.
3. APCA on this theme, then the other theme.
4. If it is Showcase, watch it in motion. A still that works can fail when the object moves onto a hotter field.

Do not invent a grey because you did not open this file.

### Tokens

[DESIGN.md — Surfaces](https://design.thorbis.com/design.md#surfaces) owns the palette and its roles. `src/styles.css` implements the shared tokens. Use those tokens instead of copying another value table into a feature or skill.

Body is reading text. Marker is a short secondary label, not a paragraph, field explanation, or recovery sentence. Status words can use `fg`; their mark or surface carries the reserved status hue. Check the resulting pair on its actual surface in both themes.

Light is a retune. Do not invert the dark palette. The sheet still lifts off the canvas, and the well is darker than the sheet. Accent stays.

No hex in JSX. No `text-white`. If the token is missing, add it at the owner. **D-003**.

### Use

| Token | Use | Never |
| --- | --- | --- |
| accent | Brand, focus ring, the live row | Every heading, a wash, a second blue |
| cream / grey | Type and surfaces | Recolored per page |
| success / danger / info | Copied, failed, info | Olive as success. Accent as info. |
| warning | Alert | Pumpkin as alert |
| extras | Quiet marks: menu icons, places, a bit of fun | A second brand. A status system. Candy. |

A live job can stay grey plus a word. Status is not a rainbow. Overdue and the amount due have to hold |Lc| on a bright windshield, not just in Figma.

Chrome likes soft color. A place mark, a menu icon, a command glyph may carry olive, forest, pumpkin, burnt, or accent mixed down until it sits with those. Phosphor Regular, 16px. The word stays `fg` or `body`. Only the mark is tinted. Selected lifts the word, not a wash behind the row. Outline at rest. Fill when this is the place. **D-020**.

You notice the hue after you read the word. If the icon shouts first, drop chroma. Mix with `marker` until it recedes.

A fill is one mix. Never a gradient unless someone asked for that wash by name. Never a solid colored border on the leading or trailing edge to mean selected, live, or status. Live is a word, a mark, or accent on the thing. **D-018**.

Do not grey every icon to look serious. That is a costume of restraint. Do not paint six loud glyphs in a sidebar. That is a costume of delight.

### Theme

Default is System. If the OS will not say, fall back to Light.

- Persist the choice (`localStorage`). Do not reset it on navigation or a view transition.
- Paint `data-theme` and `data-resolved` on the root before first paint.
- `theme-color` follows the resolved canvas.
- One hatch on the root. No flash.
- Theme control is an icon. Sun, moon, desktop. Not a segmented “Light Dark System” pill.
- Theme is the color preference they get. Not a hue picker. Not a second brand. **D-015**.
- A customer portal and an invoice do not wear one person’s theme.

### Contrast

[DESIGN.md — Color](https://design.thorbis.com/design.md#color) owns the contrast floors and correction rule. Name the actual role: a secondary sentence is still body text. Check the foreground against every surface it can occupy, including tinted status states, hover, and initial paint.

Prefer APCA for perceptual readability, using the actual font size and weight. Verify [WCAG text contrast](https://www.w3.org/WAI/WCAG22/Understanding/contrast-minimum.html) independently; an APCA value alone does not establish WCAG conformance. Keep the word readable when the hue is unavailable. Do not fix a failing pair with saturation, an outline, or a heavier font.

Flip the theme and check the same pair again. Light cream-on-paper and dark cream-on-void are not mirrors. Accent on cream is a different pair than accent on void.

### Theory

We work in OKLCH. Lightness, chroma, hue. Not HSL. Not a mood board.

| Axis | Means | In Thorbis |
| --- | --- | --- |
| Lightness | How close to white | Canvas is dark. Sheet is a step up. Type is cream. |
| Chroma | How much color | Greys are near zero. Accent has chroma. Status has chroma. |
| Hue | Which color | Accent is ~264 (electric blue). Cream is ~84 (warm). Body is ~260 (cool). |

Fix contrast on **lightness**. Never on chroma.

Hue is identity. Chroma is how loud. Lightness is whether you can read it.

#### Temperature

The product is a warm object on a cool void.

- Cream type (`hue 84.6`) is warm. Paper, ink, the sheet in light.
- Body grey (`hue 259.8`) is cool. Sentences sit off the cream so they recede.
- Accent (`hue 264.4`) is cool blue. It points. It does not warm the room.
- Canvas and panel are achromatic. No hue. The void is not blue.

Warm type on a cool field is the whole trick. Do not warm the canvas to “match” the cream. Do not cool the type to “match” the blue.

Light theme keeps the same story: cream canvas, warm ink, the same blue. It is a retune of lightness, not an invert, not a complementary swap.

#### Harmony

One family of greys. One accent. Status hues are reserved words, not a rainbow.

| School | What it means | What we do |
| --- | --- | --- |
| Achromatic | Greys only | Canvas, panel, field, marker. The work lives here. |
| Complementary | Opposite hues | Cream (~85) against blue (~264). Type vs pointer. Not a split-complementary kit. |
| Analogous | Neighbors | Do not. We do not add indigo, cyan, and violet next to accent. |
| Triadic | Three equal hues | Do not. Status is not a triad. Success, danger, warning are words with a color, not a scheme. |
| Monochrome | Tints of one hue | The greys. Accent is the exception, used sparingly. |

60 / 30 / 10 is a painting rule. Map it, then go quieter.

| Share | Role | Token |
| --- | --- | --- |
| ~60% | Field they live in | `bg` |
| ~30% | The work | `panel`, type, body |
| ~10% or less | The pointer | `accent` on the live thing only |

If accent is 10% of the screen, nothing is live. A wash is a fail. A blue rail is a fail.

#### Simultaneous contrast

A color looks different against its neighbor.

- Cream on void reads brighter than cream on panel. Titles sit on the sheet.
- Accent on void shouts. Accent on panel points. Use the second.
- Danger on a red-tinted panel disappears. Keep the panel grey.
- Body grey on cream (light theme) is a different pair than body grey on void. Check both.

Do not “fix” a pair by outlining it. Change lightness.

### Meaning

Color is a pointer, then a reserved word, then never decoration.

| Job | Color | Rule |
| --- | --- | --- |
| Brand, focus, selected, the live row | `accent` | One blue. Not every heading. |
| Copied, ok | `success` | With the word. |
| Failed, destructive | `danger` | With the word. The commit stays our shape. |
| Info | `info` | Not brand. Do not use accent for “FYI.” |
| Alert | `warning` | Not pumpkin. |
| Fun | olive, forest, pumpkin, burnt | Guests. Quiet marks. Not jobs. Not node types. Not a legend. |

Status is a word first. Open. En route. On site. Color sits with the word. A green blob is not a status.

A live job can stay grey plus a word. That is legal. That is preferred.

### Quiet marks

The interface is not monochrome. It is grey, with soft color on the things you scan for.

Places, menus, and command rows: Phosphor Regular, 16px. The **mark** may carry a hue. The **word** does not.

| Place | Mark may be | Never |
| --- | --- | --- |
| Jobs | olive, or accent mixed with marker | A blue row |
| Schedule | pumpkin, at extra chroma, 16px only | A calendar fill |
| Inbox | forest | A green blob for unread |
| Books | burnt | A red bookshelves |
| Workflow / Brain | accent mixed down to extra chroma | Neon nodes in the sidebar |

Mix: `color-mix(in oklab, var(--color-accent) 45%, var(--color-marker))`. If it still shouts, mix more marker.

Lightness sits near marker. Chroma sits with olive (~0.05), not with accent (~0.19). Pumpkin and burnt are the loudest extras; they are legal on a 16px mark and illegal as a row fill.

Selected: the word becomes `fg`. The mark may stay its hue. Hover is color on the word, gated. No wash.

Do not tint fields, commits, list identity, or body copy. Soft color is chrome, not content.

If you cannot tell Jobs from Schedule without the hue, the words failed. The hue is a courtesy.

### Video and Showcase

Same palette. Darker patience.

- The void is `bg`. One light on the object. A rim so the sheet reads as a thing.
- The product in the shot is the product we ship. Cream type, grey sheet, one blue pointer.
- Do not grade the reel toward teal-and-orange. Do not add a marketing purple.
- Skin, a truck, a shop: keep them honest. Do not cast a blue wash over a crawlspace.
- Cuts stay in the same world. Do not jump from a cream void to a black void between chapters.
- Reduced motion stills use the same crop and the same palette.

A color script is three beats: void, object, pointer. If a fourth hue appears, delete it.

### Never

- Blue as every heading
- A third green
- Contrast fixed by saturating
- Theme forgotten when the page changes
- A purple or “Linear indigo” anywhere
- Candy icons. An all-grey menu as a virtue
- A gradient, mesh, aurora, or fade, unless the brief names that exact wash
- A solid colored border on the leading or trailing edge of a row, a card, a quote, a callout, or a sheet
- A second blue
- Complementary orange “to balance the blue”
- Teal-and-orange grade on a product video
- Warming the void
- Status as a rainbow of node types
- A hex picker, a theme store

### Audit

- [ ] Token named. No hex in product code. **D-003**
- [ ] APCA |Lc| holds on this theme and the other
- [ ] Accent is a pointer, not 10% of the screen
- [ ] Status is a word plus a reserved hue
- [ ] Fill is one mix. No solid colored side rail. **D-018**
- [ ] Marks: outline at rest, fill when current. **D-020**
- [ ] Theme persists. No flash. **D-015**
- [ ] Extras are guests, not a legend

Two failures: do not ship.

### Done

Name the token, the pair you checked, and the theme. Name anything you refused: a second blue, a wash, a solid colored side rail.

### Applied bookmark research

Reviewed 2026-09-06. These are Thorbis applications and review exercises, not replacements for DESIGN.md, COMPONENTS.md, or the owning skill. Linear remains the operational baseline. External advice that conflicts with the constitution stays out.

These worked examples are not a claim that the product behaviors have been implemented or verified.

#### Use color to clarify state, not replace it

Owning skill: [color](https://design.thorbis.com/skills/color).

A borrowed visual trick can weaken contrast or make a state readable only by its color.

Keep semantic roles and Thorbis tokens in charge. Inspect state words, marks, and control edges together in both themes. External suggestions for shadows, smoothing, and image outlines are evidence to evaluate, not a new palette.

**Thorbis example:** A failed invoice action has an understandable error and a recovery action; it is not merely a red icon. A rounded input retains the real rim required by D-017 rather than losing its boundary on a similar-toned surface.

**Verify:** Review focus, selected, disabled, pending, and error states in light, dark, and forced-colors conditions. Check contrast and meaning separately from whether the screenshot feels subtle.

**Do not import:** No second accent, literal source colors, missing control rim, or ornamental gradient and blur imported from a reference.

Evidence: [Web Interface Guidelines](https://vercel.com/design/guidelines); [Details that make interfaces feel better](https://interfaces.dev/magazine/issues/details-that-make-interfaces-feel-better); [components.build](https://www.components.build/). [Source access limits](https://design.thorbis.com/research/bookmarks#application-color).

[All 26 sources and review limits](https://design.thorbis.com/research/bookmarks).

## Type

Set Inter, Geist Mono, measure, wrapping, and UI copy. Use when choosing type or writing interface words.

> **Linear baseline:** This skill specializes one part of Thorbis; it does not introduce another product grammar. Preserve quiet chrome, one dominant work region, structured density, stable action neighborhoods, contextual surfaces, visible keyboard paths, durable state, and role-adaptive mobile. Use the [Thorbis × Linear pattern matrix](https://design.thorbis.com/research/linear-patterns) only when the owning pattern is ambiguous.

<!-- thorbis-mobile-hig-reference -->
> **Mobile platform gate (D-025):** Every mobile-app task requires the [Native contract](https://design.thorbis.com/skills/native), HIG-001–HIG-022, and relevant live [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

Type is the product. Dispatchers read more than they click.

This is its own skill. Drop it at `.agents/skills/type.md`. Pick this file. Do not average it with the others.

Live: https://design.thorbis.com/skills/type

[Rules](https://design.thorbis.com) is what we ship. [Research](https://design.thorbis.com/research) is the homework. [`DESIGN.md`](https://design.thorbis.com/design.md) is the constitution. [`AGENTS.md`](https://design.thorbis.com/agents.md) is the contract.

**This skill holds:** **D-003** (no raw type in product code), **D-016** (prefer a mark; a word names the action), the type scale, wrapping, measure, and the words we use.

**Homework:** Rasmus Andersson on Inter. Optical size on the axis. Interface type that stays calm at 13 and 32. Geist Mono for numbers that must line up. Grammar, not a costume font.

UI owns the picture. Color owns the pair. This file owns the face, the scale, the wrap, and the sentence.

### First

1. Who is reading, and from where? Dispatcher at 7 a.m. Tech in a crawlspace. Owner on the books.
2. Is this chrome or content? Chrome is 13. Content is 14. Do not mix them to “fit.”
3. Is the control a mark, or does it need a word? Search, theme, close, command: no word. `Save invoice`, `Cancel job`, `Arrive`: a word. **D-016**.
4. Is the number the job? Money, hours, the shop's printed number: Geist Mono, tabular. A street is Inter.

Do not offer a menu of faces. Make the call.

### Face

- **Inter Variable** with `opsz`. `ss01` and `cv11`. The UI face. Calm at 13. Calm at 32.
- **Geist Mono** for code, the shop's printed number, money, shortcuts. Tabular. The books depend on it.

Two families. No costume font. No Inter on a number that should be tabular mono. No SF Pro on a workbench (that is iOS chrome, [Native](https://design.thorbis.com/skills/native)). No trailer face on Showcase ([Cinematic](https://design.thorbis.com/skills/cinematic)).

Root is antialiased. `-webkit-font-smoothing: antialiased`. Inter on macOS without it looks heavy.

Tokens own the size and weight. No `text-[13.5px]`. No `font-bold` as a mood. **D-003**.

### Scale

| Role | Size | Weight | Line | Where |
| --- | --- | --- | --- | --- |
| Page title | 32 | 500 | 1.25 | The h1. One per page. |
| Section | 16 | 500 | 1.5 | Inside the sheet |
| Content | 14 | 400 | 1.5 | Sentences, rows, help |
| Chrome | 13 | 500 | 1.45 | Nav, chips, pills |
| Caption | 12 | 500 | 1.4 | Location, timestamps |

Chrome is 13. Content is 14. A compact commit is about 32px tall; [Controls](https://design.thorbis.com/skills/ui#controls) owns shared density and touch sizing. A chip is about 28. If the button is louder than the sentence, shrink the button.

Display 32 tracks tight (`letter-spacing: -0.02em` or `tracking-tight`). Default tracking on a 32 is loose. Body does not track tight.

Measure 65–75ch. More space above a heading than below it. The heading belongs to what follows. Tight inside a group. Generous between groups.

A record title in the location bar is 20 / 500. It is not a second page title. The page has one 32.

### Numbers

Tabular nums on money, hours, quantities. Geist Mono when the number is the job (`$186.00`, `1.5 hr`, `JOB-1842` in a caption).

- Numerals for counts: `3 jobs`, not `three jobs`.
- Shop currency. Same precision in a column.
- Non-breaking space between a number and its unit.
- A column of money stays tabular and right-sitting. Do not wrap a dollar in the middle of the amount.
- `JOB-1842` is a caption. The title is `114 Oak`. Street first.
- Show the number the shop already prints on the work order (`JOB-1842`). Never show an internal id (`work_order_id`, a UUID, a database key). The dispatcher reads that number back from the paper. An internal id looks like a different job.

A column of totals that is technically centered but looks drunk will not be trusted on payday. Optical alignment beats geometric center.

### Wrapping

- Headings: `text-wrap: balance`.
- Body: `text-wrap: pretty`.
- Non-breaking space between a number and its unit (`$186.00`, `1.5 hr`).
- Typographic quotes and apostrophes. Ellipsis is `…`. Straight ticks look like a dump from the old software.
- Hyphenate last, never in a heading.
- A thin nbsp only when balance still leaves a widow. A lonely “due” on the next line of an invoice looks careless.
- A job street may ellipsis. Chrome labels fade the overflow (`mask-image`) instead of a hard clip when the word is the only cue.
- Keep the mark together. A hanging parenthesis after a name is how a quote looks cheap.

Do not center body on a workbench. Centered type is ceremony: a hero, a symmetrical product, a universal claim. Left-aligned type is reading: specs, comparisons, chapters, proof. Do not center a paragraph of numbers. Showcase may center a headline. Body stays left even there.

### Copy

- Sentence case. Second person. Active voice.
- Prefer a mark. When a control has a word, it names the action. `Save invoice`. `Cancel job`. Not `Continue`. Not `Submit`. Search, theme, close, command: no word. **D-016**.
- Errors name the problem and the exit. `Could not save the invoice. Check the card and try again.`
- Empty names the one action. `No open jobs. Create a job.`
- `7 a.m.`, not `7am`. Ellipsis is `…`. Typographic quotes.
- Job, stop, tech, truck. Street first: `114 Oak`, then the leak.
- Status is a word: Open. En route. On site. Not a green blob.
- No marketing on a board. No kickers. No all-caps labels.
- Title Case is allowed on Showcase headlines only.
- Labels persist. Placeholders are emptiness (`Mike Reyes`), not the label (`Enter name`).
- Help sits under the field. An error takes its place. Not a toast.
- `Assign…` means a picker is coming. `Assign` means it already happened. Techs trust the difference.

| Ours | Not |
| --- | --- |
| Job | Ticket, case, request |
| Stop | Appointment slot |
| Tech | Agent, resource, user |
| Truck | Vehicle asset |
| Board | Kanban, pipeline |
| Sheet | Modal, drawer, card |
| Dispatch | Assign, allocate |
| Arrive | Check in, clock |

### Worked: a job row

The identity is a real `<a>`. Title is `114 Oak` at 14 / 500. Caption is `Leak · Mike · 7 a.m.` at 12 / 500 `marker`. Status is the word `En route`, not a chip rainbow. Money, if present, is Geist Mono, tabular, on the end. The street may ellipsis. The status word does not.

The page title is `Jobs`. It is 32. It is not in the row.

### Worked: an invoice

The question is Inter 16 / 500. The number is Geist Mono, `$186.00`, large enough to trust, never a second blue. Assumptions sit under it in 14 / 400. A column of line items is tabular, right-sitting, same precision. Do not wrap `$186.00` as `$` then `186.00`. Evidence profile: no marketing sentence. [Product](https://design.thorbis.com/skills/product) Evidence.

### Never

- A third face
- Centered body on a workbench
- Monospace as a vibe
- A placeholder that is the label (`Enter name`)
- Inputs under 16px on a phone
- `JOB-1842` as the title of a row
- An internal id on a screen the shop reads (`work_order_id`, a UUID)
- A word on a button a mark would have made obvious
- A kicker above a page title
- All-caps labels
- `text-[13px]` or a page-local face
- SF Pro on the job (chrome on iOS only)
- A trailer font on Showcase
- Straight quotes in customer notes
- Proportional numbers in a money column

### Audit

- [ ] Inter on the UI. Geist Mono on the shop's number and money
- [ ] The number on screen is the one printed on the work order
- [ ] Chrome 13. Content 14. One 32 on the page
- [ ] Measure 65–75ch. Headings `balance`. Body `pretty`
- [ ] Street first. Status is a word
- [ ] Marks where the action is obvious. Words where it is not. **D-016**
- [ ] No raw type in product code. **D-003**
- [ ] Phone inputs 16px or larger
- [ ] Tabular money. Non-breaking unit
- [ ] Empty and error sentences exist

Two failures: do not ship.

### Done

Name the face, the role on the scale, and the sentence you wrote. Name anything you refused: a third face, a kicker, a word on a mark.

### Applied bookmark research

Reviewed 2026-09-06. These are Thorbis applications and review exercises, not replacements for DESIGN.md, COMPONENTS.md, or the owning skill. Linear remains the operational baseline. External advice that conflicts with the constitution stays out.

These worked examples are not a claim that the product behaviors have been implemented or verified.

#### Keep operational text steady and unambiguous

Owning skill: [type](https://design.thorbis.com/skills/type).

Changing digits, shifting labels, and brittle wrapping make money and status harder to inspect.

Evaluate numeric alignment where amounts are compared, stable action labels during requests, and wrapping with real content. Treat optical adjustments as controlled system decisions. Keep the existing font families and semantic type roles.

**Thorbis example:** An invoice comparison aligns changing amounts without hiding their currency or precision. A long property name wraps without displacing the next action. Save remains the action; the adjacent status explains what happened.

**Verify:** Try zero, negative and large amounts, long names, missing values, fallback fonts, text expansion, and browser zoom. Compare readability at actual size rather than approving a magnified specimen alone.

**Do not import:** No blanket balanced wrapping on data rows, copied display face, custom page-local type scale, or status copy that claims more than the system knows.

Evidence: [Details that make interfaces feel better](https://interfaces.dev/magazine/issues/details-that-make-interfaces-feel-better); [Web Interface Guidelines](https://vercel.com/design/guidelines); [Invisible Details](https://invisibledetails.com/). [Source access limits](https://design.thorbis.com/research/bookmarks#application-type).

[All 26 sources and review limits](https://design.thorbis.com/research/bookmarks).

## Cinematic

Design Showcase pages. Product larger than type, real UI in a void. Never use on a board, books, or field flow.

> **Linear baseline:** This skill specializes one part of Thorbis; it does not introduce another product grammar. Preserve quiet chrome, one dominant work region, structured density, stable action neighborhoods, contextual surfaces, visible keyboard paths, durable state, and role-adaptive mobile. Use the [Thorbis × Linear pattern matrix](https://design.thorbis.com/research/linear-patterns) only when the owning pattern is ambiguous.

<!-- thorbis-mobile-hig-reference -->
> **Mobile platform gate (D-025):** Every mobile-app task requires the [Native contract](https://design.thorbis.com/skills/native), HIG-001–HIG-022, and relevant live [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

Marketing may be theater. The product may not.

This is its own skill. Drop it at `.agents/skills/cinematic.md`. Pick this file. Do not average it with the others.

Live: https://design.thorbis.com/skills/cinematic

[Rules](https://design.thorbis.com) is what we ship. [Research](https://design.thorbis.com/research) is the homework. [`DESIGN.md`](https://design.thorbis.com/design.md) is the constitution. [`AGENTS.md`](https://design.thorbis.com/agents.md) is the contract.

**This skill holds:** **D-022** (Showcase discloses one level at a time; intent sets the mode: router, explore, film, or store; one idea per scene; cinema explains a join), plus **D-018** and **D-019** as they apply to a frame.

**Homework:** Apple’s site is the homework. Grammar, not costume. We do not ship SF Pro, a sterile hardware catalog, or cinematic behavior on a board. Framer — show the product; scroll tells the story. Cursor — marketing shows the real surface. Our hero is the shop running as one system, not a phone in a void.

If the surface is Admin, Money, a record, or a Guided field flow: **stop**. Use the inherited Linear baseline and [UI](https://design.thorbis.com/skills/ui).

### First

1. Name the object before you draw. The board. The phone in the van. The invoice. The truck.
2. Name the mode: router, explore, film, or store. **D-022**.
3. Name the one idea in the first viewport.
4. Is the UI in the shot the UI we ship? Real jobs, real streets, real times. Not Acme. Not a dribbble board.

If you cannot name the object, you do not have a Showcase page. You have a feature-card grid. Delete it.

### Modes

There is not one Showcase layout. Intent sets density.

| Mode | Visitor | Page | Density | Motion |
| --- | --- | --- | --- | --- |
| **Router** | Mixed. Repeat and new. | Homepage | One campaign per module. One claim. One or two actions. | Almost none. Stills. |
| **Explore** | Knows the family, not the model. | Jobs, Money, Arrive, a category | Comparison, shared benefits, a little education. | Rare. |
| **Film** | Considering this product. | A named product or chapter page | Cinematic. Slow. Desire, then proof. | Delight lives here. |
| **Store** | Ready to buy or price. | Pricing, signup, plans | Dense. Money, what’s in, migration, support. | None. |

A workbench is none of these. Do not pour a film into Admin. Do not pour a store into Open.

The homepage answers “where do I go?”
The product page answers “why do I want this?”
The store answers “what does it cost, and how do I start?”

Hiding practical information behind cinema, on a pricing page, is friction. Apple does not do that in the Store. Neither do we.

### The actual simplicity

Simplicity is not “show less.”

It is: **one level of information at a time, in a deliberate sequence.**

Thorbis is a large operating system. The site feels simple when that size is split across pages, sections, and moments. Never ask them to process the whole platform in one viewport. **D-022**.

Reveal in this order. Do not skip forward. Do not dump the spec in Open.

1. What it is.
2. Why it matters.
3. What is new, or what it joins.
4. How it looks and feels.
5. How it performs in the shop.
6. Technical evidence.
7. Configuration, price, start.

Emotion first. Proof second. Purchase last. A contractor still needs evidence. Apple can lean on recognition. We cannot.

### One idea per scene

Each major section is a slide. It can be understood without the section above it.

A scene has:

- One idea.
- One visual subject.
- One headline.
- One reading direction.

Isolation is the hierarchy. Scale, empty space, contrast, position, type, photography. Not a badge kit. Not a card grid of six benefits, three screenshots, and four buttons.

Whitespace is a tool. It replaces decoration. Empty space around a weak claim is still a weak claim.

### Object

One object per page or chapter. Everything else is ground. Ground recedes: void, quiet type, no second hero.

If two things compete, you have two frames. Cut.

The UI in the shot is the UI we ship. Real jobs, real streets, real times.

### Frame

One object. The void is ground. Type is a caption.

Video and stills sit on a thirds grid unless you name a centered poster.

| Law | Means | In Thorbis |
| --- | --- | --- |
| Figure and ground | One subject, a quieter field | Product on the void. Type is a caption. |
| Negative space | Empty is a tool | The void is most of the frame. Do not fill it with cards. |
| Hierarchy | Size, then position, then weight. Color last. | Object huge. Headline small. Accent only if something is live in the UI. |
| Balance | Weight, not symmetry | A phone on the right third, caption on the left. Centered is a choice. Name it. |
| Leading lines | Edges that point at the subject | The inverted L of the real UI. A van door. A street. Not a decorative stripe. |
| Frame in a frame | A rectangle that holds the object | The sheet in the void. A phone bezel. A cab window. |
| Depth | Foreground, mid, background | A rim, the sheet, the void. One light. Not a bokeh kit. |

Golden ratio is optional. Prefer thirds. They are easier to hold across a cut.

#### Where the object sits

| Shot | Put it | Empty two-thirds hold |
| --- | --- | --- |
| Phone in the van | Right vertical, lower intersection | The cab, the street, look-space left if the driver looks left |
| Board on a desk | Left vertical, the sheet on the upper third | Hands, a quiet shop, room to breathe |
| Invoice / paper | Lower third, slightly off center | The question above it |
| Truck | Lower third, wheels on the line | Sky or shop is not the subject |

Horizon sits on a third. Never through the middle unless the shot is a reflection you can name.

Lead room in the direction of the face or the move. A little headroom. Do not crowd the nose, the grille, or the cursor against the edge.

Match the line across a cut so the object does not jump left-third to right-third.

Caption in the empty third, never larger than the product. Inter. Cream. Not a trailer font.

| Frame | Use | Thirds note |
| --- | --- | --- |
| 16:9 | Site, reel, desktop proof | Horizontal thirds are long. Object on a vertical line. |
| 9:16 | Stories, a phone holding a phone | Vertical thirds are long. Object on an upper intersection. |
| 4:5 | Feed still | A compromise. Crop from 16:9. Do not re-stage a new hero. |
| 1:1 | Rare | Center is allowed. Name it. |

Safe area: keep the object inside the middle 80%. Captions sit in the lower third, not on the product.

Center is legal on Open when the object is the poster. Say so. A truck dead-center. Then Proof breaks the center so the UI can work.

Establish the whole object first. Extreme crop later. Do not shrink the desktop hero onto a phone. Recompose: the product gets larger in the frame, the crop gets closer.

Copy is HTML, sitting in a third. It is not painted into the picture. Localization, search, and contrast depend on that.

Open `references/frame.md` when you are placing an object on a thirds grid, leaving lead room, or checking gestalt. This page keeps the short law. That file keeps the picture law that does not fit here: gestalt, a face on the upper third, motion across the grid, and type burned into a frame.

### Chapters

| Chapter | On screen | Type | Motion | Fail if |
| --- | --- | --- | --- | --- |
| Open | Object, huge. One line. | Caption | One entrance | A nav of features |
| Proof | Sticky stage. Captions scroll. A job opens. | Body, quiet | The object changes | A three-column card row |
| Cut | Next object, or a closer crop. | Caption | A cut, not a wipe | A wipe that steals the wheel |
| Ask | One action, or two of different intent. | Commit | None | Two buttons of equal weight |

The void is the workbench canvas so the jump into the product does not change worlds.

Open is not a spec sheet. Ask is not a second cinema. Proof may be a scroll-tied join only when the motion explains the architecture.

A long Film page may add a local chapter map (name, buy, sections). That is not a second header on a workbench.

### The page is a film

A product page follows a cut list. Open, Proof, Cut, Ask still hold. This is the longer form.

| Beat | On screen | Fail if |
| --- | --- | --- |
| Title | Name and one promise | A nav of features |
| Hero | The product alone, on the void | A collage |
| Close-up | Material, edge, a control, a street | Crop before they know the object |
| Transformation | Things join, or a config changes | Motion that explains nothing |
| Feature scenes | One capability, one composition | Six cards in a row |
| Human proof | A shop using it. Real. | Stock |
| Technical proof | Numbers, after desire | Specs in the hero |
| Purchase | Price, what’s in, start | Cinema that hides the commercial model |

### Copy in the scene

Router and Open:

- Product, or one line.
- One supporting sentence.
- Two actions of **different intent**, or one. `Explore Thorbis`. `See how it works`. `Start dispatch`. Not two commits of equal weight.

“Learn more” is evaluation. “Start” is transaction. They are not twins.

Headlines are title cards. Short. Benefit, not an argument. Qualifications move down.

Centered type is ceremony: a hero, a symmetrical product, a universal claim.
Left-aligned type is reading: specs, comparisons, chapters, proof.
Do not center a paragraph of performance numbers.

Type is Inter. Neutral. Drama from scale and crop, not a costume font. Body is smaller, lighter, narrower. Grey, not a second black. [Type](https://design.thorbis.com/skills/type). SF Pro stays on Apple. Title Case is allowed on Showcase headlines only.

### Crop, light, color

- Dark void for performance, materials, the board at night, the product as a thing. Light void when the message is everyday, thin, friendly, the invoice on a counter.
- The background follows the story. Do not alternate dark and light for decoration.
- The product supplies the color. Interface stays grey. Screen content, a finish, a photo may carry hue. Blue remains a pointer, not a wash. **D-018**.
- Rotate evidence: the object, the UI, the inside, a person in the shop, a number. Do not shoot the same laptop from six angles.
- Same palette as the workbench. No teal-and-orange grade. No second blue. [Color](https://design.thorbis.com/skills/color).

### Scroll is a timeline

On Film pages, a sequence may be tied to scroll: it moves when they move, pauses when they stop, reverses when they go back. The visitor owns speed and attention.

The browser still owns the wheel. Do not pin the page and fake a reel. Do not hijack or artificially slow the scroll. [Motion](https://design.thorbis.com/skills/motion).

Motion must explain a join, a before/after, a config, a dimension, a workflow. Headings that drift, cards that float, objects that spin for atmosphere: refuse.

Preserve one subject. Change one or two properties: scale, position, rotation, light, opacity, camera distance, a component separating. Many objects moving at once is a template, not a film. Scaling, spinning, parallax, blur, and fake depth can hurt. Prefer a dissolve, a highlight, or a color change. Do not delete the meaning and leave a broken scene.

A film intensifies. It is not the only explanation. Ship static poster frames, real headings and body, play and pause where there is a film. No essential fact only inside video. Reduced-motion stills of the same crop. A usable page before cinematic assets load.

Media holds its hole. Aspect-ratio. **D-019**.

### Shell on a Showcase page

Global nav stays compact and quieter than the hero. It is the exit, not a second billboard.

A long Film page may add a **local** product nav: the name, the purchase action, chapter links. That is a chapter map. Do not put twenty chapter links in it.

Full-width scenes, then a contained gallery, then a narrow text passage, then a table, then purchase. Changing format resets attention. A page of only full-bleed cinema is exhausting. A page of only cards has no drama.

Dense links, legal, and the rest of the platform live in the footer. Do not “minimal” them out of existence. Do not put them in the hero.

### Mix

About:

- **60–70%** calm product: real UI, short copy, restrained motion.
- **20–30%** evidence: workflows, time, money, shops, modules.
- **10–15%** cinema: one or two sequences, a reveal, a spatial join.

Apple can make a phone the hero. Our hero is the shop running as one system. Every cinematic beat must show how Thorbis connects, simplifies, or accelerates the work. Do not add movement so the site “looks like Apple.”

One or two sequences on a homepage. Breadth is a grid, not another film. Price is easy to find.

### A Thorbis homepage

Router, not a two-minute film.

1. **Promise.** One statement. One supporting sentence. The product is the object. Two actions of different intent.
2. **Join.** One controlled sequence: call, customer, property, stop, tech, estimate, invoice, payment assembling into one timeline. Scroll explains the architecture.
3. **From the shop to the row.** Full workspace, then dispatch, customer, job, invoice. The camera says every detail belongs to one system.
4. **Chapters.** Isolated. One real product view and one operational outcome each. Answer. Dispatch. Context in the van. Work into money. The board as a whole.
5. **Breadth.** A structured grid of modules. CRM, schedule, comms, field, money, inventory, sites, reports. Not another cinematic pass.
6. **Evidence.** Time saved, response, admin work, revenue captured, a shop, migration.
7. **Price.** Starting commitment, what’s in, usage, seats, implementation, support, data. Easier to find than Apple hides it.

One or two cinematic moments. Not cinematic behavior in every section.

### Rules, short

1. The product is larger than the type. Headline is a caption under the object, not a billboard over it.
2. Dark void. Same canvas as the workbench. One light. A rim so the sheet reads as a thing.
3. Scroll is a cut list. The browser owns the wheel.
4. One entrance per chapter. Reduced motion is stills of the same crop.
5. Few words. Operator-plain. One action at the end, or two of **different intent**. `Start dispatch`, not `Get started`.
6. Title Case is allowed on Showcase headlines only. Body stays sentence case.
7. Delight lives here only. Do not export this motion into Admin.
8. One idea per scene. Intent sets the mode. **D-022**.
9. Disclose in order. Do not dump the spec in Open.
10. Every cinematic beat explains a join, a simplification, or speed. Motion that only resembles Apple: refuse.

### Audit

- [ ] Mode named: router, explore, film, or store. **D-022**
- [ ] One idea in the first viewport
- [ ] Object sits on a third, or center is named
- [ ] Lead room in the direction of face or move
- [ ] First viewport is mostly product
- [ ] Object is real Thorbis or a real trade scene
- [ ] No feature-card grid
- [ ] Scroll still belongs to the browser
- [ ] Reduced-motion stills exist
- [ ] Film is not the only proof
- [ ] Price is findable if this page sells
- [ ] One primary action, or two of different intent
- [ ] Nothing here could be a dispatch board
- [ ] Copy is HTML, not baked into the picture
- [ ] No gradient unless the brief named it. No solid colored side rail. **D-018**

Two failures: restage.

### Never

- This skill on a workbench
- Fake UI
- Scroll-jack
- Cinematic motion inside Admin
- A second brand color “for marketing”
- A thirds overlay in the finished file
- Jumping the object from left third to right third on a cut
- A gradient, mesh, or aurora behind the product, unless the brief named that wash
- A solid colored side rail on a frame or a card
- Specs in the hero
- Extreme crop before they know the object
- Video as the only explanation
- Hiding price behind a film
- Shrinking a desktop hero onto a phone
- Baking the headline into the picture
- SF Pro
- One layout for homepage, product, and pricing
- Six ideas in one viewport
- Empty space around a vague claim

### Done

Name the mode, the object, and the one idea. Name the sequence you refused to put on a board.

### Applied bookmark research

Reviewed 2026-09-06. These are Thorbis applications and review exercises, not replacements for DESIGN.md, COMPONENTS.md, or the owning skill. Linear remains the operational baseline. External advice that conflicts with the constitution stays out.

These worked examples are not a claim that the product behaviors have been implemented or verified.

#### Motion explains the product; it does not become the product

Owning skill: [cinematic](https://design.thorbis.com/skills/cinematic).

An impressive effect can consume attention without helping a contractor understand what Thorbis does.

Name the product idea a Showcase scene explains. Use representative trade content, keep the next action clear, and compare against a static explanation. Make animation optional to comprehension and task completion.

**Thorbis example:** A single scene can explain how a completed job becomes an invoice. It should not hide the invoice behind a long sequence, invent product capabilities, or turn routine billing into a celebratory animation.

**Verify:** Check the initial viewport, static and reduced-motion alternatives, readable copy, reserved media geometry, and the real cost of any proposed asset. Record license and dependency review before reuse.

**Do not import:** No effect collection imported as a style system, no shaders in the workbench, and no made-up conversion or performance evidence.

Evidence: [You Don't Need Animations](https://emilkowal.ski/ui/you-dont-need-animations); [React Bits Pro](https://pro.reactbits.dev/); [Design Engineering at Vercel](https://vercel.com/blog/design-engineering-at-vercel); [animations.dev](https://animations.dev/). [Source access limits](https://design.thorbis.com/research/bookmarks#application-cinematic).

[All 26 sources and review limits](https://design.thorbis.com/research/bookmarks).

## Native

Mandatory for every Thorbis mobile-app task. Apple HIG governs iOS and iPadOS; host conventions govern Android and desktop. Includes source receipts, accessibility requirements, and release evidence.

> **Linear baseline:** This skill specializes one part of Thorbis; it does not introduce another product grammar. Preserve quiet chrome, one dominant work region, structured density, stable action neighborhoods, contextual surfaces, visible keyboard paths, durable state, and role-adaptive mobile. Use the [Thorbis × Linear pattern matrix](https://design.thorbis.com/research/linear-patterns) only when the owning pattern is ambiguous.

<!-- thorbis-mobile-hig-reference -->
> **Mobile platform gate (D-025):** Every mobile-app task requires the [Native contract](https://design.thorbis.com/skills/native), HIG-001–HIG-022, and relevant live [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Apple HIG governs iOS/iPadOS behavior over conflicting web/Linear rules. Cite rule IDs and topic URLs in specifications, component contracts, PRs, and release evidence. Android retains host conventions. Normative requirements and exceptions have one owner: Native.

Thorbis identity. Native behavior. No website squeezed into an app.

Live: https://design.thorbis.com/skills/native

[DESIGN.md](https://design.thorbis.com/design.md) delegates mobile platform authority here through **D-025**. [AGENTS.md](https://design.thorbis.com/agents.md) routes every mobile task here. This is the canonical owner of **HIG-001–HIG-022**. Other skills reference these rules; they do not create competing mobile standards.

**Status: mandatory Thorbis policy.** These are Thorbis implementation and review requirements informed by Apple's [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines), not a claim that every MUST below is an Apple requirement or an App Store approval guarantee. Requirements deliberately stricter than Apple's guidance are labeled Thorbis policy. HIG compliance does not replace security, privacy, payment, or App Review requirements.

Baseline reviewed: **2026-09-08**. Review the live applicable topics for each change and record the review date. Do not freeze the product to a named OS release or adopt beta-only behavior without a supported-version decision.

### Platform routing

| Surface | Authority and implementation |
| --- | --- |
| iPhone app | Apple HIG; native navigation, controls, text scaling, and system interaction |
| iPad app | Apple HIG; adaptive navigation and content based on available window size |
| Android app | Host conventions and Material guidance; native Back, accessibility, and 48dp app-owned targets |
| Office browser | Thorbis workbench and inherited Linear baseline; browser semantics and URL state |
| Mobile browser | Browser semantics, accessible touch targets, reflow, zoom, safe areas; not a fake native app |
| macOS / Windows host | Native window controls, menus, keyboard conventions, and host accessibility |

Shared product identity does not mean a shared AppShell. Shared business logic does not require identical platform chrome. Keep Field Management and Network identities and release evidence separate.

### HIG-001 — Scope and source receipts

Every mobile specification, component change, implementation PR, and release review **MUST** name the app, platform, supported OS range, affected surfaces, applicable rule IDs, Apple topic URLs, and date consulted. This includes Field Management and Network, onboarding, authentication, customer-facing flows, billing surfaces, and shared native adapters. Native is mandatory context even when another skill owns the feature. Read relevant topics, not the entire HIG for every button. A source receipt is evidence of consultation, not proof of conformance.

**Source:** [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Lifecycle scope and receipts are Thorbis policy.

### HIG-002 — Platform authority before desktop resemblance

For iOS and iPadOS, implementation **MUST** follow applicable Apple HIG behavior over conflicting Linear-derived shell, density, icon-only, typography, motion, or surface rules. Preserve Thorbis terminology, identity, semantic tokens, permissions, and durable work state. Do not force Apple-specific chrome on Android. A visual preference cannot override accessibility, safety, privacy, or recovery. Report unresolved architecture conflicts under D-012 rather than silently violating the platform contract.

**Source:** [Layout](https://developer.apple.com/design/human-interface-guidelines/layout). Conflict resolution is delegated by D-025.

### HIG-003 — Native components and system materials

Use platform-native controls and approved native-backed adapters where available. Custom alternatives **MUST** demonstrate equivalent semantics, accessibility, interaction, and supported-version behavior before adoption. Do not reproduce system pickers, sharing, authentication prompts, or navigation using web-styled imitations. OS-provided materials, including Liquid Glass where supported, belong in their system-defined navigation/control roles; they are not a decorative effect for every content card. D-018 and D-021 do not prohibit native system materials. Never emulate a newer OS by painting fake chrome over an older one.

**Source:** [Materials](https://developer.apple.com/design/human-interface-guidelines/materials).

### HIG-004 — Touch geometry without density loopholes

**Thorbis policy:** every app-owned iOS/iPadOS interactive target **MUST** provide at least **44 × 44 points** of usable hit area, including icon buttons, text actions, chips, dismiss controls, and list accessories. Targets must not overlap or be occluded. Native system-owned controls retain system metrics; do not distort their geometry. Apple's accessibility guidance distinguishes a 44 × 44-point default from a smaller minimum; Thorbis deliberately adopts the stricter floor for its own controls. This is not a claim that Apple universally mandates 44 points. Points are logical native units, not physical pixels or CSS pixels. Android app-owned targets use at least 48 × 48dp. Measure effective hit areas, not only glyph bounds.

**Source:** [Accessibility](https://developer.apple.com/design/human-interface-guidelines/accessibility).

### HIG-005 — Navigation is destinations, not actions

Navigation **MUST** use an approved native stack and preserve expected visible Back and interactive back behavior, including cancellation and restored state. Tabs represent stable top-level destinations, not commands such as Arrive, Pay, or Create. Choose the destination set from the app and role; there is no universal three-tab requirement. Keep labels and selection understandable, preserve state when switching destinations, and use native adaptive navigation on iPad. Do not manufacture edge gestures or make a swipe the only way to go back. Record identity, deep links, and authorization must survive navigation.

**Source:** [Tab bars](https://developer.apple.com/design/human-interface-guidelines/tab-bars), [Layout](https://developer.apple.com/design/human-interface-guidelines/layout).

### HIG-006 — Sheets, dismissal, and task continuity

Transient tasks **MUST** use appropriate native presentations with clear dismissal, correct focus restoration, keyboard accommodation, and protection against unintended loss of meaningful input. Choose presentation and detents for the content and available space; not every task is a bottom sheet. Preserve expected dismissal gestures unless preventing actual data loss requires an explicit confirmation. Jobs, invoices, profiles, and other durable records remain navigable destinations, not sheet-only dead ends. Do not stack custom overlays to avoid designing navigation.

**Source:** [Sheets](https://developer.apple.com/design/human-interface-guidelines/sheets).

### HIG-007 — Safe areas and keyboards are live geometry

Layouts **MUST** respond to safe-area insets, system bars, device orientation, the available window, and keyboard changes. Primary actions and focused fields remain reachable above the home indicator and keyboard. Do not hard-code notch, tab-bar, or keyboard heights. Test keyboard presentation, dismissal, floating/split keyboard where supported, long forms, and transient presentations. Scroll the correct content region without losing field focus or drafts.

**Source:** [Layout](https://developer.apple.com/design/human-interface-guidelines/layout).

### HIG-008 — System text styles and Dynamic Type

iOS/iPadOS typography **MUST** use semantic text styles and support Dynamic Type, including accessibility sizes, without clipping essential information or hiding actions. Prefer the platform system font through system APIs. Custom fonts require equivalent scaling, weights, line metrics, and fallback proof; Inter is not mandatory on native job content. The system body style's default size is not a universal minimum for every label. Do not apply desktop 13/14px density, globally disable font scaling, cap accessibility sizes to preserve a screenshot, or use fixed-height text containers that truncate the task. Use tabular numerals where amounts require comparison. Do not bundle system font files to simulate native type.

**Source:** [Typography](https://developer.apple.com/design/human-interface-guidelines/typography), [Accessibility](https://developer.apple.com/design/human-interface-guidelines/accessibility).

### HIG-009 — Assistive interaction is part of the component

Each interactive component **MUST** expose an accurate accessible name, role, value, state, and logical focus order. Verify VoiceOver, Voice Control, Switch Control, and hardware-keyboard access as applicable to the flow. Announce meaningful asynchronous changes without flooding speech. Modal focus must not escape into obscured content. A gesture, hover, color, sound, or haptic cannot be the only path to critical work. Provide accessible alternatives for custom canvases, charts, signatures, and drag interactions. A visible label and accessible name must describe the same action.

**Source:** [Accessibility](https://developer.apple.com/design/human-interface-guidelines/accessibility).

### HIG-010 — Appearance, contrast, and noncolor meaning

Appearance **MUST** support System, Light, and Dark and honor applicable Increase Contrast and Reduce Transparency preferences. Use semantic native color roles/adapters rather than forcing web swatches onto system surfaces. **Thorbis policy:** ordinary app-owned informational text requires at least 4.5:1 contrast; meaningful custom nontext controls and indicators require at least 3:1 against adjacent colors. Record measured pairs and any legitimate not-applicable case. APCA may supplement, not replace, these mobile checks. Status, validation, and selection cannot rely on color alone. Preserve Thorbis identity without compromising legibility or system-owned accessibility behavior.

**Source:** [Accessibility](https://developer.apple.com/design/human-interface-guidelines/accessibility), [Materials](https://developer.apple.com/design/human-interface-guidelines/materials).

### HIG-011 — Respect system motion and Reduce Motion

Native navigation, gestures, sheets, and system controls **MUST** retain their platform transitions instead of being forced into Thorbis's web 120ms curve. Custom motion must explain state or continuity, be interruptible, and respect Reduce Motion. Provide a usable reduced-motion alternative; do not use movement as the sole explanation. Avoid decorative parallax, forced onboarding animation, or delayed interaction for visual theater. Record custom animation performance under HIG-018.

**Source:** [Motion](https://developer.apple.com/design/human-interface-guidelines/motion).

### HIG-012 — Haptics complement visible feedback

Haptics **MUST** be purposeful, brief, appropriate to the outcome, and paired with another understandable signal. Use supported system feedback rather than arbitrary vibration patterns. The app remains usable when haptics or sound are unavailable or disabled. Do not buzz on every row, use success feedback before confirmation, or make a haptic the only warning of a failed payment or upload.

**Source:** [Playing haptics](https://developer.apple.com/design/human-interface-guidelines/playing-haptics).

### HIG-013 — Native input, editing, and recovery

Inputs **MUST** preserve native editing, selection, paste, autofill, appropriate keyboard types, and accessible labels. Keep entered data after recoverable validation or network errors. Errors explain the problem and next step near the relevant input; a transient toast alone is insufficient. Money, phone numbers, dates, and addresses must respect locale and task semantics. Do not globally disable text selection or clipboard actions in pursuit of an app-like appearance. Form submission must not unexpectedly discard the current work.

**Source:** [Accessibility](https://developer.apple.com/design/human-interface-guidelines/accessibility), [Layout](https://developer.apple.com/design/human-interface-guidelines/layout). Draft and error-recovery requirements are Thorbis policy.

### HIG-014 — Permissions and private information

Permission-dependent flows **MUST** explain the task-specific need, use system authorization UI at the point of need, and handle denied, restricted, revoked, and unavailable states. Provide a safe alternative when possible. Do not simulate Face ID or system permission prompts, coerce consent, expose sensitive job/customer/payment information in notifications by default, or treat a permission request as authorization to perform an unrelated action. Use the separate security/privacy contract for data handling and OS APIs.

**Source:** [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Permission timing and data boundaries are Thorbis policy; consult the applicable live privacy topic and platform API documentation for the actual feature.

### HIG-015 — Honest states and offline work

Every consequential flow **MUST** distinguish loading, empty, denied, disabled, error, offline, queued, syncing, and confirmed states as applicable. **Thorbis policy:** preserve drafts and work state across interruptions, avoid duplicate money/dispatch/message operations, and provide explicit retry or recovery. A queued action is not a confirmed success. Do not block all navigation behind a spinner or silently discard an upload when switching tabs. Reconcile local and server state before claiming completion.

**Source:** [Accessibility](https://developer.apple.com/design/human-interface-guidelines/accessibility). Offline durability and transaction semantics are Thorbis product requirements, not claims about HIG-specific implementation mandates.

### HIG-016 — iPad is adaptive, not a stretched phone

iPad layouts **MUST** respond to the available app window rather than device-model assumptions. Use appropriate native tabs, sidebars, split content, and presentations; a rail is not universally required. Preserve selection and drafts when columns appear or collapse. Test supported resizable/multitasking configurations, portrait/landscape, pointer, hardware keyboard, and accessibility text sizes. Do not certify iPad behavior with only a 390px browser screenshot or full-screen tablet mockup.

**Source:** [Layout](https://developer.apple.com/design/human-interface-guidelines/layout), [Tab bars](https://developer.apple.com/design/human-interface-guidelines/tab-bars).

### HIG-017 — Symbols, language, and direction

Symbols **MUST** communicate the action and match supported platform capabilities. Prefer suitable system symbols for native controls, with fallbacks for the supported OS range; custom brand symbols still need semantic and accessibility proof. Preserve system labels where expected. Do not force every native control into web icon-only chrome or one outline/fill formula. Use meaningful accessible names, localized dates/numbers/plurals, long-string tests, and right-to-left layout. Mirror directional controls only when their meaning requires it, not logos or physical objects indiscriminately.

**Source:** [SF Symbols](https://developer.apple.com/design/human-interface-guidelines/sf-symbols), [Typography](https://developer.apple.com/design/human-interface-guidelines/typography).

### HIG-018 — Measured device performance

**Thorbis policy:** mobile releases **MUST** record measured launch, interaction, scrolling, transition, and memory behavior for the affected flows on representative supported physical devices, including a lower-performance supported device. Set budgets in the owning app before implementation and report actual results; do not invent a universal Apple frame-rate or launch-time mandate. Avoid main-thread work, unbounded media, unnecessary rerenders, and decorative effects that block input. Test realistic job lists, weak connections, and background/foreground transitions. Distinguish simulator observations from physical-device measurements.

**Source:** [Motion](https://developer.apple.com/design/human-interface-guidelines/motion), [Layout](https://developer.apple.com/design/human-interface-guidelines/layout).

### HIG-019 — Media and capture fit the task

Media and capture **MUST** use approved system integrations, bounded decoding/rendering, stable geometry, and accessible alternatives. Preserve upload progress and retry state when navigating or interrupted. Do not eagerly load full-resolution galleries into scrolling lists, autoplay disruptive audio, or make a photo the only carrier of essential text. Camera, photo-library, sharing, and denied-permission states must remain understandable. Use representative real-world media sizes in performance evidence.

**Source:** [Accessibility](https://developer.apple.com/design/human-interface-guidelines/accessibility), [Layout](https://developer.apple.com/design/human-interface-guidelines/layout). Resource and upload requirements are Thorbis policy.

### HIG-020 — Shared contracts, platform adapters

Implementations **MUST** reuse registered semantic tokens, domain contracts, permissions, identifiers, and business logic while allowing native platform adapters to own controls and presentation. Do not introduce another token namespace, an unregistered component kit, a WebView shell, or an architecture migration to satisfy a visual rule. Preserve the actual repository stack; React Native/Expo is not permission to draw identical chrome everywhere. A missing native adapter is a D-012 gap requiring an owner and tests, not a feature-local imitation. A specified component is not an adopted or tested component.

**Source:** [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Architecture and adoption gates are Thorbis policy.

### HIG-021 — Evidence before completion

Every affected mobile change **MUST** include a rule-by-rule applicability matrix covering HIG-001 through HIG-022. Use **pass**, **fail**, **not tested**, or **not applicable with reason**. Each applicable pass identifies the component/screen, app build, OS/device or simulator, test method, date, and artifact. Record native manual checks separately from automated checks. Screenshots alone do not prove gestures, focus, hit areas, state recovery, or performance. A website build, linter, or this repository's contract tests cannot certify an app's native behavior. One unresolved applicable MUST failure or required untested behavior blocks mobile completion.

**Source:** [Accessibility](https://developer.apple.com/design/human-interface-guidelines/accessibility). Evidence format and release blocking are Thorbis policy.

### HIG-022 — Review, maintenance, and exceptions

A deviation **MUST** have a named human owner, exact rule and Apple topic, user problem, rejected alternatives, scoped implementation, compensating protections, tracking issue, expiry, and retest plan before acceptance. Agents cannot approve their own exceptions. Safety, accessibility, privacy, and recovery requirements are not waived for visual preference or speed. Reconsult applicable live guidance when behavior, supported OS versions, SDKs, or platform components change and before release. An approved scoped deviation is not blanket HIG compliance. Do not represent an advisory check as a protected-branch requirement unless repository settings actually enforce it.

**Source:** [Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines). Governance and exception handling are Thorbis policy.

### Required review record

Keep the full rule wording here. Link rule IDs from specs, component contracts, implementation PRs, and release records.

```text
App / platform / supported OS range:
Build / commit / affected screens and components:
Apple topics consulted / date:
Rule ID | applicability | result | evidence / reason
HIG-001 through HIG-022 (one row per rule)
Physical devices and simulator configurations:
Dynamic Type / VoiceOver / other applicable assistive input:
Appearance / contrast / reduced motion / reduced transparency:
Navigation / keyboard / safe areas / iPad window changes:
Offline / retries / interruptions / performance budgets and results:
Human-approved scoped deviations / tracking issue / expiry:
Unresolved failures and untested behavior:
Reviewer and release decision:
```

A documentation-only change can mark native runtime verification not applicable with an explicit scope statement. It cannot mark untested app behavior as passed. Redact customer data, credentials, and private documents from evidence.

### Other hosts

Android retains native navigation and predictive Back where supported, device typography, native pickers, accessibility, and at least 48dp app-owned targets. Reuse the evidence discipline above with the applicable host references; do not claim Android follows Apple-specific component geometry.

Desktop retains native window controls and menus, drag regions, keyboard paths, and host accessibility. Use Command on macOS and Control on Windows where appropriate. Do not paint one operating system's chrome onto another.

Mobile web remains a browser: preserve links, history, zoom, text selection, accessible touch targets, logical layout, and scroll. Use dynamic viewport and safe-area support as appropriate. Do not disable zoom or pinch gestures, replace browser navigation with fake native chrome, or apply tiny desktop text-action targets to touch workflows.

### Done

Name the app, platform, profile, pattern, native adapters, applicable HIG rules, source receipts, evidence, and unresolved gaps. **One unresolved applicable MUST failure blocks completion.** This contract is not evidence that an existing app has already passed it.

### Applied bookmark research

Reviewed 2026-09-06. These are Thorbis applications and review exercises, not replacements for DESIGN.md, COMPONENTS.md, or the owning skill. Linear remains the operational baseline. External advice that conflicts with the constitution stays out.

These worked examples are not a claim that the product behaviors have been implemented or verified.

#### Transfer the intent, not the desktop gesture

Owning skill: [native](https://design.thorbis.com/skills/native).

An interaction that works with a precise pointer or modifier key may be unusable for a tech holding a phone.

Preserve the record and task while adapting the visible action path to the device. Use the existing native owner for target sizing, safe areas, focus, and host behavior; no critical action relies only on hover or a hidden gesture.

**Thorbis example:** A field photo remains attached to the same job when the tech changes orientation or returns from another app. The visible capture action and retry path remain available without discovering a desktop shortcut.

**Verify:** Check one-handed use, software keyboard opening, text enlargement, orientation, focus visibility, and reduced motion on the relevant device. Keep permission refusal and return-from-interruption states in the review.

**Do not import:** No desktop hover contract on a phone, blocked zoom, silent clipboard access, or unverified claim that a web imitation is native behavior.

Evidence: [Web Interface Guidelines](https://vercel.com/design/guidelines); [Design Engineer Principles](https://vercel.com/design/engineer); [Devouring Details](https://devouringdetails.com/). [Source access limits](https://design.thorbis.com/research/bookmarks#application-native).

[All 26 sources and review limits](https://design.thorbis.com/research/bookmarks).
