makeover-touch 0.10.0

The adaptation layer of the make-family design system: which affordances exist at a given input class and window size class. Names what appears and disappears, never how much space it takes.
Documentation
# makeover-touch

The adaptation layer of the make-family design system.

`makeover` answers *what colour*. `makeover-geometry` answers *how much space*,
and owns the two axes an adaptation is stated against: `Density` (pointer or
touch) and `SizeClass` (compact, medium, expanded). `makeover-layout` answers
*what the thing is*. This crate answers one question and no other:

> Does this affordance exist here?

Like `makeover-layout`, it emits nothing. It is a description, rendered to CSS by
`makeover-webview` and to whatever the other renderers can express.

## Why it is a crate and not a density preset

Measured across the MNW server's `@media` blocks (137) and goingson's
`ui-mode-*` blocks (192), bucketed by what the declarations inside actually
change:

| bucket | MNW | GO | retired by |
|---|---|---|---|
| density | 32% | 27% | a `makeover-geometry` preset |
| type | 23% | 15% | the type scale |
| columns | 20% | 12% | `makeover_layout::Column` |
| reflow | 16% | 17% | `makeover_layout::Arrangement` |
| **show/hide** | **12%** | **12%** | **this crate** |
| **reposition** | **6%** | **20%** | **this crate** |
| **appearance** | **1%** | **17%** | **this crate** |

The bottom three are the roughly 43% no spacing scale can retire. `display:
none` on a keyboard hint says the affordance does not exist on touch. No amount
of gap retuning expresses that, and a scale that tried would be putting a
product claim on a measurement axis, which is what the July 2026 Touch
demolition was for.

## What is here

`Affordance`, six members, drawn from what the two measured apps already gate by
hand:

| member | reads | rule |
|---|---|---|
| `Hover` | density | pointer only |
| `Hint` | density | pointer only |
| `Ancillary` | size | expanded only |
| `Detail` | size | medium and up |
| `Anchored` | size | compact only |
| `Overflow` | size | compact only |

`Affordance::available(density, size)` is the whole crate in one call. A
renderer asks per affordance and never branches on a width.

`column_cutoff(size)` closes the one seam neither neighbour could: layout defines
the priority ladder and `Column::kept_at`, geometry defines the boundaries, and
nothing said which cutoff a compact window uses. Both webview apps answered it
with `nth-child` on an ordinal, so inserting a column silently hid the wrong one.

## The rules the tests hold

**Density gates only what the contact patch touches.** Hovering, and the
keyboard chrome documenting shortcuts a touch surface cannot send. Not how much
screen there is: a phone is small *and* touch, a tablet is big *and* touch.
Putting a screen-budget claim on the input device is the specific failure that
produced this crate.

**Touch never gains an affordance pointer lacks.** Touch is derived from pointer
by subtracting what a fingertip cannot do, so it loses members and never gains
one.

**Collapsing is allowed, inverting is not.** Borrowed from `makeover-geometry`,
where two gap relationships both resolve to zero cells on a terminal and stay
two members. `Hover` and `Hint` have identical rules today and are still two
members, because the call site names what is gated rather than the rule.

**Compact compensates rather than only losing.** `Anchored` and `Overflow` are
available at the narrow end and not the wide one. An adaptation that only
removes things describes a degraded layout, not a different one.

## What is not here, on purpose

**Boundaries.** `makeover-geometry` quotes Material 3's window size classes at
600 and 840. This crate adds no third axis, no fourth class and no breakpoint of
its own.

**A navigation shell fork.** goingson currently carries two, concentrated in
`.app-header`, `.tab`, `.tab-navigation`, `.pill-nav`, `.saved-views-sidebar`
and `.modal-container`. That is not one shell adapting, it is two shells, and
choosing to build two is a product decision. goingson's own restructure is how
it stops being true.

**Which class applies.** The app decides, from a measured width and from what it
already knows about the input. This crate takes both as arguments and never
sniffs.

**What a renderer does when an affordance is unavailable.** Hiding it,
substituting it or showing it anyway is renderer policy, the same class of
decision `makeover-layout` deleted `Fill::fallback` for.

## Status

Seeded at 0.1.0, unpublished, no renderer has been through it. The vocabulary is
six members and the intent is to stop there: `makeover-layout`'s own warning is
that guessing at eight is how a description becomes a framework.

Design lives in the wiki note `makeover-touch`; the backlog is in GoingsOn under
the project of the same name.

## Licence

MIT.