Save-focus list

The short list of subscriptions a person might not be using, with one line of framing above it. Two entries on the one screen that carries it, never fourteen: a list of everything a person could cancel is a budgeting app, and this is not one. It is the container around the Save-focus candidate and it draws no separator of any kind, which is the unusual half.

Organism1 grey pageno axesno states, not interactivehosts 1 molecule, twice

Anatomy

A framing line, a list with its furniture taken off, and two candidates. Three declarations in the whole file. Everything below is drawn by design/system/components/save-focus-list.css and by the candidate's and the row's own files, through the same entry point a product screen loads, so this page cannot drift from the screen: there is no second copy of the CSS here to drift from.

The list draws no separator, and that is the unusual half. Every other list container in this system owns the hairline between its items; here the candidate draws its own, the way the switch row does and the opposite of the way the category group does for the subscription row. The reason is that a candidate is two controls on one line rather than one row, so the line under it belongs to the pair. save-focus-candidate.css says the same thing from the other side, in writing, so that neither file grows a second divider later.

Variants and sizes

This component has one form and no axes at all, so there is no matrix here: a matrix with one row is a table of one fact dressed as a choice. It stands in one place, holds two candidates, and has never been asked for a second form. What varies is the number of candidates, and the number is not a variant.

Two, and the cap is a product decision rather than a layout one. The screen shows the two least-used subscriptions and stops. Fourteen candidates would be a list of everything a person could cancel, which is a budgeting app and is out of scope by name in CLAUDE.md; it would also put the loudest possible frame around the whole list on the one screen whose job is calm. The framing line says "Two you have not opened in a while", so the copy and the cap agree, and changing one without the other breaks both.

What is NOT an axis

Written down because the absence is a decision. Each of these was available and each was refused for a stated reason

Why not
A tone, urgent or destructive D3 puts no paywall at the cancel moment and DESIGN.md spends clay on OUR failure only, never on something a person chose to do. Cancelling is a small win, the product's most important emotional beat, and painting its list red would say the opposite
A dense form for more entries There is no "more entries". The cap is two, and a form that only exists past a cap that cannot be reached is a rule nobody can check
An empty form When there is nothing a person is not using, the section is not rendered rather than rendered empty. An empty save-focus block would say "we looked for waste and found none", which is a sentence about waste on a screen that had none

When to use it

This is J3 read literally: "cancel what I do not use". It stands in the second slot of the Dashboard head on one state of Home, where the price-change wash usually goes, and it is the only place in the product that puts a cancel control next to a subscription rather than behind it.

The framing line does most of the work, and its two sentences were chosen against the persona rather than for brevity. "Two you have not opened in a while" is a fact with a number, and "No pressure, just a nudge" is the product declining to tell a person what to do. voice/docs/voice.md owns both, and the second one is the reason the whole block reads as help: an avoider who is shown two things she is wasting money on, with no permission to ignore them, closes the app.

Reach for it when a screen offers a small, capped set of things a person may act on, each with the action beside it. Do not reach for it for the main list: fourteen rows with a cancel button each is a control panel, and the product's main view is a place to look.

The rule, and the anti-rule

The framing line comes first

Two you have not opened in a while. No pressure, just a nudge.

A person meets the sentence before the two cancel buttons, which is the whole difference between a nudge and an accusation. It is muted ink at body size and it is not a heading: a heading over two subscriptions would make the block a section of the screen rather than a note inside the head. 8px under it, and the candidates start.

Use the Category group instead
Fourteen subscriptions, each with a Cancel button beside it

The main list is the Category group (.group) inside the Groups column set, and its rows carry no second control at all: the whole row is one target with one accessible name. Putting a cut on every row turns a place to look into a place to act, which is the opposite of what J-MAIN asks for, and it hands a person fourteen chances to hit the wrong one of two overlapping targets.

The list owns no hairline
.candidates: one margin, one framing line, one list reset

The divider between two candidates belongs to the candidate, not to the list, because a candidate is a pair of controls rather than a row. Written here as well it would draw twice: a hairline under the last candidate and a second one under the block, and nobody would be able to say from either file which one was the mistake. The two files agree in writing so this can never happen quietly.

