Skip to content

Commit 668aa08

Browse files
committed
Hero physics: bots rest on the H1, with the bookmark pill as its own shelf
The headline collision block was the whole #content rect - the new bookmark pill raised its top edge, so bots hovered mid-air left and right of the pill. The block now starts at the H1's top edge, and the pill gets a small chamfered shelf body: bots perch on the pill in the middle and fall past its sides onto the heading. renderStatic() (reduced-motion pile) bases its floor on the same H1 reference. Both null-guarded to the old behavior if elements vanish. Co-Authored-By: CRHQ <noreply@crhq.ai>
1 parent 99bf5af commit 668aa08

1 file changed

Lines changed: 25 additions & 3 deletions

File tree

src/scripts/hero.js

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -143,11 +143,30 @@ function buildStatics(){
143143
var right = M.Bodies.rectangle(W+T/2, H/2, T, H*3, opts);
144144

145145
// the headline + CTA block is part of the environment.
146+
// Operator (2026-08-25): the block used to be the WHOLE #content rect — when the bookmark
147+
// pill became content's first child, the rect's top edge rose to the pill, and bots
148+
// hovered mid-air left and right of it. Now the block starts at the H1's top edge, and
149+
// the narrow pill gets its own little shelf: bots perch on the pill in the middle and
150+
// fall past its sides onto the headline.
146151
var c=content.getBoundingClientRect();
147-
var cx=c.left-B.left+c.width/2, cy=c.top-B.top+c.height/2;
148-
var block = M.Bodies.rectangle(cx, cy, c.width, c.height, Object.assign({},opts,{chamfer:{radius:14}}));
152+
var h1El=content.querySelector('h1');
153+
var hTop=h1El ? h1El.getBoundingClientRect().top : c.top;
154+
var bTop=hTop-B.top, bH=(c.top-B.top)+c.height-bTop;
155+
var cx=c.left-B.left+c.width/2, cy=bTop+bH/2;
156+
var block = M.Bodies.rectangle(cx, cy, c.width, bH, Object.assign({},opts,{chamfer:{radius:14}}));
149157

150158
statics=[floor,left,right,block];
159+
160+
var pillEl=content.querySelector('[data-bookmark-nudge]');
161+
if(pillEl){
162+
var p=pillEl.getBoundingClientRect();
163+
var shelf=M.Bodies.rectangle(
164+
p.left-B.left+p.width/2, p.top-B.top+p.height/2,
165+
p.width, p.height,
166+
Object.assign({},opts,{chamfer:{radius:Math.min(14,p.height/2)}}));
167+
statics.push(shelf);
168+
}
169+
151170
M.Composite.add(world, statics);
152171
}
153172

@@ -403,7 +422,10 @@ function pileRows(n){
403422
}
404423
function renderStatic(){
405424
var B=stageBox(), c=content.getBoundingClientRect();
406-
var contentTop=c.top-B.top;
425+
// Same reference as buildStatics(): the pile rests just above the H1, not above the
426+
// bookmark pill (which is content's first child and would float the pile mid-air).
427+
var h1El=content.querySelector('h1');
428+
var contentTop=(h1El ? h1El.getBoundingClientRect().top : c.top)-B.top;
407429

408430
// biggest bots at the bottom of the pile
409431
var order=bots.slice().sort(function(a,b){ return b.size-a.size; });

0 commit comments

Comments
 (0)