Level 1, and the second largest control family: 1,361 placements on 106 painted screens. A control whose whole content is a mark. It was drawn in six files under six names until 2026-08-06 and it is one file now, with eight faces, and every one of them is an answer to the GROUND it stands on rather than a variation on a circle. Measured 2026-08-08.
The lift face on the footer's social row, which is the largest of the eight at 525 placements.
Same reason as button: a level is a shelf and a component is a page. This family is 1,361 placements over eight faces, and a shelf has room for one specimen. The eight are not sizes of one thing, so showing one of them teaches almost nothing about the other seven.
The thing this page can show and the level page cannot is the ONE sentence that organises the whole component: a face here is an answer to the ground it stands on. Read the eight side by side and that stops being a claim; the circle is the header band's, the tile is a photograph's corner, the bare mark is a caption row, and the small one is a toast. Read one of them alone and it is just a padding.
The declaration that this is level 1 stays on the atoms page and is not repeated here.
the circle, 137 placements, and every one is in the header
The circle is the header band's skin, not this atom's own idea, and
counting says so: all 137 plain .icon-btn in the product stand in
<header>, all of them in the utility group, and there is no plain circle
anywhere else. It answers a pointer the way the band's other three controls do.
Two marks, and it was three until 2026-08-14 and one until 2026-08-09.
Read from the screens rather than from this page: the bell on 32 and the bookmark on
105, which is 32 + 105 = 137, the number the line above already carried.
It was 242, and the 105 that left were the left group's hamburger: a
<button> labelled "Menu (reserved for future scaling)" with no handler, no
drawer and no destination, display:none below the desk on top of that. It went from
105 painted screens, 87 grey ones and 10 specimens here on 2026-08-14, and its glyph left the
sprite with it. A count can be right while the picture under it is one third of the thing. The
third one carries .desk-only, a `base.css` utility that is
display:none!important below the breakpoint, so on a phone the header's Favorites
circle is not there at all: it is the bar's Favorites slot instead. That is a fact about the
atom's placements, so it is drawn here rather than described.
bal-swap and bal-add, 73 each, and 0 of the 146 render at 390
The balance cluster: two circles at a denser size beside a figure. Their
73 screens each are all desk, because the cluster is .desk-only and
base.css hides it below 640. A face measured only at 1280 is still a face; a
placement count that does not say where it renders reads as coverage.
photo, 228 + 105 with the strong ring, and all 333 are a sheet close
The specimen stands on a photograph and not on the plate, which is the
only honest ground for it: it reads --scrim-photo, --line-on-photo and
--text-on-photo, three roles for standing on something the system cannot choose the
colour of. Its scrim is 34 per cent at rest, 55 under a pointer and 72 held down, so the mark
stays legible whatever is underneath. The image is one of the three things the rules allow on the
element, and it is here for the same reason it is on the atoms page: a face defined by an
unpredictable ground cannot be shown on a predictable one.
And it is named for a ground it does not stand on today. All 333
placements are .sheet-close inside a <dialog>, and what is
actually behind them is .sheet-head, which paints a brass radial gradient and not a
photograph. The name is kept on purpose and components/iconbtn.css says why: what
defines the face is the three on-photo roles it reads, and a dialog head is the same problem, a
ground the control cannot predict. It is written here rather than left as a smell, because
the next person to meet the class will read the name before the comment.
.icon-btn-ring-strong stood here until 2026-08-11 and it is gone.
It was a modifier on 105 of these discs, the How-it-works sheet's, changing exactly one thing: the
focus ring went white, because .hiw-glow put a brass radial in the corner the ring
lands in and the system's brass ring measured 2.52:1 there. Re-measured after the glow became
one rule with the plain sheet head's, at the button's own corner in the annulus the ring covers:
the brass ring is 2.93:1 on the How-it-works head and 2.89:1 on the PLAIN sheet head, so the
head carrying the exception was the better of the two by 0.04 and the 222 that were not carrying
it were worse. A class on 105 of 333 discs is a list, and this system has already paid for
a list. It is one rule keyed to the family now, in components/dialog.css beside the
placement, for the reason course-chrome.css writes over its own ring: a ring answers
to what it stands on, and what these 333 stand on is a sheet head.
THE SAME DISC WAS ALSO LOSING ITS CIRCLE THE MOMENT IT TOOK FOCUS, and it
was not this component doing it. Backlog 111, found by the measurement above and fixed on
2026-08-11. On the 17 standalone overlay pages this control is an <a> rather
than a <button>, because there it navigates instead of closing, and
dialog.app-dialog a:focus-visible in dialog.css set
border-radius:var(--radius-6) on every anchor in a sheet. An outline follows its
element's radius, so rounding a ring means rounding the element, and at (0,2,1) that rule beat
.icon-btn's pill: the disc was a 32px circle at rest and a 6px-cornered square
while focused, on 17 pages, and showModal() autofocuses it, which makes it the
first paint rather than a rare state. A component cannot out-specify a rule about the box it
stands in, which is the second time this week the fix belonged to the container's file and
not to this one. It is scoped to a:not([class]) there now, and all 48 shaped anchors
across those pages keep their own shape.
lift, 525 placements, the largest face in the family
The footer's social row, five marks on every one of 105 screens. It is an
<a>, and this is the face that makes the family's tag count what it is: 598
of the 1,361 placements are links rather than buttons. The atom declares
text-decoration:none and text-align:center for exactly this reason, and
the file records that it did not until 2026-08-07, when Favorites became an anchor and picked up
an underline nobody had chosen.
bare, 84 placements on 12 screens, and its target is invisible
The save mark on a card's caption row, where a circle would be a second object competing with the picture. It is the only face that answers WCAG 2.5.5 outright and it does it without a box: 44 of target with no ground and no edge, pulled back out of the flow with a negative margin so the row is not spread by it. What answers is the mark, quiet at rest, brass under a pointer, and filled brass when the event is saved, which is a state and not a press.
tile, 27 placements on 9 screens, and the only 10px corner in the family
Three of them sit in a row over the event head, and the corner is the whole
argument: three circles read as a control group, three tiles read as a toolbar. It is the
only face with a ground of its own on an ordinary surface, --bg-control, because the
head behind it is a photograph and a transparent tile would vanish into it.
small, 4 placements on 1 screen
The toast's dismiss, and it is the circle at 24 rather than a face of its own: transparent, hairline, pill, exactly the header's. It disagreed on one thing, its hover, which brightened the EDGE where the header's tints the GROUND. Four placements against 137, so the header's was the system's and this was the divergence, and the divergence was corrected rather than carried into the atom.
THIS PARAGRAPH SAID "THE DEFECT" AND IT WAS WRONG TWICE, so it is kept and
corrected rather than deleted. It read: "this is the one control in the family with no mark
in it, and the mark it is missing is a letter ... the box is 24x24, it holds 0 svg, and
its content is the text character x, with nothing on ::before or
::after ... 333 close controls in this same family draw a real cross ... one job,
two drawings. A lowercase letter is not a cross."
THE FIRST ERROR WAS THE PREMISE. iconbtn.css draws the
cross with two rotated bars on ::before and ::after, and the button is
font-size:0, so the letter draws nothing here. It was removed on that reading and
the measurement said no: in the grey tree the letter is the whole drawing, because
wireframes/ styles this as a bordered box at font-size 11 with no pseudo-element,
and the emptied button measured 16 x 8 with nothing in it. The same markup is inert in one
tree and load-bearing in the other, which no reading of one tree could find.
THE SECOND ERROR WAS "ONE JOB, TWO DRAWINGS", and the answer is a number. Measured 2026-08-10: the stroked path is a 12-unit cross in a 24 viewBox at stroke 2.2, rendered in a 16px svg inside a 32px button, so its ink spans 9.47px, 29.6% of the button. The two bars are 8 x 2 rotated 45 degrees in a 24px button, so their ink spans 7.07px, 29.5%. Two techniques, one mark, the same optical size to within half a per cent, and the technique differs because one control carries an svg and this one carries a letter the grey tree needs. It is a decision, not a divergence. What WAS a divergence was in the kit: four specimens on the toast page put an svg cross inside this button and drew the mark twice, brass over grey, and six on the vitrine shipped it empty. Backlog 75 and 88, closed 2026-08-10.
Read at 390 in both pointer branches on 2026-08-08, with every dialog forced open so the sheet close could be measured at all.
| face | worn | fine pointer | coarse | 2.5.8 AA, 24x24 |
|---|---|---|---|---|
.icon-btn, the circle | 137 | 36x36 | 44x44 | clears |
.bal-swap / .bal-add | 73 / 73 | desk only, and 0 of the 146 render at 390 | clears at 1280 | |
.icon-btn-photo | 228 | 32x32 | 32x32 | clears |
.icon-btn-photo on a sheet head | 333 | 32x32 | 32x32 | clears |
.icon-btn-lift | 0, was 525 | 28x28 | 28x28 | clears |
.icon-btn-bare | 84 | 44x44 | 44x44 | clears |
.icon-btn-tile | 27 | 28x28 | 28x28 | clears |
.icon-btn-small | 4 | 24x24 | 24x24 | clears, exactly |
ONE FACE OF THE EIGHT MOVES WHEN THE POINTER CHANGES, and that is a finding
rather than a fact about this page. The touch floor in components/base.css
excludes four of them by name, .icon-btn-photo, .icon-btn-tile,
.icon-btn-small and .icon-btn-lift, and the exclusions carry their
reason: the floor would resize all four. .icon-btn-bare needs no exclusion because it
sets the floor itself. So the circle is the only one the rule reaches. Every face clears WCAG
2.5.8's 24x24 and four of the eight do not clear this project's own 44, which is backlog 39
and is open on purpose: whether a dismiss on an overlay, a corner toolbar or a footer mark should
be 44 is a design question, and a migration is not the place to answer it quietly.
The 525 in that row is 0 since 2026-08-13, and the face is kept on purpose.
.icon-btn-lift was the footer's row of five social marks on 105 screens, and backlog
144 took them out: five anchors a screen at href="#" for accounts that do not exist,
standing directly under the trust strip. A social account can never become an internal route,
so it was not a link waiting for a screen, which is what separated it from the two kinds of
placeholder the footer's own rules already covered. The face survives its placements and
account.css did not, and the difference is the right one: that file was deleted
for having no FACE left, its two rules being another component's stone; this is a face with no
placements, and its placements return on a date somebody chooses. It is the only entry in this
table worn by nothing, and the row says so rather than reading as a face nobody measured.
A face here is an answer to the GROUND, not a variation on a circle. That was not the plan, it is what reading them out loud produced, and it is the thing worth carrying to the atoms still to migrate.
| ground | the answer | face |
|---|---|---|
| the header band | a circle that tints its ground, because the band already has a skin | plain, and the dense pair |
| something the system cannot colour | a scrim that deepens in three steps, and an on-photo ink | photo |
| a corner of a photograph, three in a row | a 10px tile with a real ground, because a transparent one would vanish | tile |
| a caption row beside a picture | no box at all, and the mark answers instead | bare |
| the footer's quiet band | a small mark that lifts | lift |
| a toast | the header's circle at 24 | small |
Six grounds, eight faces, and the two extra are a modifier that changes one value each: the balance pair is the circle at a denser padding, and the strong ring is the photo face with a white focus outline for one head. Neither is a face and both are worth having a name, because the alternative was a second declaration of the whole control in the file that happened to hold it.
As on the button page: a hover, a press and a ring are raised by a person and not by a document. The specimens above are the real controls, so raise them here with a pointer and a Tab.
| face | hover | press |
|---|---|---|
| the circle | the band's wash, --tint-brass-16, and the action edge, which is what the header's two disclosures and its ghost button also answer with | --bg-pressed, square cornered, because a radius is geometry and a state may not move the element it is on |
| photo | the scrim goes 34 to 55 per cent and the edge brightens | the scrim goes to 72 |
| lift | the mark comes up and the control lifts | settles back |
| bare | the mark goes brass, and nothing else moves because there is nothing else | the one time this face draws a shape |
| tile | the ground steps and the edge goes brass | --bg-pressed |
The saved bookmark is a STATE and not a press, and it is the one thing
in this family that survives the pointer leaving: aria-pressed="true" fills the mark
brass. That is why the control is a <button> with an ARIA state rather than a
class the page script toggles.
Its own width query: 560 one-off. The disc is fixed at every rung. The one width rule is the TILE face dropping from 36 to 28 below 560, shared with event-detail and with nothing else, so a row of them still fits. It is a one-off and the argument for keeping it is written beside the other half of the pair.
Pick the face by the ground, not by the size you want. Every one of the eight exists because something underneath it made a demand, and the sizes are what fell out of that. Asking for "the 28px one" is asking for a footer mark in a header.
A mark with no word needs a name. Every placement in this family carries
an aria-label, and the audit of 2026-08-08 read 0 nameless controls across 115
documents. A control whose whole content is an svg has nothing for a screen reader to say on its
own.
A region may say WHERE one sits and may not say what one looks like.
components/header.css keeps .app-header .left > .icon-btn{display:none}
because hiding a control in a band is the band's decision, and components/dialog.css
keeps the sheet close's absolute placement for the same reason. Neither draws the control.
Never draw one in the file of whatever holds it. Six files held the pen for this control under six names until 2026-08-06, and every one of them was right about its container and wrong about the control.
Never let a labelled press in. .hiw-btn sat in the
census row called "icon only, in the header" while carrying the words How it works on 105 screens.
A row that describes WHERE a control sits will collect anything that sits there.
Never add a face for a single element. The strong ring is a modifier and not a ninth face, because it changes one value for one head. A face is a new ground, and there are six.
The second one is the load-bearing half and it cost this component a whole census row. A group named for a place fills up with whatever is in that place: the logo left the same row before the How-it-works pill did, for the same reason. Sort by what a control IS, and an icon button is a press whose entire content is a mark.
The level and its reason: the atoms page.
The stylesheet and the argument for every value: components/iconbtn.css, which is
where all six kinds arrived on 2026-08-06 and became the first atom on the map to reach a distance
of zero. The deleted stand's writing on this component:
docs/kit-archive/authored/iconbtn.md. The counts on this page were taken on
2026-08-08 and the file's own comments carry the counts of two days earlier: 908 placements in
six files, then 836 adopted, against 1,361 measured today across eight faces. The difference is
not drift in the product, it is a wider net: this page counts .bal-swap and
.bal-add and every anchor.