fix: the Save for a card stays in view while you are inside that card

You could change an image model, scroll past it, and never learn there
was a button. The Availability card runs to about 1,300 pixels: the
image models sit above the slide reviewer, which sits above the Save, so
the fields and the thing that saves them were never on screen together.

The save row is now sticky. It pins to the bottom of the window while
you are anywhere inside its card and settles back into place at the end.
That class is already on four cards, so Clinical Assistant, Search
Sources, SMTP and OIDC get it too.

Two things were stopping sticky from working, and both were invisible:

.card sets overflow:hidden to clip its rounded header, and overflow
hidden on an ancestor silently disables position:sticky in every
descendant. clip does the same clipping without making the card a scroll
container.

Then #admin-tab sets overflow:auto as part of the tab shell — which
makes it the nearest scrolling ancestor for everything inside it while
it never actually scrolls, because the document does. bottom:0 resolved
against a box 7,700px tall, which is to say it did not stick at all.
Admin now opts out of that overflow the way #assistant-tab already does;
nothing in there needs the clipping, since every wide thing already
scrolls in a container of its own.

Checked in a browser rather than reasoned about: with the image fields
on screen the bar's bottom edge is at 820px in an 820px viewport.

Audited the other cards while here. Registration, Users and Discover &
test have no Save because they have nothing to save — they are actions
and search boxes. Roster's is called "Set default".

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Dv6sqaY6Vq3ChZHMem3cnU
This commit is contained in:
Daniel 2026-09-13 02:54:56 +02:00
parent ae602a1852
commit 109ab3951c

View file

@ -108,6 +108,14 @@ body{font-family:'Inter',system-ui,sans-serif;background:var(--g50);color:var(--
/* The assistant brings its own full-bleed layout, so it takes the shell's place
rather than nesting a second card inside it. */
.main-content > #assistant-tab.active{padding:0;border:none;box-shadow:none;background:transparent;overflow:visible;}
/* Admin gives up the shell's overflow for the same reason the assistant does,
but for a different effect: overflow:auto here makes this the nearest
scrolling ancestor for everything inside, while it never actually scrolls
the document does. A sticky element then resolves bottom:0 against a box
7,000px tall, which is to say it does not stick at all. The admin save bars
depend on it, and nothing in admin needs the clipping: every wide thing in
there already scrolls in a container of its own. */
.main-content > #admin-tab.active{overflow:visible;}
@media(max-width:768px){
.main-content{padding:8px;}
.main-content > .tab-content.active{padding:12px;border-radius:12px;}
@ -1286,7 +1294,27 @@ textarea.full-input{resize:vertical;}
.admin-note { font-size:12px; color:var(--g500); margin:0; line-height:1.5; }
.admin-badge { font-size:11px; padding:2px 8px; border-radius:10px; background:var(--g100); color:var(--g600); white-space:nowrap; }
.admin-search-row { display:flex; gap:8px; flex-wrap:wrap; align-items:center; }
.admin-save-row { border-top:1px solid var(--g100); padding-top:12px; display:flex; align-items:center; gap:8px; flex-wrap:wrap; }
/* The Save for a card, kept in view while you are inside that card.
These cards are long the image models sit above a slide reviewer, which
sits above the Save so it was possible to change a setting, scroll on, and
never learn there was a button. It sticks to the bottom of the window until
the card ends, then sits where it always did.
The negative margins let the bar span the card's padding rather than floating
in a gutter; the background is opaque because content scrolls under it. */
.admin-save-row {
border-top:1px solid var(--g100); display:flex; align-items:center; gap:8px; flex-wrap:wrap;
position:sticky; bottom:0; z-index:2;
background:var(--white,#fff);
margin:0 -16px -14px; padding:12px 16px 14px;
}
/* .card sets overflow:hidden to clip its rounded header, and overflow:hidden on
an ancestor silently disables position:sticky in every descendant. clip does
the same clipping without making the card a scroll container. Scoped to admin
cards rather than every card in the app. */
details.card { overflow:clip; }
@media (prefers-reduced-motion: no-preference) { .admin-save-row { transition:box-shadow .15s ease; } }
/* A hint of lift only while it is actually stuck, so a card at rest looks flat. */
.admin-save-row:not(:last-child) { box-shadow:0 -1px 0 var(--g100); }
.admin-kind-switch { display:flex; flex-wrap:wrap; gap:6px; }
.admin-discover-kind { display:inline-flex; align-items:center; gap:6px; padding:5px 12px; border:1px solid var(--g300); border-radius:999px; background:white; color:var(--g700); font-size:12px; font-weight:600; cursor:pointer; }
.admin-discover-kind:hover { background:var(--g100); }