rastrillo / fiesta Public

Branch review round four, finding 7: a reduced-motion disable that loses; red then green open

On branch fiesta-1-1

Astra's finding 7, round four: the reduced-motion gate finds a disable but never checks that it wins. Fixed by asking the browser, not by modelling the cascade in Go. Commit d023e75.

Shipped CSS today: nothing leaks

The new drive loaded all 168 example states, the seven layouts and the column shell among them. It ran each in day, plain and signal at 1280 and 390, with prefers-reduced-motion: reduce emulated and a mouse that hovers. Every element went through eight passes: at rest, hovered, pressed (hover and active), tapped (active), focused (focus, focus-visible, focus-within), targeted, every <details> opened, and opened and hovered. The states are forced on every element through the inspector. For each element and its ::before, ::after, ::marker, ::placeholder and ::backdrop, the drive read the computed transition and animation, and it read document.getAnimations().

Nothing moves. All six parts pass, so css/ is unchanged and no release rebuild is needed.

What counts as moving

Any transition with a duration, on any property, and any animation. Fades count as well. I read DESIGN.md and the gate's intent first:

  • DESIGN.md says that under reduced motion "nothing moves and nothing fades".
  • Every transition tokens.css and shell.css ship has a disable, the tip's opacity fade and the row tints included.
  • Several motions run through custom properties: the switch knob (--rst-switch-p), the press (--rst-press) and the row lift (--rst-hover). A rule that looked only at transform, translate, scale, rotate and position would miss them.

The tokens.css comment above the caret's disable says hover fills and colour changes are not "large motion" under 2.3.3. That is true, but Fiesta disables them anyway, so nothing deliberately keeps a fade.

Red

Astra's CSS was appended to a scratch copy of css/tokens.css, then the copy was reverted. The static gate passes it; the browser drive fails it:

--- PASS: TestReducedMotionDisablesEveryTransition (0.00s)
    under reduced motion, html > body > div[rst-snippet] is running CSSTransition transform (first in snippet/a-line-to-copy at 1280, hovered, in day; 3 readings in all)
    under reduced motion, html > body > div[rst-snippet] transitions transform over 0.2s (first in snippet/a-line-to-copy at 1280, at rest, in day; 8 readings in all)
--- FAIL: TestNothingMovesUnderReducedMotion1of6 (12.49s)

The !important variant, .rst-snippet, [rst-snippet] { transition: transform 0.2s !important; } placed before a reduce block that disables it:

--- PASS: TestReducedMotionDisablesEveryTransition (0.00s)
    under reduced motion, html > body > div[rst-snippet] transitions transform over 0.2s (first in snippet/a-line-to-copy at 1280, at rest, in day; 8 readings in all)
--- FAIL: TestNothingMovesUnderReducedMotion1of6 (13.93s)

The drive's controls (permanent tests)

  • TestTheMotionDriveSeesADisableThatLoses serves the snippet example under tokens.css with four losing disables appended. The drive must name each one: - Astra's later transition - the !important one - a transition on :hover only - an animation on ::before

The static gate reports 0 problems on the first two and catches the last two. The shipped tokens.css is the control: on it, the snippet example moves nowhere.

  • TestTheMotionDriveSeesWhatTheStylesheetsShip turns reduced motion off and runs every state in day at both widths. Each shipped motion must show up in the pass that reaches it: - the button press, the caret, the tip's ::after fade, the switch track and the spinner (both its computed animation and the one running), at rest - the row lift, only when hovered: not at rest, and not when pressed - the snippet's copy button, not when pressed or tapped - the shell menu's drop, only when opened at 390 - the index row's flash, only when targeted at 390

A pass that forced nothing would otherwise leave the main drive reading every page at rest and passing.

Mutations of the drive, each red and then reverted

| | Mutation | Fails | |---|---|---| | D1 | no state forced | LosesDisable/hover only; ShipsWhat: row hover, copy button pressed and tapped | | D2 | no pseudo-elements read | LosesDisable/::before; ShipsWhat: tip ::after | | D3 | getAnimations not read | ShipsWhat: spinner running, row transition running | | D4 | details not opened | ShipsWhat: shell drop opened at 390 | | D5 | reduced motion not emulated | the drive's own check: "reduced motion false … wants true" | | D6 | only the first transition property read | ShipsWhat: the button's translate | | D7 | desktop width only | ShipsWhat: shell drop and flash at 390 | | D8 | no hover | the drive's own check: "hover false" | | D9 | theme link not rewritten | part 3 (plain): "has not loaded themes/plain.css" |

Green

At d023e75, locally: all six parts of TestNothingMovesUnderReducedMotion pass (12.5 to 13.3s each). TestTheMotionDriveSeesADisableThatLoses passes (3.1s), and so does TestTheMotionDriveSeesWhatTheStylesheetsShip (28.7s). go test ./check, the role tests in the root package, gofmt and staticcheck pass.

Hub CI passed at d023e75. gofmt, no-rastrillo, size, history and 50-suite@49 all pass, with no FAIL lines in 49 shards. The suite step took 112s, against 134s at a92e384. The size step is unchanged: 23,823 / 23,104 / 23,217 bytes gzipped.

The check shards ran 85 to 104s each, against 77 to 99s at a92e384. On the fleet the new drives cost more than docs-t1 times 1.17 predicted. The weights need re-timing on a runner, and check may want a 15th slice.

The static gate

TestReducedMotionDisablesEveryTransition stays as the early warning: it runs in a second with no browser and names the selector to fix. Its comment now says it finds a disable but does not check that the disable wins. The authority is the browser drive, because deciding which declaration wins means ordering and weighing the whole cascade, and a copy of that in Go would be one more reader to get wrong.

Role and weight

The drive adds about 125 weight-seconds to check, whose slices were already the slowest roles on the fleet (77 to 99s at a92e384). So check goes from 13 slices to 14, and 50-suite@48 becomes @49. Each slice now deals 78 to 79 weight-seconds: it was 76, and it would be 85 at 13 slices. The weights are docs-t1 times scaled by 1.17: each part 15, the ship control 33, the loses control 3. A runner has not timed them yet.

Not covered

  • States that a script sets: the switch's data-rst-settle and data-rst-drag. The static gate still names the settle selector's disable.
  • The view transition between shell pages. TestTheSlideKnowsWhichWayItIsGoing already holds that under reduced motion no transition starts.
  • A coarse-pointer rig. Its rules change sizes, not motion.