diff --git a/skills/leaf/assets/runtime/chrome-style.js b/skills/leaf/assets/runtime/chrome-style.js index 7a8f859f2..48407efa9 100644 --- a/skills/leaf/assets/runtime/chrome-style.js +++ b/skills/leaf/assets/runtime/chrome-style.js @@ -235,17 +235,26 @@ export function chromeStyle({ shape and loses the gesture: BAKE takes the role and the tab stop off a standing reaction mark and leaves the mark itself, so a hand hung on the class alone promises a press no file can answer. It reads the two ways a press is spelled - here: the platform's element, and the explicit selectable-offer exception. */ + here: the platform's element, and the explicit selectable-offer exception. + + The lift under the pointer is the same promise in the other property, and the tones + below are that lift wearing a colour, so all of them are spelled the same way. The + hand is the only half a gate can see — the copy's offering reading takes the cursor and + nothing else — and aria-disabled is no guard in a file either: BAKE strips it with + the rest of the aria state, so a decided suggestion's record, which survives on + data-lf-said, would light its accept tint under a pointer that can decide nothing. */ .lf-margin-action:is(button, [role="button"]) { cursor: pointer; } - .lf-margin-action:hover:not([aria-disabled="true"]) { background: var(--chip); } + .lf-margin-action:is(button, [role="button"]):hover:not([aria-disabled="true"]) { + background: var(--chip); + } .lf-margin-action:is(:focus-visible, .lf-focus-visible) { outline: var(--here-ring); --lf-here-ring: margin-action; outline-offset: 1px; } .lf-margin-action[aria-disabled="true"] { cursor: default; } - .lf-margin-action[data-lf-tone="positive"]:hover:not([aria-disabled="true"]) { + .lf-margin-action[data-lf-tone="positive"]:is(button, [role="button"]):hover:not([aria-disabled="true"]) { border-color: var(--ok); color: var(--ok-ink); background: var(--ok-tint); } - .lf-margin-action[data-lf-tone="negative"]:hover:not([aria-disabled="true"]) { + .lf-margin-action[data-lf-tone="negative"]:is(button, [role="button"]):hover:not([aria-disabled="true"]) { border-color: var(--danger); color: var(--danger-ink); background: var(--danger-tint); } .lf-margin-action[data-lf-tone="positive"][aria-disabled="true"] { @@ -257,7 +266,7 @@ export function chromeStyle({ .lf-margin-action[data-lf-tone="primary"] { border-color: var(--accent); background: var(--accent); color: var(--paper); } - .lf-margin-action[data-lf-tone="primary"]:hover:not([aria-disabled="true"]) { + .lf-margin-action[data-lf-tone="primary"]:is(button, [role="button"]):hover:not([aria-disabled="true"]) { filter: brightness(.92); background: var(--accent); } .lf-margin-action.lf-react[aria-pressed="true"] { diff --git a/tests/test_render_reactions.py b/tests/test_render_reactions.py index 23b3befda..4185e7a41 100644 --- a/tests/test_render_reactions.py +++ b/tests/test_render_reactions.py @@ -1223,5 +1223,15 @@ def test_a_copy_keeps_a_standing_reaction_as_a_mark_and_drops_the_press( assert copy == {"washed": ["every edit"], "glyph": [["−", "img", "cut", None]]}, ( copy ) + # The other half of the same promise, and the half no gate can see: the copy's + # `offering` reads the cursor and nothing else, so paint that arrives with the + # pointer rather than standing on the page is invisible to it. A receipt in a file + # that lifts under the pointer says a press is there to take. + mark = page.locator( + '.lf-margin-item[data-lf-margin-for="how-store"] .lf-react-mark' + ) + resting = mark.evaluate("el => getComputedStyle(el).backgroundColor") + mark.hover() + assert mark.evaluate("el => getComputedStyle(el).backgroundColor") == resting assert errors == [] page.close()