Contents
- 0. Opening
- 1. Same by default
- 2. The register
- 3. The method
- 4. Components, Cards and Pages
- 5. OmoCatalog
- 6. The reviewed copy, and the debt
- 7. What stays outside, and what the final brings into line
- Appendix A. The tokens
- Appendix B. The inventory
- The Card drawings
- The frame
- Controls
- Marks and states
- The interactions
- The thirteen views
- Appendix C. The differences register
- Appendix D. Glossary
Omo Design System#
The third document, after Omo Plan (1-Omo-Plan.md) and Omo Architecture (2-Omo-Architecture.md). Written by
Native Canvas, Omo's design lead, through the studio's writing process (docs/canon/writing-process.md), from précis V4.
Final, 2026-11-12. Ryan pre-approved its précis and its final as gates, and reads it after publication. Its working
files and reviews are in docs/archive/2026-11/omo-design-system/.
0. Opening#
Why it exists. Omo Architecture made the things consistent: one Place that every list conforms to, one list contract that every Place keeps, one Item that a task, a letter and a decision all conform to. The design didn't follow. Each Space was designed afresh, so Mail grew its own row, its own open letter, its own list header and its own copy of the selection colour beside the project's. Ryan kept asking why something was different when nothing required it (12 November). This document is where the architecture reaches the design.
What it is:
- the components: each part of Omo's interface, built once in OmoKit and used everywhere;
- the method: five questions a designer answers before every change.
Where it ranks:
- Third, after Omo Plan and Omo Architecture. The architecture says what a thing is; the plan says who builds what, and when.
- For
design-principles.md,design-process.mdandux.md, it specialises them for Omo. It adds detail, wins over them on that detail, and never weakens one of their rules. The list contract's minimums hold in full (architecture 4.4).
What it isn't: a brand book, a token dump, or a fourth source of truth.
How to read it:
- A designer reads §1 to §3 before every change.
- A builder reads §4 to §6 and appendices A and B, and the debt list.
- A reviewer reads §1, §2 and appendix C.
1. Same by default#
Ryan set the rule on 12 November, reviewing the desktop prototype, where Mail's lists had their own styling and clicks.
He asked for everything to follow the pattern already established (design-principles.md, "Same by default").
Components. A component is one reusable piece of Omo's interface (a row, a list card, a button), built once in OmoKit, the code library every Omo screen is drawn from. It's used wherever its job appears.
Siblings. Two places are siblings when they draw the same construct in the same view, in different Spaces or on different devices.
- Mail's Receipts and a project's Doing in the Board view are siblings. So are a letter's row and a task's row, and the Mac's row and the phone's.
- Two views of one Place are not siblings. A Manifold is the architecture's list of the ways a Place can be drawn (9.1), and each of its cases has one view. The Board view and the Focus view are two cases, each drawn its own way.
- One component at two Scales is still one component. A Scale is the architecture's size for a drawing (
Scale.line,Scale.sheet,Scale.screen,Scale.spread), each a compression of the next, never a different thing (9.2).
Content and form. Siblings differ only in content.
- Content is what the Node fills in, a Node being any thing Omo records (a list's title, colour and count; an Item's title, chip values, body and activity). It's also what the viewer chose in their PlaceLayout, their own view of a Place (their own colour, column widths, which lists are collapsed).
- Form is everything else: geometry, the named values the component uses (its tokens), the order of things, and every interaction (what a click, a key, a drag or a finish does).
Each component's form is written once, in its component specification, kept beside its code (§4).
Conditions. A component specification may make a part of a component depend on something, with its reason. That's a condition, and it applies the same way to every sibling. It may depend only on:
- a capability the Place or Item declares: the add row shows where the Place takes members typed in; the finish circle shows where the Item can be finished;
- the input: a pointer, touch, a keyboard, or Vision Pro's gaze. Hover shows only with a pointer, and key hints only where there's a keyboard. Under gaze, a looked-at thing brightens and grows 5%, since visionOS can't move it toward you;
- the space a view gives it, its Scale: what each Scale keeps.
A condition is never worded by Space, by kind of Place, or by device name. "Mail's lists have no add row" is wrong; "the add row shows where the Place takes members typed in" is right, and it hides the add row on any Place like that.
Differences and defects. A sibling may depart from its component specification only as an intended difference:
- it departs from one named rule, and changes only that;
- its reason can be written in a sentence;
- Ryan approves it.
Anything else is a defect, removed rather than defended. A missing implementation is always a defect, whatever is
written about it (design-principles.md, "Required behavior").
The model case is where an Item is finished.
- A task finishes from the circle on its row, just above its open item, so its open item has no Done.
- A letter finishes from Done in its open item, where it's read, beside Reply, Later, Task and Label.
One rule is departed from ("an Item finishes from its row's glyph"), for one reason, and everything else is the same: the glide, the fold, the counts, the Undo. It's register entry d-002.
2. The register#
The differences register (appendix C) is the one list of intended differences.
A register entry has:
- its anchor (
d-NNN); - the component, and the rule it departs from, cited by anchor;
- the siblings it separates;
- the one thing that differs;
- why, in one sentence;
- its status.
A register entry for a list also gives what the list contract asks of an exception: the exact collection, the feature left out, the structural reason, its replacement, and the independent review that accepted it.
What a register entry may depart from: this document, a component specification, design-principles.md or ux.md.
A departure from the architecture isn't a register entry. It's a change to the architecture, proposed on its Omo item
(c9fb2142) and made in docs/canon/architecture-source/.
Ryan approves every register entry, and every condition. A treatment's token values aren't on his list: they come from the reviewed copies, and they're form.
- The design lead proposes either one. It's provisional, and may be built.
- At this document's final, every provisional register entry and condition goes to Ryan as one list on the document's Omo item, for him to strike any he doesn't want. A struck one becomes a defect.
- After the final, each new one goes to him with the work that uses it, in the normal review after deployment.
- A condition on a list also has the list contract's independent review.
- Omo's own models may propose a register entry, and never add one.
For lists, the register has a code form:
ListExceptions(architecture 4.4) is to be generated from the register entries for lists, so appendix C stays the one source;ListConformance, the list contract's tests, fails a list that differs without one.
Both are still to be built.
3. The method#
Before every change, the designer answers five questions, in writing, on the work's Omo item.
-
Which component is this? Name it, the construct it draws, its view and its Scale.
- If no component fits, it's a new component: below.
-
What one thing differs between siblings? If nothing does, or the variation is already a condition, go to 5.
-
Why? Write the reason in one sentence. If you can't, the difference goes.
-
Is it in the register? If not, propose the register entry (or the condition) as provisional, before it's built.
-
Did the change reach every caller? This runs on every change, including one with no difference.
- Every caller: each place the app uses the component, from the callers list, a list generated from the code that names each one with how it's configured (§5).
- Every copy still on the debt list, the list of copies of a component still outside OmoKit (§6). A copy doesn't receive the change by itself, so each is changed or retired in the same commit.
- Seen in
OmoCatalog, the design-only target that shows each component in each of its callers' cases (§5), in light and dark, in each treatment, a treatment being a component's sizes and type for touch, a pointer or Vision Pro (§4). UntilOmoCatalogis built, the app's development build stands in (§5). - Tried: clicks, keys, drag and Undo, in
OmoCatalogand in the app's development build, with the interaction recorded.
This is "One note covers every instance" (
design-principles.md): Ryan never gives the same note twice.
The case the method exists for. Ryan changes the row's hover. Projects get it through the row. Mail's own rows are on the debt list, so question 5 names them, and the change retires or changes each. It isn't done until both Spaces show it.
Other cases, in a line each:
- A defect: Mail's row copies
KitColor.selection's values by hand. The colour is the same today; its source will drift. No reason can be written. - A provisional register entry: a letter's row shows its sender's avatar (d-015).
- A condition: the add row shows where the Place takes members typed in.
- No difference, still question 5: the running stroke's hover takes the phone's press on a pointer (Ryan, 12 November). Every caller is checked.
A new component follows design-process.md, "Inside Omo":
- it's described first in words, cue by cue, and a cue that would mean a second thing is Ryan's to settle on a working case;
- it's designed in
OmoCatalogat every Scale where it can appear, in light and dark; - if it shows a result that arrives unasked, it brings its result type, its row in the table of the presenter (the architecture's Presenter, which decides how such a result is shown), and two filled examples;
- if it moves, its moment has the full specification
design-process.md, "A moment has a spec", asks for.
4. Components, Cards and Pages#
The layers follow design-process.md's layer cake:
- principles, in
design-principles.md; - materials: Liquid Glass for floating chrome and the frame, solid fills for content;
- tokens: named values (colour, the nine list hues, type, spacing, corners, motion), each living once in OmoKit (appendix A);
- components;
- interactions, the layer cake's patterns: select, open, finish, drag, resize, turn the view, arrive, and the keys. Each is defined once and offered by every component that needs it. (The lexicon gives "pattern", and "behaviours" too, to the dkini, the template every synth of a lineage is made from; so this document says interactions.)
- screens, which are Pages;
- flows, which are sequences of Pages, such as the intro.
A component is a view (the row), a style (the button's ButtonStyle) or a modifier (the glass modifier). Supporting
types, such as an enum of widths or a value model, belong to the component they serve.
Its component specification is written by Native Canvas, in OmoKit beside the code, as the component enters
OmoCatalog (Omo item 64ae294b). The row's, the open item's and the list card's come first, before the first merge.
It follows ux.md's format:
- purpose;
- data contract;
- states;
- Scales;
- motion;
- Reduce Motion;
- hover;
- light and dark;
- Lock Screen;
- accessibility;
- devices.
To that format it adds two fields:
- Rules, numbered, which a register entry cites;
- Conditions, each with its reason.
A style or a modifier fills only the fields that apply to it.
Card and Page. Architecture 9.2 declares one Card(node:scale:), one Page(node:scale:) and
Presenter.present(_:mode:) in OmoKit.
- Today none of them exists, and neither does
Scale.Manifoldis in the Kernel (KernelVocabulary), which today's OmoKit can't see. - The first merge adds
Scaleto today's OmoKit: an enum that depends on nothing, where architecture 5.7 puts it. UntilCardandPageexist, the components are the entry points, each taking a value model: a plain Swift value the Space fills (§4, the seam). - Plan 1.31 moves OmoKit into Mindplex, the package every Omo Kit and Core lives in, where it depends on
KernelVocabulary(architecture 5.7).Card,PageandPresenterare then added over the components.
Card(node:scale:) draws, as 9.2 has it:
- an Item: the row at
Scale.line; the open item atScale.sheet; the Focus card atScale.screen. AtScale.spreadit draws its Page: this document's own fallback, which 9.1's fallback rule allows. - a Place: the list card, at the Scale its view gives it.
- a Member: the hover card at
Scale.sheet. AtScale.line, the row, with the Member's name, face and role filling its value model: also this document's own fallback. - an Ask: the ask card at
Scale.line(as a notification) andScale.sheet. A.decideAsk is drawn atScale.screenorScale.spread, as 9.2 says: the ask card at those Scales, with its options and criteria. - anything at a Scale with no drawing falls back as 9.1 says: to the row, then to its title and a way to reload.
The presenter's other cards. The Presenter chooses a card from a result's type and returns "the Card to show" (9.2).
- The consent card is for a request for a Release or a Lane; the alert card is for a safety alert.
Card(node:scale:)can't tell them apart: nothing on an Ask marks a Release or Lane request, and a safety alert isn't a Node.- So the proposal is that the Presenter builds them from a value model that carries the kind (
KitAskModel.kind: ask, consent or alert). - That goes beyond 9.2, so it's proposed on c9fb2142 and pending. Until it's settled, the consent card and the alert card aren't built.
Not in V1: the day's CheckIn is an Item, and comes with Core Memory in Omo V2, which is paused. Its card isn't built now.
Page shows one Node in full: a Place's whole screen, or one Node opened on its own. A Space's Kit fills Pages and
Cards with value models, and the app's Spaces/ folder only wires them (architecture chapter 5, "The package
layout").
- New work: a new view outside OmoKit that draws, rather than composes, fails review.
- Existing app views that draw are the debt list, not review failures.
The seam. Every component takes one shape of input and output, as OmoKit's CONTRACT.md says:
-
A value model in, never a store or a database type.
- The row takes
KitItem, extended with what the reviewed row shows. - The open item takes
KitOpenItemModel, theKitItemwith its activity, description and ask. - The menu's model is
KitMenuItem, extended with what the app'sMenuEntrycarries. For the first merge, the moved components take a menu-presenting closure instead, and the menus are unified onKitMenuItemin a later merge.
The fields are listed in the debt list's first merge, and fixed in each component's specification.
- The row takes
-
Capabilities are fields on the value model, filled by the Space's Kit, as
KitList.canAddalready is. Conditions read them, so neither the Place nor the Item declares anything new in the architecture. The first merge needs:- takes members typed in;
- can be finished;
- its title is Omo's;
- can be handed on;
- its visibility can be set;
- can move between boards;
- can be read or unread.
-
An actions value out: open, toggle, finish, select, rename, the menu (a closure that presents it), drop and accept. The Space supplies each.
-
Slots for content: the open item's body is a
@ViewBuilderslot, so Mail supplies the letter and a project the task's details. -
The treatment from the environment.
- What it is: a component's tokens for touch, a pointer or Vision Pro: its sizes, type and insets, and nothing else.
- Where it comes from: one environment value,
KitTreatment(.touch,.pointer,.spatial), new in the first merge. One OmoKit modifier,.kitTreatment(), applied atPhoneRootand atMainView, sets it from the window's primary input: a touchscreen is.touch, the Mac's pointer.pointer, Vision Pro's eyes and hands.spatial. It never reads the device idiom. So an iPad, with or without a trackpad, takes the touch treatment's sizes (the 52 pt row, the 15.5 pt title), and a trackpad still gives hover, because hover is a condition on input (the chief of staff, 12 November). A condition on input reads the input present at that moment (a pointer hovering, a hardware keyboard attached), so an iPad with a trackpad shows hover. A token's value never comes from#if os(...)orUIDevice. Branches for a platform's own API stay where they are (NSColoragainstUIColorinColour.swift, the glass API inKitGlass.swift, the avatar's image type,AppleFontSmoothinginThemes.swift). - Dynamic Type isn't part of a treatment. It's the person's setting, and it scales the treatment's sizes in every treatment, through text styles, on the Mac as on iPhone (architecture 9.3). The Mac's fixed-size type helpers are debt for that reason.
- How a token varies by treatment: it's resolved from the treatment, for example
KitFont.rowTitle(for:)orKitMetrics.cardRow(for:). So a phone row renders with its phone type on the Mac. Any split by width is a condition on Scale, never a device test;Metrics.isPhoneis debt. - Debt: the size branches in
Foundations/Type.swiftandFoundations/Themes.swift, andKitTouch(Foundations/Touch.swift), move onto it, along with OmoKit's environment valueskitTouchLayoutandkitRowInsetand the app'sMetricsoverrides. Only branches that change a token move onto it. A branch that changes layout (the phone row puts its date and chips below the title, where other rows put them beside it) is a condition on Scale, written in the row's specification. - Anything else that differs between touch and a pointer (structure, gestures, where a control sits) is a condition on input or on Scale, worded that way and on Ryan's list, or a register entry.
-
Gestures through a hook: a UIKit recognizer stays in the app and attaches through a modifier hook the component offers.
Who owns the state. Components draw and never write. They read three things:
- the Place's shared settings:
color,defaultManifold,manifolds, its sort and its hand-chosen order; - the viewer's PlaceLayout: the view they chose, collapsed or not, their own colour, column widths, board grouping, and the open Slot;
@State: only for what is momentary.
This is architecture 9.1's "presentation state lives in the graph". Until the cutover (the move from today's store to
the Kernel's graph, Omo Plan's stage 1), the app's store holds the list's state app-wide: the Item open in place
(drawerItemID, which becomes openInPlaceID), the selection,
the cursor, the Item being renamed, the open menu, the scroll target, the finishing hold. The first merge adds one
interim OmoKit observable, KitListState, owned by the store.
- It holds only transient interface state the components share, so each move uses the same bindings.
- Lasting per-viewer state (the collapse overrides, Show All's open lists) goes in PlaceLayout, and the store until the cutover.
- Actions stay closures.
The debt list's first merge places each field.
An interaction is shared, and its effect belongs to the Space.
- A drag is the same lift, landing slot and Undo everywhere.
- What a drop does comes from the Space's authorised adapter: a task moves, a letter is labelled.
- The component shows the effect before the drop, refuses a destination the adapter can't take, and says why.
Selecting and opening (architecture 9.1 and 9.3; design-principles.md, "Lists work the same way").
- On the Mac:
- a click selects, shown as the lapis selection band;
- ⌘-click adds an Item to the selection, and Shift-click selects a run;
- a double-click or Return opens, and Return closes;
- a click never opens.
- On touch, a tap opens. A selection starts from a row's menu (Select), and while rows are selected, a tap adds or removes a row.
- In the Rows and Board views, an Item opens in place, under its row, and opening another closes the first.
- In the Focus view, the Item already fills its card, and it finishes from the card's Done (X).
- In every other view, its component specification says how, and no Space uses that view until it's designed.
- Keys follow the Mac's shipped map (
Interface/KeySheet.swift), including: ↑↓ or J K move, Return opens or closes, X completes or undoes, E renames, R replies, ⌥ with the arrows moves, N adds, C collapses, M opens the list's options, ⌘Z undoes, and ? shows the keys. In code, Space also opens and closes, and ⌘⌫ deletes (Interface/RowActivation.swift). They join the map.- Every list, not only a project's board. Today
RowActivationlets X, E, R, N, C, M and J/K act on a project board only, so the keys are missing on Today, the smart lists and Mail. That's a missing implementation, so a defect, on the debt list. - A key whose action only some Items have is a condition: it acts only where the Item has that action. That covers a letter's Later, Label, Task, and Read or Unread.
- On a letter, E finishes and never renames: provisional register entry d-019.
- Every list, not only a project's board. Today
- The proposed change to selection: Ryan asked on 12 November for two faint lapis lines on a click, and the fill only for a selection of several. It changes architecture 9.3, so it's proposed on c9fb2142, and this document follows 9.3 until it's approved.
Each Manifold case has one view, drawn by OmoKit and used by every Place shown in that case (appendix B).
- A list of one has no view: it opens as its Node's Page.
- Every view keeps the list contract, with the ordering rule its case gives:
- importance first where the Place keeps its own order;
- by the property in Timeline, Days and Map;
- the Focus view's own queue.
- A Place with a declared domain order (Mail's newest first) sorts by it, and shows it as the selected sort.
- The Rows and Board views draw each Place as a list card.
The list menu has one order: Rename, Order, Colour, Collapse, then what the list is for. Ryan approved it with the audit on 12 November. Each action is a condition on a capability:
- Rename shows where the Place's title is Omo's (decision fe8cf76e covers a Gmail label);
- New Items Are shows where the Place makes new Items of a chosen kind;
- Private shows where the Place's visibility can be set;
- Move to Board shows where the Place can move between boards;
- Mark All Read and Done All show where its Items can be read or finished.
Values live in code. A token's value is in OmoKit and nowhere else. Appendix A names each token's code home, and the ones still in the app are debt.
5. OmoCatalog#
Ryan noticed that a web prototype isn't built the way the native app is, so moving a design between them costs more than it saves (12 November). Design for Omo now happens in SwiftUI.
OmoCatalog is a design-only target beside OmoKit. It isn't built yet, and nor are its checks. Native Canvas builds
it (the target, its hosts, the source check and the callers-list script) on its own omo-apple branch, as Omo item
64ae294b, and the iPhone builder reviews it. It lands before or with the first merge.
- What counts: a treatment rendered on the Mac counts. A gesture recognizer, or iPhone Duo's hinge, is checked in the simulator.
- Until it works, the app's development build stands in.
- Before a reviewed copy moves into OmoKit, question 5 still applies: its callers are the app's callers of that
copy (today, every caller of
ItemRow). - Where:
omo-apple's OmoKit package, beside theOmoKitSnapshotstarget. It moves beside OmoKit into Mindplex with 1.31. - What it shows: only what's in OmoKit. A reviewed copy still in the app gets its case in the merge that moves it.
- What it holds: one case for each caller of each component, with that caller's real configuration and sample data.
- How a case works: it works fully for its moment, through a small container with
@State, and never needs the rest of the app. - It never ships.
- Its hosts: an iOS host target for the simulator (an Xcode target in
omo-apple'sproject.yml, depending only on theOmoCataloglibrary, since a Swift package can't make an iOS app), and an offscreenNSHostingViewcapture for the AppKit-backed parts (GlowField,SidebarClick, the menu's panel), whichImageRenderercan't draw.
Three checks hold "same by default" where memory couldn't:
-
the package boundary:
OmoCatalogcan't reach the app's copies; -
a source check: it fails if
OmoCatalogdeclares a view, style or modifier that draws, beyond its@Statecontainers; -
the callers list: generated by a script in
omo-apple'sscripts/and read in review. It lists:- every caller of each component, with its parameters, any modifier wrapped around it, and its handlers;
- every app view not yet on the debt list.
A wrapper that changes a component's form is a register entry, or a defect.
What Ryan approves. For a visible step, the plan's release order needs the prototype approved first, and the
prototype is now the working OmoCatalog case. On the step's Omo item, Ryan sees light and dark renders of every caller's
case, and a recording of it working, and approves there.
- Until
OmoCatalogworks, the prototype is the change in the app's development build, approved the same way, as the 0.11 gates do today. - The renders and the recording meet only the prototype gate. The rest of the release order still applies: the build's independent review, Native Canvas's fidelity packet, delivery through TestFlight and the notarised Mac build, and Ryan's review of the release.
- HTML prototypes for Omo stop. The desktop and phone prototypes stay as history, and as the record of what he approved before.
Every builder's branch is gated side by side (Ryan, 12 November, through the chief of staff). Native Canvas compares
the app with the approved prototype screen by screen, in light and dark: on the Mac, the desktop prototype (dist-45,
served at http://127.0.0.1:4325); on touch, the phone prototype. Any difference that isn't a register entry or a
condition fails the gate, whatever the branch was about. A builder's own description of what it built is never enough.
A design change is a code change, made on a branch in OmoKit and merged like any code. The app draws OmoKit's components, so it reaches every caller in one merge.
6. The reviewed copy, and the debt#
The parts the app ships, the ones Ryan has reviewed, mostly live in the app target, not OmoKit: the row and the open item, five list headers, a menu system, and the sidebar. OmoKit holds unused earlier originals of most of them, and Mail adds copies of its own.
The reviewed copy wins. Where a component has several copies, the one Ryan last reviewed wins, as long as it meets the current canon and accessibility rules.
- An approved feature on a losing copy moves into the winner first, as a rule, a condition or a register entry. The sender's avatar on Mail's row is one.
- Where each device has its own reviewed copy, the two become one component. Their tokens become its treatments, and each other difference becomes a condition on input or Scale, on Ryan's list. This covers the menu, the Focus view, the view switcher, the sidebar and the selection bar, and appendix B lists each one's differences.
- A winner's evidence is recorded before anything is deleted against it: its commit, and the review that settled it. Without that, it goes back to Ryan first.
The debt list is Omo Plan 1.31's worklist. It lives in docs/working/apps/omo/design-system-debt.md, because it
changes as 1.31 lands. 1.31 has two parts: it moves the surfaces into OmoKit, in omo-apple, and then moves OmoKit into
Mindplex.
The first merge is the first move of 1.31, ahead of the rest of that step. It moves the row, the open item and the
list card into today's OmoKit in omo-apple, because the proof (phone Mail redone from shared components) needs them.
- Decided by the chief of staff under Ryan's pre-approval of this work, 12 November (Omo item d78908ce).
- Who: the iPhone builder, acting as 1.31's builder for these three. The Mac builder reviews it, and Native Canvas checks it.
- When: once 0.11 has landed for them, meaning the gates of
redesign/open,redesign/finishand the list cards have passed and merged. And before phone Mail. - The plan: Omo Plan 1.31's text is amended at this document's final (§7).
- Its device-branch rewrite covers only the three components it moves. Plan 1.32's inventory of every idiom branch, its change per file family and its static check still follow.
The rest of 1.31 is its stage-1 builder's, the builder Omo Plan names for stage 1, checked by Native Canvas.
- Meanwhile, a new shared part goes into OmoKit when everything it reads is a Kit value, a closure or a Kit observable. Otherwise it goes into the app, onto the debt list.
Ownership is by owner, not by file.
- Native Canvas owns OmoKit and the look.
omo-apple-parity, the session that keeps the Mac and iPhone behaving alike, owns behaviour,Menus.swiftandMenuPanel.swift.- A move that touches both is reviewed by both.
7. What stays outside, and what the final brings into line#
What stays in its own document:
- the studio's principles, in
design-principles.md; - the process, in
design-process.md; - the grammar of views and cards, in
ux.md; - what each thing is, in the architecture's chapter 9.
Apps outside Omo keep their own design systems.
Proposed changes to the architecture, pending Ryan on c9fb2142:
- 9.3: selection becomes two faint lines on a click, and the band for a selection of several.
- 9.5: on the Mac, the sidebar's foot gives way to the Omo mark menu and a Search row under Goals (Ryan, 17.05, 12 November).
- 9.2: the Presenter builds the consent card and the alert card from a value model that carries the kind.
The plan's amendment, made at the final (as the chief of staff decided). Omo Plan 1.31 now says:
- its first merge (the row, the open item, the list card) is the iPhone builder's, ahead of the rest of 1.31;
- that merge needs only 0.11's open, finish and list-card gates, not the whole of 0.11;
- its device-branch rewrite covers only those three components, and 1.32's inventory, per-family changes and static check still follow.
The canon's index, made at the final: docs/README.md and the opening of AGENTS.md rank this document third,
after the plan and the architecture.
Changes made below at the final (12 November):
design-principles.md:- "Same by default" points to the register and to conditions;
- the list contract's "closed exception registry" points to appendix C;
- "Buttons behave the same everywhere" adds the running stroke to Omo's own exceptions: a screen's one recommended action, glass with a spectral stroke running round it, whose hover on a pointer takes the press.
ux.md:- "until Omo's design system document holds them" becomes a pointer to appendix A;
- "spec" becomes "component specification";
- "Sheet (iPhone sheet)" is corrected.
design-process.md, "Inside Omo":- prototypes are made in
OmoCatalog; - the layer cake's words map to this document's;
- "a part a component" is corrected.
- prototypes are made in
- The glossary (
docs/canon/glossary.md) gains component, component specification, condition, treatment, register entry andOmoCatalog. design-system-facts.mdwent to the archive (docs/archive/2026-11/apps/omo/).- Still to come, in
omo-apple, through its own branch:docs/design-handover.mdpoints here;AGENTS.mdgains how to look atOmoCatalog.
Appendix A. The tokens#
Each token's value lives in code, and this appendix names its home. A value is given here only where none is in code yet.
Where the older sources disagree (docs/archive/2026-11/apps/omo/design-system-facts.md, omo-apple/docs/design-handover.md, the phone's design notes, 12 November's
decisions), the latest reviewed decision wins.
Colour (KitColor, Foundations/Colour.swift). Each is designed separately for light and dark, and dark is pure
black.
ground,panel,card,hair;inktoink4;accent, for the one main action and focus only;danger;attentionandattentionInk, never an error colour;lateDot;newRow;hover;selectionandselectionHair;recommendWash,recommendWashHoverandquietRing.
Colour in the app, to move: the open tone (Color.openItemTone, Interface/ItemDrawer.swift), the menu's values
(Interface/Floating.swift), tintedGlassFill and GlassTuning (Interface/Theme.swift).
List hues (KitHue): terracotta, saffron, moss, jade, lagoon, lapis, amethyst, rose, slate.
list(scheme)andink(scheme).forKey(_:)gives an unassigned list a hue.- Each hue appears with its list's title, so colour is never the only cue.
- A list's colour belongs to what the list is, not to where it's shown.
Type (KitFont, KitFonts, Foundations/Type.swift): Geist and Geist Mono, relative to text styles.
- The tokens:
body,bodyMedium,rowTitle,rowTitleBold,askPill,secondary, thecommentfamily,mono,monoMedium,listTitle,cardTitle,button,suggestion,heading,approval. - The phone's sizes are in
Phone/PhoneShell.swift, and the reviewed phone row (15.5 pt title) is the app'sMetricsoverride. They move intoKitFont, chosen by the treatment. - Weights: 400 reads, 500 labels, 600 titles, 700 marks what needs the person.
- Nothing is under 12 pt (architecture 9.3). In code, three things break it, and are debt:
- the Mac's
askPill, at 11.5 pt; commentDateoff the Mac, at 11 pt;- 42 calls below 12 pt across the app, through the Mac's fixed-size font helpers. The two in
ItemRoware fixed in the first merge.
- the Mac's
Layout (KitMetrics, Foundations/Layout.swift, with its extension in Foundations/Themes.swift).
- Rows and cards:
rowMin,cardHeader,cardRadius,bodyRadius,bodyInset,todayCardRadius,glyph,rowInset. - Controls:
chipHeight,chipRadius,buttonHeight,buttonRadius,cardButton, thesuggestionvalues. - Page:
sidebarIcon,pagePadding,columnGap,pageColumn. - Other:
finishCircle,touchTarget,hoverCardWidth,cardAvatar,ring,factGap,factRow. - Row heights:
KitMetrics.sidebarRowandKitMetrics.cardRow. The reviewed phone card row, 52 pt, is the app's override, and moves in, chosen by the treatment. - The phone's and iPad's extras (
Phone/PhoneShell.swift,Adaptive/AdaptiveShell.swift) move into Foundations. - Column widths are the viewer's, and apply at once everywhere.
- The modal, in the app, to move: 74 pt below the top, a 45% scrim, a 0.32 s spring (
MacSheetHost), with its raw fill, corner and shadow. - Not yet in code:
- Settings' overlay on the Mac (d-004);
- the resize edge's line: a hairline and a 1.5 pt glow following the pointer, fading over 480 pt, only as tall as the box it resizes.
Touch (KitTouch).
- The policy: 44 pt on touch, 60 pt on visionOS, at least 28 pt for a pointer, never under 20 pt.
- Debt: the Mac's
menuRowis 26 pt.
Materials (.kitGlass; KitGlassTuning in Patterns/Glass.swift). Liquid Glass for floating chrome and the frame;
content stays solid.
Motion (KitMotion, Foundations/Motion.swift; KitMotion.land in Patterns/Drag.swift).
- Curves:
settle(_:),glide(_:),snappy. - Durations:
instant,short,medium,scene. - Staggers and rises:
stagger,listStagger,staggerCap,rise,rowRise. - Glows:
cardGlow,bodyGlow,bodyGlowDark. - The finish:
sparkCount,sparkSize,sparkTravel,sparkLife,burstHold,checkDraw. - In the app, to move:
- the springs,
PhoneSpring.Params(App/Phone/PhoneMotion.swift): the pager, the drawer opening and the drawer closing, stepped at 1/960 s with a frame's catch-up capped at 1/30 s. Giving the Mac's view turns the pager's spring too is proposed, by same by default. It's a visible change to the Mac, so it goes through question 5 and Ryan's review; - the arrival cascade,
BoardArrival, which replaces OmoKit's.kitArrival; - about 59 raw curves and springs across 27 files, each to become a token.
- the springs,
- Movement follows the finger (architecture 9.3), and each such gesture is tested by recording.
Haptics. One per physical act, paired with something seen, none while the person reads (architecture 9.3).
Icons and avatars (KitGlyph, Foundations/Icons.swift; KitAvatarView, Foundations/Avatars.swift). 15 to 16 pt
line icons in an 18 pt box.
Words. As design-principles.md, "Words and case".
Appendix B. The inventory#
Every component has the same entry:
- is: what it is;
- draws: the construct, view and Scale;
- code: its name in OmoKit once its reviewed copy moves there;
- reviewed copy: the file and type at
omo-applea428de7; - tokens;
- interactions;
- conditions known so far, including, for a component with a reviewed copy on each device, what differs between them.
A line that doesn't apply to a component is left out. Its component specification is written as it enters OmoCatalog.
The debt list holds its other copies.
The Card drawings#
Row
- Is: one Item in a list.
- Draws: an Item at
Scale.line. - Code:
KitRow. - Reviewed copy:
Interface/ItemRow.swift,ItemRow. - Tokens:
rowMin,cardRow,rowInset,glyph;rowTitle,rowTitleBold,mono;newRow,hover,selection,selectionHair; the open tone. - Interactions: select, open, finish, drag, keys, rename; on touch, the hold and carry, through the gesture hook.
- Conditions on input: with a pointer, a click on a selected row's title renames it, and Esc cancels; on touch, rename is in the row's menu.
- Conditions:
- the glyph is the finish circle where the Item can be finished, and otherwise the Item's own mark (a sender's initial, a story's paper mark);
- the avatar is whoever has the Item, except under d-015.
Open item
- Is: an Item opened under its row.
- Draws: an Item at
Scale.sheet. - Code:
KitOpenItem. - Reviewed copy:
Interface/ItemDrawer.swift,ItemDrawer. - Rule 1: an Item finishes from its row's glyph, and the open item has no finishing control, except under d-002.
- Frame: the same for every Item: its margins; its fields row, with Open in Gmail (or any link the Item carries) at the top right; its ask; its body (a slot); its activity; its reply.
- Tokens: the open tone,
bodyRadius,heading,body,approval. - Interactions: open (keeping place on close), finish, keys.
- Conditions: a letter's actions (Reply, Later, Task, Label) show where the Item has them. Pasting a file or an image into the open item attaches it, on every input.
Focus card
- Is: one Item at a time in the Focus view.
- Draws: an Item at
Scale.screen. - Code:
KitFocusCard. - Reviewed copies:
Spaces/Projects/FocusView.swift(Mac) andApp/Phone/PhoneFocus.swift(iPhone). - Interactions: finish, from the card's Done (X); Later (S); turn to the next card; keys.
- Conditions: with a keyboard, the buttons show their key hints (X, S). On touch, the cards are a vertical carousel the finger drives (architecture 9.3); with a pointer, one card with its buttons, and the keys.
List card
- Is: a list, with its header, rows and add row.
- Draws: a Place in the Rows or Board view: at
Scale.sheetin a board's column and on Today. A Place shown alone is its Page, whose view draws one list card atScale.screen. Settled here; the specification records it. - Code:
KitListCard. - Reviewed copy:
Spaces/Projects/BoardView.swift,ListCard. - Tokens:
cardRadius,cardHeader, the list's hue as a wash. - Interactions: collapse, reorder lists, drag between lists, arrive.
- Conditions:
- the add row shows where the Place takes members typed in;
- where the Place declares a first count (
KitList.firstCount, a capability field), it shows that many rows, then, after + Add, "Show All N Items" (N being every row), and once open, "Show First" with the count. The reviewed counts are Today's To Read at 5 and Coming Up at 6 (Spaces/Today/TodayView.swift). Whether it's open is the viewer's, kept in PlaceLayout (today the store'sexpandedWidgets). A board's lists show every row until a design sets a count (Mail's, in the proof); - a Place with a declared domain order sorts by it.
- A group is a list card nested in a list card, never called a column.
List header
- Is: a list card's 44 pt top: the lead mark (the owner, or the list mark), the title, the count, the menu and the chevron.
- Draws: part of the list card.
- Code: inside
KitListCard. - Reviewed copy:
BoardView.swift,CardHeader. - Tokens:
cardHeader,listTitle,mono. - Interactions: collapse (a double-click too), the list menu; with a pointer and a keyboard, ⌥-drag a list onto another to group them.
- Conditions: the owner shows where the Place can be handed on, and otherwise the list mark; the menu's actions as in §4.
Add row
- Is: "+ Add" at a list's foot.
- Draws: part of the list card.
- Code:
KitAddRow. - Reviewed copy:
Interface/NewItemField.swift,AddRow. - Interactions: keys (N to add; Esc cancels).
- Conditions: shows where the Place takes members typed in.
Ask card, consent card, alert card
- Is: what the presenter shows for an Ask, for a Release or Lane request, and for a safety alert.
- Draws: an Ask at
Scale.lineandScale.sheet; a.decideAsk atScale.screenandScale.spread, with its options and criteria (architecture 9.2). The consent card and the alert card are pending on c9fb2142. - Code:
KitAskCard,KitConsentCard,KitAlertCard. - Reviewed copy: for the ask card, Needs You's
ProposalCard. The other two aren't built. - Tokens:
suggestionvalues,recommendWash,quietRing. - Interactions: answer (A, D, R in Needs You).
Hover card
- Is: a person or a synth, at a glance.
- Draws: a Member at
Scale.sheet. - Code and reviewed copy:
KitSynthCardandKitPersonCard, already OmoKit's. - Tokens:
hoverCardWidth,cardAvatar.
The frame#
Page header
- Is: the Place's title, which rolls between pages, and its view switcher.
- Code:
KitPageHeader. - Reviewed copy:
App/MainView.swift,TitleRow, withInterface/RollingText.swift.
View switcher
- Is: the views a Place offers.
- Code:
KitViewSwitcher. - Reviewed copies:
BoardTabs(Mac) andPhoneViewPill(iPhone). - Interactions: turn the view; the number keys.
- Conditions: numbered tabs with a pointer, in the window's toolbar where it has one; a pill swiped between on touch, under the title.
Sidebar (and the drawer, its treatment where there's no room for a column)
- Is: the shell's list of Places.
- Code:
KitSidebar. - Tokens:
KitMetrics.sidebarRow,sidebarIcon,KitFont.body. - Reviewed copies: the Mac's sidebar structs in
App/MainView.swift, withApp/SidebarClick.swift; on iOS,App/Phone/PhoneDrawer.swift. - Interactions: select, drag (rows reorder; items drop on boards), resize, collapse.
- Conditions: a standing column where the window is at regular width; the drawer, pulled out from the left, at compact width. (So iPhone Duo open, at regular width, gets the column; see the debt list's layout line.) The Omo mark menu and the Search row are the Mac's, pending 9.5's change on c9fb2142.
Command bar
- Is: "Search or Create": a glass pill, with its results in their own card below.
- Conditions on input: with a keyboard, ⌘K opens it; on touch, Search in the bottom bar does.
- Code:
KitCommandBar. - Reviewed copy:
Spaces/Search/SearchPalette.swift,CommandPalette. - Tokens:
.kitGlass, the field's caret, its widths per treatment. - Interactions: keys; Esc or a click outside closes it.
- Conditions: the dictation button shows where there's no microphone beside it already (on iPhone, the bottom bar has one).
Bottom bar
- Is: Search, the add button and the microphone at the foot of the window.
- Conditions: shows with touch at compact width. At regular width its controls sit in the toolbar, as the specification sets.
- Code:
KitBottomBar. - Reviewed copy:
App/Phone/PhoneChrome.swift,PhoneBottomBar. - Tokens:
.kitGlass; round buttons 48 pt and the add button 64 pt (architecture 9.3), to become tokens.
Modal
- Is: a step or a form over Omo.
- Code:
KitModal. - Reviewed copy:
Interface/MacForm.swift,MacSheetHost. - Conditions on input: with a pointer, it grows in below the window's top, over the scrim; with touch, it slides up from the bottom (drawn with SwiftUI's sheet presentation).
- Interactions: Esc or Later closes it; Return takes the primary.
- Cases: the composer (
Composeron the Mac, opened by ⌘N, andPhoneComposeron iPhone) is one modal case, with two reviewed copies, on the debt list.
Columns
- Is: a page's lists side by side at the shared width, each to the shortest column.
- Code and reviewed copy:
KitMagneticColumns, already OmoKit's and used by the app. - Tokens:
columnGap,pageColumn.
Resize edge
- Is: the edge you drag to resize a column or the sidebar.
- Code and reviewed copy:
KitColumnEdge, already OmoKit's. The sidebar'sSidebarResizeHandlemoves onto it. - Interactions: resize. A double-click on the sidebar's edge resets its width, as the code does today.
- Designed, not yet built: a click on the sidebar's edge collapses it ("Drag to resize, Click to collapse"; Ryan's recording, 17.05).
- Conditions: shows only with a pointer.
Controls#
Button
- Is: primary or outline.
- Code and reviewed copy:
KitButtonStyle, already OmoKit's, reached through the app's aliasOmoButtonStyle. - Tokens:
buttonHeight,buttonRadius,button;ink,card,ink2,hair,hover. - Conditions: hover only with a pointer.
Running stroke
- Is: a screen's one recommended action: glass, with a spectral stroke running round it.
- Code and reviewed copy:
KitRunningStrokeStyle, already OmoKit's. - Tokens:
.kitGlass,KitSpectrum; regular and compact. - Conditions: on a pointer, hover takes the press look.
Chip
- Is: a fact or a picker on an open item.
- Code:
KitChip, withAskChipandKitDueLabel(both already used by the row). - Reviewed copy: the open item's
TChip(Interface/ItemDrawer.swift). - Tokens:
chipHeight,chipRadius,mono,hair. - Interactions: each is a picker or a link; chips wrap; Open in Gmail holds the top right.
Field
- Is: a ⌘K bar for typing, with the spectral caret.
- Code:
KitFormBar. - Reviewed copy:
Interface/GlowField.swift,GlowField. - Tokens:
.kitGlass,KitSpectrum. - Conditions: a small field shows the caret alone; in a big one, the glow fades once you type.
Menu
- Is: Omo's own drawn menu.
- Code:
KitMenuPresenter, on theKitMenuItemmodel. - Reviewed copies: the Mac's
MenuPanels(Interface/Floating.swift,Interface/MenuPanel.swift) and iPhone's liveKitMenuPresenter. - Conditions: with a pointer, it opens at the pointer (a right-click, or the ··· button) as a panel; on touch, it opens on a hold, at the press. With a pointer, a menu closes 0.26 s after a choice; on touch, a menu with a palette (the workspace menu's Work, Personal and Both) stays open after a choice, as iOS's palettes do, and a tap outside closes it.
- Tokens:
card,cardRadius,hover,danger,mono. - Interactions: keys; destructive items last.
Selection bar
- Is: what acts on a selection.
- Code:
KitSelectionBar. - Reviewed copies: the Mac's
SelectionBar(App/MainView.swift) and iPhone'sKitSelectionBar(throughPhoneSelectionBar). - Conditions: none known beyond the treatment's tokens. Its component specification checks.
- Tokens:
.kitGlass,mono.
Segmented control
- Is: one choice among a few.
- Code:
KitSegments. - Reviewed copy:
Spaces/Settings/MacSettingsWindow.swift,Segments.
Form row
- Is: a label and its value, or a setting to edit.
- Code: to be named when Settings is designed in
OmoCatalog. - Reviewed copies:
SettingsLine,RuleRowandMacRow.
Marks and states#
Avatar
- Is: a face: a person's photo, or a synth's oil swirl.
- Code:
KitAvatarView. - Reviewed copies: the app's
ProfilePhoto,OrbandOilAvatar. - Tokens:
cardAvatar,glyph. - Conditions: a sender's initial on its own colour where there's no photo.
Glyph
- Is: the mark at a row's start: the finish circle, or the kind's icon.
- Code and reviewed copy:
KitGlyph, already OmoKit's and used by the row. - Tokens:
glyph,finishCircle,ink3,accent. - Interactions: finish; on hover the kind turns into the check it would make.
List mark
- Is: the list's icon in its colour, in a header.
- Code: inside
KitListCard. - Reviewed copy: none yet; it's new.
- Conditions: where the Place can't be handed on.
Conversation line
- Is: one line in an open item's activity, or in the Conversation view.
- Code and reviewed copy:
KitCommentandKitReactionStrip, already OmoKit's. - Tokens: the
commentfamily.
Empty state, loading line, failure note, undo toast
- Code:
KitVoid,KitLoadingLine,KitFailureNote,.kitUndoToast. - Reviewed copies:
KitVoid(already used on four pages); the app'sErrorBannerandNoticeBar.
The interactions#
Select and open: as in §4.
Finish: a task from its circle, a letter from Done (d-002), a Focus card from its Done. Either way the row and its open item fade, slip and fold together, the counts update in place, and nothing re-lays the list. On the Mac too.
Drag (KitDragLift, KitDragSlot): its effect comes from the Space's adapter, shown before the drop.
Resize: at a resize edge; widths are the viewer's.
Turn the view: the pager's spring between a Place's views. A sideways swipe turns one view per gesture, leaning at the ends, and gives way only to something that can still scroll that way.
Arrive: the lists rise one after another, only for a move the person made.
Keys: as in §4.
The thirteen views#
Each is named Kit<Case>View.
- Rows: drawn page by page today (
SmartListView,ToReadView,InboxView, Mail's lists). - Board:
Spaces/Projects/BoardView.swift. Mail draws its own columns. - Focus:
FocusViewandPhoneFocus. - Timeline: the app's
TimelineView, which the canvas calls Gantt. - Table: only
MacTable, for forms. - Conversation:
Interface/ConversationView.swift. - Glance:
KitTodayGlance, unused. - Days:
CalendarWeekPage, unused. - Chart, Prose, Canvas, Map, Gallery: not built, and designed in
OmoCatalogbefore any Space uses one.
Appendix C. The differences register#
Every register entry is provisional, for Ryan's list at this document's final. The conditions in appendix B go to him in the same list.
d-002 · open item · a task's open item and a letter's open item
- Rule: open item, rule 1.
- Differs: a letter finishes from Done in its open item.
- Why: a task's circle sits just above its open item, while a letter is read in its open item and Done follows.
- Status: provisional (the design lead's gate of Mac v70, agreed by the chief of staff, 12 November).
d-004 · modal · Settings on the Mac and on iPhone (designed, not yet built)
- Rule:
design-principles.md, "Settings": "Every app has Settings at/settings", which in a native app means a page. - Differs: on the Mac, Settings is to be an overlay inside the window, 980 × 700. Today the Mac uses the system's Settings window. iPhone keeps v60's grouped list, as a page.
- Why: the Mac has room to keep Omo visible behind Settings, and iPhone's screen is the list.
- Status: provisional (Ryan's recording, 17.05, 12 November).
d-014 · withdrawn. The design lead proposes, for the Newsletters design, that This Week is a Place of Paper Items in the Board view, a list card per topic, with the paper mark as the glyph's condition. Then it departs from nothing. The proposal goes to Ryan with that design.
d-015 · row · a letter's row and a task's row
- Rule: row, "the avatar is whoever has the Item".
- Differs: a letter's row shows its sender's avatar.
- Why: a letter's first question is who wrote it, and Who Has It shows in its open item.
- Status: provisional (Ryan's recording, 17.37, 12 November).
d-019 · keys · a letter and every other Item
- Rule: §4's keys, "E renames".
- Differs: on a letter, E finishes and never renames, as in Gmail. X completes, as everywhere.
- Why: Ryan presses E in Mail, from Gmail (his recording, 17.58, 12 November).
- Status: provisional. (d-016 was a retired seed number, so this one takes d-019.)
Open questions, each an Omo decision item for Ryan:
- Rename on a Gmail label (fe8cf76e);
- making your own newsletter topic (46b43cb3);
- the phone in light as well as dark (ef7dc1de).
Appendix D. Glossary#
- add row, list card, list header, row, open item, Focus card, ask card, consent card, alert card, hover card: the Card drawings (appendix B).
- callers list: generated from the code; every caller of each component, with its configuration. §5
- component: a view, style or modifier in OmoKit, built once. Narrower than the lexicon's "a piece of a subsystem". §1
- component specification: a component's one description, beside its code. Never "spec": Spec is the architecture's CanonClaim. §4
- condition: a rule in a component specification that makes a part depend on a capability, the input or the Scale.
Not the architecture's
Conditionin a MatchRule. §1 - content, form: what siblings may differ in; what the specification fixes. §1
- debt list: every copy of a component outside OmoKit; Plan 1.31's worklist. §6
- defect: any difference that isn't an approved intended difference. §1
- differences register: the one list of intended differences. §2
- glyph: the mark at a row's start. Not Core Text's glyph, a drawn character. appendix B
- lead mark: the owner, or the list mark, at the start of a list header. appendix B
- intended difference: one sibling's departure from one named rule, for one reason, approved by Ryan. §1
- interaction: a way of acting defined once in OmoKit. The layer cake's "pattern"; not the dkini's "pattern" or "behaviours". §4
KitListState: the interim OmoKit observable for a list's state, added in the first merge. §4KitMenuItem,KitOpenItemModel: the menu's model and the open item's model, in OmoKit. §4KitTreatment: the environment value that picks a treatment:.touch,.pointeror.spatial. §4ListExceptions,ListConformance: the register entries for lists in code, and the tests that hold lists to them. §2- modal: a step or form over Omo. Not
Scale.sheet. On iPhone it's drawn with SwiftUI's.sheet(...), but the word means the component. appendix B - OmoKit: the code library every Omo screen is drawn from (a System Kit). §1
OmoCatalog: the design-only target beside OmoKit. Never "the catalog". §5- open item: an Item at
Scale.sheet, under its row. Not the drawer, which is iPhone's sidebar. appendix B - presenter: the architecture's Presenter, which decides how a result that arrives unasked is shown (9.2). §4
- provisional: proposed by the design lead and buildable, not yet approved by Ryan. §2
- register entry: one intended difference in the register. Never a bare "entry". §2
- reviewed copy: of several copies, the one Ryan last reviewed. §6
- seam: the one shape of a component's input and output. §4
- selection band, selection bar: the lapis fill on a selected row; the bar that acts on a selection. §4, appendix B
- sibling: one of two places that draw the same construct in the same view, in another Space or on another device. §1
TimelineView: SwiftUI's view for time-driven redraws. The app's ownTimelineViewshadows it until it becomesKitTimelineView. appendix B- token: a named value in OmoKit. Not Foundation, Mindplex with its Cores and Kernel. §4
- treatment: a component's tokens (sizes, type, insets) for touch, a pointer or Vision Pro, from
KitTreatment. Anything else that differs is a condition or a register entry. Not chapter 9's title, or SwiftUI's presentations. §4 - value model: a plain Swift value a Space fills for a component; never a store or a database type. §4
- Focus, three senses, always written in full: the Focus view (
Manifold.focus); the Focus mode (Mode.focus); Apple's Focus.