diff --git a/static/css/custom.css b/static/css/custom.css index c9c0cd3..9bf287e 100644 --- a/static/css/custom.css +++ b/static/css/custom.css @@ -1780,11 +1780,12 @@ body, .card, .modal-content, .form-control, .form-select, } /* --- Popover positioned under the pill --- */ -/* max-height + flex column keeps the sticky footer visible even when the - popover body has to scroll (Choices.js can render a long list of options). - Border + shadow beefed up 2026-04-23 so the popover visually detaches +/* Border + shadow beefed up 2026-04-23 so the popover visually detaches from the report body behind it — previous subtle shadow was getting - lost against the amber-accented report cards. */ + lost against the amber-accented report cards. + The popover uses a flex column so a sticky footer stays pinned at the + bottom even when the body scrolls. We DO NOT set overflow: hidden on + the popover itself — see the Choices.js override below for why. */ .filter-popover { position: absolute; top: calc(100% + 6px); @@ -1804,7 +1805,6 @@ body, .card, .modal-content, .form-control, .form-select, 0 18px 44px rgba(0, 0, 0, 0.55), /* deep drop shadow */ 0 6px 12px rgba(0, 0, 0, 0.35); /* near shadow for edge crispness */ padding: 0; - overflow: hidden; /* clip Choices.js dropdown so the sticky footer wins */ } /* Light theme: shadow and halo need different opacity to read against white */ :root.light .filter-popover { @@ -1837,6 +1837,38 @@ body, .card, .modal-content, .form-control, .form-select, z-index: 2; } +/* --- Choices.js dropdown override (scoped to filter popovers) --- + Choices.js renders its option list as position: absolute beneath the + input. Inside our popovers (a flex column with a max-height and a + sticky footer) that's a problem: + 1. The absolute-positioned dropdown doesn't contribute to the body's + scrollHeight, so the body's overflow-y: auto never creates a + scrollbar — and the user's wheel scroll falls through to the page. + 2. The dropdown's rendered position overlaps / sits behind the sticky + footer, so options aren't visible. + Forcing the dropdown to position: static lets it flow inline: the body + grows to contain it, the sticky footer pushes below, and for long + option lists the dropdown's own max-height + overflow-y gives a clean + internal scroll. + + Specificity note: we mirror Choices.js's selector list + (`.choices__list--dropdown, .choices__list[aria-expanded]`) because + the second branch carries a class+attribute specificity (0,0,2,0) + that ties with a naive two-class override. Source order then decides + the winner and Choices.js's stylesheet loads AFTER ours. Mirroring + the selector lifts our specificity one step on the aria-expanded + branch and wins cleanly without needing !important. + + Scoped to .filter-popover so other Choices.js usages in the app + (worker/team pickers on edit pages, etc.) keep their default behaviour. */ +.filter-popover .choices__list--dropdown, +.filter-popover .choices__list[aria-expanded] { + position: static; + margin-top: 0.35rem; + max-height: 260px; + overflow-y: auto; +} + /* --- Mobile: popovers stretch full-width below the pill strip --- */ @media (max-width: 576px) { .filter-popover {