Mobile platform gate (D-025): Every mobile-app task requires the Native contract, HIG-001–HIG-022, and relevant live Apple Human Interface Guidelines (opens in a new tab). 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.
This is law. Not a mood board. Quiet chrome. Precise work. Drop this in the repo root.
You are building Thorbis, the operating system for the trades. A dispatcher at 7 a.m. A tech in a crawlspace. An owner closing the books. The job is to be the cleanest thing they touch all day.
Live kit: https://design.thorbis.com. (opens in a new tab) Rules, Research, and the eleven specialist skills, rendered with specimens.
Rules is what we ship. Research is the homework. Eleven skills under .agents/skills/. `SKILLS.md` is the bundle. This file is the constitution. `AGENTS.md` is the contract.
We studied Linear, Vercel, and Cursor. We did not steal their dress. Grammar, not costume.
Feature agents assemble approved infrastructure. They do not invent UI.
Linear baseline
Linear is the inherited operational baseline for every Thorbis rule, profile, pattern, primitive, and specialist skill. It is not a separate skill and it is not an optional visual style.
- Quiet chrome. The current work earns the strongest contrast.
- Structure through geometry, alignment, tone, rhythm, and stable ordering before borders.
- Remove noise before useful information.
- Repeated actions stay in repeated neighborhoods across modules.
- Route, modal, popover, inspector, Peek, and inline keep distinct roles.
- URL, Back, focus, selection, filters, scroll, drafts, uploads, offline state, and device handoff are product state.
- Critical actions have visible paths even when shortcuts exist.
- Mobile preserves object identity and work state while adapting navigation and action priority to the role.
- AI inhabits ordinary Thorbis records, evidence, approvals, and language. It does not receive another product costume.
The Thorbis × Linear pattern matrix is a selective reference for operational ambiguity, not another skill. Open the smallest owning skill first. If the matrix or registry has no matching pattern, stop under D-012.
Authority
- What the person in front of you just asked for.
- This file.
- `AGENTS.md`.
- The skill that owns this surface. Eleven files under
.agents/skills/. The bundle is `SKILLS.md`. Pick one. Live: https://design.thorbis.com/resources#skills - `REFERENCES.md` for source-linked visual evidence.
- Canonical specimens and screenshot baselines on Rules.
- Your preference last.
Existing product code is evidence. It is not permission to drift. If the screen and this file disagree, this file wins and the screen is a bug.
Apple HIG mobile authority
D-025 Every Thorbis mobile-app task MUST apply the Native contract. For iOS and iPadOS, the current applicable Apple Human Interface Guidelines (opens in a new tab) are the primary platform authority, not optional research. The Native contract owns HIG-001–HIG-022, source references, verification, and exceptions. This applies to Field Management and Network, including shared components, onboarding, billing surfaces, and release reviews.
Apple platform behavior outranks the Linear baseline, web specimens, and generic visual rules when they conflict on navigation, native controls, typography scaling, accessibility, materials, gestures, or adaptive layout. Accessibility, safety, privacy, and recovery are never traded away. Thorbis keeps its identity, semantic tokens, product words, permissions, and work state. Android follows its host conventions; Apple-specific chrome is not imposed on Android or the browser.
The fixed CSS sizes, inverted-L geometry, Inter/Geist defaults, icon-only chrome, custom surface rims, APCA-only checks, and custom motion timings below describe Thorbis-owned web/workbench UI, not overrides of native system components. Native controls retain their system labels, dimensions, materials, and transitions. D-018 and D-021 do not ban OS-provided materials in their HIG-defined roles. The Native contract owns the iOS/iPadOS equivalents and stricter Thorbis mobile requirements.
Every mobile specification, component contract, implementation PR, and release review MUST cite applicable HIG rule IDs and topic URLs, with evidence or a reasoned not-applicable decision. One unresolved applicable MUST failure blocks mobile completion; the older two-failure language does not apply to mobile. Reading this paragraph alone is not sufficient: open the Native contract and the relevant live Apple topics before implementation.
Context and visual references
Select context before implementation: name the person, device, profile, pattern, surface, and one action. Read this constitution and AGENTS.md, choose the smallest owning skill, then use `REFERENCES.md` to retrieve only source-linked images that match the task facets.
- Rules are law. Skills are the smallest specialist owner. Research and images explain or challenge a decision; they do not override the law.
get_design_contextis the bounded handoff for AI work. It returns the authority order, selected skills, focused rule sections, verification gates, refusals, and a small image set.get_documentremains the complete-source escape hatch.- Use the
compact,standard, ordeepcontext budget. Standard is the default: no more than 6 documents, 3 skills, 6 images, and 14 focused rule matches. - Each image needs a creator/source, attribution status, rule references, a concrete use, and a refusal note. If no image matches, use no image.
- Never copy a reference's brand, language, product identity, layout, behavior, or visual costume. Cite the source beside any image used for comparison.
Who
Name the person and the interruption before you draw.
- Dispatcher. Office. Keyboard. 27-inch board. URL is a share. Jobs, trucks, the day.
- Tech. Van, crawlspace, sun, gloves. One thumb. One action. Arrive. Capture. Done.
- Owner. Books, zoom, print. The number must be right. Invoice. Payroll. Who is on call.
Do not design for “users.” Design for one of those three, in the interruption they are in.
When things compete
- Meaning, money, permissions.
- Accessibility and recovery.
- Existing architecture.
- The job on this view.
- Tokens and primitives.
- Input method.
- Speed.
- Polish.
Never trade 1–2 for 8.
Profiles
Pick one. Do not mix on one view.
| Profile | Where | Density | Motion |
|---|---|---|---|
| Workbench | Board, books, Admin | High. Keyboard. Inverted L. | Press only. |
| Guided | Arrive, estimate, portal | One action. | Rare; follow Motion. |
| Evidence | Invoice, report, audit | Paper. | None. |
| Showcase | Marketing, first-run | Product larger than type. | Delight lives here only. |
A dispatch board is not a landing page. A landing page is not a dispatch board.
Showcase has four modes. Name one: router (homepage), explore (a family: Jobs, Money, Arrive), film (a named product page), store (pricing, signup). One idea per scene. D-022.
Stack
tokens → primitives → components → patterns → pages
Pages fill patterns. They do not invent buttons.
- Tokens own color, type, space, radius, shadow, motion. No hex in JSX. No
text-white. Nop-[13px]. - Primitives are the kit. Copy shadcn in, dress with tokens. Base UI when a primitive is missing. We own the styles.
- Components are stable combinations: SearchField, DataTable, EmptyState, CommandMenu.
- Patterns are List, Record, Settings, Evidence, Guided, Board, Inbox, Search, Canvas.
- Pages put trade data in a pattern. A job is a route. Collecting a payment is a modal.
Search the registry before you create. A new primitive is design-system work, not a feature shortcut.
Constitution
- D-001 A page uses an approved pattern or records why none fits.
- D-002 Shell geometry is owned by the pattern, not the page.
- D-003 No raw color, type, radius, shadow, z-index, or motion in product code.
- D-004 Interactive controls 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, not a feature shortcut.
- D-007 Search the registry before you create.
- D-008 A critical action cannot live only on hover, right-click, or a shortcut.
- D-009 Loading, empty, error, disabled, permission, and destructive states are designed.
- D-010 Canonical code outranks agent taste.
- D-011 Gold screens have screenshot baselines.
- D-012 If no pattern exists, stop and name the gap. Do not invent a page-local shell.
- D-013 A surface must earn its role. A page is a place. A modal is a transaction. A popover is a choice. An inspector is context. Peek is inspection. Inline is a small edit.
- D-014 Never use a transient surface for a durable workflow. Never force a durable page for a momentary transaction. A desktop drawer is not a page.
- D-015 Prefer a preference when the work varies person to person. Persist it. The default must still be complete. Customization may not rewrite the grammar, the tokens, or a shared document.
- D-016 Prefer a mark. Add a word to a control only when the action would be guessed wrong without it. Icon-only always has an accessible name.
- D-017 A radius is a curve you can see. The stroke that finds a rounded surface is a
borderthat follows the radius. Never an inset box-shadow as the outer edge of an overflowing box. Never a canvas-colored figure on canvas without that rim. Overflow clips content, not the stroke. - D-018 A fill is one mix. Never a gradient, mesh, or fade unless the brief names that exact wash. Never a solid colored border on the leading or trailing edge of a row, a card, a quote, a callout, an alert, a sheet, or a guidance column. Not a 2px rail. Not a box-shadow stripe. Not a
::beforebar. Live is a word, a mark, or accent on the thing itself. A full quiet rim may carry a mixed status hue; a one-sided colored rail may not. - D-019 Reserve the space. Media has an
aspect-ratiobefore it loads. A horizontal list shows 16–32px of the next item. Where a list continues, fade the edge. Nothing jumps. - D-020 A mark is outline at rest, fill when this is the place. Directional marks flip in RTL. Nudge when the geometry is a lie.
- D-021 An 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-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; it is not the product, and it is not the price.
- D-023 In one action neighborhood, role owns prominence and the group owns geometry. Peers share height, radius, type rhythm, alignment, and state footprint. A commit may lift while a utility stays quiet; unrelated dimensions may not create hierarchy.
- D-024 Attention orders media. Only first-viewport media may load eagerly. Every other image is right-sized, lazy, and asynchronously decoded. Video is poster-first, preloads nothing in a collection, and plays only while visible. Long media collections render incrementally and cache immutable variants.
- D-025 Mobile follows the Apple HIG mobile authority section and the Native contract; platform-specific rules, source citations, and release evidence are mandatory.
- D-026 Context is selected before it is generated. Name the audience, device, profile, pattern, surface, depth, and smallest owning skill; do not flood the model with unrelated rules, skills, or images.
- D-027 A visual reference is provenance-backed evidence. It must carry a source, creator, attribution status, facet metadata, related rule ids, a use statement, and a refusal statement.
- D-028 Rules precede references. An image, research source, component library, or preference never overrides
DESIGN.md,AGENTS.md,COMPONENTS.md, or the owning skill.
In Thorbis words: a page fills a pattern or names the gap. The page does not own the sidebar, the location bar, or the view bar. A durable workflow is a route. A momentary transaction is a modal. Context sits in an inspector. Taste loses to this file. An agent does not grant itself an exception.
Places
A page is a place. A modal is a transaction. A popover is a choice. An inspector is context. Peek is inspection.
Linear is not anti-modal. It is anti-ambiguous surface. We take that discipline. We do not ban sheets. Sheet is the work surface. A drawer is an overlay that slides over the work. Those are not the same word.
| Surface | Means | Thorbis |
|---|---|---|
| Route | Durable. Share, search, revisit, work inside. | Job, customer, invoice, estimate, equipment, report, search |
| Modal | One task. Create, confirm, cancel. Done or not. | Quick-create stop, collect payment, assign tech, add note, invite |
| Popover | One local choice. Little typing. | Status, priority, tech, date, tags, payment method |
| Inspector | Context beside the work. In the layout, not floating. | Job properties, invoice math, customer while scheduling, history |
| Split | Inspect many without leaving the collection. | Search results, inbox, list-detail |
| Peek | Look without navigating. | Hold Space on a job |
| Inline | A small edit that must not interrupt. | Title, a property, a comment |
| Drawer | Overlay slide-over. Desktop escape hatch. | Refuse. Make it a route or a modal. |
| Bottom sheet | Mobile only. Thumb, gesture, secondary. | Collapsed inspector, a secondary action |
⌘K goes somewhere or does something. It is an action system. Instant. It may open a record. It is not a place to compare fifty jobs.
Search as a route is a workspace: refine, filter, sort, split-preview, move through results. / may still filter this view. Different kinds of finding deserve different tools.
A quick create is a modal. A long create may expand into a place. Both are legal. A create that dumps them onto a blank page and loses the board is not. A nested overlay is not.
A desktop drawer fails because it is not a page (no durable URL) and not a modal (Back is a guess). It covers the thing they were comparing. If the content is important enough to hold navigation, history, or several next actions, it is a route. If it is metadata, it is an inspector in the layout.
If it needs a URL, history, filters, or more than one next action, it is a route. If it is Save, Create, Confirm, or Cancel, it is a modal.
Shell
Most of Thorbis is one app. The chrome does not change. The occupant does.
canvas
sidebar places (Jobs, Schedule, Inbox, Books)
main
location bar where you are
view bar how this work is sliced
sheet the work
inspector optional, one selected thingThis is the inverted L. Sidebar is the long arm. Location + view + sheet is the short arm. The sheet is the product. The page does not own the sidebar, the location bar, or the view bar. D-002.
Allowed occupants: AppShell, LocationBar, ViewBar, ListPage, BoardPage, RecordWorkspace, SplitInspector, ScheduleTimeline, GuidedFlow, SearchPage, SettingsPage, EvidencePage, CanvasWorkspace.
A spatial graph, Workflow, or Brain is CanvasWorkspace. It fills the sheet. It does not invent a shell.
| Slot | Size |
|---|---|
| Sidebar | 232px, first to collapse |
| Sidebar row | 28px, 13px type |
| Location bar | 44px |
| View bar | ~36px |
| Inspector | 320px, or a bottom sheet on a phone |
| Controls | 28 / 32 / 36px |
| Rows | 28 / 36 / 40px |
| Icons | 14 / 16px |
| Grid | 4px |
Sidebar open/close is transform plus negative margin. Do not animate width.
If the page invents a second header, a card grid as the page, a hero inside Admin, or a dashboard of equal buttons, fail. Recompose.
Keyboard
| Key | Action |
|---|---|
⌘K | Command. Instant. No scale. No fade. Go or do. |
/ | Filter this view, or open search if this is find-and-compare |
J K | Move the row |
X | Select |
Enter | Open |
Space | Peek |
Esc | Close the top layer |
C | Quick-create modal |
Hover ≠ focus ≠ selected. Hover is color only, gated to a real mouse. Focus is an accent ring. Selected is a fill or a mark. Shortcut-only is a defect. D-008.
Patterns
Choose the pattern from the job. Do not start from a dashboard template.
A pattern with an owner is a component you compose. A pattern without one is a gap: name it. Do not invent a page-local shell. D-012.
| Pattern | Owner | Job |
|---|---|---|
| List | ListPage | Today. Street first. A bar for the selected row. |
| Board | BoardPage | Open, en route, on site. Compact cards. |
| Record | DetailPage | 114 Oak. The feed. Inspector on the right. |
| Schedule | gap | Time is the spine. Trucks are rows. |
| Inbox | gap | The thread stays. The job beside it changes. |
| Search | SearchPage | Find, filter, compare. A route. Not only ⌘K. |
| Settings | SettingsPage | Save sits with the setting. Danger sits apart. |
| Guided | GuidedFlow | One action. Arrive. Not a squeezed board. |
| Evidence | EvidencePage | The question, then $186.00. Paper. |
| Canvas | CanvasWorkspace | Workflow, Brain, a map of steps. Spatial work on the sheet. |
| Showcase | none, on purpose | Product larger than type. Each campaign earns its move. |
Same chrome for List, Board, Schedule, Inbox, Record, Search, Canvas. The view changes. The operator does not relearn the app.
List. Street first. 114 Oak, then the leak. Not JOB-1842 as the title. The identity cell is a real <a>. Metrics stay quiet. Bulk actions appear in a visible bar when rows are selected, never only on hover. Empty names the one action. No open jobs. Create a job.
Board. Same chrome as List. Columns are status words: Open. En route. On site. Compact cards. One street, one status, one next action. Do not invent a second color language for columns.
Record. Identity, status, one primary action, history, inspector. Location stays put when the record changes. Destructive sits apart and names the consequence. Cancel job. Not Delete. The feed is what happened. It is not a chat toy. Inspector is 320px, in the layout. On a phone it is a bottom sheet.
Schedule. Time is the spine. Trucks are rows. This is a gap until ScheduleTimeline exists. Do not fake it with a board of hours.
Inbox. The thread stays. The job beside it changes. This is a gap. Do not invent a Messenger.
Search. A route. Use it when they do not know the title, must refine, filter, sort, or compare. Split preview. Jobs, customers, invoices, estimates, equipment. If they only needed one jump, you wanted ⌘K.
Settings. Local nav. Each section saves itself. No giant form. No one Save at the bottom of five topics. Display that is about this list lives on the view bar. Theme, density, default place, pinned places: this person. Shop-wide facts (who is on call, tax) are Settings. A customer portal and an invoice do not wear one person’s theme.
Evidence. Question, answer, comparison on one scale, exact table, assumptions. Every number has a basis and a period. Paper. No motion. No electric-blue wash. The owner must be able to print it.
Guided. One step. Progress. Recovery. 44px targets. Not workbench density. One action. Arrive. Capture. Send estimate. If they drop the phone, they can pick up the same step.
Canvas. Workflow. Brain. A map of steps. Same chrome as List. The plane is the sheet. Nodes are small sheets. Location names the graph. View bar slices Map / List. Inspector is the selected node. Dress the library. Do not ship its theme. Inventing this occupant: Product. .agents/skills/product.md.
Showcase. Illegal on a workbench. Product larger than type. Cinematic. .agents/skills/cinematic.md.
When nothing fits: stop. Write the gap. Do not invent a shell so the ticket can close. Do not invent a drawer so you can skip a route. D-012. D-014.
Customize
Prefer to let them change the interface where the work varies person to person. D-015.
A dispatcher wants compact rows. A tech on a tablet wants comfortable. An owner wants Light at the books. That is the product being polite. It is not a theme store.
| They may change | Where | Persist |
|---|---|---|
| Theme | System, Light, Dark | localStorage. Do not reset on navigation. |
| Density | Compact, default, comfortable. A view, not a new page. | This person. This device. |
| This list | Columns, sort, group, filters | The view. The URL when it is shareable. |
| Saved views | “Today’s leaks.” “Mike’s board.” | Named. Theirs, or the shop’s if they share it. |
| Default place | Where they land | This person. |
| Pinned places | Sidebar order, what’s present | This person. |
| They may not change | Why |
|---|---|
| The inverted L, the tokens, the words | That is this file. |
| A personal hex, a second brand, a card-grid layout | Costume. |
| A customer portal, an invoice, an evidence PDF | Shared. Their theme does not reprint the shop. |
| Arrive, capture, a Guided step | One action. Do not make the van a preferences panel. |
| Showcase | The picture is ours. |
The default ships finished. If the board is unusable until they open Display, you built a kit, not a product.
Workbench may be dense with a density control. Guided may not. Evidence may zoom and print; it may not wear a personal accent as the number.
Surfaces
canvas #0a0a0a oklch(14.5% 0 none) near-black void
panel #171717 oklch(20.5% 0 none) the sheet
field well one step darker inputs, icon circles
type #f7f4ee oklch(96.8% 0.009 84.6) cream
body #e6ecf4 oklch(94% 0.013 259.8) cool reading grey
marker #b7b7b7 oklch(78% 0 none) secondary labels
accent #3a6ae0 oklch(55.8% 0.188 264.4) electric blue. the brand
success #16a34a copied
danger #e5484d failed
info #3b82f6 info only, not brand
warning #ffb800 alert
olive forest pumpkin burnt extras. quiet marks. not jobs.Light is a retune, not an invert.
| Token | Light |
|---|---|
| canvas | cream oklch(96.8% 0.009 84.6) |
| panel | paper oklch(99.2% 0.0035 84.6) |
| field | warm well oklch(93.6% 0.011 84.6) |
| type | warm ink oklch(22.4% 0.014 72) |
| accent | the same electric blue |
System is the default. Persist the choice. Do not reset it on navigation. theme-color follows the resolved canvas. No flash.
- Canvas is never a working surface.
- The sheet is brighter than chrome.
- Regions have no borders as separators. A rounded figure that must be found, a field, a commit, a photo, a canvas-colored frame on canvas, has a 1px rim that follows the radius. D-017.
- A field is a well: one step darker, inset, 1px rim.
- A commit is ink: type-color fill, inverse type, 10px, 1px rim.
- Same fill as the parent is illegal.
- Chips are pills. Icon-only is a circle. Sheets are 14px.
- Nested radii stay concentric:
inner = outer − padding. - Photos on this canvas get a 1px rim that follows the radius, plus a short lift.
- Depth is a whisper: rest, sink, lift, overlay. 1px inset light, 1px drop. Not a card stack. If it lifts, you can press it.
Color
OKLCH. Lightness, chroma, hue. Not HSL. Not a mood board.
- Fix contrast on lightness. Never by adding chroma. Saturating a failing pair is a costume.
- Warm cream (
hue ~85) on a cool void (achromatic canvas, cool body grey). Do not warm the canvas. Do not cool the type. - One family of greys. One accent (
hue ~264). Status hues are reserved words, not a rainbow and not a triad. - 60 / 30 / 10, then quieter. Canvas is the field. The sheet is the work. Accent is a pointer, not 10% of the screen.
- A color looks different against its neighbor. Check the pair on the sheet it will live on. Then flip the theme and check again.
- Showcase uses the same palette. Void, object, pointer. No teal-and-orange grade. No second blue.
- Chrome likes quiet color. Place marks, menu icons, command glyphs may carry a soft hue: olive, forest, pumpkin, burnt, or accent mixed down to sit with them. The word stays cream or body. Only the mark is tinted. You notice the color after the word, not before.
- Do not grey every icon to “be serious.” Do not candy them. A selected place lifts the word, not a blue wash on the row. The mark is outline at rest, fill when this is the place. D-020.
- A fill is one mix. Never a gradient, mesh, aurora, or fade across a surface unless the brief names that wash. D-018.
- Never a solid colored border on the leading or trailing edge. Not on a row, a card, a quote, a callout, an alert, a sheet, or a guidance column. Live is a word, a mark, or accent on the thing.
Body contrast APCA |Lc| ≥ 75, prefer 90. Labels ≥ 60. Chrome ≥ 30. Disabled ≥ 15, never below. If a pair fails, increase lightness separation: lighten text or darken its surface in dark mode; darken text or lighten its surface in light mode. Do not add saturation. Do not draw a stroke to “help.”
A live job can stay grey plus a word. Status is not a rainbow. Olive is not success. Accent is not info. Pumpkin is not warning.
Picture
One focus. The sheet is figure. Chrome is ground. Size, then position, then weight. Color last.
- Tight inside a group. Generous between groups. Measure 65–75ch.
- The inverted L is the composition. Do not break it with a second header, a hero, or a card grid.
- F-pattern on a list. Street first. A thirds grid is not a layout tool for a board.
- Rest, sink, lift, overlay. If it lifts, you can press it.
- Media holds its hole. Aspect-ratio. A horizontal list shows 16–32px of the next item. Fade the edge of a list that continues. D-019. Delivery order is defined by D-024.
- Overlay is a mix, not a blur. A popover grows from its trigger. D-021.
- More space above a heading than below it. The heading belongs to what follows.
Frame
Showcase and product video only. A dispatch board does not get a thirds overlay.
- One object, named, before you draw. The board. The phone in the van. The invoice. The truck. Everything else is ground.
- Rule of thirds. Subject on an intersection. Horizon on a third. Never through the middle unless you can name a reflection.
- 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.
- Center is legal when the object is the poster. Open chapter. Name it.
- 16:9 and 9:16. Safe area is the middle 80%. Reduced motion is stills of the same crop.
- Establish the object, then crop. Recompose on a phone. Do not shrink the desktop hero. Copy is HTML in a third, not painted into the picture.
- The product supplies color in the shot. The chrome stays grey.
- Intent sets density. Homepage is a router of scenes. A product page is a film. Pricing is a store. One idea per viewport. Disclose in order: what it is, why it matters, how it looks, how it performs, proof, price. About 60–70% calm product, 20–30% evidence, 10–15% cinema. D-022.
The film is optional. Price is findable. Motion that only resembles Apple: refuse.
Type
Inter Variable for UI (opsz, ss01, cv11). Geist Mono for code, the shop's printed number, and money. Which number a screen may show is owned by Type.
| Role | Size | Weight | Line |
|---|---|---|---|
| Page title | 32 | 500 | 1.25 |
| Section | 16 | 500 | 1.5 |
| Content | 14 | 400 | 1.5 |
| Chrome | 13 | 500 | 1.45 |
| Caption | 12 | 500 | 1.4 |
Chrome is 13. Content is 14. A compact commit is about 32px; comfortable controls follow the density rule below. A chip is about 28. If the button is louder than the sentence, shrink the button.
Measure 65–75ch. Headings text-wrap: balance. Body text-wrap: pretty. More space above a heading than below it. Display 32 tracks tight. Root is antialiased. Tabular numbers on money and hours. Sentence case. No kickers. Title Case is allowed on Showcase headlines only. Centered type is ceremony. Left-aligned type is reading.
Controls
Web control density: compact fields and commits are 32px; comfortable fields and commits are 36px. A field/action neighborhood uses one density for all peers. Guided and touch controls are at least 44px. These are visual sizes, not permission to reduce the separate hit target below. Native controls follow D-025.
- Prefer a mark. Add a word only when the action would be guessed wrong without it. D-016.
- Action-neighborhood geometry and prominence are defined by D-023.
- Chrome is icon-only: search, theme, command, close, back, overflow, density. Circle, 16px Phosphor Regular, ~28px. Outline at rest. Fill when this is the place. 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 action on a Guided view.
Save invoice.Cancel job.Arrive. NotContinue. NotSubmit. - A chip that is a value stays a word.
Leakis not an icon. - Every icon-only control has an accessible name, and a title on a mouse.
- Hover is color only. No wash behind a word. Gate hover to
(hover: hover) and (pointer: fine). - Focus is visible and is not selection.
- Keyboard works everywhere.
⌘Kis instant. - Labels persist. Placeholders are emptiness (
Mike Reyes), not the label. - 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.
- Two rimmed controls keep 12px. Field to commit is 12px.
- Desktop hit 40. Touch 44. Mobile-app targets follow D-025, including text actions. Hit areas never overlap.
- Workbench controls stay compact at 32px by default on every viewport. Opt into 44px only for a touch-critical control or a Guided/mobile action; do not promote every button, field, tab, menu item, or icon because the pointer is coarse.
- A full-width commit sits in the sheet’s pad, not flush to the viewport.
- If it lifts, you can press it.
Motion
Frequency first. 100 times a day does not animate. Keyboard is instant. Destructive commits on release, not on press.
120ms. Ease-out cubic-bezier(0.23, 1, 0.32, 1). transform and opacity only. Never transition: all. Never scale(0). Never ease-in on UI. Never backdrop-filter as an overlay.
Press 80–120ms. Hover 100–120ms. Dialog and sheet 160–200ms. Ordinary web UI transitions take at most 200ms. Popovers, menus, and other events follow the Motion recipes. Exit the way it entered.
Reduced motion keeps opacity, drops movement. Hover motion gated to a real mouse.
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. D-022.
Platforms
Tokens are shared. Chrome is not. D-025 and the Native contract govern every mobile decision.
- Web workbench. Inverted L. Sidebar, location, view, sheet. Keyboard. URL is state.
- iOS and iPadOS. Apple HIG is authoritative. Use native navigation and adaptive presentation, meaningful destinations, system text styles, and accessible controls. Cite and verify the applicable HIG rules. Do not turn actions into tabs or copy a desktop shell onto a phone.
- Android. Material 3 navigation. Predictive back. 48dp. Device type on chrome. Inter on the job. Accent stays electric blue. Do not ship Google dress.
- Desktop. Host window chrome.
⌘Kon Mac.Ctrl+Kon Windows. Traffic lights on Mac. Caption buttons on Windows. Do not paint the other OS. - Web on a phone. Still a browser. Collapse the sidebar. Use a sheet. Do not add a fake tab bar on top of Safari. Inputs ≥ 16px. Never
user-scalable=no. Nevermaximum-scale=1.
Do not pour one shell into another.
Words
| 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.
Active voice. Second person. Concrete verbs. When a control has a word, it names the action: Save invoice, not Continue. Prefer a mark. 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 …. No marketing inside the workbench. No all-caps labels.
Primitives
The UI package owns primitives and tokens. Feature code consumes them.
- Extend
@theme. Do not fork a color on a page. - One button. One field. One dialog. Variants are semantic (
destructive,ghost), notisInvoice. - A dialog is a transaction. It is not a place to put a job.
- Every primitive has hover, focus, disabled, loading, and the keyboard path.
- Icon-only is a circle. Chip is a pill. Commit is 10px ink. Field is a well.
- Motion uses the tokens.
--motion-fast,--ease-out. No private curve. - Light and dark are both first-class.
- Do not import a second component kit. Do not hand-roll a menu or a tabs list.
- A primitive does not know what a job is. Do not put feature copy in it.
- If a boolean exists to hide a slot the caller could have omitted, delete the boolean. Compose the pieces.
Credit
We studied Linear (Karri Saarinen, Jori Lallo, Tuomas Artman), Vercel (Rauno Freiberg, Paco Coursey), Cursor (Ryo Lu), Emil Kowalski on motion, Steve Schoger on spacing. The names live on Research. The homework is public. The costume is not ours.
What we keep: inverted L, quiet chrome, dense rows, instant command, wells and lifts, 120ms, tokens, one accent, a sheet brighter than chrome, a page as a place and a modal as a transaction.
What we never ship: their logo, purple, or product copy. “Issue”, “Cycle”, “Project” as our objects. A pixel-identical chrome that claims to be Linear. A comment that says “like Linear” instead of a rule.
Routine work on an approved pattern does not need a new study. Do not open Linear to pick a grey. Mobile work still requires the applicable Apple HIG references under D-025.
Never
- A second visual language on one product
- A line between two jobs, under a heading, or around a room
- A dashboard of equal buttons
- A blue rail with a shouting logo
- A second header invented by the page
- Card-of-cards as the page
user-scalable=noor inputs under 16px on a phone- Positive
tabindex - Lorem, Acme, or “Welcome to the future” on a board
- Hex,
text-white, or a raw shadow in product code - Linear purple, the Linear mark, or “Issue”
- A desktop drawer used as a page
- A nested overlay
- Search that only lives in
⌘Kwhen they need to compare - A thirds grid on a workbench
- Teal-and-orange grade, or a second blue, on a product video
- Type larger than the product in a frame
- Contrast “fixed” by saturating
- An all-grey menu as a virtue, or candy icons
- A theme store, a hex picker, or a Guided flow with display options
- A default that is broken until they open Settings
- A word on a button that a mark would have made obvious
- Mystery-meat chrome with no accessible name
- A gradient, mesh, aurora, or fade, 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, an alert, a sheet, or a guidance column
- A blurred overlay
- A scroller that hides the next item
- Layout shift from a photo without an aspect-ratio
- Specs in a Showcase hero
- Hiding price behind a film
- Mixing Workbench density with Showcase theater on one view
The native-platform scope in D-025 applies to these visual prohibitions; do not use them to disable Apple's system components or accessibility behavior.
Done when
The person, the profile, the pattern, and the surface are named. Tokens only. Keyboard path works. Hover is gated. Contrast holds (APCA |Lc| ≥ 75 body). Empty, loading, and error exist. The words are ours. A preference exists where people differ, or you named why not. Controls are marks unless a word is required. No gradient unless the brief named it. No solid colored side rail. Media holds its hole. Marks are outline at rest. Overlay is a mix. If Showcase: mode named, one idea per scene, film is not the only proof.
Render desktop and 390px. Keyboard the path. Flip the theme. Check the console.
For mobile apps, complete the Native contract evidence matrix. A browser screenshot is not native-device proof. One unresolved applicable MUST failure blocks completion.
Two failures: do not ship. For mobile, the stricter D-025 gate applies.
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.
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 (opens in a new tab); How we think about design (opens in a new tab); Component Architecture for React Server Components (opens in a new tab). Source access limits.
Frequent work stays immediate; allowed motion can be interrupted
Owning skill: 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 (opens in a new tab); 7 Practical Animation Tips (opens in a new tab); Train Your Judgement (opens in a new tab); Details that make interfaces feel better (opens in a new tab). Source access limits.
Use color to clarify state, not replace it
Owning skill: 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 (opens in a new tab); Details that make interfaces feel better (opens in a new tab); components.build (opens in a new tab). Source access limits.