From f82f2b589d20197c3df5f64866775d8fc09e4758 Mon Sep 17 00:00:00 2001 From: prosolis <5590409+prosolis@users.noreply.github.com> Date: Tue, 28 Jul 2026 22:21:33 -0700 Subject: [PATCH] Measure the corner the kitten sits in, not the kitten MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The overlap test read the badge's own box, which bobs, shrinks 10% when it yields, and grows 4% on hover — so the mascot's answer to "is a card in my way" depended on what it was currently doing. Against the live build, with three cards up and no bubble, it flipped between drawn widths of 293 and 264 on its own: the 0.9 yield scale, cycling. Measure a probe span instead. It sits exactly where the badge sits, never animates, and moves the size variable to .petal-corner so both are sized from the same number. Nothing the mascot does can now change what it yields to. Cards also settle a pixel from the corner routinely — a rail re-pack, a resize, a browser bar appearing — so hold a yield until the card has retreated 24px rather than deciding on the exact edge. Verified in a real browser over CDP: seven overlap depths against the mascot's top edge, each settling once and holding, drawn width steady where it used to swing. Claude-Session: https://claude.ai/code/session_01GJHNvirh7Hzhc9RL3HAvz7 --- .../components/Companion/PetalCompanion.tsx | 19 ++++++- .../components/Companion/useCardOverlap.ts | 52 ++++++++++++------- web/src/index.css | 7 ++- 3 files changed, 55 insertions(+), 23 deletions(-) diff --git a/web/src/components/Companion/PetalCompanion.tsx b/web/src/components/Companion/PetalCompanion.tsx index efc03aa..91ece65 100644 --- a/web/src/components/Companion/PetalCompanion.tsx +++ b/web/src/components/Companion/PetalCompanion.tsx @@ -88,13 +88,18 @@ export function PetalCompanion({ const [pickerOpen, setPickerOpen] = useState(false) const rootRef = useRef(null) const badgeRef = useRef(null) + // Stand-in for the badge's corner, used only for measuring — see + // useCardOverlap. It sits exactly where the badge sits but never bobs, shrinks + // or hovers, so what the mascot yields to can't depend on whether it is + // currently yielding. + const probeRef = useRef(null) // When suggestion cards stack down into the corner, the kitten fades to // translucent and shrinks a step so the card stays readable and clickable. // It wakes back up whenever it has something to say (bubble) or is being // interacted with (picker open) — except under an open History or Garden // panel, where even a cheer would cover the controls she just reached for. - const crowded = useCardOverlap(badgeRef) + const crowded = useCardOverlap(probeRef) const faded = crowded.modal || (crowded.cards && !pickerOpen && !bubble) // Awake companions (no sleeping clip) don't visibly nap — when the engine @@ -135,7 +140,7 @@ export function PetalCompanion({ return (
{pickerOpen && (
)} + +