Use the Divided list instead
Four alerts, newest first, the container drawing the line between them

When the container IS the thing that separates its items, the component is the Divided list (.divlist, which was .alerts and .navrows until step 6), which owns the hairline and whose items draw none. The two are mirror images and picking the wrong one gives you either no divider or two. The test is one question: is the item a single row, or a pair of controls sharing a line?

States

No states, and it is structural rather than an omission. The list is a container with no fill, no edge and no target of its own: it holds no anchor, no button and no pressed element. A pointer that appears to be over it is over a row, over a cut, or in the gap between two candidates, which is over nothing. Faking one with a class the product does not carry would document something the product cannot do.

The four states it contains are live in the anatomy above and belong to two other files: hover and focus on the row, from subscription-row.css, and hover and focus on the cut, from save-focus-candidate.css. The cut's ring earns its place more than most, because it sits immediately after a full-width row in the tab order and a keyboard user needs to see that focus has moved from "open it" to "end it".

The technical half

ReadsWhich tokenGrowing from
the framing line--text-muted--muted, the single secondary tier. 5.8:1 light, 6.4:1 dark
its size--type-bodyprimitive, straight: 14px, a sentence
the block's gap and the line's gap--space-24, --space-8, --space-0primitive, straight
no fill, no border, no radius, no dividernoneby decision. The candidate draws its own hairline; the list draws nothing

The framing line is a rename candidate and has no row on the map. kit.css wrote it at 13px, which folds to --type-body, and its ink was already --text-muted: after the fold it is the Muted line atom plus a host margin, exactly like the nine names that atom already collapsed. docs/inventory.md has no row for .lead in the renaming map, so step 6 renamed everything around it and left this name standing. The scoping under .candidates is still load-bearing: the muted line has a .lead modifier of its own with a different owner, and kit.css said so at the line this rule came from.

A tension it inherits, stated rather than fixed. .cand is registered as a MOLECULE in docs/inventory.md while hosting the Subscription row, which is itself a molecule, and the ladder in docs/architecture.md calls a thing that hosts a molecule an ORGANISM. It is a live row in docs/backlog.md, owned by step 9 at the reconcile. It is left exactly as the inventory has it rather than changed mid round: a level decides the @import order, and an order changed halfway through a round is how a composite lands above its own parts in the cascade. This list hosts the candidate as it is registered today, and its own @import sits below the candidate's either way.

No container query, and none was dropped. This component has no rule inside any of the product's three container steps. The one width rule near it belongs to the candidate: under 460px the cut drops to its own line, and that lives in save-focus-candidate.css and subscription-row.css, as a media query rather than a container query, carried exactly as kit.css wrote it.

The stand shows it at wide, which is 620px. Measured on the real coloured save-focus screen, the list renders 313px at a 360 viewport, 477px at 1024, 490px at 1440 and 766px at 1920: it is the second slot of the dashboard head, so its width is a fraction of the screen rather than a fixed column. 620 sits inside that range and above the desktop case, which is the honest choice for a component whose real width is a ratio; the default 440 would be under its own desktop measure and bleed would show a component that never spans.

Lives in design/system/components/save-focus-list.css. Stands on 1 grey page and 1 coloured one: Home. It moved there on 2026-08-21, out of the second slot of the Dashboard head and down under the list, when the founder retired the Save tab because its destination was Home in a state. The page count did not move and the placement did: it is a direct child of the screen now, so it carries a top hairline and the 620 reading measure this file gives it, both of which the head used to supply.

<section class="candidates" aria-label="Subscriptions you might not be using"> <p class="lead" role="status">Two you have not opened in a while. No pressure, just a nudge.</p> <ul> <li class="cand"> <a class="row" href="subscription-detail.html" aria-label="...">...</a> <a class="cut" href="cancel-guide.html" aria-label="Cancel Peloton App">Cancel</a> </li> </ul> </section>

The role="status" on the framing line is part of the copy: the nudge arrives after the list is already on screen, so a screen reader is told once, politely, and is not interrupted. The aria-label on the section is what makes the block findable as a region.