diff --git a/index.html b/index.html
index 8b347e5..5ee3749 100644
--- a/index.html
+++ b/index.html
@@ -2,7 +2,7 @@
-
+
Hive Commons
@@ -1146,14 +1146,17 @@ Thanks to the organizations that power Hive Commons<
}
function stop() { clearInterval(timer); timer = null; }
function restart() { stop(); start(); }
- root.addEventListener('mouseenter', function () { pointerPaused = true; stop(); });
- root.addEventListener('mouseleave', function () { pointerPaused = false; start(); });
- root.addEventListener('focusin', function () { focusPaused = true; stop(); });
- root.addEventListener('focusout', function (e) {
- if (!root.contains(e.relatedTarget)) {
- focusPaused = false;
- start();
- }
+ [root, controls].forEach(function (el) {
+ if (!el) return;
+ el.addEventListener('mouseenter', function () { pointerPaused = true; stop(); });
+ el.addEventListener('mouseleave', function () { pointerPaused = false; start(); });
+ el.addEventListener('focusin', function () { focusPaused = true; stop(); });
+ el.addEventListener('focusout', function (e) {
+ if (!root.contains(e.relatedTarget) && !(controls && controls.contains(e.relatedTarget))) {
+ focusPaused = false;
+ start();
+ }
+ });
});
document.addEventListener('visibilitychange', function () { document.hidden ? stop() : start(); });
if (reduceMotion.addEventListener) {
diff --git a/scripts/carousels.test.mjs b/scripts/carousels.test.mjs
index 1e9f678..f33f909 100644
--- a/scripts/carousels.test.mjs
+++ b/scripts/carousels.test.mjs
@@ -789,6 +789,22 @@ test("projects pause: pointer hovering then external focusout stays paused until
assert.deepEqual(t.timers.intervals(), [PROJECT_ADVANCE_MS], "resumes once neither is inside");
});
+test("projects pause: hovering or focusing the external Prev/Next controls pauses auto-advance", () => {
+ const t = bootProjects();
+ t.controls.dispatch("mouseenter");
+ assert.deepEqual(t.timers.intervals(), [], "hover on controls pauses");
+ t.controls.dispatch("mouseleave");
+ assert.deepEqual(t.timers.intervals(), [PROJECT_ADVANCE_MS], "leaving controls resumes");
+ t.controls.dispatch("focusin");
+ assert.deepEqual(t.timers.intervals(), [], "focus on controls pauses");
+ t.controls.dispatch("focusout", { relatedTarget: t.root });
+ assert.deepEqual(t.timers.intervals(), [], "focus moving into the carousel stays paused");
+ t.root.dispatch("focusout", { relatedTarget: t.next });
+ assert.deepEqual(t.timers.intervals(), [], "focus moving back to the controls stays paused");
+ t.controls.dispatch("focusout", { relatedTarget: null });
+ assert.deepEqual(t.timers.intervals(), [PROJECT_ADVANCE_MS], "resumes once focus leaves both");
+});
+
test("projects reduced-motion toggle: stops and resumes auto-advance", () => {
const t = bootProjects();
t.mq.set(true);