Level 2. The file that drew three controls and now draws none. What is left is a band, a rail, four scrollers and two plate edges. 57 bands and 33 rails on 106 painted screens, and one sub-filter. Measured 2026-08-08 in a browser, at 390 and 1280.
The sub-category rail the way the feed draws it. 16 elements against 38, and the rail is one of the three components in this system whose content is written by a page script, so the stand writes it by hand.
The level and its reason stay on the molecules page. What needs the room here is a cycle: for one afternoon this component contained the atom that contained it, and the way out was not a rule but an admission that two classes had been named after the wrong thing.
The category strip's chip (285 placements), the sub-category rail's chip (234) and the Trending sub-filter's (5) are one atom with two faces, and both faces are in chip with the other three.
Six declarations and one whole rule went out DEAD in the same pass.
.cat-nav button was written twice unscoped, a padding with a font size and a surface
ground on a hairline at a pill corner, and every one of those eight values lost to a two-class
rule. Measured on the painted page at 1440 and 380 in both themes before deleting: the chip
renders the chip ground on the notice bevel at a 10px corner with 12/20 padding at 14px, which
is the scoped rule in every value. Only the cursor and the white-space were live, and both
went with the face.
The first cut of that pass kept the category MARK and the COUNT here, on the
bottom nav's precedent: a figure inside a nav slot had stayed with the bar. The containment map
answered within the minute: chip contains catnav, through
.cat-ic and .cnt. It is a true reading of the DOM, a category mark
really does stand inside a chip, and with catnav contains chip already true it is a
CYCLE.
An atom that contains a component is not an atom. The chip computed
level 1 from its own stand and level 3 from the product, and the only ways out were to declare
the edge away or to admit the classes were named after the wrong thing. They were named after
the wrong thing. .cat-ic is .chip-ic and .cnt is
.chip-cnt, both in the chip's file with the face that holds them, and the cycle is
gone rather than declared.
The bottom nav's balance stayed where it was, and the difference is measurable: it answers nothing. No rule anywhere changes it when the slot is hovered or current. The two that moved brighten and recolour with the control's own state, which is what a part of a face does.
| at 390 | at 1280 | |
|---|---|---|
| the band | 351x77, a horizontal scroller | 969x77, still a scroller |
| the rail | 293x96, a row of pills that scrolls sideways | 214x478, a pinned column beside the content |
The rail is the same markup at both widths and it is not the same object, which is the reading that put its chip in the wrong atom for a day: at 900 it looks like a navigation column and at 380 it is a strip of pills. The chip carries that media query itself, because what changes is the SURFACE it stands on.
Pinned at 120px and 563px tall, this rail needs 683px of window. On a 1366x768 laptop the last two sub-categories were off the bottom of the screen and no amount of scrolling brought them back, because the page scrolls and a pinned rail does not. Eight category screens. The cap is written twice, in viewport units and then in small-viewport units, so a phone's collapsing address bar does not take the bottom of the list with it.
It is the same defect and the same afternoon as the contents rail in
components/toc.css. Two components, one shape, found by scrolling rather than by
reading.
Nothing left in this file answers a pointer, which is the honest description of what it now is: a band, a rail, four scrollers and two plate edges. All four scrollers hide their scrollbar in three vendor spellings, because a strip of chips with a bar under it reads as a broken window rather than a rail.
The plate the strip stands on is not here either. It applies only under
the feed's own wrapper, so it is the page and not the component, and it lives with the page
frame. Two more classes went to components/patterns/browse-shell.css for the same
reason: they were here because this was the first file that needed them, and nothing in either
rule was about a category.
The sub-filter has exactly one placement in the product. Its chips are buttons rather than links, because it filters the page it is on instead of navigating away from it, and that is the whole difference between it and the band above.
Its own width query: 900 RAIL, and nothing else since 2026-08-14. Two different components live in this file and only one of them is a rail. At RAIL 900 .subcat becomes a flex:0 0 214px sticky column beside the content with its own scroll, which is the second of the three arrivals the ladder is named for. The DESK 640 block is gone and the band it was written for is 24px shorter without it. All it did was give .cat-nav a margin-bottom below the desk, and .feed .feed-inner is a flex column with a 16px gap: a margin under a flex child is ADDED to the gap and never merged with it, so a phone got 32px under the strip and a desk got 16. Measured at 360 and 390 before it went, and at 640, 900 and 1280 to see what it was being compared against. The rung is still cut for this strip, in base.css, where the plate that wraps it drops its vertical padding from 12 to 8 below the desk: the whole band from the header to the first plate was 126px on a phone to show a 48px chip, and is 102 now.
And the sub-filter stopped wrapping on 2026-08-14, with no query at all.
Its five chips need 332px of row and the feed column offers 298 at 360, so the row
stood in two courses and cost 83.0px where one course costs 37.5. Measured at four widths
before the change: 83.0 at 320, 360 and 390, and 37.5 at 430. The defect lived entirely below
430, so an audit reading 390 and 1280 saw one of the two states and never the pair. It is
flex-wrap:nowrap with overflow-x:auto now, which is what
.cat-nav above it has always been. This is not a padding tune and the difference
is what happens next: a sixth category adds a whole course to a wrapping row and adds nothing
to a scrolling one.
A scroll container clips on both axes, because overflow-y
computes auto the moment overflow-x stops being visible.
The chip's focus ring is 2px wide at 2px offset, so 4px of it stood outside a chip with nothing
between it and the scrollport edge. The ring turns inward, which is the repair
filters.css already makes for the panel's rows. Block padding with an equal
negative margin was tried first and it is the wrong shape: the negative margin collapses
THROUGH the wrapper in a block container, so it does not hand the height back to the row, it hands
it to the neighbours. Measured with it in place: 4px above the row and 12 below, where the file
declares 2 and 16.
The Trending feed carries a category strip at the top and a category
sub-filter under its heading, and until 2026-08-14 they said the same five words:
Trending / Politics / Crypto / Culture / General against
All / Politics / Crypto / Culture / General. The strip routes to a category
page; the sub-filter narrows the list already on screen. Both are true and neither is
visible from the words.
The faces already differed and it was never enough. A strip chip carries
a mark and stands on a plate, a sub-filter chip is bare, and the two rows are a hundred pixels
apart, so a person compares them by reading, not by looking. The repair is a label:
Show: in front of the row. It is not a new idea in this feed and that is the argument
for it: the other two filters have been Sort: and How often: all along,
and this was the only one of the three with no label at all.
What was refused: renaming the chips. The words are the four categories, and giving them a second set of names to say the same four things would have made the product speak twice about one taxonomy. The label costs one word and no vocabulary.
The label stands outside the scroller, so .
is the flex row and the <ul> is the item that scrolls: a label inside a
scroller is a label that leaves. min-width:0 on the item, because a flex item's
default min-width:auto refuses to shrink below its content and the row would push the
label off the edge instead. Measured at seven widths in both engines: the label is 35px, pinned
at x=31 on every phone width, the row is one course everywhere, and the band from the heading to
the first card is 112.0 at 320, 360, 390 and 430, which is what it was before the label.
Three rows in this file are horizontal scrollers and not one of them told the
reader so. .cat-nav>ul cut Crypto off mid-word at 360 and that hard edge was
the only hint the product gave; the sub-category rail gave none, because its last chip usually ends
before the edge.
A fade painted on permanently is the usual answer and it is wrong twice. It fades the last chip once the row is scrolled to its end, so the thing a person has just reached is the thing that goes pale, and it fades empty space on a row that fits, which is a hint pointing at nothing. Both of those read the PAINT when the question is about the SCROLL.
animation-timeline:scroll(self inline) binds progress to the row's
own inline scroll: no left fade at 0, both between, no right fade at the end. And when the row
does not overflow the timeline is inactive and the element falls back to its base style, which
declares no mask at all, so a row that fits is a row with no fade and it costs neither a query nor
a class to say so.
Measured in both engines before a line of it was written, because this
system has been burned by a mask twice. CSS.supports is true in Chromium 151 and
WebKit 26.5, the computed mask-image MOVED when the row was scrolled in both, and the
row was then screenshot with the mask on and with mask-image:none forced: the two
images differ in both engines, and the same shot taken twice unchanged is byte-identical. That
last reading is the control, and without it the first two prove only that a property parses.
One layer and no mask-composite: the two-layer mask that drew nothing in WebKit
is written up in components/CLAUDE.md. A gradient is also the one kind of mask safe
from disk, because it is generated rather than fetched.
A scroller does not start at its active item, and that was a live defect on
3 of the 5 category pages. At 360 the chip carrying aria-current stood off the
right edge: Crypto by 92px, Culture by 223, General by 356, which is the whole chip. A
person landed on a page whose navigation showed nothing chosen. scroll-start-target is
the CSS answer to exactly this and neither Chromium 151 nor WebKit 26.5 supports it,
measured, so it is nine lines of script on the 57 screens that carry the strip, and the script says
so in its own first comment. 0 of 106 screens now.
A region keeps the place and gives up the face. Where the rail pins, how wide it is, how far it may run, and whether it scrolls: those are the region's. What the thing inside it looks like is not.
A part that changes with the control's state belongs to the control. That single test moved the mark and the count out of this file and left the bottom nav's balance where it was.
Never let an atom contain a component. It is a cycle, and the chip computed two different levels depending on which tree you read it from.
Never pin a rail without capping it to the window. Two sub-categories were unreachable on a 768px laptop and scrolling could not help.
Never delete an unscoped rule without rendering it first. Eight of these values were dead and two were not, and only the page could say which.
The level and its reason: the molecules
page. The stylesheet: components/catnav.css. The two chips and the two parts:
chip. The shell the band stands in:
components/patterns/browse-shell.css. The other rail with the same defect:
components/toc.css.