diff --git a/static/css/documents-gallery-editor.css b/static/css/documents-gallery-editor.css
index 348401983..19c7f5adb 100644
--- a/static/css/documents-gallery-editor.css
+++ b/static/css/documents-gallery-editor.css
@@ -339,6 +339,13 @@ mark.doc-find-mark {
height: 100%;
min-height: 0;
}
+ /* The container now fills the body exactly, so its inline 2px top margin
+ (spacing for the grid view) would push it 2px past the body and add a
+ second, outer scrollbar beside the inspector's own. !important is needed
+ to beat the inline style. */
+ .gallery-images-container:has(> #gallery-detail[style*="flex"]) {
+ margin-top: 0 !important;
+ }
}
.gallery-detail-image:hover .gallery-detail-rotate { opacity: 0.85; }
.gallery-detail-nav-disabled {
diff --git a/static/index.html b/static/index.html
index b1d2031df..93b6895e2 100644
--- a/static/index.html
+++ b/static/index.html
@@ -247,32 +247,32 @@
real request is discarded and the font fetched a second time. -->
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
@@ -2709,7 +2709,7 @@
-
+
diff --git a/static/sw.js b/static/sw.js
index a4f448c8f..628b0d872 100644
--- a/static/sw.js
+++ b/static/sw.js
@@ -7,7 +7,7 @@
// - Other static assets (images/fonts/libs): cache-first with bg refresh.
// - API / non-GET: never cached.
// Bump CACHE_NAME whenever the precache list or SW logic changes.
-const CACHE_NAME = 'odysseus-v1134-pr40-editor-precache';
+const CACHE_NAME = 'odysseus-v1135-pr40-editor-precache';
// KaTeX resolves these from its own stylesheet, so caching the CSS without them
// gives offline math fallback glyphs instead of proper typesetting.
@@ -40,28 +40,28 @@ const KATEX_FONTS = [
const PRECACHE = [
'/static/js/compare/sse.js',
'/',
- '/static/css/00-tokens.css?v=20260929csssplit',
- '/static/css/01-agent-chat.css?v=20260929csssplit',
- '/static/css/02-compare.css?v=20260929csssplit',
- '/static/css/03-agent-chat.css?v=20260929csssplit',
- '/static/css/04-memory.css?v=20260929csssplit',
- '/static/css/05-documents.css?v=20260929csssplit',
- '/static/css/06-admin-settings.css?v=20260929csssplit',
- '/static/css/07-documents.css?v=20260929csssplit',
- '/static/css/08-skills.css?v=20260929csssplit',
- '/static/css/09-gallery.css?v=20260929csssplit',
- '/static/css/10-cookbook.css?v=20260929csssplit',
- '/static/css/11-tasks.css?v=20260929csssplit',
- '/static/css/12-gallery.css?v=20260929csssplit',
- '/static/css/13-image-editor.css?v=20260929csssplit',
- '/static/css/14-email.css?v=20260929csssplit',
- '/static/css/15-notes.css?v=20260929csssplit',
- '/static/css/16-calendar.css?v=20260929csssplit',
- '/static/css/17-research.css?v=20260929csssplit',
- '/static/css/documents-gallery-editor.css?v=20260929csssplit',
- '/static/css/email-calendar-notes-tasks.css?v=20260929csssplit',
- '/static/css/cookbook-research-memory-settings.css?v=20260929csssplit',
- '/static/app.js?v=20260929csssplit',
+ '/static/css/00-tokens.css?v=20261007detailscroll1',
+ '/static/css/01-agent-chat.css?v=20261007detailscroll1',
+ '/static/css/02-compare.css?v=20261007detailscroll1',
+ '/static/css/03-agent-chat.css?v=20261007detailscroll1',
+ '/static/css/04-memory.css?v=20261007detailscroll1',
+ '/static/css/05-documents.css?v=20261007detailscroll1',
+ '/static/css/06-admin-settings.css?v=20261007detailscroll1',
+ '/static/css/07-documents.css?v=20261007detailscroll1',
+ '/static/css/08-skills.css?v=20261007detailscroll1',
+ '/static/css/09-gallery.css?v=20261007detailscroll1',
+ '/static/css/10-cookbook.css?v=20261007detailscroll1',
+ '/static/css/11-tasks.css?v=20261007detailscroll1',
+ '/static/css/12-gallery.css?v=20261007detailscroll1',
+ '/static/css/13-image-editor.css?v=20261007detailscroll1',
+ '/static/css/14-email.css?v=20261007detailscroll1',
+ '/static/css/15-notes.css?v=20261007detailscroll1',
+ '/static/css/16-calendar.css?v=20261007detailscroll1',
+ '/static/css/17-research.css?v=20261007detailscroll1',
+ '/static/css/documents-gallery-editor.css?v=20261007detailscroll1',
+ '/static/css/email-calendar-notes-tasks.css?v=20261007detailscroll1',
+ '/static/css/cookbook-research-memory-settings.css?v=20261007detailscroll1',
+ '/static/app.js?v=20261007detailscroll1',
'/static/js/storage.js',
'/static/js/appConfig.js',
'/static/js/ui.js?v=20260916largetoolscroll1',
diff --git a/tests/test_gallery_visual_static.py b/tests/test_gallery_visual_static.py
index 3e6cebe9a..2e0c74e92 100644
--- a/tests/test_gallery_visual_static.py
+++ b/tests/test_gallery_visual_static.py
@@ -162,6 +162,20 @@ def test_gallery_body_uses_available_window_height_without_grid_crop():
assert "max-height: 60vh;" not in grid_rule
+def test_gallery_detail_container_drops_grid_margin_so_body_does_not_scroll():
+ # With a photo open on desktop, the modal body, the images container and
+ # the detail view are each `height: 100%`. The container's inline 2px top
+ # margin (grid-view spacing) would then overflow the body by 2px, which
+ # shows a second, outer scrollbar next to the inspector's own.
+ js = _read("static/js/gallery.js")
+ css = app_css()
+
+ assert 'id="gallery-images-container" style="margin-top:2px"' in js
+ rule = '.gallery-images-container:has(> #gallery-detail[style*="flex"]) {'
+ idx = css.index(rule)
+ assert "margin-top: 0 !important;" in css[idx:idx + 120]
+
+
def test_gallery_photo_search_is_not_vertically_offset():
css = app_css()