.root {
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 10;
    padding: var(--spacing-12) var(--spacing-16) var(--spacing-16);
    background: var(--color-bg-base-light);
    border-top: var(--border-width-sm) solid var(--border-color-light);
    transform: translateY(100%);
    /* Hidden bars must not paint at all: in container mode the "hidden" translateY(±100%) pose is
       only off-screen while the sticky sentinel is pinned to the container edge — at the scroll
       extremes the sentinel un-sticks and rides with the content, which would drag a visible empty
       bar strip into the viewport. Visibility flips after the slide-out finishes (0s transition
       delayed by the transform duration) and instantly on show (see `.visible`). */
    visibility: hidden;
    transition: transform 0.25s ease, visibility 0s linear 0.25s;
    pointer-events: none;
}

/* Pin to the top instead of the bottom; hidden state slides up out of view. Declared before
   `.visible` so the shared `.visible` transform wins when the bar is on screen. */
.anchorTop {
    top: 0;
    bottom: auto;
    border-top: none;
    border-bottom: var(--border-width-sm) solid var(--border-color-light);
    transform: translateY(-100%);
}

.visible {
    transform: translateY(0);
    /* Show instantly (no visibility delay) — the delayed flip is only for hiding. */
    visibility: visible;
    transition: transform 0.25s ease, visibility 0s;
    pointer-events: auto;
}

/* Container mode (mode="container"): a zero-height sticky sentinel rides the scroll
   container's visible bottom edge without reserving layout space; the bar is absolutely
   positioned to hang upward from it. Hidden state slides below the edge, clipped by the
   container's overflow. Declared after `.visible` so `.containerMode.visible` still wins
   via the compound selector below. */
.containerSentinel {
    position: sticky;
    bottom: 0;
    height: 0;
    z-index: 10;
}

/* Clip layer between the sentinel and the bar (see the JS-side comment in StickyFooter.tsx).
   `position: absolute` so it's removed from flow regardless of height — it can carry a real
   height (set inline, the bar's own measured height) + `overflow: hidden` as a genuine clipping
   box without the zero-height sentinel's constraint of adding no layout space. */
.containerClip {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    overflow: hidden;
}

.containerClipTop {
    top: 0;
    bottom: auto;
}

.containerMode {
    position: absolute;
    bottom: 0;
    left: 0;
    right: 0;
    transform: translateY(100%);
}

.containerMode.visible {
    transform: translateY(0);
}

.inner {
    width: 100%;
    max-width: 520px;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: var(--spacing-8);
}

.manualEntry {
    display: flex;
    justify-content: center;
    padding: var(--spacing-4) 0;
}

/* Submit error under the CTA — centered to sit with the full-width button group. */
.submitError {
    text-align: center;
}

/* Top-edge container variant: the sentinel rides the container's visible TOP edge (host renders it
   at the start of the scrolling content) and the bar hangs downward; hidden state slides up above
   the edge, clipped by the container's overflow. Compound selectors so they beat the single-class
   `.containerMode` / `.visible` rules above regardless of specificity ties. */
.containerSentinelTop {
    top: 0;
    bottom: auto;
}

.containerMode.anchorTop {
    top: 0;
    bottom: auto;
    border-top: none;
    border-bottom: var(--border-width-sm) solid var(--border-color-light);
    transform: translateY(-100%);
}

.containerMode.anchorTop.visible {
    transform: translateY(0);
}

/* One-paint transition suppression for hidden edge changes — see the noTransition prop. Last in
   the file so it wins the transition declaration from `.root` at equal specificity. */
.noTransition {
    transition: none;
}
